diff --git a/apps/studio/components/interfaces/Explorer/QueryCell/DisplaySettingsButton.tsx b/apps/studio/components/interfaces/Explorer/QueryCell/DisplaySettingsButton.tsx index 96460ec03ec24..29a8ee384277d 100644 --- a/apps/studio/components/interfaces/Explorer/QueryCell/DisplaySettingsButton.tsx +++ b/apps/studio/components/interfaces/Explorer/QueryCell/DisplaySettingsButton.tsx @@ -1,4 +1,5 @@ import { BarChart2, Settings2, Table } from 'lucide-react' +import { useEffect, useEffectEvent, useMemo } from 'react' import { Checkbox, Popover, @@ -12,23 +13,34 @@ import { SelectValue, ToggleGroup, ToggleGroupItem, + Tooltip, + TooltipContent, + TooltipTrigger, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { type Snapshot } from 'valtio' import { ExplorerToolbarAction } from '../ExplorerToolbar' +import { type QueryResult } from '../types' +import { checkHasNonPositiveValues } from '@/components/ui/QueryBlock/QueryBlock.utils' import { type DatabaseCell as DatabaseCellSchema } from '@/data/content/notebooks/notebook-schema' import { useCurrentNotebook, useNotebooksStateSnapshot } from '@/state/notebooks/notebooks-state' interface DisplaySettingsButtonProps { cell: Snapshot + result?: QueryResult columns: string[] disabled: boolean } // [Joshen] TODO support multiple y axis charts -export const DisplaySettingsButton = ({ cell, columns, disabled }: DisplaySettingsButtonProps) => { +export const DisplaySettingsButton = ({ + cell, + result, + columns, + disabled, +}: DisplaySettingsButtonProps) => { const snap = useNotebooksStateSnapshot() const currentNotebook = useCurrentNotebook() const cells = currentNotebook?.notebook.content?.cells ?? [] @@ -37,12 +49,22 @@ export const DisplaySettingsButton = ({ cell, columns, disabled }: DisplaySettin const { type = 'bar', x_column, - y_columns, + y_columns = [], cumulative = false, show_labels = false, scale = 'linear', } = chart ?? {} + const hasNonPositiveValues = useMemo( + () => checkHasNonPositiveValues(result?.rows ?? [], y_columns[0]), + [result, y_columns] + ) + + const canToggleLogScale = useMemo(() => { + if (y_columns.length === 0 || !result || (result.rows ?? []).length === 0) return false + return !hasNonPositiveValues + }, [hasNonPositiveValues, result, y_columns.length]) + const onChangeView = (view: 'table' | 'chart') => { const notebookId = currentNotebook?.notebook.id if (!notebookId) return @@ -84,12 +106,22 @@ export const DisplaySettingsButton = ({ cell, columns, disabled }: DisplaySettin snap.updateCells({ id: notebookId, cells: nextCells }) } + const resetToLinearScale = useEffectEvent(() => { + onUpdateChartConfig({ scale: 'linear' }) + }) + + useEffect(() => { + if (hasNonPositiveValues && scale === 'log') { + resetToLinearScale() + } + }, [hasNonPositiveValues, scale]) + return ( } tooltip="Result settings" /> - +

Result display settings @@ -187,7 +219,24 @@ export const DisplaySettingsButton = ({ cell, columns, disabled }: DisplaySettin Linear - Logarithmic + + + + Logarithmic + + + {!canToggleLogScale && ( + + {y_columns.length === 0 + ? 'Select a column for the Y axis first' + : 'Data contains zero or negative values'} + + )} + diff --git a/apps/studio/components/interfaces/Explorer/QueryCell/QueryResultChart.tsx b/apps/studio/components/interfaces/Explorer/QueryCell/QueryResultChart.tsx index 8f6db1ffc8c47..ddee91b17b7f5 100644 --- a/apps/studio/components/interfaces/Explorer/QueryCell/QueryResultChart.tsx +++ b/apps/studio/components/interfaces/Explorer/QueryCell/QueryResultChart.tsx @@ -4,7 +4,7 @@ import { type Snapshot } from 'valtio' import { type QueryResult } from '../types' import NoDataPlaceholder from '@/components/ui/Charts/NoDataPlaceholder' -import { getCumulativeResults } from '@/components/ui/QueryBlock/QueryBlock.utils' +import { formatLogTick, getCumulativeResults } from '@/components/ui/QueryBlock/QueryBlock.utils' import { type DatabaseCell as DatabaseCellSchema } from '@/data/content/notebooks/notebook-schema' interface QueryResultChartProps { @@ -23,7 +23,7 @@ const toChartValue = (value: unknown): string | number => { export const QueryResultChart = ({ cell, result }: QueryResultChartProps) => { const { chart } = cell - const { type, x_column, y_columns = [], cumulative, show_labels } = chart ?? {} + const { type, x_column, y_columns = [], cumulative, show_labels, scale } = chart ?? {} const hasConfig = !!x_column && y_columns.length > 0 const chartRows = useMemo(() => { @@ -76,6 +76,11 @@ export const QueryResultChart = ({ cell, result }: QueryResultChartProps) => { showXAxis={show_labels} showYAxis={show_labels} data={resultToRender} + YAxisProps={{ + scale: scale === 'log' ? 'log' : 'auto', + domain: scale === 'log' ? [1, 'auto'] : undefined, + tickFormatter: scale === 'log' ? formatLogTick : undefined, + }} /> )} {type === 'line' && ( @@ -86,6 +91,11 @@ export const QueryResultChart = ({ cell, result }: QueryResultChartProps) => { showXAxis={show_labels} showYAxis={show_labels} data={resultToRender} + YAxisProps={{ + scale: scale === 'log' ? 'log' : 'auto', + domain: scale === 'log' ? [1, 'auto'] : undefined, + tickFormatter: scale === 'log' ? formatLogTick : undefined, + }} /> )}

diff --git a/apps/studio/components/interfaces/Explorer/QueryCell/index.tsx b/apps/studio/components/interfaces/Explorer/QueryCell/index.tsx index bf225ba54c55a..2a2a6a8ff1f6f 100644 --- a/apps/studio/components/interfaces/Explorer/QueryCell/index.tsx +++ b/apps/studio/components/interfaces/Explorer/QueryCell/index.tsx @@ -120,6 +120,7 @@ export const QueryCell = ({ cell }: QueryCellProps) => { diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx index 5b4dd4f5ed970..13160f9235c62 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx @@ -170,12 +170,6 @@ export const DowngradeModal = ({ - - {subscription?.billing_via_partner === true && subscription.billing_partner === 'fly' && ( -

- Your organization will be downgraded at the end of your current billing cycle. -

- )} - { - e.preventDefault() - switchSource('database') - }} - > - - - Database - - {!isLogs && } - - {(canCreateLogsSnippet || isLogs) && ( + {selectableSources.map((source) => ( { e.preventDefault() - switchSource('logs') + switchSource(source.id) }} > - - Logs + + {QUERY_SOURCE_LABELS[source.id]} - {isLogs && } + {currentSource === source.id && } - )} + ))} {runSource.type === 'logs' ? ( - sessionSnap.setLogRange(id, range)} onOpenCustomRange={() => setIsCustomRangeOpen(true)} onShowUpgrade={() => setShowUpgradePrompt(true)} /> ) : ( <> - {IS_PLATFORM && } + {IS_PLATFORM && ( + + )} @@ -169,7 +156,7 @@ export const QuerySourceMenu = ({ id, runSource, canCreateLogsSnippet }: QuerySo diff --git a/apps/studio/components/interfaces/SQLEditor/querySource.test.ts b/apps/studio/components/interfaces/SQLEditor/querySource.test.ts index 6c68f56e2db46..93f38dcfa7278 100644 --- a/apps/studio/components/interfaces/SQLEditor/querySource.test.ts +++ b/apps/studio/components/interfaces/SQLEditor/querySource.test.ts @@ -1,43 +1,11 @@ -import dayjs from 'dayjs' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { - datePickerValueToLogDateRange, - DEFAULT_LOG_DATE_RANGE, getSnippetSource, isLogsSource, - logDateRangesEqual, - logDateRangeToDatePickerValue, - resolveLogRunRange, resolveSnippetSource, sqlSourceToFenceLanguage, - type LogDateRange, } from './querySource' -import { - EXPLORER_DATEPICKER_HELPERS, - getDefaultHelper, -} from '@/components/interfaces/Settings/Logs/Logs.constants' -import { generateHelpersFromInput } from '@/components/interfaces/Settings/Logs/Logs.datePickerHelpers' -import type { DatePickerValue } from '@/components/interfaces/Settings/Logs/Logs.DatePickers' -import type { DatetimeHelper } from '@/components/interfaces/Settings/Logs/Logs.types' -import { isoDateTimeString } from '@/lib/iso-datetime' - -/** Build the `DatePickerValue` the Logs picker submits when a helper is selected. */ -const valueFromHelper = (helper: DatetimeHelper): DatePickerValue => ({ - from: helper.calcFrom(), - to: helper.calcTo(), - isHelper: true, - text: helper.text, -}) - -/** The single dynamic helper produced from typed input like "2h" / "30m". */ -const dynamicHelper = (input: string): DatetimeHelper => { - const generated = generateHelpersFromInput(input) - if (!generated || generated.length !== 1) { - throw new Error(`Expected a single dynamic helper for "${input}"`) - } - return generated[0] -} describe('querySource.ts:getSnippetSource', () => { it('maps log_sql to the logs source', () => { @@ -91,221 +59,3 @@ describe('querySource.ts:resolveSnippetSource', () => { expect(resolveSnippetSource(undefined, 'nonsense')).toBe('database') }) }) - -describe('querySource.ts:datePickerValueToLogDateRange', () => { - it('parses every static preset into a relative range', () => { - const cases: Array<[string, { amount: number; unit: 'minute' | 'hour' | 'day' }]> = [ - ['Last hour', { amount: 1, unit: 'hour' }], - ['Last 3 hours', { amount: 3, unit: 'hour' }], - ['Last 24 hours', { amount: 24, unit: 'hour' }], - ['Last 3 days', { amount: 3, unit: 'day' }], - ['Last 7 days', { amount: 7, unit: 'day' }], - ] - - for (const [text, last] of cases) { - const helper = EXPLORER_DATEPICKER_HELPERS.find((h) => h.text === text) - expect(helper, `preset "${text}" exists`).toBeDefined() - expect(datePickerValueToLogDateRange(valueFromHelper(helper!))).toEqual({ - kind: 'relative', - last, - }) - } - }) - - it('parses dynamic helpers ("2h", "30m", "7d") into relative ranges', () => { - expect(datePickerValueToLogDateRange(valueFromHelper(dynamicHelper('2h')))).toEqual({ - kind: 'relative', - last: { amount: 2, unit: 'hour' }, - }) - expect(datePickerValueToLogDateRange(valueFromHelper(dynamicHelper('30m')))).toEqual({ - kind: 'relative', - last: { amount: 30, unit: 'minute' }, - }) - expect(datePickerValueToLogDateRange(valueFromHelper(dynamicHelper('7d')))).toEqual({ - kind: 'relative', - last: { amount: 7, unit: 'day' }, - }) - }) - - it('treats a preset (calcTo() === "") as relative — the empty end means "now"', () => { - const lastHour = getDefaultHelper(EXPLORER_DATEPICKER_HELPERS) - const value = valueFromHelper(lastHour) - expect(value.to).toBe('') - expect(datePickerValueToLogDateRange(value)).toEqual({ - kind: 'relative', - last: { amount: 1, unit: 'hour' }, - }) - }) - - it('degrades an unparseable helper to an absolute range using from/now (never empty)', () => { - vi.useFakeTimers() - const now = new Date('2025-01-01T12:00:00.000Z') - vi.setSystemTime(now) - - const from = '2024-12-31T00:00:00.000Z' - const result = datePickerValueToLogDateRange({ - from, - to: '', - isHelper: true, - text: 'Some custom label', - }) - - expect(result).toEqual({ - kind: 'absolute', - from, - to: dayjs(now).toISOString(), - }) - }) - - it('maps a custom (non-helper) pick to an absolute range with both endpoints', () => { - const from = '2025-01-01T00:00:00.000Z' - const to = '2025-01-02T00:00:00.000Z' - expect(datePickerValueToLogDateRange({ from, to, isHelper: false })).toEqual({ - kind: 'absolute', - from, - to, - }) - }) - - it('falls back to the default range when the value has no usable from', () => { - expect(datePickerValueToLogDateRange({ from: '', to: '', isHelper: false })).toEqual( - DEFAULT_LOG_DATE_RANGE - ) - }) -}) - -describe('querySource.ts:logDateRangeToDatePickerValue', () => { - beforeEach(() => { - vi.useFakeTimers() - vi.setSystemTime(new Date('2025-01-01T12:00:00.000Z')) - }) - - it('renders a relative range exactly as the picker would emit the helper', () => { - const value = logDateRangeToDatePickerValue({ - kind: 'relative', - last: { amount: 1, unit: 'hour' }, - }) - expect(value).toEqual({ - from: dayjs().subtract(1, 'hour').toISOString(), - to: dayjs().toISOString(), - isHelper: true, - text: 'Last 1 hour', - }) - }) - - it('pluralizes the label for amounts greater than one', () => { - expect( - logDateRangeToDatePickerValue({ kind: 'relative', last: { amount: 3, unit: 'day' } }).text - ).toBe('Last 3 days') - }) - - it('round-trips through datePickerValueToLogDateRange', () => { - const range: LogDateRange = { kind: 'relative', last: { amount: 30, unit: 'minute' } } - expect(datePickerValueToLogDateRange(logDateRangeToDatePickerValue(range))).toEqual(range) - }) - - it('passes an absolute range through as a non-helper value', () => { - const range: LogDateRange = { - kind: 'absolute', - from: isoDateTimeString('2025-01-01T00:00:00.000Z')!, - to: isoDateTimeString('2025-01-02T00:00:00.000Z')!, - } - expect(logDateRangeToDatePickerValue(range)).toEqual({ - from: '2025-01-01T00:00:00.000Z', - to: '2025-01-02T00:00:00.000Z', - isHelper: false, - }) - }) -}) - -describe('querySource.ts:resolveLogRunRange', () => { - afterEach(() => { - vi.useRealTimers() - }) - - it('re-resolves a relative range against the current time', () => { - vi.useFakeTimers() - const now = new Date('2025-06-15T08:30:00.000Z') - vi.setSystemTime(now) - - expect(resolveLogRunRange({ kind: 'relative', last: { amount: 2, unit: 'hour' } })).toEqual({ - from: dayjs(now).subtract(2, 'hour').toISOString(), - to: dayjs(now).toISOString(), - }) - }) - - it('re-resolves the same relative range differently as time advances', () => { - vi.useFakeTimers() - vi.setSystemTime(new Date('2025-06-15T08:00:00.000Z')) - const first = resolveLogRunRange({ kind: 'relative', last: { amount: 1, unit: 'hour' } }) - - vi.setSystemTime(new Date('2025-06-15T10:00:00.000Z')) - const second = resolveLogRunRange({ kind: 'relative', last: { amount: 1, unit: 'hour' } }) - - expect(first).not.toEqual(second) - expect(second.to).toBe(dayjs('2025-06-15T10:00:00.000Z').toISOString()) - }) - - it('passes an absolute range through unchanged', () => { - const from = isoDateTimeString('2025-01-01T00:00:00.000Z')! - const to = isoDateTimeString('2025-01-02T00:00:00.000Z')! - expect(resolveLogRunRange({ kind: 'absolute', from, to })).toEqual({ - from: '2025-01-01T00:00:00.000Z', - to: '2025-01-02T00:00:00.000Z', - }) - }) -}) - -describe('querySource.ts:logDateRangesEqual', () => { - it('matches relative ranges on amount + unit regardless of label formatting', () => { - const lastHourPreset = EXPLORER_DATEPICKER_HELPERS.find((h) => h.text === 'Last hour')! - const presetRange = datePickerValueToLogDateRange({ - from: lastHourPreset.calcFrom(), - to: lastHourPreset.calcTo(), - isHelper: true, - text: lastHourPreset.text, - }) - - expect( - logDateRangesEqual(presetRange, { kind: 'relative', last: { amount: 1, unit: 'hour' } }) - ).toBe(true) - }) - - it('does not match relative ranges with a different amount or unit', () => { - expect( - logDateRangesEqual( - { kind: 'relative', last: { amount: 1, unit: 'hour' } }, - { kind: 'relative', last: { amount: 3, unit: 'hour' } } - ) - ).toBe(false) - expect( - logDateRangesEqual( - { kind: 'relative', last: { amount: 1, unit: 'hour' } }, - { kind: 'relative', last: { amount: 1, unit: 'day' } } - ) - ).toBe(false) - }) - - it('matches absolute ranges on their ISO endpoints', () => { - const from = isoDateTimeString('2025-01-01T00:00:00.000Z')! - const to = isoDateTimeString('2025-01-02T00:00:00.000Z')! - expect(logDateRangesEqual({ kind: 'absolute', from, to }, { kind: 'absolute', from, to })).toBe( - true - ) - }) - - it('never matches a relative range against an absolute one', () => { - const from = isoDateTimeString('2025-01-01T00:00:00.000Z')! - const to = isoDateTimeString('2025-01-02T00:00:00.000Z')! - expect( - logDateRangesEqual( - { kind: 'relative', last: { amount: 1, unit: 'hour' } }, - { - kind: 'absolute', - from, - to, - } - ) - ).toBe(false) - }) -}) diff --git a/apps/studio/components/interfaces/SQLEditor/querySource.ts b/apps/studio/components/interfaces/SQLEditor/querySource.ts index 4a1174f837537..49f57612446ce 100644 --- a/apps/studio/components/interfaces/SQLEditor/querySource.ts +++ b/apps/studio/components/interfaces/SQLEditor/querySource.ts @@ -1,11 +1,5 @@ -import dayjs from 'dayjs' - -import type { Unit } from '@/components/interfaces/Settings/Logs/Logs.datePickerHelpers' -import { generateDynamicHelper } from '@/components/interfaces/Settings/Logs/Logs.datePickerHelpers' -import type { DatePickerValue } from '@/components/interfaces/Settings/Logs/Logs.DatePickers' -import type { ResolvedLogDateRange } from '@/components/interfaces/Settings/Logs/logsDateRange' import type { Snippet } from '@/data/content/sql-folders-query' -import { isoDateTimeString, type IsoDateTimeString } from '@/lib/iso-datetime' +import { type LogTimeRange, type QuerySourceId } from '@/data/query-sources/query-source-registry' /** * Domain view of where a snippet's query runs. Derived from the content TYPE: @@ -14,7 +8,7 @@ import { isoDateTimeString, type IsoDateTimeString } from '@/lib/iso-datetime' * immutable — switching backends means creating a new snippet, not toggling this * value. */ -export type SqlSnippetSource = 'database' | 'logs' +export type SqlSnippetSource = QuerySourceId /** * The single reader every surface (AI, reports, tabs, nav, execution) uses to @@ -61,128 +55,10 @@ export function resolveSnippetSource( return snippet !== undefined ? getSnippetSource(snippet) : parseSqlSnippetSource(sourceParam) } -/** `now` as a branded ISO datetime — `toISOString()` is always valid ISO-8601. */ -function nowIsoDateTime(): IsoDateTimeString { - return dayjs().toISOString() as IsoDateTimeString -} - -/** - * The units a relative log range is expressed in. Aliases the Logs date picker's - * `Unit` so the two stay in lockstep rather than drifting as parallel unions. - */ -export type RelativeTimeUnit = Unit - -/** - * A log query's time range. Relative ranges are structural (amount + unit) and - * re-resolve against `now` at every run — so a saved "last hour" always means the - * hour before the run, not the hour before the snippet was opened. Absolute ranges - * carry validated ISO datetimes and pass through unchanged. - */ -export type LogDateRange = - | { kind: 'relative'; last: { amount: number; unit: RelativeTimeUnit } } - | { kind: 'absolute'; from: IsoDateTimeString; to: IsoDateTimeString } - -/** The range a freshly opened logs snippet starts with: the last hour. */ -export const DEFAULT_LOG_DATE_RANGE: LogDateRange = { - kind: 'relative', - last: { amount: 1, unit: 'hour' }, -} - /** * The runtime query source for a snippet, pairing the database/logs discriminant * with the extra state each backend needs to run. A logs run carries the active * time range (session state, re-resolved at every run); a database run needs * nothing beyond the connection the execution pipeline already resolves. */ -export type QuerySource = { type: 'database' } | { type: 'logs'; dateRange: LogDateRange } - -/** - * Parse a date-picker helper's label (e.g. "Last hour", "Last 3 hours", "Last 30 - * minutes") into a relative amount/unit. Covers both the static presets in - * `EXPLORER_DATEPICKER_HELPERS` and the dynamic helpers `generateHelpersFromInput` - * produces from typed input like "2h"/"30m". A label with no number means one unit - * ("Last hour"). Returns null for any other label. - */ -function parseRelativeHelperLabel( - text: string | undefined -): { amount: number; unit: RelativeTimeUnit } | null { - if (!text) return null - const match = text - .trim() - .toLowerCase() - .match(/^last\s+(?:(\d+)\s+)?(minute|hour|day)s?$/) - if (!match) return null - const amount = match[1] ? parseInt(match[1], 10) : 1 - if (!Number.isFinite(amount) || amount <= 0) return null - const unit = match[2] - if (unit !== 'minute' && unit !== 'hour' && unit !== 'day') return null - return { amount, unit } -} - -/** - * Convert a Logs date-picker value into a `LogDateRange`. Helper picks (presets and - * dynamic "2h"/"30m" helpers) become relative ranges by parsing the helper label; - * a preset's `calcTo()` resolves to `''` (meaning "now"), which the relative variant - * models implicitly. Everything else — custom calendar picks, or a helper whose label - * we can't parse — becomes an absolute range with validated ISO datetimes, degrading - * via `from`/now rather than rejecting an empty string. A value with no usable `from` - * falls back to the default range. - */ -export function datePickerValueToLogDateRange(value: DatePickerValue): LogDateRange { - if (value.isHelper) { - const relative = parseRelativeHelperLabel(value.text) - if (relative) return { kind: 'relative', last: relative } - } - - const from = isoDateTimeString(value.from) - if (from === null) return DEFAULT_LOG_DATE_RANGE - const to = isoDateTimeString(value.to) ?? nowIsoDateTime() - return { kind: 'absolute', from, to } -} - -/** - * Render a `LogDateRange` back into a Logs date-picker value for display. Relative - * ranges reuse the picker's own `generateDynamicHelper` to derive the resolved - * `from`/`to` and matching "Last N unit(s)" label, so the value is byte-for-byte - * what the picker itself would emit for that helper. Absolute ranges pass their - * datetimes through. - */ -export function logDateRangeToDatePickerValue(range: LogDateRange): DatePickerValue { - if (range.kind === 'relative') { - const helper = generateDynamicHelper(range.last.amount, range.last.unit) - return { from: helper.calcFrom(), to: helper.calcTo(), isHelper: true, text: helper.text } - } - return { from: range.from, to: range.to, isHelper: false } -} - -/** - * Structural equality for two log date ranges. Relative ranges match on amount + - * unit, NOT display text — "Last hour" and "Last 1 hour" render differently but - * are the same range, so comparing labels is unreliable. Absolute ranges match on - * their (validated) ISO endpoints. - */ -export function logDateRangesEqual(a: LogDateRange, b: LogDateRange): boolean { - if (a.kind === 'relative' && b.kind === 'relative') { - return a.last.amount === b.last.amount && a.last.unit === b.last.unit - } - if (a.kind === 'absolute' && b.kind === 'absolute') { - return a.from === b.from && a.to === b.to - } - return false -} - -/** - * Resolve a `LogDateRange` to concrete ISO endpoints for a run. Relative ranges - * re-resolve against `now` (so "last hour" is always the hour before the run); - * absolute ranges pass through. Reuses the Logs `ResolvedLogDateRange` shape. - */ -export function resolveLogRunRange(range: LogDateRange): ResolvedLogDateRange { - if (range.kind === 'relative') { - const now = dayjs() - return { - from: now.subtract(range.last.amount, range.last.unit).toISOString(), - to: now.toISOString(), - } - } - return { from: range.from, to: range.to } -} +export type QuerySource = { type: 'database' } | { type: 'logs'; dateRange: LogTimeRange } diff --git a/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.test.tsx b/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.test.tsx index 38e3fb8634b26..97bd6bdd789ee 100644 --- a/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.test.tsx +++ b/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.test.tsx @@ -99,8 +99,9 @@ describe('useLogsSqlExecution', () => { it('resolves a relative session range to a from/to window around now', async () => { const captured = mockLogsAllOtel([]) sqlEditorSessionState.setLogRange(SNIPPET_ID, { - kind: 'relative', - last: { amount: 2, unit: 'hour' }, + type: 'relative', + amount: 2, + unit: 'hour', }) const { result } = renderLogsExecution() diff --git a/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.ts b/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.ts index 4c1c006bfd7b0..ddbd7fd3175b7 100644 --- a/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.ts +++ b/apps/studio/components/interfaces/SQLEditor/useLogsSqlExecution.ts @@ -1,10 +1,13 @@ import { useFlag, useParams } from 'common' import { useCallback } from 'react' -import { DEFAULT_LOG_DATE_RANGE, resolveLogRunRange } from './querySource' +import { resolveLogTimeRange } from '@/components/interfaces/QuerySources/LogTimeRange.utils' import { useExecuteLogsSqlMutation } from '@/data/logs/execute-logs-sql-mutation' -import { logsAllEndpointUrl } from '@/data/logs/logs-endpoint' import { type SafeLogSqlFragment } from '@/data/logs/safe-analytics-sql' +import { + DEFAULT_LOG_TIME_RANGE, + QUERY_SOURCE_REGISTRY, +} from '@/data/query-sources/query-source-registry' import { useTrack } from '@/lib/telemetry/track' import { getSqlEditorSessionSnapshot, @@ -46,11 +49,11 @@ export function useLogsSqlExecution({ id }: UseLogsSqlExecutionArgs) { // Re-read imperatively so a range picked immediately before the run is // honored; relative ranges re-resolve against `now` here. - const range = resolveLogRunRange( - getSqlEditorSessionSnapshot().logRange[id] ?? DEFAULT_LOG_DATE_RANGE + const range = resolveLogTimeRange( + getSqlEditorSessionSnapshot().logRange[id] ?? DEFAULT_LOG_TIME_RANGE ) - mutate({ projectRef, sql, range, endpoint: logsAllEndpointUrl(true) }) + mutate({ projectRef, sql, range, endpoint: QUERY_SOURCE_REGISTRY.logs.endpoint }) track('sql_editor_query_run_button_clicked', { source: 'logs' }) }, diff --git a/apps/studio/components/interfaces/SQLEditor/useRunSource.test.tsx b/apps/studio/components/interfaces/SQLEditor/useRunSource.test.tsx index 820caa97c00f9..3d63dece309ac 100644 --- a/apps/studio/components/interfaces/SQLEditor/useRunSource.test.tsx +++ b/apps/studio/components/interfaces/SQLEditor/useRunSource.test.tsx @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it } from 'vitest' -import { DEFAULT_LOG_DATE_RANGE } from './querySource' import { useRunSource } from './useRunSource' +import { DEFAULT_LOG_TIME_RANGE } from '@/data/query-sources/query-source-registry' import { sqlEditorSessionState } from '@/state/sql-editor/sql-editor-session-state' import { renderSqlEditorHook, @@ -31,22 +31,23 @@ describe('useRunSource', () => { const { result } = renderSqlEditorHook(() => useRunSource(id)) - expect(result.current).toEqual({ type: 'logs', dateRange: DEFAULT_LOG_DATE_RANGE }) + expect(result.current).toEqual({ type: 'logs', dateRange: DEFAULT_LOG_TIME_RANGE }) }) it('resolves a logs snippet to its session-stored range when one is set', () => { const id = 'logs-snippet-custom-range' seedSnippet({ id, source: 'logs' }) sqlEditorSessionState.setLogRange(id, { - kind: 'relative', - last: { amount: 2, unit: 'hour' }, + type: 'relative', + amount: 2, + unit: 'hour', }) const { result } = renderSqlEditorHook(() => useRunSource(id)) expect(result.current).toEqual({ type: 'logs', - dateRange: { kind: 'relative', last: { amount: 2, unit: 'hour' } }, + dateRange: { type: 'relative', amount: 2, unit: 'hour' }, }) }) }) diff --git a/apps/studio/components/interfaces/SQLEditor/useRunSource.ts b/apps/studio/components/interfaces/SQLEditor/useRunSource.ts index 95c83d782a597..b9362d4827950 100644 --- a/apps/studio/components/interfaces/SQLEditor/useRunSource.ts +++ b/apps/studio/components/interfaces/SQLEditor/useRunSource.ts @@ -1,12 +1,8 @@ import { useParams } from 'common' import { useMemo } from 'react' -import { - DEFAULT_LOG_DATE_RANGE, - isLogsSource, - resolveSnippetSource, - type QuerySource, -} from './querySource' +import { isLogsSource, resolveSnippetSource, type QuerySource } from './querySource' +import { DEFAULT_LOG_TIME_RANGE } from '@/data/query-sources/query-source-registry' import { useSqlEditorSessionSnapshot } from '@/state/sql-editor/sql-editor-session-state' import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor/sql-editor-state' @@ -33,7 +29,7 @@ export function useRunSource(id: string): QuerySource { return useMemo(() => { if (isLogsSource(source)) { - return { type: 'logs', dateRange: logRange ?? DEFAULT_LOG_DATE_RANGE } + return { type: 'logs', dateRange: logRange ?? DEFAULT_LOG_TIME_RANGE } } return { type: 'database' } }, [source, logRange]) diff --git a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccess.utils.test.ts b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccess.utils.test.ts index edcdee317cdc9..9857f1069a661 100644 --- a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccess.utils.test.ts +++ b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccess.utils.test.ts @@ -121,6 +121,7 @@ describe('getJitMemberOptions', () => { const organizationMembers: OrganizationMembersData = [ { gotrue_id: 'de305d54-75b4-431b-adb2-eb6b9e546014', + avatar_url: null, primary_email: 'active@example.com', username: 'Active User', is_sso_user: false, @@ -130,6 +131,7 @@ describe('getJitMemberOptions', () => { }, { gotrue_id: '', + avatar_url: null, invited_id: 123, invited_at: '2026-03-01T00:00:00.000Z', primary_email: 'expired-invite@example.com', diff --git a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx index f6dd58a29073a..dab3b686cd3cd 100644 --- a/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/JitDatabaseAccess/JitDbAccessConfiguration.tsx @@ -318,19 +318,15 @@ export const JitDbAccessConfiguration = () => { const unavailableTitle = unavailableReason === 'postgres_upgrade_required' ? 'Postgres upgrade required' - : unavailableReason === 'manual_migration_required' - ? 'Migration required' - : unavailableReason === 'ssl_enforcement_required' - ? 'SSL enforcement required' - : 'Temporary access unavailable' + : unavailableReason === 'ssl_enforcement_required' + ? 'SSL enforcement required' + : 'Temporary access unavailable' const unavailableDescription = unavailableReason === 'postgres_upgrade_required' ? 'must be upgraded to Postgres 17 or later before temporary access can be enabled.' - : unavailableReason === 'manual_migration_required' - ? 'must be migrated before temporary access can be enabled. Contact support to migrate this project.' - : unavailableReason === 'ssl_enforcement_required' - ? 'must have SSL enforcement enabled before temporary access can be enabled.' - : 'This feature is currently unavailable for this project. Contact support if you need help enabling it.' + : unavailableReason === 'ssl_enforcement_required' + ? 'must have SSL enforcement enabled before temporary access can be enabled.' + : 'This feature is currently unavailable for this project. Contact support if you need help enabling it.' useEffect(() => { if (!isLoadingConfiguration && jitDbAccessConfiguration) { @@ -386,12 +382,13 @@ export const JitDbAccessConfiguration = () => { layout="responsive" title={unavailableTitle} description={ - unavailableReason === 'temporarily_unavailable' ? ( - unavailableDescription - ) : ( + unavailableReason === 'postgres_upgrade_required' || + unavailableReason === 'ssl_enforcement_required' ? ( <> {projectReference} {unavailableDescription} + ) : ( + unavailableDescription ) } actions={ diff --git a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx index 02c2844a13950..8b2b0b1776f81 100644 --- a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx @@ -1,59 +1,14 @@ import type { UIMessage as MessageType } from '@ai-sdk/react' -import { useChat } from '@ai-sdk/react' -import { lastAssistantMessageIsCompleteWithApprovalResponses } from 'ai' -import { LOCAL_STORAGE_KEYS, useFlag } from 'common' -import { useParams, useSearchParamsShallow } from 'common/hooks' -import { AnimatePresence, motion } from 'framer-motion' -import { Eraser, Pencil, X } from 'lucide-react' +import { useParams } from 'common/hooks' import { useRouter } from 'next/router' -import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { Button, cn, KeyboardShortcut } from 'ui' -import { Admonition } from 'ui-patterns/Admonition' +import { useEffect } from 'react' -import { AlertError } from '../AlertError' -import { ButtonTooltip } from '../ButtonTooltip' -import { ErrorBoundary } from '../ErrorBoundary/ErrorBoundary' -import { InlineLinkClassName } from '../InlineLink' -import { ASSISTANT_ERRORS } from './AiAssistant.constants' -import { - containsLogsSnippets, - hasPendingToolApproval, - onErrorChat, - resolvePendingToolApprovalsAsDenied, -} from './AIAssistant.utils' import { AIAssistantHeader } from './AIAssistantHeader' -import { AIOnboarding } from './AIOnboarding' -import { AssistantChatForm } from './AssistantChatForm' -import { - Conversation, - ConversationContent, - ConversationScrollButton, -} from './elements/Conversation' -import { Message } from './Message' -import { Markdown } from '@/components/interfaces/Markdown' +import { AssistantChat } from './AssistantChat' import { resolveSnippetSource } from '@/components/interfaces/SQLEditor/querySource' import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' -import { useCheckOpenAIKeyQuery } from '@/data/ai/check-api-key-query' -import { useRateMessageMutation } from '@/data/ai/rate-message-mutation' -import { useTablesQuery } from '@/data/tables/tables-query' -import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements' -import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage' -import { useOrgAiOptInLevel } from '@/hooks/misc/useOrgOptedIntoAi' -import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' -import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' -import type { AssistantMessageMetadata } from '@/lib/ai/assistant-message-metadata' -import { getParallelApprovalIdsToReject } from '@/lib/ai/message-utils' -import { - DEFAULT_ASSISTANT_BASE_MODEL_ID, - defaultAssistantModelId, - isAssistantBaseModelId, - isKnownAssistantModelId, -} from '@/lib/ai/model.utils' -import { IS_PLATFORM } from '@/lib/constants' -import { uuidv4 } from '@/lib/helpers' -import { useTrack } from '@/lib/telemetry/track' -import type { AssistantModel, SqlSnippet } from '@/state/ai-assistant-state' import { useAiAssistantState, useAiAssistantStateSnapshot } from '@/state/ai-assistant-state' +import type { SqlSnippet } from '@/state/ai-assistant-state' import { SHORTCUT_IDS } from '@/state/shortcuts/registry' import { useShortcut } from '@/state/shortcuts/useShortcut' import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state' @@ -64,646 +19,89 @@ interface AIAssistantProps { className?: string } +type CurrentQuerySnippet = Exclude + +const isSameSnippet = (snippet: SqlSnippet, currentQuery: CurrentQuerySnippet) => + typeof snippet !== 'string' && + snippet.label === currentQuery.label && + snippet.content === currentQuery.content && + snippet.source === currentQuery.source + export const AIAssistant = ({ className }: AIAssistantProps) => { const router = useRouter() const { id: entityId, source: sourceParam } = useParams() - const { data: project } = useSelectedProjectQuery() - const searchParams = useSearchParamsShallow() - - const { data: selectedOrganization, isPending: isLoadingOrganization } = - useSelectedOrganizationQuery() - - useShortcut(SHORTCUT_IDS.AI_ASSISTANT_CANCEL_EDIT, () => cancelEdit()) - useShortcut(SHORTCUT_IDS.AI_ASSISTANT_NEW_CHAT, () => snap.newChat()) - - const disablePrompts = useFlag('disableAssistantPrompts') - const { snippets } = useSqlEditorV2StateSnapshot() const snap = useAiAssistantStateSnapshot() const state = useAiAssistantState() + const { snippets } = useSqlEditorV2StateSnapshot() const { activeSidebar, closeSidebar } = useSidebarManagerSnapshot() + const shortcutsEnabled = activeSidebar?.id === SIDEBAR_KEYS.AI_ASSISTANT - const { hasAccess: hasAccessToAdvanceModel, isLoading: isLoadingEntitlements } = - useCheckEntitlements('assistant.advance_model') - - const selectedModel = useMemo(() => { - // While entitlements are loading, use the stored model without enforcing access - if (isLoadingEntitlements) { - return snap.model ?? DEFAULT_ASSISTANT_BASE_MODEL_ID - } - - const defaultModel = defaultAssistantModelId(hasAccessToAdvanceModel) - const model = snap.model ?? defaultModel - - if (!isKnownAssistantModelId(model)) return defaultModel - if (!hasAccessToAdvanceModel && !isAssistantBaseModelId(model)) { - return DEFAULT_ASSISTANT_BASE_MODEL_ID - } - - return model - }, [isLoadingEntitlements, hasAccessToAdvanceModel, snap.model]) - - const [updatedOptInSinceMCP] = useLocalStorageQuery( - LOCAL_STORAGE_KEYS.AI_ASSISTANT_MCP_OPT_IN, - false - ) - - const inputRef = useRef(null) - - const { aiOptInLevel, isHipaaProjectDisallowed } = useOrgAiOptInLevel() - // Whether attached queries are sent at all. One definition, shared by the chat form - // (which folds them into the message text) and the message metadata (which states - // whether any of them was a logs query), so the two can't disagree. - const includeSnippetsInMessage = aiOptInLevel !== 'disabled' - const showMetadataWarning = - IS_PLATFORM && - !!selectedOrganization && - (aiOptInLevel === 'disabled' || aiOptInLevel === 'schema') - - // Add a ref to store the last user message - const lastUserMessageRef = useRef(null) - - // Keep latest selected organization to avoid stale values in useChat transport - const selectedOrganizationRef = useRef(selectedOrganization) - useEffect(() => { - selectedOrganizationRef.current = selectedOrganization - }, [selectedOrganization]) - - const [value, setValue] = useState(snap.initialInput || '') - const [editingMessageId, setEditingMessageId] = useState(null) - const [isResubmitting, setIsResubmitting] = useState(false) - const [messageRatings, setMessageRatings] = useState>({}) + const handleNewChat = () => state.newChat() - const { data: check, isSuccess } = useCheckOpenAIKeyQuery() - const isApiKeySet = !!check?.hasKey - - const { mutateAsync: rateMessage } = useRateMessageMutation() + useShortcut(SHORTCUT_IDS.AI_ASSISTANT_NEW_CHAT, handleNewChat, { + enabled: shortcutsEnabled, + }) const isInSQLEditor = router.pathname.includes('/sql/[id]') const snippet = snippets[entityId ?? ''] const snippetContent = snippet?.snippet?.content?.unchecked_sql - const openSnippetSource = isInSQLEditor ? resolveSnippetSource(snippet?.snippet, sourceParam) : undefined - const { data: tables } = useTablesQuery( - { - projectRef: project?.ref, - connectionString: project?.connectionString, - schema: 'public', - }, - { enabled: isApiKeySet } - ) - - const currentTable = tables?.find((t) => t.id.toString() === entityId) - const currentSchema = searchParams?.get('schema') ?? 'public' - - // Update context in state useEffect(() => { - state.setContext({ - projectRef: project?.ref, - orgSlug: selectedOrganizationRef.current?.slug, - connectionString: project?.connectionString ?? '', - }) - }, [project?.ref, project?.connectionString, selectedOrganizationRef.current?.slug, state]) - - const track = useTrack() - - const { - messages: chatMessages, - status: chatStatus, - error, - sendMessage, - setMessages, - addToolApprovalResponse, - stop, - regenerate, - } = useChat({ - id: snap.activeChatId, - ...(snap.activeChatId && snap.chatInstances[snap.activeChatId] - ? { chat: snap.chatInstances[snap.activeChatId] } - : {}), - sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses, - onError: onErrorChat, - }) - - const isChatLoading = chatStatus === 'submitted' || chatStatus === 'streaming' - const hasPendingApproval = hasPendingToolApproval(chatMessages) - const supportMetadata = snap.activeChat?.supportMetadata - const isSupportChat = !!supportMetadata?.isSupportChat - const isSupportChatClosed = isSupportChat && supportMetadata.lifecycleStatus !== 'bot_active' - const activeChatId = snap.activeChatId - const supportConversationId = supportMetadata?.frontConversationId - const isChatInputDisabled = - !isApiKeySet || disablePrompts || isLoadingOrganization || isSupportChatClosed - - const branchedFrom = snap.activeChat?.branchedFrom - const branchedConversation = branchedFrom ? snap.chats[branchedFrom.chatId] : undefined - - const deleteMessageFromHere = useCallback( - (messageId: string) => { - // Find the message index in current chatMessages - const messageIndex = chatMessages.findIndex((msg) => msg.id === messageId) - if (messageIndex === -1) return - - if (isChatLoading) stop() - - snap.deleteMessagesAfter(messageId, { includeSelf: true }) - - const updatedMessages = chatMessages.slice(0, messageIndex) - setMessages(updatedMessages) - }, - [snap, setMessages, chatMessages, isChatLoading, stop] - ) - - const editMessage = useCallback( - (messageId: string) => { - const messageIndex = chatMessages.findIndex((msg) => msg.id === messageId) - if (messageIndex === -1) return - - // Target message - const messageToEdit = chatMessages[messageIndex] - - // Activate editing mode - setEditingMessageId(messageId) - const textContent = - messageToEdit.parts - ?.filter((part) => part.type === 'text') - .map((part) => part.text) - .join('') ?? '' - setValue(textContent) - - setTimeout(() => { - if (inputRef.current) { - inputRef?.current?.focus() + if (!shortcutsEnabled || !isInSQLEditor || !snippetContent) return - // [Joshen] This is just to make the cursor go to the end of the text when focusing - const val = inputRef.current.value - inputRef.current.value = '' - inputRef.current.value = val - } - }, 100) - }, - [chatMessages, setValue] - ) - - const cancelEdit = useCallback(() => { - setEditingMessageId(null) - setValue('') - }, [setValue]) - - const handleRateMessage = useCallback( - async (messageId: string, rating: 'positive' | 'negative', reason?: string) => { - if (!project?.ref || !selectedOrganization?.slug) return - - // Optimistically update UI - setMessageRatings((prev) => ({ ...prev, [messageId]: rating })) - - try { - const result = await rateMessage({ - rating, - messages: chatMessages, - messageId, - projectRef: project.ref, - orgSlug: selectedOrganization.slug, - reason, - spanId: state.messageSpanIds[messageId], - }) - - track('assistant_message_rating_submitted', { - rating, - category: result.category, - ...(reason && { reason }), - chatId: state.activeChatId, - }) - } catch (error) { - console.error('Failed to rate message:', error) - // Rollback on error - setMessageRatings((prev) => { - const { [messageId]: _, ...rest } = prev - return rest - }) - } - }, - [chatMessages, project?.ref, selectedOrganization?.slug, rateMessage, track, state] - ) - - const isContextExceededError = - error && - (error.message?.includes('context_length_exceeded') || - error.message?.includes('exceeds the context window')) - - const renderedMessages = useMemo( - () => - chatMessages.map((message, index) => { - const isBeingEdited = editingMessageId === message.id - const isAfterEditedMessage = editingMessageId - ? chatMessages.findIndex((m) => m.id === editingMessageId) < index - : false - const isLastMessage = index === chatMessages.length - 1 - - return ( - - - {branchedConversation && branchedFrom?.messageId === message.id && ( -
-
-
- Branched from - -
-
-
- )} - - ) - }), - [ - chatMessages, - deleteMessageFromHere, - editMessage, - cancelEdit, - editingMessageId, - chatStatus, - addToolApprovalResponse, - handleRateMessage, - messageRatings, - branchedConversation, - branchedFrom, - snap, - ] - ) - - const hasMessages = chatMessages.length > 0 - - const sendMessageToAssistant = (finalContent: string) => { - if (editingMessageId) { - // Handling when the user is in edit mode - // delete the message(s) from the chat just like the delete button - setIsResubmitting(true) - deleteMessageFromHere(editingMessageId) - setEditingMessageId(null) - } - - // Read off the attachments this message actually carries, so detaching the - // "Current Query" chip also drops the claim. Gated on the same condition that - // decides whether attachments make it into the text at all: with AI opt-in - // disabled the chip is shown but no query is sent, and claiming otherwise would - // have the server prepend ClickHouse context for a message holding no query. - // Rides on the message rather than the request, so a Retry reproduces the context - // the message was asked in. - const metadata: AssistantMessageMetadata = { - containsLogsSnippets: includeSnippetsInMessage && containsLogsSnippets(snap.sqlSnippets), - } - - const payload = { - role: 'user', - createdAt: new Date(), - parts: [{ type: 'text', text: finalContent }], - id: uuidv4(), - metadata, - } as MessageType - - snap.clearSqlSnippets() - lastUserMessageRef.current = payload - if (hasPendingApproval && !editingMessageId) { - setMessages(resolvePendingToolApprovalsAsDenied(chatMessages)) - } - sendMessage(payload, { - body: { - schema: currentSchema, - table: currentTable?.name, - }, - }) - setValue('') - - if (finalContent.includes('Help me to debug')) { - track('assistant_debug_submitted', { chatId: snap.activeChatId }) - } else { - track('assistant_prompt_submitted', { chatId: snap.activeChatId }) - } - } - - const handleClearMessages = () => { - if (isChatLoading) stop() - snap.clearMessages() - setMessages([]) - lastUserMessageRef.current = null - setEditingMessageId(null) - } - - useEffect(() => { - // Keep "Thinking" visible while stopping and resubmitting during edit - // Only clear once the new response actually starts streaming (or errors) - if (isResubmitting && (chatStatus === 'streaming' || !!error)) { - setIsResubmitting(false) + const currentQuery = { + label: 'Current Query', + content: snippetContent, + source: openSnippetSource, } - }, [isResubmitting, chatStatus, error]) + state.setSqlSnippets([currentQuery]) - useEffect(() => { - // Approval-required tools can't run in parallel. Auto-deny extras so the model reissues them sequentially. - for (const id of getParallelApprovalIdsToReject(chatMessages)) { - addToolApprovalResponse?.({ - id, - approved: false, - reason: - 'Only one approval-required tool call is allowed per turn. Please reissue this tool call after the current one completes.', - }) - } - }, [chatMessages, addToolApprovalResponse]) + return () => { + const currentSnippets = state.sqlSnippets + const remainingSnippets = currentSnippets?.filter( + (snippet) => !isSameSnippet(snippet, currentQuery) + ) - useEffect(() => { - setValue(snap.initialInput || '') - if (inputRef.current && snap.initialInput) { - inputRef.current.focus() - inputRef.current.setSelectionRange(snap.initialInput.length, snap.initialInput.length) + if (currentSnippets && remainingSnippets?.length !== currentSnippets.length) { + state.setSqlSnippets(remainingSnippets ?? []) + } } - }, [snap.initialInput]) + }, [shortcutsEnabled, isInSQLEditor, snippetContent, openSnippetSource, state]) - useEffect(() => { - const isOpen = activeSidebar?.id === SIDEBAR_KEYS.AI_ASSISTANT - if (isOpen && isInSQLEditor && !!snippetContent) { - snap.setSqlSnippets([ - { label: 'Current Query', content: snippetContent, source: openSnippetSource }, - ]) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [activeSidebar?.id, isInSQLEditor, snippetContent, openSnippetSource]) + if (!snap.activeChatId) return null return ( - state.selectChat(chatId)} + onBranchChat={(messageId) => state.branchChat(messageId)} + composerContext={{ + initialInput: snap.initialInput, + sqlSnippets: snap.sqlSnippets as SqlSnippet[] | undefined, + suggestions: snap.suggestions + ? { + title: snap.suggestions.title, + prompts: snap.suggestions.prompts?.map((prompt) => ({ ...prompt })), + } + : undefined, + onSetSqlSnippets: state.setSqlSnippets, + onClearSqlSnippets: state.clearSqlSnippets, }} - actions={[ - { - label: 'Clear messages and refresh', - onClick: () => { - handleClearMessages() - window.location.reload() - }, - }, - ]} - > -
+ renderHeader={(props) => ( closeSidebar(SIDEBAR_KEYS.AI_ASSISTANT)} - showMetadataWarning={showMetadataWarning} - updatedOptInSinceMCP={updatedOptInSinceMCP} - isHipaaProjectDisallowed={isHipaaProjectDisallowed} - aiOptInLevel={aiOptInLevel} /> - {hasMessages ? ( - - - {renderedMessages} - {error && ( - <> - - {isContextExceededError ? ( - - ) : ( - <> - - } - tooltip={{ content: { side: 'bottom', text: 'Clear messages' } }} - /> - - )} -
- } - /> - - )} - {isChatLoading && ( - - )} - -

- The Assistant can make mistakes. Double check responses. -

- - - - ) : ( - setValue(val)} - onFocusInput={() => inputRef.current?.focus()} - /> - )} - - - {editingMessageId && ( - -
- -
-
- - Editing message -
- } - onClick={cancelEdit} - className="w-6 h-6 p-0" - title="Cancel editing" - aria-label="Cancel editing" - tooltip={{ - content: { side: 'top', text: }, - }} - /> -
-
-
-
- )} -
- -
- {isSupportChat && !isSupportChatClosed && ( -
-
-
- - -
-
- )} - - {disablePrompts && ( - - )} - - {isSuccess && !isApiKeySet && ( - - } - /> - )} - - form>textarea]:text-base [&>form>textarea]:md:text-sm [&>form>textarea]:border', - '[&>form>textarea]:rounded-md [&>form>textarea]:outline-hidden!', - '[&>form>textarea]:ring-offset-0! [&>form>textarea]:ring-0!' - )} - loading={isChatLoading} - isEditing={!!editingMessageId} - disabled={isChatInputDisabled} - placeholder={ - hasMessages - ? isSupportChat - ? 'Share details so the assistant can help with your support request...' - : 'Ask a follow up question...' - : (snap.sqlSnippets ?? [])?.length > 0 - ? 'Ask a question or make a change...' - : isSupportChat - ? 'Describe your support issue...' - : 'Chat to Postgres...' - } - value={value} - onValueChange={(e) => setValue(e.target.value)} - onSubmit={(finalMessage) => { - sendMessageToAssistant(finalMessage) - }} - onStop={() => { - stop() - // to save partial responses from the AI - const lastMessage = chatMessages[chatMessages.length - 1] - if (lastMessage && lastMessage.role === 'assistant') { - state.updateMessage(lastMessage) - } - }} - sqlSnippets={snap.sqlSnippets as SqlSnippet[] | undefined} - onRemoveSnippet={(index) => { - const newSnippets = [...(snap.sqlSnippets ?? [])] - newSnippets.splice(index, 1) - snap.setSqlSnippets(newSnippets) - }} - includeSnippetsInMessage={includeSnippetsInMessage} - selectedModel={selectedModel} - onSelectModel={(model) => snap.setModel(model)} - /> -
-
-
+ )} + /> ) } diff --git a/apps/studio/components/ui/AIAssistantPanel/AIAssistantChatSelector.tsx b/apps/studio/components/ui/AIAssistantPanel/AIAssistantChatSelector.tsx index e5631c81b38d0..11b87ad765386 100644 --- a/apps/studio/components/ui/AIAssistantPanel/AIAssistantChatSelector.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/AIAssistantChatSelector.tsx @@ -24,9 +24,13 @@ import { useShortcut } from '@/state/shortcuts/useShortcut' interface AIAssistantChatSelectorProps { disabled?: boolean + shortcutsEnabled?: boolean } -export const AIAssistantChatSelector = ({ disabled = false }: AIAssistantChatSelectorProps) => { +export const AIAssistantChatSelector = ({ + disabled = false, + shortcutsEnabled = true, +}: AIAssistantChatSelectorProps) => { const snap = useAiAssistantStateSnapshot() const [chatSelectorOpen, setChatSelectorOpen] = useState(false) @@ -35,7 +39,13 @@ export const AIAssistantChatSelector = ({ disabled = false }: AIAssistantChatSel const chats = Object.entries(snap.chats) - useShortcut(SHORTCUT_IDS.AI_ASSISTANT_TOGGLE_HISTORY, () => setChatSelectorOpen((prev) => !prev)) + useShortcut( + SHORTCUT_IDS.AI_ASSISTANT_TOGGLE_HISTORY, + () => setChatSelectorOpen((prev) => !prev), + { + enabled: shortcutsEnabled, + } + ) const handleSelectChat = (id: string) => { snap.selectChat(id) diff --git a/apps/studio/components/ui/AIAssistantPanel/AIAssistantHeader.tsx b/apps/studio/components/ui/AIAssistantPanel/AIAssistantHeader.tsx index 49351c8a205b4..c2f7294590ac5 100644 --- a/apps/studio/components/ui/AIAssistantPanel/AIAssistantHeader.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/AIAssistantHeader.tsx @@ -33,6 +33,7 @@ import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state' interface AIAssistantHeaderProps { isChatLoading: boolean + shortcutsEnabled?: boolean onNewChat: () => void onCloseAssistant: () => void showMetadataWarning: boolean @@ -43,6 +44,7 @@ interface AIAssistantHeaderProps { export const AIAssistantHeader = ({ isChatLoading, + shortcutsEnabled = true, onNewChat, onCloseAssistant, showMetadataWarning, @@ -87,15 +89,15 @@ export const AIAssistantHeader = ({ } useShortcut(SHORTCUT_IDS.AI_ASSISTANT_COPY_CHAT_ID, handleCopyChatId, { - enabled: !isChatLoading, + enabled: shortcutsEnabled && !isChatLoading, }) useShortcut(SHORTCUT_IDS.AI_ASSISTANT_OPEN_PERMISSIONS, () => setIsOptInModalOpen(true), { - enabled: !isChatLoading, + enabled: shortcutsEnabled && !isChatLoading, }) useShortcut(SHORTCUT_IDS.AI_ASSISTANT_MAXIMIZE, toggleMaximise, { - enabled: !isChatLoading, + enabled: shortcutsEnabled && !isChatLoading, }) return ( @@ -128,7 +130,7 @@ export const AIAssistantHeader = ({
- + void + onClearSqlSnippets?: () => void +} + +interface AssistantChatProps { + className?: string + chatId: string + shortcutsEnabled?: boolean + onNewChat: () => void + onSelectChat: (chatId: string) => void + onBranchChat: (messageId: string) => void + composerContext?: AssistantChatComposerContext + renderHeader?: (props: AssistantChatHeaderProps) => ReactNode +} + +export const AssistantChat = ({ + className, + chatId, + shortcutsEnabled = true, + onNewChat, + onSelectChat, + onBranchChat, + composerContext, + renderHeader, +}: AssistantChatProps) => { + const { id: entityId } = useParams() + const { data: project } = useSelectedProjectQuery() + const searchParams = useSearchParamsShallow() + + const { data: selectedOrganization, isPending: isLoadingOrganization } = + useSelectedOrganizationQuery() + + const disablePrompts = useFlag('disableAssistantPrompts') + const snap = useAiAssistantStateSnapshot() + const state = useAiAssistantState() + const currentChat = snap.chats[chatId] + + useShortcut(SHORTCUT_IDS.AI_ASSISTANT_CANCEL_EDIT, () => cancelEdit(), { + enabled: shortcutsEnabled, + }) + + const { hasAccess: hasAccessToAdvanceModel, isLoading: isLoadingEntitlements } = + useCheckEntitlements('assistant.advance_model') + + const selectedModel = useMemo(() => { + // While entitlements are loading, use the stored model without enforcing access + if (isLoadingEntitlements) { + return snap.model ?? DEFAULT_ASSISTANT_BASE_MODEL_ID + } + + const defaultModel = defaultAssistantModelId(hasAccessToAdvanceModel) + const model = snap.model ?? defaultModel + + if (!isKnownAssistantModelId(model)) return defaultModel + if (!hasAccessToAdvanceModel && !isAssistantBaseModelId(model)) { + return DEFAULT_ASSISTANT_BASE_MODEL_ID + } + + return model + }, [isLoadingEntitlements, hasAccessToAdvanceModel, snap.model]) + + const [updatedOptInSinceMCP] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.AI_ASSISTANT_MCP_OPT_IN, + false + ) + + const inputRef = useRef(null) + + const { aiOptInLevel, isHipaaProjectDisallowed } = useOrgAiOptInLevel() + // Whether attached queries are sent at all. One definition, shared by the chat form + // (which folds them into the message text) and the message metadata (which states + // whether any of them was a logs query), so the two can't disagree. + const includeSnippetsInMessage = aiOptInLevel !== 'disabled' + const showMetadataWarning = + IS_PLATFORM && + !!selectedOrganization && + (aiOptInLevel === 'disabled' || aiOptInLevel === 'schema') + + // Add a ref to store the last user message + const lastUserMessageRef = useRef(null) + + const [value, setValue] = useState(composerContext?.initialInput || '') + const [editingMessageId, setEditingMessageId] = useState(null) + const [isResubmitting, setIsResubmitting] = useState(false) + const [messageRatings, setMessageRatings] = useState>({}) + + const { data: check, isSuccess } = useCheckOpenAIKeyQuery() + const isApiKeySet = !!check?.hasKey + + const { mutateAsync: rateMessage } = useRateMessageMutation() + + const { data: tables } = useTablesQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + schema: 'public', + }, + { enabled: isApiKeySet } + ) + + const currentTable = tables?.find((t) => t.id.toString() === entityId) + const currentSchema = searchParams?.get('schema') ?? 'public' + + // Update context in state + useEffect(() => { + state.setContext({ + projectRef: project?.ref, + orgSlug: selectedOrganization?.slug, + connectionString: project?.connectionString ?? '', + }) + }, [project?.ref, project?.connectionString, selectedOrganization?.slug, state]) + + const track = useTrack() + + useEffect(() => { + state.ensureChatInstance(chatId) + }, [chatId, state]) + + const chatInstance = snap.chatInstances[chatId] + + const { + messages: chatMessages, + status: chatStatus, + error, + sendMessage, + setMessages, + addToolApprovalResponse, + stop, + regenerate, + } = useChat({ + id: chatId, + ...(chatInstance ? { chat: chatInstance } : {}), + sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses, + onError: onErrorChat, + }) + + const isChatLoading = chatStatus === 'submitted' || chatStatus === 'streaming' + const hasPendingApproval = hasPendingToolApproval(chatMessages) + const supportMetadata = currentChat?.supportMetadata + const isSupportChat = !!supportMetadata?.isSupportChat + const isSupportChatClosed = isSupportChat && supportMetadata.lifecycleStatus !== 'bot_active' + const supportConversationId = supportMetadata?.frontConversationId + const isChatInputDisabled = + !isApiKeySet || disablePrompts || isLoadingOrganization || isSupportChatClosed + + const branchedFrom = currentChat?.branchedFrom + const branchedConversation = branchedFrom ? snap.chats[branchedFrom.chatId] : undefined + + const deleteMessageFromHere = useCallback( + (messageId: string) => { + // Find the message index in current chatMessages + const messageIndex = chatMessages.findIndex((msg) => msg.id === messageId) + if (messageIndex === -1) return + + if (isChatLoading) stop() + + snap.deleteMessagesAfter(messageId, { includeSelf: true, chatId }) + + const updatedMessages = chatMessages.slice(0, messageIndex) + setMessages(updatedMessages) + }, + [snap, setMessages, chatMessages, isChatLoading, stop, chatId] + ) + + const editMessage = useCallback( + (messageId: string) => { + const messageIndex = chatMessages.findIndex((msg) => msg.id === messageId) + if (messageIndex === -1) return + + // Target message + const messageToEdit = chatMessages[messageIndex] + + // Activate editing mode + setEditingMessageId(messageId) + const textContent = + messageToEdit.parts + ?.filter((part) => part.type === 'text') + .map((part) => part.text) + .join('') ?? '' + setValue(textContent) + + setTimeout(() => { + if (inputRef.current) { + inputRef?.current?.focus() + + // [Joshen] This is just to make the cursor go to the end of the text when focusing + const val = inputRef.current.value + inputRef.current.value = '' + inputRef.current.value = val + } + }, 100) + }, + [chatMessages, setValue] + ) + + const cancelEdit = useCallback(() => { + setEditingMessageId(null) + setValue('') + }, [setValue]) + + const handleRateMessage = useCallback( + async (messageId: string, rating: 'positive' | 'negative', reason?: string) => { + if (!project?.ref || !selectedOrganization?.slug) return + + // Optimistically update UI + setMessageRatings((prev) => ({ ...prev, [messageId]: rating })) + + try { + const result = await rateMessage({ + rating, + messages: chatMessages, + messageId, + projectRef: project.ref, + orgSlug: selectedOrganization.slug, + reason, + spanId: state.messageSpanIds[messageId], + }) + + track('assistant_message_rating_submitted', { + rating, + category: result.category, + ...(reason && { reason }), + chatId, + }) + } catch (error) { + console.error('Failed to rate message:', error) + // Rollback on error + setMessageRatings((prev) => { + const { [messageId]: _, ...rest } = prev + return rest + }) + } + }, + [chatMessages, project?.ref, selectedOrganization?.slug, rateMessage, track, state, chatId] + ) + + const isContextExceededError = + error && + (error.message?.includes('context_length_exceeded') || + error.message?.includes('exceeds the context window')) + + const renderedMessages = useMemo( + () => + chatMessages.map((message, index) => { + const isBeingEdited = editingMessageId === message.id + const isAfterEditedMessage = editingMessageId + ? chatMessages.findIndex((m) => m.id === editingMessageId) < index + : false + const isLastMessage = index === chatMessages.length - 1 + + return ( + + + {branchedConversation && branchedFrom?.messageId === message.id && ( +
+
+
+ Branched from + +
+
+
+ )} + + ) + }), + [ + chatMessages, + deleteMessageFromHere, + editMessage, + cancelEdit, + editingMessageId, + chatStatus, + addToolApprovalResponse, + handleRateMessage, + messageRatings, + branchedConversation, + branchedFrom, + onSelectChat, + onBranchChat, + ] + ) + + const hasMessages = chatMessages.length > 0 + + const sendMessageToAssistant = (finalContent: string) => { + if (editingMessageId) { + // Handling when the user is in edit mode + // delete the message(s) from the chat just like the delete button + setIsResubmitting(true) + deleteMessageFromHere(editingMessageId) + setEditingMessageId(null) + } + + // Read off the attachments this message actually carries, so detaching the + // "Current Query" chip also drops the claim. Gated on the same condition that + // decides whether attachments make it into the text at all: with AI opt-in + // disabled the chip is shown but no query is sent, and claiming otherwise would + // have the server prepend ClickHouse context for a message holding no query. + // Rides on the message rather than the request, so a Retry reproduces the context + // the message was asked in. + const metadata: AssistantMessageMetadata = { + containsLogsSnippets: + includeSnippetsInMessage && containsLogsSnippets(composerContext?.sqlSnippets), + } + + const payload = { + role: 'user', + createdAt: new Date(), + parts: [{ type: 'text', text: finalContent }], + id: uuidv4(), + metadata, + } as MessageType + + composerContext?.onClearSqlSnippets?.() + lastUserMessageRef.current = payload + if (hasPendingApproval && !editingMessageId) { + setMessages(resolvePendingToolApprovalsAsDenied(chatMessages)) + } + sendMessage(payload, { + body: { + schema: currentSchema, + table: currentTable?.name, + }, + }) + setValue('') + + if (finalContent.includes('Help me to debug')) { + track('assistant_debug_submitted', { chatId }) + } else { + track('assistant_prompt_submitted', { chatId }) + } + } + + const handleClearMessages = () => { + if (isChatLoading) stop() + snap.clearMessages(chatId) + setMessages([]) + lastUserMessageRef.current = null + setEditingMessageId(null) + } + + useEffect(() => { + // Keep "Thinking" visible while stopping and resubmitting during edit + // Only clear once the new response actually starts streaming (or errors) + if (isResubmitting && (chatStatus === 'streaming' || !!error)) { + setIsResubmitting(false) + } + }, [isResubmitting, chatStatus, error]) + + useEffect(() => { + // Approval-required tools can't run in parallel. Auto-deny extras so the model reissues them sequentially. + for (const id of getParallelApprovalIdsToReject(chatMessages)) { + addToolApprovalResponse?.({ + id, + approved: false, + reason: + 'Only one approval-required tool call is allowed per turn. Please reissue this tool call after the current one completes.', + }) + } + }, [chatMessages, addToolApprovalResponse]) + + useEffect(() => { + setValue(composerContext?.initialInput || '') + if (inputRef.current && composerContext?.initialInput) { + inputRef.current.focus() + inputRef.current.setSelectionRange( + composerContext.initialInput.length, + composerContext.initialInput.length + ) + } + }, [composerContext?.initialInput]) + + return ( + { + handleClearMessages() + window.location.reload() + }, + }, + ]} + > +
+ {renderHeader?.({ + isChatLoading, + showMetadataWarning, + updatedOptInSinceMCP, + isHipaaProjectDisallowed, + aiOptInLevel, + })} + {hasMessages ? ( + + + {renderedMessages} + {error && ( + <> + + {isContextExceededError ? ( + + ) : ( + <> + + } + tooltip={{ content: { side: 'bottom', text: 'Clear messages' } }} + /> + + )} +
+ } + /> + + )} + {isChatLoading && ( + + )} + +

+ The Assistant can make mistakes. Double check responses. +

+ + + + ) : ( + setValue(val)} + onFocusInput={() => inputRef.current?.focus()} + /> + )} + + + {editingMessageId && ( + +
+ +
+
+ + Editing message +
+ } + onClick={cancelEdit} + className="w-6 h-6 p-0" + title="Cancel editing" + aria-label="Cancel editing" + tooltip={{ + content: { side: 'top', text: }, + }} + /> +
+
+
+
+ )} +
+ +
+ {isSupportChat && !isSupportChatClosed && ( +
+
+
+ + +
+
+ )} + + {disablePrompts && ( + + )} + + {isSuccess && !isApiKeySet && ( + + } + /> + )} + + form>textarea]:text-base [&>form>textarea]:md:text-sm [&>form>textarea]:border', + '[&>form>textarea]:rounded-md [&>form>textarea]:outline-hidden!', + '[&>form>textarea]:ring-offset-0! [&>form>textarea]:ring-0!' + )} + loading={isChatLoading} + isEditing={!!editingMessageId} + disabled={isChatInputDisabled} + placeholder={ + hasMessages + ? isSupportChat + ? 'Share details so the assistant can help with your support request...' + : 'Ask a follow up question...' + : (composerContext?.sqlSnippets ?? []).length > 0 + ? 'Ask a question or make a change...' + : isSupportChat + ? 'Describe your support issue...' + : 'Chat to Postgres...' + } + value={value} + onValueChange={(e) => setValue(e.target.value)} + onSubmit={(finalMessage) => { + sendMessageToAssistant(finalMessage) + }} + onStop={() => { + stop() + // to save partial responses from the AI + const lastMessage = chatMessages[chatMessages.length - 1] + if (lastMessage && lastMessage.role === 'assistant') { + state.updateMessage(lastMessage, chatId) + } + }} + sqlSnippets={composerContext?.sqlSnippets} + onRemoveSnippet={(index) => { + const newSnippets = [...(composerContext?.sqlSnippets ?? [])] + newSnippets.splice(index, 1) + composerContext?.onSetSqlSnippets?.(newSnippets) + }} + includeSnippetsInMessage={includeSnippetsInMessage} + selectedModel={selectedModel} + onSelectModel={(model) => snap.setModel(model)} + /> +
+
+
+ ) +} diff --git a/apps/studio/components/ui/AIAssistantPanel/Message.Context.tsx b/apps/studio/components/ui/AIAssistantPanel/Message.Context.tsx index 3ce0cb1dd57cf..d39824361ee19 100644 --- a/apps/studio/components/ui/AIAssistantPanel/Message.Context.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/Message.Context.tsx @@ -26,6 +26,7 @@ export interface MessageActions { onDelete: (id: string) => void onEdit: (id: string) => void + onBranch: (id: string) => void onCancelEdit: () => void onRate?: (id: string, rating: 'positive' | 'negative', reason?: string) => void } diff --git a/apps/studio/components/ui/AIAssistantPanel/Message.tsx b/apps/studio/components/ui/AIAssistantPanel/Message.tsx index c9a5ef5e6e530..6ec5780bec6c6 100644 --- a/apps/studio/components/ui/AIAssistantPanel/Message.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/Message.tsx @@ -8,11 +8,9 @@ import { MessageActions } from './Message.Actions' import type { AddToolApprovalResponse, MessageInfo } from './Message.Context' import { MessageProvider, useMessageActionsContext, useMessageInfoContext } from './Message.Context' import { MessageDisplay } from './Message.Display' -import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state' function AssistantMessage({ message }: { message: VercelMessage }) { - const snap = useAiAssistantStateSnapshot() - const { onCancelEdit, onRate } = useMessageActionsContext() + const { onBranch, onCancelEdit, onRate } = useMessageActionsContext() const { id, variant, state, isLastMessage, readOnly, rating, isLoading } = useMessageInfoContext() const handleRate = (newRating: 'positive' | 'negative', reason?: string) => { @@ -51,7 +49,7 @@ function AssistantMessage({ message }: { message: VercelMessage }) { isActive={rating === 'negative'} disabled={!!rating} /> - snap.branchChat(id)} /> + onBranch(id)} /> )} @@ -107,6 +105,7 @@ interface MessageProps { addToolApprovalResponse?: AddToolApprovalResponse onDelete: (id: string) => void onEdit: (id: string) => void + onBranch: (id: string) => void isAfterEditedMessage: boolean isBeingEdited: boolean onCancelEdit: () => void @@ -139,6 +138,7 @@ export function Message(props: MessageProps) { addToolApprovalResponse: props.addToolApprovalResponse, onDelete: props.onDelete, onEdit: props.onEdit, + onBranch: props.onBranch, onCancelEdit: props.onCancelEdit, onRate: props.onRate, } diff --git a/apps/studio/data/api-keys/api-key-create-mutation.ts b/apps/studio/data/api-keys/api-key-create-mutation.ts index 1aa32df38b210..3e07cfe8020af 100644 --- a/apps/studio/data/api-keys/api-key-create-mutation.ts +++ b/apps/studio/data/api-keys/api-key-create-mutation.ts @@ -18,7 +18,7 @@ export async function createAPIKey(payload: APIKeyCreateVariables) { params: { path: { ref: payload.projectRef }, query: { - reveal: false, + reveal: 'false', }, }, body: { @@ -29,7 +29,7 @@ export async function createAPIKey(payload: APIKeyCreateVariables) { role: 'service_role', }, } - : name), + : {}), type: payload.type, name: payload.name, diff --git a/apps/studio/data/api-keys/api-key-delete-mutation.ts b/apps/studio/data/api-keys/api-key-delete-mutation.ts index 18d0e767c4f1e..10fb0eabff918 100644 --- a/apps/studio/data/api-keys/api-key-delete-mutation.ts +++ b/apps/studio/data/api-keys/api-key-delete-mutation.ts @@ -16,7 +16,7 @@ export async function deleteAPIKey(payload: APIKeyDeleteVariables) { const { data, error } = await del('/v1/projects/{ref}/api-keys/{id}', { params: { path: { ref: payload.projectRef, id: payload.id }, - query: { reveal: false }, + query: { reveal: 'false' }, }, }) diff --git a/apps/studio/data/api-keys/api-key-id-query.ts b/apps/studio/data/api-keys/api-key-id-query.ts index 9149361f40194..7340bafe0695d 100644 --- a/apps/studio/data/api-keys/api-key-id-query.ts +++ b/apps/studio/data/api-keys/api-key-id-query.ts @@ -16,7 +16,7 @@ export async function getAPIKeysById( const { data, error } = await get('/v1/projects/{ref}/api-keys/{id}', { params: { path: { ref: projectRef, id }, - query: { reveal }, + query: { reveal: reveal ? 'true' : 'false' }, }, signal, }) diff --git a/apps/studio/data/api-keys/api-keys-query.ts b/apps/studio/data/api-keys/api-keys-query.ts index a9f87625e3878..5ce1f14441741 100644 --- a/apps/studio/data/api-keys/api-keys-query.ts +++ b/apps/studio/data/api-keys/api-keys-query.ts @@ -55,7 +55,7 @@ async function getAPIKeys({ projectRef, reveal }: APIKeysVariables, signal?: Abo if (!projectRef) throw new Error('projectRef is required') const { data, error } = await get(`/v1/projects/{ref}/api-keys`, { - params: { path: { ref: projectRef }, query: { reveal } }, + params: { path: { ref: projectRef }, query: { reveal: reveal ? 'true' : 'false' } }, signal, }) diff --git a/apps/studio/data/api-keys/legacy-api-key-toggle-mutation.ts b/apps/studio/data/api-keys/legacy-api-key-toggle-mutation.ts index 72799e7686afc..cc4c0849c7124 100644 --- a/apps/studio/data/api-keys/legacy-api-key-toggle-mutation.ts +++ b/apps/studio/data/api-keys/legacy-api-key-toggle-mutation.ts @@ -16,7 +16,7 @@ export async function toggleLegacyAPIKeys(payload: ToggleLegacyAPIKeysVariables) const { data, error } = await put('/v1/projects/{ref}/api-keys/legacy', { params: { path: { ref: payload.projectRef }, - query: { enabled: payload.enabled }, + query: { enabled: payload.enabled ? 'true' : 'false' }, }, }) diff --git a/apps/studio/data/branches/branch-diff-query.ts b/apps/studio/data/branches/branch-diff-query.ts index a858a48a3a4d8..4719993ac9cbe 100644 --- a/apps/studio/data/branches/branch-diff-query.ts +++ b/apps/studio/data/branches/branch-diff-query.ts @@ -24,10 +24,7 @@ export async function getBranchDiff({ const { data: diffData, error } = await get('/v1/branches/{branch_id_or_ref}/diff', { params: { path: { branch_id_or_ref: branchRef }, - query: - Object.keys(query).length > 0 - ? (query as { included_schemas?: string; pgdelta?: boolean }) - : undefined, + query: Object.keys(query).length > 0 ? query : undefined, }, headers: { Accept: 'text/plain', diff --git a/apps/studio/data/content/sql-snippets-query.ts b/apps/studio/data/content/sql-snippets-query.ts index ec554a92b0c43..dbc4643479dad 100644 --- a/apps/studio/data/content/sql-snippets-query.ts +++ b/apps/studio/data/content/sql-snippets-query.ts @@ -40,7 +40,7 @@ export async function getSqlSnippets( type, cursor, visibility, - favorite, + favorite: favorite?.toString(), name, limit: SNIPPET_PAGE_LIMIT.toString(), sort_by: sort, diff --git a/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts b/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts index 9d88c477b7f9d..56da08a1e1595 100644 --- a/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts +++ b/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts @@ -18,7 +18,7 @@ export async function deleteCustomDomain({ const { data, error } = await del(`/v1/projects/{ref}/custom-hostname`, { params: { path: { ref: projectRef }, - query: { remove_addon: removeAddon }, + query: { remove_addon: removeAddon ? 'true' : 'false' }, }, }) diff --git a/apps/studio/data/organizations/organization-available-regions-query.ts b/apps/studio/data/organizations/organization-available-regions-query.ts index 0c7ec9ec51b8d..2dbb1a9154213 100644 --- a/apps/studio/data/organizations/organization-available-regions-query.ts +++ b/apps/studio/data/organizations/organization-available-regions-query.ts @@ -10,7 +10,7 @@ export type DesiredInstanceSizeForAvailableRegions = export type OrganizationAvailableRegionsVariables = { slug?: string - cloudProvider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + cloudProvider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' desiredInstanceSize?: DesiredInstanceSizeForAvailableRegions } diff --git a/apps/studio/data/query-sources/query-source-registry.test.ts b/apps/studio/data/query-sources/query-source-registry.test.ts new file mode 100644 index 0000000000000..03c2045655bcf --- /dev/null +++ b/apps/studio/data/query-sources/query-source-registry.test.ts @@ -0,0 +1,116 @@ +import { describe, expect, it } from 'vitest' + +import { + cellSourceSchema, + createDefaultCellSource, + getQuerySource, + logTimeRangeSchema, + QUERY_SOURCES, +} from './query-source-registry' + +describe('query source registry', () => { + it('registers database and logs sources with their execution endpoints', () => { + expect(QUERY_SOURCES.map(({ id }) => id)).toEqual(['database', 'logs']) + expect(getQuerySource('database').endpoint).toBe('/platform/pg-meta/{ref}/query') + expect(getQuerySource('logs').endpoint).toBe( + '/platform/projects/{ref}/analytics/endpoints/logs.all.otel' + ) + }) + + it('creates independent, valid default cell bindings', () => { + const first = createDefaultCellSource('logs') + const second = createDefaultCellSource('logs') + + expect(cellSourceSchema.parse(first)).toEqual({ + id: 'logs', + type: 'logs', + parameters: { + time_range: { type: 'relative', amount: 1, unit: 'hour' }, + }, + }) + expect(first.parameters.time_range).not.toBe(second.parameters.time_range) + expect(cellSourceSchema.parse(createDefaultCellSource('database'))).toEqual({ + id: 'database', + type: 'database', + parameters: {}, + }) + }) + + it('rejects parameters that do not match the selected source type', () => { + expect(() => + cellSourceSchema.parse({ + id: 'logs', + type: 'logs', + parameters: { identifier: 'replica-1' }, + }) + ).toThrow() + + expect(() => + cellSourceSchema.parse({ + id: 'database', + type: 'database', + parameters: { time_range: { type: 'relative', amount: 1, unit: 'hour' } }, + }) + ).toThrow() + + expect(() => + cellSourceSchema.parse({ + id: 'logs', + type: 'logs', + parameters: { time_range: { type: 'relative', amount: 2, unit: 'week' } }, + }) + ).toThrow() + }) + + it('rejects absolute ranges that do not move forward in time', () => { + expect( + logTimeRangeSchema.safeParse({ + type: 'absolute', + from: '2025-01-01T00:00:00.000Z', + to: '2025-01-02T00:00:00.000Z', + }).success + ).toBe(true) + + const equal = logTimeRangeSchema.safeParse({ + type: 'absolute', + from: '2025-01-01T00:00:00.000Z', + to: '2025-01-01T00:00:00.000Z', + }) + expect(equal.success).toBe(false) + expect(equal.error?.issues[0].path).toEqual(['to']) + + expect( + logTimeRangeSchema.safeParse({ + type: 'absolute', + from: '2025-01-02T00:00:00.000Z', + to: '2025-01-01T00:00:00.000Z', + }).success + ).toBe(false) + + expect(() => + cellSourceSchema.parse({ + id: 'logs', + type: 'logs', + parameters: { + time_range: { + type: 'absolute', + from: '2025-01-02T00:00:00.000Z', + to: '2025-01-01T00:00:00.000Z', + }, + }, + }) + ).toThrow() + }) + + it('reports an invalid endpoint against its own field rather than the ordering rule', () => { + const result = logTimeRangeSchema.safeParse({ + type: 'absolute', + from: 'not-a-date', + to: '2025-01-01T00:00:00.000Z', + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + expect(result.error?.issues[0].path).toEqual(['from']) + }) +}) diff --git a/apps/studio/data/query-sources/query-source-registry.ts b/apps/studio/data/query-sources/query-source-registry.ts new file mode 100644 index 0000000000000..eb8124a4f5830 --- /dev/null +++ b/apps/studio/data/query-sources/query-source-registry.ts @@ -0,0 +1,152 @@ +import dayjs from 'dayjs' +import * as z from 'zod' + +import { logsAllEndpointUrl } from '@/data/logs/logs-endpoint' +import { isoDateTimeString } from '@/lib/iso-datetime' + +export type LogTimeRange = + | { + type: 'relative' + amount: number + unit: 'minute' | 'hour' | 'day' + } + | { + type: 'absolute' + from: string + to: string + } + +export type DatabaseSource = { + id: 'database' + type: 'database' + endpoint: '/platform/pg-meta/{ref}/query' + parameters: { + /** + * Query-owned database selection. The SQL editor still adapts its legacy + * global/local-storage selector into this shape; new consumers persist the + * identifier directly with their query. + */ + identifier?: string + } +} + +export type LogsSource = { + id: 'logs' + type: 'logs' + endpoint: ReturnType + parameters: { + time_range: LogTimeRange + } +} + +/** Sources are registered by Studio; query surfaces only store a source binding. */ +export type Source = DatabaseSource | LogsSource + +export type CellSourceOf = Pick + +export type CellSource = CellSourceOf | CellSourceOf + +export const DEFAULT_LOG_TIME_RANGE: LogTimeRange = { + type: 'relative', + amount: 1, + unit: 'hour', +} + +export const QUERY_SOURCE_REGISTRY = { + database: { + id: 'database', + type: 'database', + endpoint: '/platform/pg-meta/{ref}/query', + parameters: {}, + }, + logs: { + id: 'logs', + type: 'logs', + endpoint: logsAllEndpointUrl(true), + parameters: { time_range: DEFAULT_LOG_TIME_RANGE }, + }, +} as const satisfies Record + +export type QuerySourceId = keyof typeof QUERY_SOURCE_REGISTRY + +export const QUERY_SOURCES = Object.values(QUERY_SOURCE_REGISTRY) satisfies Source[] + +export const QUERY_SOURCE_LABELS: Record = { + database: 'Database', + logs: 'Logs', +} + +const isoDateTimeSchema = z.string().refine((value) => isoDateTimeString(value) !== null, { + message: 'must be a valid ISO-8601 datetime', +}) + +export const logTimeRangeSchema = z + .discriminatedUnion('type', [ + z + .object({ + type: z.literal('relative'), + amount: z.number().int().positive(), + unit: z.enum(['minute', 'hour', 'day']), + }) + .strict(), + z + .object({ + type: z.literal('absolute'), + from: isoDateTimeSchema, + to: isoDateTimeSchema, + }) + .strict(), + ]) + .refine( + (range) => { + if (range.type !== 'absolute') return true + + const from = dayjs(range.from) + const to = dayjs(range.to) + // An unparseable endpoint is already reported against its own field; the + // ordering rule stays quiet so it doesn't add a second, misleading issue. + if (!from.isValid() || !to.isValid()) return true + + return to.isAfter(from) + }, + { + message: 'must be later than the start of the range', + path: ['to'], + } + ) + +export const cellSourceSchema = z.discriminatedUnion('type', [ + z + .object({ + id: z.literal('database'), + type: z.literal('database'), + parameters: z.object({ identifier: z.string().optional() }).strict(), + }) + .strict(), + z + .object({ + id: z.literal('logs'), + type: z.literal('logs'), + parameters: z.object({ time_range: logTimeRangeSchema }).strict(), + }) + .strict(), +]) + +export function createDefaultCellSource(id: 'database'): CellSourceOf +export function createDefaultCellSource(id: 'logs'): CellSourceOf +export function createDefaultCellSource(id: QuerySourceId): CellSource +export function createDefaultCellSource(id: QuerySourceId): CellSource { + const source = QUERY_SOURCE_REGISTRY[id] + + if (source.type === 'logs') { + return { + id: source.id, + type: source.type, + parameters: { time_range: { ...source.parameters.time_range } }, + } + } + + return { id: source.id, type: source.type, parameters: { ...source.parameters } } +} + +export const getQuerySource = (id: QuerySourceId): Source => QUERY_SOURCE_REGISTRY[id] diff --git a/apps/studio/data/sql/execute-sql-mutation.ts b/apps/studio/data/sql/execute-sql-mutation.ts index 3718fac1f5996..d1c2122cbf6af 100644 --- a/apps/studio/data/sql/execute-sql-mutation.ts +++ b/apps/studio/data/sql/execute-sql-mutation.ts @@ -12,6 +12,7 @@ import { createNodeTree, } from '@/components/interfaces/ExplainVisualizer/ExplainVisualizer.parser' import { handleError as handleErrorFetchers, post } from '@/data/fetchers' +import { QUERY_SOURCE_REGISTRY } from '@/data/query-sources/query-source-registry' import { MB } from '@/lib/constants' import { sqlEventParser } from '@/lib/sql-event-parser' import { useTrack } from '@/lib/telemetry/track' @@ -159,7 +160,7 @@ export async function executeSql( const key = queryKey?.filter((seg) => typeof seg === 'string' || typeof seg === 'number').join('-') ?? '' - const result = await post('/platform/pg-meta/{ref}/query', { + const result = await post(QUERY_SOURCE_REGISTRY.database.endpoint, { ...options, body: { query: sql, disable_statement_timeout: isStatementTimeoutDisabled }, params: { diff --git a/apps/studio/data/storage/iceberg-namespace-table-delete-mutation.ts b/apps/studio/data/storage/iceberg-namespace-table-delete-mutation.ts index d14f52fca5c3e..d78bd1d7678a0 100644 --- a/apps/studio/data/storage/iceberg-namespace-table-delete-mutation.ts +++ b/apps/studio/data/storage/iceberg-namespace-table-delete-mutation.ts @@ -25,7 +25,7 @@ async function deleteIcebergNamespaceTable({ { params: { path: { ref: projectRef, id: warehouse, namespace, table }, - query: { purge: true }, + query: { purge: 'true' }, }, } ) diff --git a/apps/studio/lib/api/self-hosted/signing-keys.test.ts b/apps/studio/lib/api/self-hosted/signing-keys.test.ts index 69493f6509f7c..8e06231cb9068 100644 --- a/apps/studio/lib/api/self-hosted/signing-keys.test.ts +++ b/apps/studio/lib/api/self-hosted/signing-keys.test.ts @@ -30,6 +30,7 @@ describe('api/self-hosted/signing-keys', () => { expect(key).toEqual({ id: '00000000-0000-0000-0000-000000000000', algorithm: 'HS256', + public_jwk: '', status: 'in_use', created_at: '1970-01-01T00:00:00.000Z', updated_at: '1970-01-01T00:00:00.000Z', diff --git a/apps/studio/lib/api/self-hosted/signing-keys.ts b/apps/studio/lib/api/self-hosted/signing-keys.ts index 86eb60d58f323..3541f2e8e7128 100644 --- a/apps/studio/lib/api/self-hosted/signing-keys.ts +++ b/apps/studio/lib/api/self-hosted/signing-keys.ts @@ -24,6 +24,7 @@ export function getLegacySigningKey(): SigningKeyResponse { return { id: LEGACY_KEY_ID, algorithm: 'HS256', + public_jwk: '', status: 'in_use', created_at: LEGACY_KEY_CREATED_AT, updated_at: LEGACY_KEY_CREATED_AT, diff --git a/apps/studio/pages/api/platform/organizations/[slug]/billing/subscription.ts b/apps/studio/pages/api/platform/organizations/[slug]/billing/subscription.ts index f585fc29b4e55..d7cee03359e45 100644 --- a/apps/studio/pages/api/platform/organizations/[slug]/billing/subscription.ts +++ b/apps/studio/pages/api/platform/organizations/[slug]/billing/subscription.ts @@ -35,7 +35,7 @@ const handleGet = async (_req: NextApiRequest, res: NextApiResponse { // FE-3954: syncing the live array into valtio corrupted it with Proxies, breaking structuredClone in addToolApprovalResponse @@ -44,3 +44,82 @@ describe('AI assistant chat message sync', () => { expect(() => structuredClone(replacedMessage)).not.toThrow() }) }) + +describe('AI assistant chat surface isolation', () => { + it('creates chats without changing the sidebar selection', () => { + const state = createAiAssistantState() + const sidebarChatId = state.newChat({ name: 'Sidebar chat' }) + + const explorerChatId = state.createChat({ name: 'Explorer chat' }) + + expect(explorerChatId).not.toBe(sidebarChatId) + expect(state.activeChatId).toBe(sidebarChatId) + expect(state.chats[explorerChatId]?.name).toBe('Explorer chat') + }) + + it('branches a specified chat without changing the sidebar selection', () => { + const state = createAiAssistantState() + const sidebarChatId = state.newChat({ name: 'Sidebar chat' }) + const explorerChatId = state.createChat({ name: 'Explorer chat' }) + state.chats[explorerChatId].messages = [ + { id: 'message-1', role: 'user', parts: [{ type: 'text', text: 'Hello' }] }, + ] + + const branchId = state.createBranch(explorerChatId, 'message-1') + + expect(branchId).toBeDefined() + expect(state.activeChatId).toBe(sidebarChatId) + expect(state.chats[branchId!]?.branchedFrom).toEqual({ + chatId: explorerChatId, + messageId: 'message-1', + }) + }) + + it('mutates an explicit chat without changing or clearing the sidebar chat', () => { + const state = createAiAssistantState() + const sidebarChatId = state.newChat({ name: 'Sidebar chat' }) + const explorerChatId = state.createChat({ name: 'Explorer chat' }) + state.chats[sidebarChatId].messages = [ + { id: 'sidebar-message', role: 'user', parts: [{ type: 'text', text: 'Keep me' }] }, + ] + state.chats[explorerChatId].messages = [ + { id: 'explorer-message', role: 'user', parts: [{ type: 'text', text: 'Clear me' }] }, + ] + state.chatInstances[explorerChatId].messages = [ + { id: 'explorer-message', role: 'user', parts: [{ type: 'text', text: 'Clear me' }] }, + ] + + state.clearMessages(explorerChatId) + + expect(state.activeChatId).toBe(sidebarChatId) + expect(state.chats[sidebarChatId].messages).toHaveLength(1) + expect(state.chats[explorerChatId].messages).toHaveLength(0) + expect(state.chatInstances[explorerChatId].messages).toHaveLength(0) + }) + + it('keeps explicit chat message edits synchronized with the live chat instance', () => { + const state = createAiAssistantState() + const chatId = state.createChat({ name: 'Explorer chat' }) + const messages = [ + { id: 'message-1', role: 'user' as const, parts: [{ type: 'text' as const, text: 'First' }] }, + { + id: 'message-2', + role: 'user' as const, + parts: [{ type: 'text' as const, text: 'Second' }], + }, + ] + state.chats[chatId].messages = messages + state.chatInstances[chatId].messages = messages + + state.deleteMessagesAfter('message-2', { chatId }) + state.updateMessage( + { id: 'message-1', role: 'user', parts: [{ type: 'text', text: 'Updated' }] }, + chatId + ) + + expect(state.chats[chatId].messages).toEqual([ + { id: 'message-1', role: 'user', parts: [{ type: 'text', text: 'Updated' }] }, + ]) + expect(state.chatInstances[chatId].messages).toEqual(state.chats[chatId].messages) + }) +}) diff --git a/apps/studio/state/ai-assistant-state.tsx b/apps/studio/state/ai-assistant-state.tsx index 5355074cf655c..8e0413bbc46a6 100644 --- a/apps/studio/state/ai-assistant-state.tsx +++ b/apps/studio/state/ai-assistant-state.tsx @@ -60,7 +60,7 @@ export type SupportChatMetadata = { isLifecycleSyncing: boolean } -type ChatSession = { +export type ChatSession = { id: string name: string messages: AssistantMessageType[] @@ -87,6 +87,10 @@ type AiAssistantData = { context: AiAssistantContext } +type CreateChatOptions = { name?: string; initialMessage?: string } +type NewChatOptions = CreateChatOptions & + Partial> + // Data structure stored in IndexedDB type StoredAiAssistantState = { projectRef: string @@ -389,11 +393,7 @@ export const createAiAssistantState = (): AiAssistantState => { return state.activeChatId ? state.chats[state.activeChatId] : undefined }, - newChat: ( - options?: { name?: string; initialMessage?: string } & Partial< - Pick - > - ) => { + createChat: (options?: CreateChatOptions) => { const chatId = uuidv4() const newChat: ChatSession = { id: chatId, @@ -407,21 +407,23 @@ export const createAiAssistantState = (): AiAssistantState => { ...state.chats, [chatId]: newChat, } - state.activeChatId = chatId - // Create new chat instance const chatInstance = createChatInstance(state, { id: chatId, initialMessages: [] }) - state.chatInstances[chatId] = ref(chatInstance) - // If initialMessage is provided, append it to the chat instance if (options?.initialMessage) { chatInstance.sendMessage({ text: options.initialMessage, }) } - // Update non-chat related state based on options, falling back to current state, then initial + return chatId + }, + + newChat: (options?: NewChatOptions) => { + const chatId = state.createChat(options) + state.selectChat(chatId) + const initialAiAssistantData = createInitialAiAssistantData() state.initialInput = options?.initialInput ?? initialAiAssistantData.initialInput state.sqlSnippets = options?.sqlSnippets ?? initialAiAssistantData.sqlSnippets @@ -431,8 +433,8 @@ export const createAiAssistantState = (): AiAssistantState => { return chatId }, - branchChat: (messageId: string) => { - const sourceChat = state.activeChat + createBranch: (sourceChatId: string, messageId: string) => { + const sourceChat = state.chats[sourceChatId] if (!sourceChat) return const messageIndex = sourceChat.messages.findIndex((msg) => msg.id === messageId) @@ -456,12 +458,22 @@ export const createAiAssistantState = (): AiAssistantState => { ...state.chats, [chatId]: newChat, } - state.activeChatId = chatId state.chatInstances[chatId] = ref( createChatInstance(state, { id: chatId, initialMessages: branchedMessages }) ) + return chatId + }, + + branchChat: (messageId: string) => { + if (!state.activeChatId) return + + const chatId = state.createBranch(state.activeChatId, messageId) + if (!chatId) return + + state.selectChat(chatId) + const initialAiAssistantData = createInitialAiAssistantData() state.initialInput = initialAiAssistantData.initialInput state.sqlSnippets = initialAiAssistantData.sqlSnippets @@ -493,35 +505,33 @@ export const createAiAssistantState = (): AiAssistantState => { }) }, - selectChat: (id: string) => { - if (id !== state.activeChatId) { - state.activeChatId = id - const chat = state.chats[id] - if (chat) { - if (!state.chatInstances[id]) { - state.chatInstances[id] = ref( - createChatInstance(state, { id, initialMessages: chat.messages }) - ) - } - } + ensureChatInstance: (id: string) => { + const chat = state.chats[id] + if (chat && !state.chatInstances[id]) { + state.chatInstances[id] = ref( + createChatInstance(state, { id, initialMessages: chat.messages }) + ) } }, + selectChat: (id: string) => { + if (!state.chats[id]) return + + state.activeChatId = id + state.ensureChatInstance(id) + }, + deleteChat: (id: string) => { const { [id]: _, ...remainingChats } = state.chats state.chats = remainingChats + delete state.chatInstances[id] if (id === state.activeChatId) { const remainingChatIds = Object.keys(remainingChats) state.activeChatId = remainingChatIds.length > 0 ? remainingChatIds[0] : undefined if (state.activeChatId) { - const chat = state.chats[state.activeChatId] - if (!state.chatInstances[state.activeChatId]) { - state.chatInstances[state.activeChatId] = ref( - createChatInstance(state, { id: state.activeChatId, initialMessages: chat.messages }) - ) - } + state.ensureChatInstance(state.activeChatId) } } }, @@ -534,19 +544,27 @@ export const createAiAssistantState = (): AiAssistantState => { } }, - clearMessages: () => { - const chat = state.activeChat + clearMessages: (chatId = state.activeChatId) => { + if (!chatId) return + + const chat = state.chats[chatId] if (chat) { chat.messages = [] + const chatInstance = state.chatInstances[chatId] + if (chatInstance) chatInstance.messages = [] chat.updatedAt = new Date() - state.suggestions = undefined - state.sqlSnippets = [] - state.initialInput = '' + if (chatId === state.activeChatId) { + state.suggestions = undefined + state.sqlSnippets = [] + state.initialInput = '' + } } }, - deleteMessagesAfter: (id: string, { includeSelf = true } = {}) => { - const chat = state.activeChat + deleteMessagesAfter: (id: string, { includeSelf = true, chatId = state.activeChatId } = {}) => { + if (!chatId) return + + const chat = state.chats[chatId] if (!chat) return const messageIndex = chat.messages.findIndex((msg) => msg.id === id) @@ -555,17 +573,37 @@ export const createAiAssistantState = (): AiAssistantState => { // Delete all messages from the target message (optionally including) to the end const startIndex = includeSelf ? messageIndex : messageIndex + 1 chat.messages.splice(startIndex) + const chatInstance = state.chatInstances[chatId] + const instanceMessageIndex = chatInstance?.messages.findIndex((message) => message.id === id) + if (chatInstance && instanceMessageIndex !== undefined && instanceMessageIndex !== -1) { + chatInstance.messages = chatInstance.messages.slice( + 0, + includeSelf ? instanceMessageIndex : instanceMessageIndex + 1 + ) + } chat.updatedAt = new Date() }, - updateMessage: (updatedMessage: MessageType) => { - const chat = state.activeChat + updateMessage: (updatedMessage: MessageType, chatId = state.activeChatId) => { + if (!chatId) return + + const chat = state.chats[chatId] if (!chat) return const messageIndex = chat.messages.findIndex((msg) => msg.id === updatedMessage.id) if (messageIndex !== -1) { // Clone first — valtio's proxy() mutates nested properties in place and would corrupt the SDK's live array - chat.messages[messageIndex] = sanitizeForCloning(updatedMessage) + const clonedMessage = sanitizeForCloning(updatedMessage) + chat.messages[messageIndex] = clonedMessage + const chatInstance = state.chatInstances[chatId] + const instanceMessageIndex = chatInstance?.messages.findIndex( + (message) => message.id === updatedMessage.id + ) + if (chatInstance && instanceMessageIndex !== undefined && instanceMessageIndex !== -1) { + chatInstance.messages = chatInstance.messages.map((message, index) => + index === instanceMessageIndex ? sanitizeForCloning(updatedMessage) : message + ) + } chat.updatedAt = new Date() } }, @@ -620,18 +658,7 @@ export const createAiAssistantState = (): AiAssistantState => { } // Initialize chat instance for the active chat - if ( - state.activeChatId && - state.chats[state.activeChatId] && - !state.chatInstances[state.activeChatId] - ) { - state.chatInstances[state.activeChatId] = ref( - createChatInstance(state, { - id: state.activeChatId, - initialMessages: state.chats[state.activeChatId].messages, - }) - ) - } + if (state.activeChatId) state.ensureChatInstance(state.activeChatId) }, clearStorage: async () => { @@ -650,19 +677,18 @@ export type AiAssistantState = AiAssistantData & { messageSpanIds: Record setContext: (context: Partial) => void setModel: (model: AssistantModel) => void - newChat: ( - options?: { name?: string; initialMessage?: string } & Partial< - Pick - > - ) => string + createChat: (options?: CreateChatOptions) => string + newChat: (options?: NewChatOptions) => string + createBranch: (sourceChatId: string, messageId: string) => string | undefined branchChat: (messageId: string) => string | undefined setSupportLifecycleStatus: (chatId: string, status: AiSupportStatus) => void + ensureChatInstance: (id: string) => void selectChat: (id: string) => void deleteChat: (id: string) => void renameChat: (id: string, name: string) => void - clearMessages: () => void - deleteMessagesAfter: (id: string, options?: { includeSelf?: boolean }) => void - updateMessage: (message: MessageType) => void + clearMessages: (chatId?: string) => void + deleteMessagesAfter: (id: string, options?: { includeSelf?: boolean; chatId?: string }) => void + updateMessage: (message: MessageType, chatId?: string) => void setSqlSnippets: (snippets: SqlSnippet[]) => void clearSqlSnippets: () => void loadPersistedState: (persistedState: StoredAiAssistantState) => void diff --git a/apps/studio/state/sql-editor/sql-editor-session-state.ts b/apps/studio/state/sql-editor/sql-editor-session-state.ts index 38aeafc030c19..b7813f58333ab 100644 --- a/apps/studio/state/sql-editor/sql-editor-session-state.ts +++ b/apps/studio/state/sql-editor/sql-editor-session-state.ts @@ -1,6 +1,6 @@ import { proxy, ref, snapshot, useSnapshot } from 'valtio' -import type { LogDateRange } from '@/components/interfaces/SQLEditor/querySource' +import type { LogTimeRange } from '@/data/query-sources/query-source-registry' /** * Ephemeral, per-session SQL editor state that is NOT persisted: query results, @@ -35,11 +35,11 @@ export const sqlEditorSessionState = proxy({ * The logs time range for a logs snippet, keyed by snippet id. Session state — * never written to snippet content — so it works on read-only shared snippets * and resets on reload. An unset snippet has no entry; read sites fall back to - * `DEFAULT_LOG_DATE_RANGE`. + * `DEFAULT_LOG_TIME_RANGE`. */ - logRange: {} as { [snippetId: string]: LogDateRange }, + logRange: {} as { [snippetId: string]: LogTimeRange }, - setLogRange: (id: string, range: LogDateRange) => { + setLogRange: (id: string, range: LogTimeRange) => { sqlEditorSessionState.logRange[id] = range }, diff --git a/apps/studio/tests/components/Organization/TeamSettings/InviteMemberButton.network.test.tsx b/apps/studio/tests/components/Organization/TeamSettings/InviteMemberButton.network.test.tsx index c8138d6dc595e..1ab2641ffaede 100644 --- a/apps/studio/tests/components/Organization/TeamSettings/InviteMemberButton.network.test.tsx +++ b/apps/studio/tests/components/Organization/TeamSettings/InviteMemberButton.network.test.tsx @@ -67,6 +67,7 @@ const buildRole = (id: number, name: string): OrganizationRoleResponse['org_scop const buildMember = (overrides: Partial): Member => ({ gotrue_id: 'gotrue-test', + avatar_url: null, is_sso_user: false, metadata: {}, mfa_enabled: false, diff --git a/apps/studio/tests/components/Organization/TeamSettings/UpdateRolesPanel.network.test.tsx b/apps/studio/tests/components/Organization/TeamSettings/UpdateRolesPanel.network.test.tsx index c8c4ca7bbabae..0ab629a98b246 100644 --- a/apps/studio/tests/components/Organization/TeamSettings/UpdateRolesPanel.network.test.tsx +++ b/apps/studio/tests/components/Organization/TeamSettings/UpdateRolesPanel.network.test.tsx @@ -83,6 +83,7 @@ const buildPermission = (resource: string): AccessControlPermission => ({ const MEMBER: OrganizationMember = { gotrue_id: 'gotrue-member', + avatar_url: null, is_sso_user: false, metadata: {}, mfa_enabled: false, diff --git a/apps/studio/tests/components/SQLEditor/QuerySourceMenu.test.tsx b/apps/studio/tests/components/SQLEditor/QuerySourceMenu.test.tsx index 6985f0ad82202..d1ef963eb6342 100644 --- a/apps/studio/tests/components/SQLEditor/QuerySourceMenu.test.tsx +++ b/apps/studio/tests/components/SQLEditor/QuerySourceMenu.test.tsx @@ -1,42 +1,58 @@ import { screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { mockAnimationsApi } from 'jsdom-testing-mocks' -import { describe, expect, it } from 'vitest' +import { beforeEach, describe, expect, it } from 'vitest' -import { DEFAULT_LOG_DATE_RANGE } from '@/components/interfaces/SQLEditor/querySource' import { QuerySourceMenu } from '@/components/interfaces/SQLEditor/UtilityPanel/QuerySourceMenu/QuerySourceMenu' +import { DEFAULT_LOG_TIME_RANGE } from '@/data/query-sources/query-source-registry' import { customRender } from '@/tests/lib/custom-render' import { addAPIMock } from '@/tests/lib/msw' // QuerySourceMenu renders a Radix dropdown (+ nested dialog), both of which use Web Animations. mockAnimationsApi() -addAPIMock({ - method: 'get', - path: '/platform/projects/:ref', - response: { - id: 1, - ref: 'default', - organization_id: 1, - name: 'Test Project', - status: 'ACTIVE_HEALTHY', - cloud_provider: 'AWS', - region: 'us-east-1', - db_host: 'db.default.supabase.co', - restUrl: 'https://default.supabase.co/rest/v1/', - inserted_at: '2024-01-01T00:00:00Z', - updated_at: '2024-01-01T00:00:00Z', - subscription_id: 'sub_123', - is_branch_enabled: false, - is_physical_backups_enabled: false, - high_availability: false, - integration_source: null, - connectionString: 'postgresql://postgres@localhost:5432/postgres', - is_hibernating: false, - }, +beforeEach(() => { + addAPIMock({ + method: 'get', + path: '/platform/projects/:ref', + response: { + id: 1, + ref: 'default', + organization_id: 1, + name: 'Test Project', + status: 'ACTIVE_HEALTHY', + cloud_provider: 'AWS', + region: 'us-east-1', + db_host: 'db.default.supabase.co', + restUrl: 'https://default.supabase.co/rest/v1/', + inserted_at: '2024-01-01T00:00:00Z', + updated_at: '2024-01-01T00:00:00Z', + subscription_id: 'sub_123', + is_branch_enabled: false, + is_physical_backups_enabled: false, + high_availability: false, + integration_source: null, + connectionString: 'postgresql://postgres@localhost:5432/postgres', + is_hibernating: false, + }, + }) }) describe('QuerySourceMenu', () => { + it('hides logs when creating logs queries is unavailable', async () => { + customRender( + + ) + + await userEvent.click(screen.getByRole('button', { name: 'Query source: Database' })) + + expect(screen.queryByText('Logs')).not.toBeInTheDocument() + }) + it('keeps the dropdown open across a source switch, so the new source’s controls appear without reopening it', async () => { // Selecting a source doesn't mutate `runSource` in place — it navigates to a // fresh tab, and the parent re-renders this component with the new source once @@ -57,7 +73,7 @@ describe('QuerySourceMenu', () => { rerender( ) diff --git a/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx b/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx index 09e328d5f4ec5..c9bff95574f13 100644 --- a/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx +++ b/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx @@ -96,7 +96,7 @@ describe('generateDynamicHelper', () => { }) describe('generateDynamicHelpers', () => { - test('generates 3 helpers for minutes, hours, days', () => { + test('generates helpers for every supported relative unit', () => { const helpers = generateDynamicHelpers(5) expect(helpers).toHaveLength(3) expect(helpers[0].text).toBe('Last 5 minutes') @@ -112,7 +112,7 @@ describe('generateHelpersFromInput', () => { expect(generateHelpersFromInput('2yoie')).toBeNull() }) - test('returns 3 helpers for number only input', () => { + test('returns a helper for every unit for number only input', () => { const helpers = generateHelpersFromInput('25') expect(helpers).toHaveLength(3) expect(helpers![0].text).toBe('Last 25 minutes') diff --git a/apps/www/data/PricingFAQ.json b/apps/www/data/PricingFAQ.json index 222e0620e9ef6..4a268d4c1804a 100644 --- a/apps/www/data/PricingFAQ.json +++ b/apps/www/data/PricingFAQ.json @@ -17,19 +17,19 @@ }, { "question": "Are you going to change your pricing in the future?", - "answer": "Our pricing is in Beta. You can read more about our decisions in our [pricing blog post](/blog/2021/03/29/pricing). Pricing may change in the future, however as a team of developers we are committed to pricing being as developer friendly as possible." + "answer": "Pricing may change in the future. As a team of developers, we are committed to keeping our pricing as developer friendly as possible." }, { "question": "What happens if I cancel my subscription?", "answer": "The organization is allocated credits for unused time during the billing month. Those credits can be used for other projects." }, { - "question": "Do I get a notification if I am approaching my usage limits?", - "answer": "Yes, we will email you when you are within 20% of your Plan limits." + "question": "How can I track my usage?", + "answer": "You can track your organization's usage at any time on the [usage page](https://supabase.com/dashboard/org/_/usage) in the dashboard, which shows how each project is tracking against your plan's limits. Your upcoming invoice on the [billing page](https://supabase.com/dashboard/org/_/billing) updates as you go, and organizations on the Pro Plan or above can use the [Spend cap](https://supabase.com/docs/guides/platform/cost-control) to control costs." }, { "question": "What if I need one project for development and one for production?", - "answer": "We are working on multi-environment projects. For now, you can create a project for your development backend and production backend. We give you 2 free projects as part of our Free Plan. This means you could have a development and a production server as part of your Free Plan." + "answer": "You can create two projects, one for development and one for production — the Free Plan includes two free projects. You can also use [Branching](https://supabase.com/docs/guides/deployment/branching), available on the Pro Plan and above, to run a separate development environment off your production project." }, { "question": "Can I self-host Supabase for free?", diff --git a/packages/api-types/index.ts b/packages/api-types/index.ts index 4870d902de659..9c89e97947a55 100644 --- a/packages/api-types/index.ts +++ b/packages/api-types/index.ts @@ -1,25 +1,38 @@ import type { - components as apiComponents, - operations as apiOperations, - paths as apiPaths, -} from './types/api' + components as apiV1Components, + operations as apiV1Operations, + paths as apiV1Paths, +} from './types/api-v1' +import type { + components as apiV2Components, + operations as apiV2Operations, + paths as apiV2Paths, +} from './types/api-v2' import type { components as platformComponents, operations as platformOperations, paths as platformPaths, } from './types/platform' -export type { webhooks, $defs } from './types/api' +export type { webhooks, $defs } from './types/api-v2' -export interface paths extends apiPaths, platformPaths {} -export interface operations extends apiOperations, platformOperations {} +export interface paths extends apiV2Paths, apiV1Paths, platformPaths {} +export interface operations extends apiV2Operations, apiV1Operations, platformOperations {} export interface components { - schemas: apiComponents['schemas'] & platformComponents['schemas'] - responses: apiComponents['responses'] & platformComponents['responses'] - parameters: apiComponents['parameters'] & platformComponents['parameters'] - requestBodies: apiComponents['requestBodies'] & platformComponents['requestBodies'] - headers: apiComponents['headers'] & platformComponents['headers'] - pathItems: apiComponents['pathItems'] & platformComponents['pathItems'] + schemas: apiV2Components['schemas'] & apiV1Components['schemas'] & platformComponents['schemas'] + responses: apiV2Components['responses'] & + apiV1Components['responses'] & + platformComponents['responses'] + parameters: apiV2Components['parameters'] & + apiV1Components['parameters'] & + platformComponents['parameters'] + requestBodies: apiV2Components['requestBodies'] & + apiV1Components['requestBodies'] & + platformComponents['requestBodies'] + headers: apiV2Components['headers'] & apiV1Components['headers'] & platformComponents['headers'] + pathItems: apiV2Components['pathItems'] & + apiV1Components['pathItems'] & + platformComponents['pathItems'] } -export type { platformComponents, apiComponents } +export type { platformComponents, apiV1Components, apiV2Components } diff --git a/packages/api-types/redocly.yaml b/packages/api-types/redocly.yaml index 59023bf6afc39..1d34a034cef1a 100644 --- a/packages/api-types/redocly.yaml +++ b/packages/api-types/redocly.yaml @@ -1,9 +1,13 @@ apis: - api: + api-v2: + root: http://localhost:8080/api/v2-json + x-openapi-ts: + output: ./types/api-v2.d.ts + api-v1: root: http://localhost:8080/api/v1-json x-openapi-ts: - output: ./types/api.d.ts + output: ./types/api-v1.d.ts platform: root: http://localhost:8080/api/platform-json x-openapi-ts: - output: ./types/platform.d.ts \ No newline at end of file + output: ./types/platform.d.ts diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api-v1.d.ts similarity index 94% rename from packages/api-types/types/api.d.ts rename to packages/api-types/types/api-v1.d.ts index eef705e690efe..182549218cac2 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api-v1.d.ts @@ -521,6 +521,35 @@ export interface paths { patch?: never trace?: never } + '/v1/projects/{ref}/analytics/endpoints/logs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Gets all project's logs in a single log stream + * @description Executes an SQL or LQL query on the project's unified logs stream. + * + * Either the `iso_timestamp_start` and `iso_timestamp_end` parameters must be provided. + * If both are not provided, only the last 1 minute of logs will be queried. + * The timestamp range must be no more than 24 hours and is rounded to the nearest minute. If the range is more than 24 hours, a validation error will be thrown. + * + * Filter by the `source` column to specify specific log sources, such as edge_logs, postgres_logs, etc. + * + * Note: SQL must be written in **ClickHouse SQL dialect**. + * + */ + get: operations['v1-get-project-logs'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/v1/projects/{ref}/analytics/endpoints/logs.all': { parameters: { query?: never @@ -530,6 +559,7 @@ export interface paths { } /** * Gets project's logs + * @deprecated * @description Executes a SQL query on the project's logs. * * Either the `iso_timestamp_start` and `iso_timestamp_end` parameters must be provided. @@ -539,7 +569,27 @@ export interface paths { * Note: Unless the `sql` parameter is provided, only edge_logs will be queried. See the [log query docs](/docs/guides/telemetry/logs?queryGroups=product&product=postgres&queryGroups=source&source=edge_logs#querying-with-the-logs-explorer:~:text=logs%20from%20the-,Sources,-drop%2Ddown%3A) for all available sources. * */ - get: operations['v1-get-project-logs'] + get: operations['v1-get-project-logs-all'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v1/projects/{ref}/analytics/endpoints/metrics': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Scrape a project's metrics + * @description Prometheus scrape endpoint. Returns metrics of a customer project in the Prometheus open exposition format. + */ + get: operations['v1-scrape-project-metrics'] put?: never post?: never delete?: never @@ -1315,6 +1365,66 @@ export interface paths { patch?: never trace?: never } + '/v1/projects/{ref}/database/jit/invite': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Invites an external user to a database for JIT access + * @description Invites the external user and sets initial roles that can be assumed and for how long + */ + post: operations['v1-invite-external-jit-access'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v1/projects/{ref}/database/jit/invite/{invite_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Deletes the invite for an external user to a database for JIT access + * @description Revokes and deletes the invitation + */ + delete: operations['v1-delete-invite-external-jit-access'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v1/projects/{ref}/database/jit/invite/accept': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Accepts invitation for JIT database access + * @description Accepts the invitation to JIT database access + */ + post: operations['v1-accept-invite-external-jit-access'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/v1/projects/{ref}/database/jit/list': { parameters: { query?: never @@ -1342,25 +1452,13 @@ export interface paths { path?: never cookie?: never } - /** - * List applied migration versions - * @description Only available to selected partner OAuth apps - */ + /** List applied migration versions */ get: operations['v1-list-migration-history'] - /** - * Upsert a database migration without applying - * @description Only available to selected partner OAuth apps - */ + /** Upsert a database migration without applying */ put: operations['v1-upsert-a-migration'] - /** - * Apply a database migration - * @description Only available to selected partner OAuth apps - */ + /** Apply a database migration */ post: operations['v1-apply-a-migration'] - /** - * Rollback database migrations and remove them from history table - * @description Only available to selected partner OAuth apps - */ + /** Rollback database migrations and remove them from history table */ delete: operations['v1-rollback-migrations'] options?: never head?: never @@ -1374,20 +1472,14 @@ export interface paths { path?: never cookie?: never } - /** - * Fetch an existing entry from migration history - * @description Only available to selected partner OAuth apps - */ + /** Fetch an existing entry from migration history */ get: operations['v1-get-a-migration'] put?: never post?: never delete?: never options?: never head?: never - /** - * Patch an existing entry in migration history - * @description Only available to selected partner OAuth apps - */ + /** Patch an existing entry in migration history */ patch: operations['v1-patch-a-migration'] trace?: never } @@ -2114,6 +2206,15 @@ export interface paths { export type webhooks = Record export interface components { schemas: { + /** @example { + * "email": "external-user@somedomain.xyz", + * "token": "" + * } */ + AcceptInviteExternalUserJitAccessBody: { + /** Format: email */ + email: string + token: string + } ActionRunResponse: { branch_id: string check_run_id: number | null @@ -2749,7 +2850,6 @@ export interface components { domains?: { created_at?: string domain?: string - id: string updated_at?: string }[] id: string @@ -2765,7 +2865,6 @@ export interface components { } } entity_id: string - id: string metadata_url?: string metadata_xml?: string /** @enum {string} */ @@ -2932,7 +3031,6 @@ export interface components { domains?: { created_at?: string domain?: string - id: string updated_at?: string }[] id: string @@ -2948,7 +3046,6 @@ export interface components { } } entity_id: string - id: string metadata_url?: string metadata_xml?: string /** @enum {string} */ @@ -3053,7 +3150,7 @@ export interface components { * } * } */ FunctionDeployBody: { - file?: string[] + file: string[] metadata: { entrypoint_path: string import_map_path?: string @@ -3122,7 +3219,6 @@ export interface components { domains?: { created_at?: string domain?: string - id: string updated_at?: string }[] id: string @@ -3138,7 +3234,6 @@ export interface components { } } entity_id: string - id: string metadata_url?: string metadata_xml?: string /** @enum {string} */ @@ -3150,6 +3245,63 @@ export interface components { } updated_at?: string } + /** @example { + * "email": "external-user@somedomain.xyz", + * "roles": [ + * { + * "role": "postgres", + * "expires_at": 1740787200, + * "allowed_networks": { + * "allowed_cidrs": [ + * { + * "cidr": "203.0.113.0/24" + * } + * ] + * }, + * "branches_only": false + * } + * ] + * } */ + InviteExternalUserJitAccessBody: { + /** Format: email */ + email: string + roles: { + allowed_networks?: { + allowed_cidrs?: { + /** Format: cidrv4 */ + cidr: string + }[] + allowed_cidrs_v6?: { + /** Format: cidrv6 */ + cidr: string + }[] + } + branches_only?: boolean + expires_at?: number + role: string + }[] + } + InviteExternalUserJitResponse: { + /** Format: email */ + email: string + /** Format: uuid */ + invite_id: string + user_roles: { + allowed_networks?: { + allowed_cidrs?: { + /** Format: cidrv4 */ + cidr: string + }[] + allowed_cidrs_v6?: { + /** Format: cidrv6 */ + cidr: string + }[] + } + branches_only?: boolean + expires_at?: number + role: string + }[] + } /** @example { * "state": "enabled" * } */ @@ -3159,13 +3311,15 @@ export interface components { } JitAccessResponse: { /** Format: uuid */ - user_id: string + user_id?: string user_roles: { allowed_networks?: { allowed_cidrs?: { + /** Format: cidrv4 */ cidr: string }[] allowed_cidrs_v6?: { + /** Format: cidrv6 */ cidr: string }[] } @@ -3180,9 +3334,11 @@ export interface components { user_role: { allowed_networks?: { allowed_cidrs?: { + /** Format: cidrv4 */ cidr: string }[] allowed_cidrs_v6?: { + /** Format: cidrv6 */ cidr: string }[] } @@ -3193,14 +3349,19 @@ export interface components { } JitListAccessResponse: { items: { + expires_at: null + invite_id: null + primary_email: string | null /** Format: uuid */ user_id: string user_roles: { allowed_networks?: { allowed_cidrs?: { + /** Format: cidrv4 */ cidr: string }[] allowed_cidrs_v6?: { + /** Format: cidrv6 */ cidr: string }[] } @@ -3210,22 +3371,6 @@ export interface components { }[] }[] } - JitStateResponse: - | { - appliedSuccessfully?: boolean - /** @enum {string} */ - state: 'enabled' | 'disabled' - } - | { - /** @enum {string} */ - state: 'unavailable' - /** @enum {string} */ - unavailableReason: - | 'manual_migration_required' - | 'postgres_upgrade_required' - | 'ssl_enforcement_required' - | 'temporarily_unavailable' - } LegacyApiKeysResponse: { enabled: boolean } @@ -3288,8 +3433,7 @@ export interface components { | 'auth_mfa_web_authn_default' | 'log_drain_default' | 'etl_pipeline_default' - /** @description Any JSON-serializable value */ - meta?: unknown + meta?: components['schemas']['ListProjectAddonsResponseJsonValue'] name: string price: { amount: number @@ -3341,8 +3485,7 @@ export interface components { | 'auth_mfa_web_authn_default' | 'log_drain_default' | 'etl_pipeline_default' - /** @description Any JSON-serializable value */ - meta?: unknown + meta?: components['schemas']['ListProjectAddonsResponseJsonValue'] name: string price: { amount: number @@ -3355,13 +3498,19 @@ export interface components { } }[] } + /** @description Any JSON-serializable value */ + ListProjectAddonsResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['ListProjectAddonsResponseJsonValue'][] + | { + [key: string]: components['schemas']['ListProjectAddonsResponseJsonValue'] + } ListProvidersResponse: { items: { created_at?: string domains?: { created_at?: string domain?: string - id: string updated_at?: string }[] id: string @@ -3377,7 +3526,6 @@ export interface components { } } entity_id: string - id: string metadata_url?: string metadata_xml?: string /** @enum {string} */ @@ -3437,7 +3585,17 @@ export interface components { NetworkRestrictionsResponse: { /** Format: date-time */ applied_at?: string - /** @description At any given point in time, this is the config that the user has requested be applied to their project. The `status` field indicates if it has been applied to the project, or is pending. When an updated config is received, the applied config is moved to `old_config`. */ + /** + * @description At any given point in time, this is the config that the user has requested be applied to their project. The `status` field indicates if it has been applied to the project, or is pending. When an updated config is received, the applied config is moved to `old_config`. + * @example { + * "dbAllowedCidrs": [ + * "203.0.113.0/24" + * ], + * "dbAllowedCidrsV6": [ + * "2001:db8::/32" + * ] + * } + */ config: { dbAllowedCidrs?: string[] dbAllowedCidrsV6?: string[] @@ -3669,9 +3827,29 @@ export interface components { */ slug: string } + /** @example { + * "root_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + * } */ PgsodiumConfigResponse: { + /** @description The pgsodium root key: 32 bytes, hex-encoded (64 characters). */ root_key: string } + PlanGateErrorBody: { + /** @description Present on entitlement denials. Other errors with this status code (validation, billing state) carry only message. */ + error?: { + /** + * @description Machine-readable marker for plan-gated denials + * @enum {string} + */ + code: 'entitlement_required' + /** @description Entitlement feature key that failed the check */ + feature: string + /** @description Billing page URL for the organization, present when the org is resolvable */ + upgrade_url?: string + } + /** @description Human-readable explanation of the plan gate */ + message: string + } PostgresConfigResponse: { /** @description Default unit: s */ checkpoint_timeout?: string @@ -3694,6 +3872,7 @@ export interface components { maintenance_work_mem?: string max_connections?: number max_locks_per_transaction?: number + max_logical_replication_workers?: number max_parallel_maintenance_workers?: number max_parallel_workers?: number max_parallel_workers_per_gather?: number @@ -3701,6 +3880,7 @@ export interface components { max_slot_wal_keep_size?: string max_standby_archive_delay?: string max_standby_streaming_delay?: string + max_sync_workers_per_subscription?: number max_wal_senders?: number max_wal_size?: string max_worker_processes?: number @@ -3720,6 +3900,8 @@ export interface components { db_extra_search_path: string /** @description If `null`, the value is automatically configured based on compute size. */ db_pool: number | null + /** @description If `null`, the value is automatically configured to 10. */ + db_pool_acquisition_timeout: number | null db_schema: string jwt_secret?: string max_rows: number @@ -3807,7 +3989,6 @@ export interface components { } | { obj_name: string - /** @enum {string} */ obj_type: 'table' | 'function' schema_name: string /** @enum {string} */ @@ -3906,7 +4087,7 @@ export interface components { | 'sa-east-1' name: string /** @enum {string} */ - provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -3944,7 +4125,7 @@ export interface components { | 'sa-east-1' name: string /** @enum {string} */ - provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -4014,7 +4195,7 @@ export interface components { created_at: string /** Format: uuid */ id: string - public_jwk?: unknown + public_jwk: unknown /** @enum {string} */ status: 'in_use' | 'previously_used' | 'revoked' | 'standby' /** Format: date-time */ @@ -4028,7 +4209,7 @@ export interface components { created_at: string /** Format: uuid */ id: string - public_jwk?: unknown + public_jwk: unknown /** @enum {string} */ status: 'in_use' | 'previously_used' | 'revoked' | 'standby' /** Format: date-time */ @@ -4131,6 +4312,9 @@ export interface components { imageTransformation: { enabled: boolean } + purgeCache: { + enabled: boolean + } s3Protocol: { enabled: boolean } @@ -4483,8 +4667,8 @@ export interface components { UpdateCustomHostnameResponse: { custom_hostname: string data: { - errors: unknown[] - messages: unknown[] + errors: components['schemas']['UpdateCustomHostnameResponseJsonValue'][] + messages: components['schemas']['UpdateCustomHostnameResponseJsonValue'][] result: { custom_origin_server: string hostname: string @@ -4517,6 +4701,13 @@ export interface components { | '4_origin_setup_completed' | '5_services_reconfigured' } + /** @description Any JSON-serializable value */ + UpdateCustomHostnameResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['UpdateCustomHostnameResponseJsonValue'][] + | { + [key: string]: components['schemas']['UpdateCustomHostnameResponseJsonValue'] + } /** @example { * "user_id": "55555555-5555-4555-8555-555555555555", * "roles": [ @@ -4538,9 +4729,11 @@ export interface components { roles: { allowed_networks?: { allowed_cidrs?: { + /** Format: cidrv4 */ cidr: string }[] allowed_cidrs_v6?: { + /** Format: cidrv6 */ cidr: string }[] } @@ -4552,9 +4745,10 @@ export interface components { user_id: string } /** @example { - * "root_key": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=" + * "root_key": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" * } */ UpdatePgsodiumConfigBody: { + /** @description The pgsodium root key: 32 bytes, hex-encoded (64 characters). */ root_key: string } /** @example { @@ -4585,6 +4779,7 @@ export interface components { maintenance_work_mem?: string max_connections?: number max_locks_per_transaction?: number + max_logical_replication_workers?: number max_parallel_maintenance_workers?: number max_parallel_workers?: number max_parallel_workers_per_gather?: number @@ -4592,6 +4787,7 @@ export interface components { max_slot_wal_keep_size?: string max_standby_archive_delay?: string max_standby_streaming_delay?: string + max_sync_workers_per_subscription?: number max_wal_senders?: number max_wal_size?: string max_worker_processes?: number @@ -4641,7 +4837,6 @@ export interface components { domains?: { created_at?: string domain?: string - id: string updated_at?: string }[] id: string @@ -4657,7 +4852,6 @@ export interface components { } } entity_id: string - id: string metadata_url?: string metadata_xml?: string /** @enum {string} */ @@ -4754,6 +4948,9 @@ export interface components { imageTransformation?: { enabled: boolean } + purgeCache?: { + enabled: boolean + } s3Protocol?: { enabled: boolean } @@ -4875,6 +5072,8 @@ export interface components { | '48xlarge_optimized_memory' | '48xlarge_optimized_cpu' | '48xlarge_high_memory' + /** @description [Experimental] Whether to enable high availability for the project. */ + high_availability?: boolean /** * @deprecated * @description This field is deprecated and is ignored in this request @@ -4898,6 +5097,8 @@ export interface components { * @enum {string} */ plan?: 'free' | 'pro' + /** @deprecated */ + postgres_engine?: null /** * @deprecated * @description Region you want your server to reside in. Use region_selection instead. @@ -4960,6 +5161,8 @@ export interface components { /** @enum {string} */ type: 'smartGroup' } + /** @deprecated */ + release_channel?: null /** * Format: uri * @description Template URL used to create the project from the CLI. @@ -5047,6 +5250,7 @@ export interface components { | 'storage.image_transformations' | 'storage.vector_buckets' | 'storage.iceberg_catalog' + | 'storage.purge_cache' | 'security.audit_logs_days' | 'security.questionnaire' | 'security.soc2_report' @@ -5096,6 +5300,8 @@ export interface components { | 'integrations.github_connections' | 'dedicated_pooler' | 'observability.dashboard_advanced_metrics' + | 'api.members.invitations' + | 'api.members.roles' /** @enum {string} */ type: 'boolean' | 'numeric' | 'set' } @@ -5109,6 +5315,7 @@ export interface components { version: string }[] V1OrganizationMemberResponse: { + avatar_url: string | null email?: string mfa_enabled: boolean role_name: string @@ -5151,6 +5358,8 @@ export interface components { db_extra_search_path: string /** @description If `null`, the value is automatically configured based on compute size. */ db_pool: number | null + /** @description If `null`, the value is automatically configured to 10. */ + db_pool_acquisition_timeout: number | null db_schema: string max_rows: number } @@ -5451,6 +5660,7 @@ export interface components { V1UpdatePostgrestConfigBody: { db_extra_search_path?: string db_pool?: number + db_pool_acquisition_timeout?: number db_schema?: string max_rows?: number } @@ -5523,7 +5733,7 @@ export interface operations { parameters: { query?: { /** @description If set to false, schedule deletion with 1-hour grace period (only when soft deletion is enabled). */ - force?: boolean + force?: string } header?: never path: { @@ -5588,8 +5798,13 @@ export interface operations { parameters: { query?: { included_schemas?: string - /** @description Use pg-delta instead of Migra for diffing when true */ - pgdelta?: boolean + /** @description Use pg-delta instead of Migra for diffing when true. + * Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + pgdelta?: string } header?: never path: { @@ -5760,6 +5975,7 @@ export interface operations { response_type: 'code' | 'token' | 'id_token token' scope?: string state?: string + target_flow?: string } header?: never path?: never @@ -6908,6 +7124,68 @@ export interface operations { } content?: never } + /** @description Usage exceeded. Enable additional usage to continue querying */ + 402: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + 'v1-get-project-logs-all': { + parameters: { + query?: { + iso_timestamp_end?: string + iso_timestamp_start?: string + /** @description Custom SQL query to execute on the logs. See [querying logs](/docs/guides/telemetry/logs?queryGroups=product&product=postgres&queryGroups=source&source=edge_logs#querying-with-the-logs-explorer) for more details. */ + sql?: string + } + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['AnalyticsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Usage exceeded. Enable additional usage to continue querying */ + 402: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Forbidden action */ 403: { headers: { @@ -6924,6 +7202,58 @@ export interface operations { } } } + 'v1-scrape-project-metrics': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Prometheus / OpenMetrics text exposition */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/openmetrics-text': string + 'text/plain': string + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to fetch project's metrics */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } 'v1-get-project-usage-api-count': { parameters: { query?: { @@ -7029,8 +7359,12 @@ export interface operations { 'v1-get-project-api-keys': { parameters: { query?: { - /** @description Boolean string, true or false */ - reveal?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + reveal?: string } header?: never path: { @@ -7075,8 +7409,12 @@ export interface operations { 'v1-create-project-api-key': { parameters: { query?: { - /** @description Boolean string, true or false */ - reveal?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + reveal?: string } header?: never path: { @@ -7125,8 +7463,12 @@ export interface operations { 'v1-get-project-api-key': { parameters: { query?: { - /** @description Boolean string, true or false */ - reveal?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + reveal?: string } header?: never path: { @@ -7174,9 +7516,9 @@ export interface operations { query?: { reason?: string /** @description Boolean string, true or false */ - reveal?: boolean + reveal?: string /** @description Boolean string, true or false */ - was_compromised?: boolean + was_compromised?: string } header?: never path: { @@ -7222,8 +7564,12 @@ export interface operations { 'v1-update-project-api-key': { parameters: { query?: { - /** @description Boolean string, true or false */ - reveal?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + reveal?: string } header?: never path: { @@ -7316,8 +7662,12 @@ export interface operations { 'v1-update-project-legacy-api-keys': { parameters: { query: { - /** @description Boolean string, true or false */ - enabled: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + enabled: string } header?: never path: { @@ -9513,7 +9863,7 @@ export interface operations { parameters: { query?: { /** @description If true, also removes the custom domain add-on from the project subscription. */ - remove_addon?: boolean + remove_addon?: string } header?: never path: { @@ -9985,7 +10335,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -10060,7 +10412,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -10275,7 +10629,7 @@ export interface operations { } content?: never } - /** @description Failed to upsert database migration */ + /** @description Failed to update JIT access */ 500: { headers: { [name: string]: unknown @@ -10387,6 +10741,142 @@ export interface operations { } } } + 'v1-invite-external-jit-access': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['InviteExternalUserJitAccessBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['InviteExternalUserJitResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to invite external user */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + 'v1-delete-invite-external-jit-access': { + parameters: { + query?: never + header?: never + path: { + invite_id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to revoke invite for external user */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + 'v1-accept-invite-external-jit-access': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['AcceptInviteExternalUserJitAccessBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['JitAccessResponse'] + } + } + /** @description Failed to accept invitation */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } 'v1-list-jit-access': { parameters: { query?: never @@ -11127,13 +11617,11 @@ export interface operations { query?: { entrypoint_path?: string ezbr_sha256?: string - /** @description Boolean string, true or false */ - import_map?: boolean + import_map?: string import_map_path?: string name?: string slug?: string - /** @description Boolean string, true or false */ - verify_jwt?: boolean + verify_jwt?: string } header?: never path: { @@ -11301,13 +11789,11 @@ export interface operations { query?: { entrypoint_path?: string ezbr_sha256?: string - /** @description Boolean string, true or false */ - import_map?: boolean + import_map?: string import_map_path?: string name?: string slug?: string - /** @description Boolean string, true or false */ - verify_jwt?: boolean + verify_jwt?: string } header?: never path: { @@ -11418,8 +11904,7 @@ export interface operations { 'v1-deploy-a-function': { parameters: { query?: { - /** @description Boolean string, true or false */ - bundleOnly?: boolean + bundleOnly?: string slug?: string } header?: never @@ -11483,16 +11968,19 @@ export interface operations { 'v1-get-services-health': { parameters: { query: { - services: ( - | 'auth' - | 'db' - | 'db_postgres_user' - | 'pooler' - | 'realtime' - | 'rest' - | 'storage' - | 'pg_bouncer' - )[] + /** @description Comma-separated list of enums or array of enums. */ + services: + | string + | ( + | 'auth' + | 'db' + | 'db_postgres_user' + | 'pooler' + | 'realtime' + | 'rest' + | 'storage' + | 'pg_bouncer' + )[] timeout_ms?: number } header?: never @@ -11559,7 +12047,21 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['JitStateResponse'] + 'application/json': + | { + appliedSuccessfully?: boolean + /** @enum {string} */ + state: 'enabled' | 'disabled' + } + | { + /** @constant */ + state: 'unavailable' + /** @enum {string} */ + unavailableReason: + | 'postgres_upgrade_required' + | 'ssl_enforcement_required' + | 'temporarily_unavailable' + } } } /** @description Unauthorized */ @@ -11613,7 +12115,21 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['JitStateResponse'] + 'application/json': + | { + appliedSuccessfully?: boolean + /** @enum {string} */ + state: 'enabled' | 'disabled' + } + | { + /** @constant */ + state: 'unavailable' + /** @enum {string} */ + unavailableReason: + | 'postgres_upgrade_required' + | 'ssl_enforcement_required' + | 'temporarily_unavailable' + } } } /** @description Unauthorized */ @@ -12291,7 +12807,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -13121,7 +13639,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { @@ -13230,7 +13750,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { @@ -13291,7 +13813,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { diff --git a/packages/api-types/types/api-v2.d.ts b/packages/api-types/types/api-v2.d.ts new file mode 100644 index 0000000000000..0824bc203aad8 --- /dev/null +++ b/packages/api-types/types/api-v2.d.ts @@ -0,0 +1,12062 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + '/v1/webhooks/events': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Publish event + * @description Ingests and schedules a new webhook event to be published out to all subscribed endpoints. + * + * In case of non-successful response status codes, early termination, networking issues, + * requests to this endpoint should be retried until it succeeds, otherwise there is a risk of + * loosing events. + * + * `meta.idempotency_key` is used to ensure idempotency when retrying the requests and so it + * must always be provided. + */ + post: operations['postV1WebhooksEvents'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/integrations/github/connections': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List GitHub connections of an organization + * @description Returns a cursor-paginated list of the GitHub connections of the organization's projects. + * + * Use `page[after]` and `page[before]` to navigate pages and `page[size]` to control the page size. + * Paging walks the organization projects, so a page holds at most `page[size]` connections and can hold fewer (or none) when some of its projects are not connected. + * Follow `links.next` until it is `null` rather than stopping on a short page. + * + * Use `filter[project_ref]` to narrow the list down to a single project. + */ + get: operations['v2-list-organization-github-connections'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/members': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List members of an organization + * @description Returns a cursor-paginated list of organization members including their roles and project-scoped permissions. + */ + get: operations['v2-list-organization-members'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/members/{user_id}/roles': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + delete?: never + options?: never + head?: never + /** + * Assign or change an organization member role + * @description Assigns an org-wide role when projects is omitted, or creates a project-scoped assignment when projects is provided. Uses an org-level role template id from GET /v2/organizations/{slug}/roles. Stale role assignments are automatically cleaned up: if a role no longer has any projects, it is deleted; overlapping project assignments in other roles are automatically removed to avoid duplication. + */ + patch: operations['v2-assign-organization-member-role'] + trace?: never + } + '/v2/organizations/{slug}/members/invitations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Creates organization invitations + * @description Creates member invitations for an organization. Each invitation can have different role and project scope settings. + */ + post: operations['v2-create-organization-invitations'] + /** + * Deletes organization invitations by email + * @description Bulk delete member invitations for an organization by email address. + */ + delete: operations['v2-delete-organization-invitations'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/projects': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List projects of an organization + * @description Returns a cursor-paginated list of projects for the specified organization, including their databases. + * + * Use `page[after]` and `page[before]` to navigate pages and `page[size]` to control the number of projects returned per page. + */ + get: operations['v2-list-organization-projects'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/roles': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List roles of an organization + * @description Returns a list of org-level roles for the organization. + */ + get: operations['v2-list-organization-roles'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/webhooks/deliveries/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Get delivery + * @description Get details of a specific delivery attempt. + */ + get: operations['allV2OrganizationsBySlugWebhooks'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/webhooks/deliveries/{id}/retry': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Retry delivery + * @description Retry delivering the same event again. + * + * Automatic retries are not applicable to manual retries - if the delivery fails, there won't be any automatic retries attempted. + * + * This endpoint is heavy rate-limited to allow for 10 request within 60 seconds. + */ + post: operations['allV2OrganizationsBySlugWebhooks'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/webhooks/endpoints': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List endpoints + * @description List all Webhook endpoints based on a project's ref or an organization's slug. + */ + get: operations['allV2OrganizationsBySlugWebhooks'] + put?: never + /** + * Create endpoint + * @description Create new endpoint configuration to subscribe to specific webhook events. + */ + post: operations['allV2OrganizationsBySlugWebhooks'] + /** + * Delete all endpoints + * @description Delete all endpoints including all events and deliveries. + * + * Any in-flight webhooks will result in a no-op. + */ + delete: operations['allV2OrganizationsBySlugWebhooks'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/webhooks/endpoints/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Get endpoint + * @description Get details of a specific endpoint. + */ + get: operations['allV2OrganizationsBySlugWebhooks'] + put?: never + post?: never + /** + * Delete endpoint + * @description Delete the endpoint including all events and deliveries + * + * Any in-flight webhooks will result in a no-op. + */ + delete: operations['allV2OrganizationsBySlugWebhooks'] + options?: never + head?: never + /** + * Update endpoint + * @description Update endpoint's configuration. + */ + patch: operations['allV2OrganizationsBySlugWebhooks'] + trace?: never + } + '/v2/organizations/{slug}/webhooks/endpoints/{id}/deliveries': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List deliveries + * @description List all deliveries for a specific endpoint in descending order (newest first). + * + * Deliveries which has expired are no longer available and will not be listed. + */ + get: operations['allV2OrganizationsBySlugWebhooks'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/organizations/{slug}/webhooks/endpoints/{id}/test': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Send test event + * @description Ingests and schedules a test webhook event to be published out this endpoints. + * + * Which event type to use can be specified in the request body, otherwise + * it will use any matching type the endpoint is listening for. + * + * The event will contain `is_test: true` in it's payload. + * + * This endpoint is heavy rate-limited to allow for 10 request within 60 seconds. + */ + post: operations['allV2OrganizationsBySlugWebhooks'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/analytics/log-drains': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** List project log drains */ + get: operations['v2-list-log-drains'] + put?: never + /** Create a log drain for a project */ + post: operations['v2-create-log-drain'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/analytics/log-drains/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + /** Update a project log drain */ + put: operations['v2-update-log-drain'] + post?: never + /** Delete a project log drain */ + delete: operations['v2-delete-log-drain'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/config': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * [Alpha] Get a project's service configuration + * @description Returns the project's database, pooler, Auth, Data API, Realtime and Storage configuration — the same configuration a branch inherits from its base project. Each is the effective config, so a setting the project has never overridden is reported at its platform default rather than as null. Auth secrets are returned as an HMAC of their value. `storage` is read live from the storage service; the rest come from this platform's own records. + */ + get: operations['v2-get-project-config'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/private-link/associations': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** List AWS accounts attached to the project PrivateLink share */ + get: operations['v2-list-private-link-associations'] + put?: never + /** + * Add an AWS account to the project PrivateLink share + * @description Adds an AWS account to the project's PrivateLink configuration and schedules the AWS resources to be created. + */ + post: operations['v2-create-private-link-association'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/private-link/associations/aws-account/{aws_account_id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Remove an AWS account from the project PrivateLink share + * @description Removes an AWS account from the project's PrivateLink configuration (targeting the primary database). Cleans up the associated AWS resources. + */ + delete: operations['v2-delete-private-link-association'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/private-link/associations/aws-account/{aws_account_id}/database/{database_identifier}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Remove an AWS account from a specific database PrivateLink share + * @description Removes an AWS account from the project's PrivateLink configuration for the given read replica. Cleans up the associated AWS resources. + */ + delete: operations['v2-delete-private-link-association-for-database'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/transfers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Transfers a project to a different organization */ + post: operations['v2-transfer-a-project'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/transfers/previews': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Previews transferring a project to a different organizations, shows eligibility and impact */ + post: operations['v2-preview-a-project-transfer'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/webhooks/deliveries/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Get delivery + * @description Get details of a specific delivery attempt. + */ + get: operations['allV2ProjectsByRefWebhooks'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/webhooks/deliveries/{id}/retry': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Retry delivery + * @description Retry delivering the same event again. + * + * Automatic retries are not applicable to manual retries - if the delivery fails, there won't be any automatic retries attempted. + * + * This endpoint is heavy rate-limited to allow for 10 request within 60 seconds. + */ + post: operations['allV2ProjectsByRefWebhooks'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/webhooks/endpoints': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List endpoints + * @description List all Webhook endpoints based on a project's ref or an organization's slug. + */ + get: operations['allV2ProjectsByRefWebhooks'] + put?: never + /** + * Create endpoint + * @description Create new endpoint configuration to subscribe to specific webhook events. + */ + post: operations['allV2ProjectsByRefWebhooks'] + /** + * Delete all endpoints + * @description Delete all endpoints including all events and deliveries. + * + * Any in-flight webhooks will result in a no-op. + */ + delete: operations['allV2ProjectsByRefWebhooks'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/webhooks/endpoints/{id}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Get endpoint + * @description Get details of a specific endpoint. + */ + get: operations['allV2ProjectsByRefWebhooks'] + put?: never + post?: never + /** + * Delete endpoint + * @description Delete the endpoint including all events and deliveries + * + * Any in-flight webhooks will result in a no-op. + */ + delete: operations['allV2ProjectsByRefWebhooks'] + options?: never + head?: never + /** + * Update endpoint + * @description Update endpoint's configuration. + */ + patch: operations['allV2ProjectsByRefWebhooks'] + trace?: never + } + '/v2/projects/{ref}/webhooks/endpoints/{id}/deliveries': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List deliveries + * @description List all deliveries for a specific endpoint in descending order (newest first). + * + * Deliveries which has expired are no longer available and will not be listed. + */ + get: operations['allV2ProjectsByRefWebhooks'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/webhooks/endpoints/{id}/test': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * Send test event + * @description Ingests and schedules a test webhook event to be published out this endpoints. + * + * Which event type to use can be specified in the request body, otherwise + * it will use any matching type the endpoint is listening for. + * + * The event will contain `is_test: true` in it's payload. + * + * This endpoint is heavy rate-limited to allow for 10 request within 60 seconds. + */ + post: operations['allV2ProjectsByRefWebhooks'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/workers': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * [Alpha] List all workers + * @description Returns all workers you've previously deployed to the specified project. + */ + get: operations['v2-list-all-workers'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/workers/{name}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * [Alpha] Retrieve a worker + * @description Returns a worker along with its instance tally. Poll this after a deploy until `build_state` leaves `building`. + */ + get: operations['v2-get-a-worker'] + put?: never + post?: never + /** + * [Alpha] Delete a worker + * @description Tombstones the worker. Its instances and image are torn down asynchronously. + */ + delete: operations['v2-delete-a-worker'] + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/workers/{name}/deploy': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * [Alpha] Deploy a worker + * @description Creates the worker if it does not exist, building from a context staged through the uploads endpoint. The build runs asynchronously: this answers 202 and the worker reaches `build_state` `active` or `failed` later. + */ + post: operations['v2-deploy-a-worker'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/v2/projects/{ref}/workers/{name}/uploads': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** + * [Alpha] Mint a presigned slot for a build-context upload + * @description PUT the `.tar.gz` build context to the returned `url` before `expires_at`, then deploy with the upload id as `context_upload_id`. The bytes go straight to storage — no management API request carries them. + */ + post: operations['v2-create-worker-upload'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export type webhooks = Record +export interface components { + schemas: { + APIErrorObject: { + code: string + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + message: string + meta?: { + [key: string]: unknown + } + } + CreateLogDrainRequestOpenApi: { + data: { + attributes: { + /** @enum {string} */ + backend_type: + | 'postgres' + | 'bigquery' + | 'clickhouse' + | 'webhook' + | 'datadog' + | 'loki' + | 'sentry' + | 's3' + | 'axiom' + | 'last9' + | 'otlp' + | 'syslog' + config: + | { + hostname?: string + password?: string | null + port?: number | null + schema?: string + url?: string | null + username?: string | null + } + | { + gzip?: boolean + headers?: { + [key: string]: string + } + /** @enum {string} */ + http?: 'http1' | 'http2' + url?: string + } + | { + dataset_id?: string + project_id?: string + } + | { + api_key?: string + region?: string + } + | { + headers?: { + [key: string]: string + } + password?: string | null + url?: string + username?: string | null + } + | { + dsn?: string + } + | { + api_token?: string + dataset_name?: string + domain?: string + } + | { + ca_cert?: string + cipher_key?: string + client_cert?: string + client_key?: string + host?: string + port?: number + structured_data?: string + /** @default false */ + tls?: boolean + } + description?: string + name: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'log_drain' + } + } + ErrorResponseBody: { + error: components['schemas']['ErrorResponseBodyAPIErrorObject'] + } + ErrorResponseBodyAPIErrorObject: { + code: string + description?: string + id?: string + issues?: components['schemas']['ErrorResponseBodyAPIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + message: string + meta?: { + [key: string]: unknown + } + } + ListLogDrainsResponse: { + data: { + attributes: { + /** @enum {string} */ + backend_type: + | 'postgres' + | 'bigquery' + | 'clickhouse' + | 'webhook' + | 'datadog' + | 'loki' + | 'sentry' + | 's3' + | 'axiom' + | 'last9' + | 'otlp' + | 'syslog' + config: + | { + hostname?: string + password?: string | null + port?: number | null + schema?: string + url?: string | null + username?: string | null + } + | { + gzip?: boolean + headers?: { + [key: string]: string + } + /** @enum {string} */ + http?: 'http1' | 'http2' + url?: string + } + | { + dataset_id?: string + project_id?: string + } + | { + api_key?: string + region?: string + } + | { + headers?: { + [key: string]: string + } + password?: string | null + url?: string + username?: string | null + } + | { + dsn?: string + } + | { + api_token?: string + dataset_name?: string + domain?: string + } + | { + ca_cert?: string + cipher_key?: string + client_cert?: string + client_key?: string + host?: string + port?: number + structured_data?: string + /** @default false */ + tls?: boolean + } + description?: string + name: string + } + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'log_drain' + }[] + } + LogDrainResponse: { + data: { + attributes: { + /** @enum {string} */ + backend_type: + | 'postgres' + | 'bigquery' + | 'clickhouse' + | 'webhook' + | 'datadog' + | 'loki' + | 'sentry' + | 's3' + | 'axiom' + | 'last9' + | 'otlp' + | 'syslog' + config: + | { + hostname?: string + password?: string | null + port?: number | null + schema?: string + url?: string | null + username?: string | null + } + | { + gzip?: boolean + headers?: { + [key: string]: string + } + /** @enum {string} */ + http?: 'http1' | 'http2' + url?: string + } + | { + dataset_id?: string + project_id?: string + } + | { + api_key?: string + region?: string + } + | { + headers?: { + [key: string]: string + } + password?: string | null + url?: string + username?: string | null + } + | { + dsn?: string + } + | { + api_token?: string + dataset_name?: string + domain?: string + } + | { + ca_cert?: string + cipher_key?: string + client_cert?: string + client_key?: string + host?: string + port?: number + structured_data?: string + /** @default false */ + tls?: boolean + } + description?: string + name: string + } + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'log_drain' + } + } + OrganizationMemberRoleResponse: { + data: { + attributes: { + /** + * @description Role name. For project-scoped assignments this is the base role name. + * @example developer + */ + name: string + /** @description Project refs this role is scoped to. Empty array for org-level roles. */ + projects: { + name: string + ref: string + }[] + /** + * @description Whether this role applies org-wide or is scoped to specific projects for the user. + * @enum {string} + */ + scope: 'organization' | 'project' + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_member_role' + } + } + UpdateLogDrainRequestOpenApi: { + data: { + attributes: { + /** @enum {string} */ + backend_type: + | 'postgres' + | 'bigquery' + | 'clickhouse' + | 'webhook' + | 'datadog' + | 'loki' + | 'sentry' + | 's3' + | 'axiom' + | 'last9' + | 'otlp' + | 'syslog' + config?: + | { + hostname?: string + password?: string | null + port?: number | null + schema?: string + url?: string | null + username?: string | null + } + | { + gzip?: boolean + headers?: { + [key: string]: string + } + /** @enum {string} */ + http?: 'http1' | 'http2' + url?: string + } + | { + dataset_id?: string + project_id?: string + } + | { + api_key?: string + region?: string + } + | { + headers?: { + [key: string]: string + } + password?: string | null + url?: string + username?: string | null + } + | { + dsn?: string + } + | { + api_token?: string + dataset_name?: string + domain?: string + } + | { + ca_cert?: string + cipher_key?: string + client_cert?: string + client_key?: string + host?: string + port?: number + structured_data?: string + /** @default false */ + tls?: boolean + } + description?: string + name?: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'log_drain' + } + } + V2AssignOrganizationMemberRoleRequest: { + data: { + attributes: { + /** @description The projects to assign a project-scoped role for. If omitted, assigns an org-wide role. */ + projects?: { + /** + * @description Project ref + * @example abcjuqabhgwjjutfvtpa + */ + ref: string + }[] + /** + * @description Role name to assign. Must be one of: owner, administrator, developer, read-only. Must be on a Team or Enterprise plan to use the read-only role. + * @example developer + * @enum {string} + */ + role: 'owner' | 'administrator' | 'developer' | 'read-only' + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_member_role' + } + } + V2CreateInvitationsRequest: { + data: { + attributes: { + /** Format: email */ + email: string + /** @description The projects to limit a user to. If omitted, user will have org-wide access with the provided role. */ + projects?: { + /** + * @description Project ref + * @example abcjuqabhgwjjutfvtpa + */ + ref: string + }[] + require_sso?: boolean + /** + * @description Role name to assign. Must be on a Team or Enterprise plan to use the read-only role. + * @example developer + * @enum {string} + */ + role: 'owner' | 'administrator' | 'developer' | 'read-only' + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_invitation' + }[] + } + V2CreateInvitationsResponse: { + data: { + attributes: { + /** Format: email */ + email: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_invitation' + }[] + error?: { + code: string + description?: string + id?: string + issues?: { + code: string + description?: string + id?: string + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + message: string + meta: { + /** Format: email */ + email: string + } + }[] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + message: string + meta?: { + [key: string]: unknown + } + } + } + V2CreatePrivateLinkAssociationRequest: { + data: { + attributes: { + /** @description Optional human-readable name for the AWS account. */ + account_name?: string + /** @description The AWS account ID to add to the project PrivateLink share. */ + aws_account_id: string + /** @description Identifier of the read replica this PrivateLink share should target. Omit to target the primary database. */ + database_identifier?: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'private_link_association' + } + } + V2DeleteInvitationsRequest: { + data: { + attributes: { + /** Format: email */ + email: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_invitation' + }[] + } + V2DeleteInvitationsResponse: { + data: { + attributes: { + /** Format: email */ + email: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_invitation' + }[] + } + V2DeployWorkerRequest: { + data: { + attributes: { + /** @description Id of a build context staged through the uploads endpoint. Required unless `runtime` is set. */ + context_upload_id?: string + spec: { + backend?: string + /** @example public */ + exposure: string + /** @example 1 */ + instances: number + /** @example node */ + runtime?: string + /** @example 2gb-1vcpu */ + size: string + } + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_worker' + } + } + V2ListGitHubConnectionsResponse: { + data: { + attributes: { + /** @description Maximum number of preview branches */ + branch_limit: number + /** @description When the connection was created */ + inserted_at: string + /** @description GitHub App installation id */ + installation_id: number + /** @description Whether a preview branch is created for every pull request */ + new_branch_per_pr: boolean + /** @description The connected Supabase project */ + project: { + id: number + name: string + /** + * @description Project ref + * @example abcdefghijklmnopqrst + */ + ref: string + } + /** @description The connected GitHub repository */ + repository: { + id: number + name: string + } + /** @description Whether branches are only created for changes under `supabase/` */ + supabase_changes_only: boolean + /** @description When the connection was last updated */ + updated_at: string + /** @description The user who created the connection, if still known */ + user: { + id: number + primary_email: string | null + username: string + } | null + /** @description Directory within the repository the project lives in */ + workdir: string + } + /** + * @description Connection id. + * @example 7 + */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'github_connection' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organizations/my-org/integrations/github/connections?page[size]=10 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organizations/my-org/integrations/github/connections?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organizations/my-org/integrations/github/connections?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organizations/my-org/integrations/github/connections?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7 + */ + prev: string | null + } + } + V2ListMembersResponse: { + data: { + attributes: { + /** @description Member's avatar URL */ + avatar_url: string | null + /** @description Whether this member is a Single Sign-On user */ + is_sso_user: boolean + /** @description Whether Multi-Factor Authentication is enabled for this member */ + mfa_enabled: boolean + /** @description Member's primary email */ + primary_email: string | null + /** @description Roles assigned to this member. Includes both org-level and project-scoped roles. */ + roles: { + /** + * @description Role name. For project-scoped roles this is the base role name. + * @example developer + */ + name: string + /** @description Project refs this role is scoped to. Empty array for org-level roles. */ + projects: { + name: string + ref: string + }[] + /** + * @description Whether this role applies org-wide or is scoped to specific projects for the user. + * @enum {string} + */ + scope: 'organization' | 'project' + }[] + /** @description Member's username */ + username: string | null + } + /** Format: uuid */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_member' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organizations/my-org/members?page[size]=10 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organizations/my-org/members?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organizations/my-org/members?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organizations/my-org/members?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7 + */ + prev: string | null + } + } + V2ListPrivateLinkAssociationsResponse: { + data: { + attributes: { + /** @description Human-readable name for the AWS account. */ + account_name?: string + /** @description The AWS account ID this PrivateLink share is associated with. */ + aws_account_id: string + /** @description Identifier of the database this PrivateLink share targets - the project ref for the primary, or the read replica identifier. */ + database_identifier: string + /** + * @description Whether this PrivateLink share targets the primary database or a read replica. + * @enum {string} + */ + database_type: 'PRIMARY' | 'READ_REPLICA' + /** @description ARN of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_arn?: string + /** @description ID of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_id?: string + /** @description ARN of the AWS Resource Access Manager resource share for this association. */ + resource_access_manager_share_arn?: string + /** + * Format: date-time + * @description The time and date at which the AWS Resource Share Association was requested from Supabase. `null` means that the association was not yet requested while the PrivateLink Association is pending. + */ + shared_at: string | null + /** + * @description + * - `CREATING`: The PrivateLink resources and the Association are in the process of being created. The PrivateLink Share cannot be accepted yet. + * - `READY`: The PrivateLink resources have been created and the PrivateLink Share can be accepted for the duration of 12h after sharing. See `shared_at`. + * - `ASSOCIATION_REQUEST_EXPIRED`: The PrivateLink Share has not been accepted within the 12h time limit. This association can now be deleted. + * - `ASSOCIATION_ACCEPTED`: The PrivateLink Share was successfully accepted. + * - `CREATION_FAILED`: The PrivateLink resources failed to create. This likely means something went wrong on Supabase's and and support should be contacted. + * - `DELETING`: The PrivateLink resources and the Association are in the process of being deleted. The PrivateLink Share cannot be accepted yet. + * + * @enum {string} + */ + status: + | 'CREATING' + | 'READY' + | 'ASSOCIATION_REQUEST_EXPIRED' + | 'ASSOCIATION_ACCEPTED' + | 'CREATION_FAILED' + | 'DELETING' + } + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'private_link_association' + }[] + } + V2ListProjectsResponse: { + data: { + attributes: { + /** @description Cloud provider hosting the project */ + cloud_provider: string + /** @description The project's databases including compute and disk attributes. */ + databases: { + cloud_provider: string + disk_last_modified_at?: string + disk_throughput_mbps?: number + /** @enum {string} */ + disk_type?: 'gp3' | 'io2' + disk_volume_size_gb?: number + identifier: string + /** @enum {string} */ + infra_compute_size?: + | 'pico' + | 'nano' + | 'micro' + | 'small' + | 'medium' + | 'large' + | 'xlarge' + | '2xlarge' + | '4xlarge' + | '8xlarge' + | '12xlarge' + | '16xlarge' + | '24xlarge' + | '24xlarge_optimized_memory' + | '24xlarge_optimized_cpu' + | '24xlarge_high_memory' + | '48xlarge' + | '48xlarge_optimized_memory' + | '48xlarge_optimized_cpu' + | '48xlarge_high_memory' + region: string | null + /** @enum {string} */ + status: + | 'ACTIVE_HEALTHY' + | 'ACTIVE_UNHEALTHY' + | 'COMING_UP' + | 'GOING_DOWN' + | 'INIT_FAILED' + | 'REMOVED' + | 'RESTORING' + | 'UNKNOWN' + | 'INIT_READ_REPLICA' + | 'INIT_READ_REPLICA_FAILED' + | 'RESTARTING' + | 'RESIZING' + /** @enum {string} */ + type: 'PRIMARY' | 'READ_REPLICA' + }[] + /** @description When the project was created */ + inserted_at: string + /** @description Project name */ + name: string + /** @description Region the project is hosted in */ + region: string + /** + * @description Project status + * @enum {string} + */ + status: + | 'INACTIVE' + | 'ACTIVE_HEALTHY' + | 'ACTIVE_UNHEALTHY' + | 'COMING_UP' + | 'UNKNOWN' + | 'GOING_DOWN' + | 'INIT_FAILED' + | 'REMOVED' + | 'RESTORING' + | 'UPGRADING' + | 'PAUSING' + | 'RESTORE_FAILED' + | 'RESTARTING' + | 'PAUSE_FAILED' + | 'RESIZING' + } + /** + * @description Project ref + * @example abcdefghijklmnopqrst + */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'project' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organizations/my-org/projects?page[size]=10 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organizations/my-org/projects?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organizations/my-org/projects?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organizations/my-org/projects?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7 + */ + prev: string | null + } + } + V2ListRolesResponse: { + data: { + attributes: { + /** + * @description Role name. + * @example developer + */ + name: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'organization_role' + }[] + } + V2ListWorkersResponse: { + data: { + attributes: { + /** @enum {string} */ + build_state: 'building' | 'active' | 'failed' + deleting?: boolean + image_version?: string + instances?: { + declared: number + live: number + ready: number + stale: number + } + instances_error?: string + secret_generation: string + spec: { + backend?: string + /** @example public */ + exposure: string + /** @example 1 */ + instances: number + /** @example node */ + runtime?: string + /** @example 2gb-1vcpu */ + size: string + } + state_reason?: string + } + /** + * @description Worker name. + * @example hello-world + */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_worker' + }[] + } + V2PreviewProjectTransferResponse: { + data: { + attributes: { + errors: { + key: string + message: string + }[] + info: { + key: string + message: string + }[] + valid: boolean + warnings: { + key: string + message: string + }[] + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_transfer_result' + } + } + V2PrivateLinkAssociationResponse: { + data: { + attributes: { + /** @description Human-readable name for the AWS account. */ + account_name?: string + /** @description The AWS account ID this PrivateLink share is associated with. */ + aws_account_id: string + /** @description Identifier of the database this PrivateLink share targets - the project ref for the primary, or the read replica identifier. */ + database_identifier: string + /** + * @description Whether this PrivateLink share targets the primary database or a read replica. + * @enum {string} + */ + database_type: 'PRIMARY' | 'READ_REPLICA' + /** @description ARN of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_arn?: string + /** @description ID of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_id?: string + /** @description ARN of the AWS Resource Access Manager resource share for this association. */ + resource_access_manager_share_arn?: string + /** + * Format: date-time + * @description The time and date at which the AWS Resource Share Association was requested from Supabase. `null` means that the association was not yet requested while the PrivateLink Association is pending. + */ + shared_at: string | null + /** + * @description + * - `CREATING`: The PrivateLink resources and the Association are in the process of being created. The PrivateLink Share cannot be accepted yet. + * - `READY`: The PrivateLink resources have been created and the PrivateLink Share can be accepted for the duration of 12h after sharing. See `shared_at`. + * - `ASSOCIATION_REQUEST_EXPIRED`: The PrivateLink Share has not been accepted within the 12h time limit. This association can now be deleted. + * - `ASSOCIATION_ACCEPTED`: The PrivateLink Share was successfully accepted. + * - `CREATION_FAILED`: The PrivateLink resources failed to create. This likely means something went wrong on Supabase's and and support should be contacted. + * - `DELETING`: The PrivateLink resources and the Association are in the process of being deleted. The PrivateLink Share cannot be accepted yet. + * + * @enum {string} + */ + status: + | 'CREATING' + | 'READY' + | 'ASSOCIATION_REQUEST_EXPIRED' + | 'ASSOCIATION_ACCEPTED' + | 'CREATION_FAILED' + | 'DELETING' + } + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'private_link_association' + } + } + V2ProjectConfigResponse: { + data: { + attributes: { + api: { + db_extra_search_path: string + /** @description If `null`, no pool size is written to the project's PostgREST config and PostgREST's own default applies. The platform does not pick a value here. */ + db_pool: number | null + db_pool_acquisition_timeout: number + /** @description Schemas exposed through the Data API */ + db_schema: string + max_rows: number + } + /** @description Effective Auth config, keyed by lowercased GoTrue setting name and resolved through the `gotrue_config` view, so a setting the project has never overridden is reported at its platform default. Secrets are returned as an HMAC of their value, never in plaintext. */ + auth: { + [key: string]: unknown + } + database: { + network_restrictions: { + allowed_cidrs: { + address: string + /** @enum {string} */ + type: 'v4' | 'v6' + }[] + applied_at?: string + /** @enum {string} */ + entitlement: 'disallowed' | 'allowed' + /** + * @description Whether the allowlist below is applied to the project or only stored. + * @enum {string} + */ + status: 'stored' | 'applied' + updated_at?: string + } + /** @description Postgres parameter overrides. Empty when the project runs entirely on defaults. */ + postgres_settings: { + /** @description Default unit: s */ + checkpoint_timeout?: string + cron_log_statement?: boolean + effective_cache_size?: string + hot_standby_feedback?: boolean + /** @description Default unit: ms */ + log_autovacuum_min_duration?: string + log_checkpoints?: boolean + log_connections?: boolean + log_disconnections?: boolean + log_duration?: boolean + log_lock_waits?: boolean + log_recovery_conflict_waits?: boolean + log_replication_commands?: boolean + /** @description Default unit: ms */ + log_startup_progress_interval?: string + log_temp_files?: string + logical_decoding_work_mem?: string + maintenance_work_mem?: string + max_connections?: number + max_locks_per_transaction?: number + max_logical_replication_workers?: number + max_parallel_maintenance_workers?: number + max_parallel_workers?: number + max_parallel_workers_per_gather?: number + max_replication_slots?: number + max_slot_wal_keep_size?: string + max_standby_archive_delay?: string + max_standby_streaming_delay?: string + max_sync_workers_per_subscription?: number + max_wal_senders?: number + max_wal_size?: string + max_worker_processes?: number + /** @enum {string} */ + session_replication_role?: 'origin' | 'replica' | 'local' + shared_buffers?: string + /** @description Default unit: ms */ + statement_timeout?: string + track_activity_query_size?: string + track_commit_timestamp?: boolean + wal_keep_size?: string + /** @description Default unit: ms */ + wal_sender_timeout?: string + work_mem?: string + } + /** @description Whether the database rejects plaintext connections */ + ssl_enforced: boolean + } + pooler: { + /** @description Defaults to the pooler's size for the project's compute when not overridden. */ + default_pool_size: number + ignore_startup_parameters: string + /** @description Defaults to the pooler's size for the project's compute when not overridden. */ + max_client_conn: number + /** @enum {string} */ + pool_mode: 'transaction' | 'session' | 'statement' + query_wait_timeout: number + reserve_pool_size: number + server_idle_timeout: number + server_lifetime: number + } + realtime: { + /** @description Defaults to Realtime's pool size for the project's compute when not overridden. */ + connection_pool: number + max_bytes_per_second: number + max_channels_per_client: number + max_concurrent_users: number + max_events_per_second: number + max_joins_per_second: number + max_payload_size_in_kb: number + max_presence_events_per_second: number + /** @description If `null`, no override is stored and Realtime applies its own default. */ + postgres_changes_pool: number | null + presence_enabled: boolean + private_only: boolean + suspend: boolean + } + /** @description Read from the storage service's admin API rather than the middleware DB, so unlike the rest of this resource it reflects the tenant's live config. */ + storage: { + capabilities: { + iceberg_catalog: boolean + list_v2: boolean + } + database_pool_mode: string + features: { + iceberg_catalog: { + enabled: boolean + max_catalogs: number + max_namespaces: number + max_tables: number + } + image_transformation: { + enabled: boolean + } + purge_cache: { + enabled: boolean + } + s3_protocol: { + enabled: boolean + } + vector_buckets: { + enabled: boolean + max_buckets: number + max_indexes: number + } + } + /** Format: int64 */ + file_size_limit: number + migration_version: string + /** @enum {string} */ + upstream_target: 'main' | 'canary' + } + } + /** @description Project ref. */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_config' + } + } + V2TransferProjectBody: { + data: { + attributes: { + target_organization_slug: string + } + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_transfer_input' + } + } + V2WorkerResponse: { + data: { + attributes: { + /** @enum {string} */ + build_state: 'building' | 'active' | 'failed' + deleting?: boolean + image_version?: string + instances?: { + declared: number + live: number + ready: number + stale: number + } + instances_error?: string + secret_generation: string + spec: { + backend?: string + /** @example public */ + exposure: string + /** @example 1 */ + instances: number + /** @example node */ + runtime?: string + /** @example 2gb-1vcpu */ + size: string + } + state_reason?: string + } + /** + * @description Worker name. + * @example hello-world + */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_worker' + } + } + V2WorkerUploadResponse: { + data: { + attributes: { + /** @description When the slot stops accepting the upload. */ + expires_at: string + /** @example PUT */ + method: string + /** @description Presigned destination for the `.tar.gz` build context. */ + url: string + } + /** + * @description Upload id to pass to the deploy endpoint as `context_upload_id`. + * @example cafe0000000000000000000000000000 + */ + id: string + /** + * @description Resource type. + * @enum {string} + */ + type: 'project_worker_upload' + } + } + } + responses: never + parameters: never + requestBodies: never + headers: never + pathItems: never +} +export type $defs = Record +export interface operations { + postV1WebhooksEvents: { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data: { + attributes: { + /** + * @description Organization slug + * @example tsrqponmlkjihgfedcba + */ + organization_slug: string + /** @description Extra data to pass to consumers. `organization_slug` and `project_ref` (if applicable) are always provided by default. */ + payload?: { + [key: string]: unknown + } + /** @description Project's ref. If left unspecified or `null`, the event will published as organization-wide, only to organization-wide endpoints. */ + project_ref?: string | null + /** + * Format: date-time + * @description Optional timestamp of event publication. + */ + timestamp?: string + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | 'project.v1.paused' + | 'project.v1.created' + | 'project.v1.restored' + | 'project.v1.transferred' + | 'project.v1.removed' + | 'project.v1.restarted' + | 'project.v1.status.changed' + | 'project.v1.backup.started' + | 'project.v1.branch.created' + | 'project.v1.branch.updated' + | 'project.v1.branch.removed' + | 'organization.v1.member.invitation.created' + | 'organization.v1.member.invitation.canceled' + | 'organization.v1.member.added' + | 'organization.v1.member.removed' + | 'organization.v1.member.role.assigned' + | 'organization.v1.member.role.removed' + | 'organization.v1.member.role.updated' + | 'organization.v1.billing.plan.upgraded' + | 'organization.v1.billing.plan.downgraded' + | 'project.v1.branch.deleted' + } + /** + * @description Resource type. + * @constant + */ + type: 'event' + } + meta: { + /** @description Idempotency key. */ + idempotency_key: string + } + } + } + } + responses: { + /** @description Events published */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + id: string + /** + * @description Resource type. + * @constant + */ + type: 'ingress' + } + } + } + } + /** @description PermissionDenied */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'internal_server_error.event.ingress_failed' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error: Failed to ingress the event' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description TemporarilyDisabled */ + 503: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'service_unavailable.temporarily_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Service Unavailable: Temporarily disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + 'v2-list-organization-github-connections': { + parameters: { + query?: { + filter?: { + /** + * @description Project ref + * @example abcdefghijklmnopqrst + */ + project_ref?: string + } + page?: { + /** + * @description Project ref + * @example abcdefghijklmnopqrst + */ + after?: string + /** + * @description Project ref + * @example abcdefghijklmnopqrst + */ + before?: string + size?: number + } + } + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListGitHubConnectionsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-list-organization-members': { + parameters: { + query?: { + filter?: { + /** Format: email */ + primary_email?: string + username?: string + } + page?: { + /** Format: uuid */ + after?: string + /** Format: uuid */ + before?: string + size?: number + } + } + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListMembersResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-assign-organization-member-role': { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + user_id: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2AssignOrganizationMemberRoleRequest'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['OrganizationMemberRoleResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description This feature requires the Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to assign organization member role */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-create-organization-invitations': { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2CreateInvitationsRequest'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2CreateInvitationsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description This feature requires the Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-delete-organization-invitations': { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2DeleteInvitationsRequest'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2DeleteInvitationsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description This feature requires the Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-list-organization-projects': { + parameters: { + query?: { + page?: { + after?: string + before?: string + size?: number + } + /** @description Case-insensitive substring match on the project name. */ + search?: string + /** @description Sort order by creation time: `inserted_at` (oldest first) or `-inserted_at` (newest first). Defaults to `inserted_at`. */ + sort?: 'inserted_at' | '-inserted_at' + } + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListProjectsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-list-organization-roles': { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListRolesResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of a delivery (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Delivery details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of the attempt. + */ + attempt_timestamp: string + event: { + /** @description Final data sent to the consumer. */ + payload: { + /** + * @description Organization slug + * @example tsrqponmlkjihgfedcba + */ + organization_slug: string + project_ref: string | null + } & { + [key: string]: unknown + } + /** + * Format: date-time + * @description Timestamp of event publication. + */ + timestamp: string + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | 'project.v1.paused' + | 'project.v1.created' + | 'project.v1.restored' + | 'project.v1.transferred' + | 'project.v1.removed' + | 'project.v1.restarted' + | 'project.v1.status.changed' + | 'project.v1.backup.started' + | 'project.v1.branch.created' + | 'project.v1.branch.updated' + | 'project.v1.branch.removed' + | 'organization.v1.member.invitation.created' + | 'organization.v1.member.invitation.canceled' + | 'organization.v1.member.added' + | 'organization.v1.member.removed' + | 'organization.v1.member.role.assigned' + | 'organization.v1.member.role.removed' + | 'organization.v1.member.role.updated' + | 'organization.v1.billing.plan.upgraded' + | 'organization.v1.billing.plan.downgraded' + | 'project.v1.branch.deleted' + } + /** + * Format: uuid + * @description Identifier of the event, which triggered the delivery (UUID v7). + */ + event_id: string + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + response_body: + | ( + | { + [key: string]: string + } + | string + ) + | null + /** @description HTTP status code of the response, `0` if unavailable. */ + response_code: number + /** @description HTTP headers of the response, `{}` if unavailable. */ + response_headers: { + [key: string]: string + } | null + /** + * @description Status of the delivery attempt. + * @enum {string} + */ + status: 'pending' | 'success' | 'failure' | 'skipped' + } + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'delivery' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description DeliveryNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.delivery' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Delivery not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of a delivery (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Delivery details */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + id: string + /** + * @description Resource type. + * @constant + */ + type: 'ingress' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description DeliveryNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.delivery' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Delivery not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: { + /** @description Up to how many records to return. */ + 'page[limit]'?: string + /** @description Offset for offset-based pagination. + * + * Offset should be dividable by `page[limit]` without a reminder (`offset % limit === 0`), otherwise it will cause weird behavior when used on a frontend. */ + 'page[offset]'?: string + } + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Collection of endpoints */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=30 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0 + */ + prev: string | null + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data: { + attributes: { + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description?: string | null + /** + * @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. + * @default true + */ + enabled?: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** @description Secret key to use when signing. All events will be signed according to the [Standard Webhooks](https://www.standardwebhooks.com/) specification. */ + signing_secret: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + responses: { + /** @description Created endpoint */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Deleted endpoints */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + }[] + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Deleted endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data: { + attributes: { + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description?: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled?: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types?: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** @description Secret key to use when signing. All events will be signed according to the [Standard Webhooks](https://www.standardwebhooks.com/) specification. */ + signing_secret?: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url?: string + } + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + responses: { + /** @description Updated endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: { + /** @description Cursor in cursor-based pagination to return up to `page[size]` records after (exclusive) the entry specified by this query param. */ + 'page[after]'?: string + /** @description Cursor in cursor-based pagination to return up to `page[size]` records before (exclusive) the entry specified by this query param. */ + 'page[before]'?: string + /** @description Up to how many records to return. */ + 'page[size]'?: string + } + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description List of deliveries */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of the attempt. + */ + attempt_timestamp: string + /** + * Format: uuid + * @description Identifier of the event, which triggered the delivery (UUID v7). + */ + event_id: string + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + response_body: + | ( + | { + [key: string]: string + } + | string + ) + | null + /** @description HTTP status code of the response, `0` if unavailable. */ + response_code: number + /** @description HTTP headers of the response, `{}` if unavailable. */ + response_headers: { + [key: string]: string + } | null + /** + * @description Status of the delivery attempt. + * @enum {string} + */ + status: 'pending' | 'success' | 'failure' | 'skipped' + } + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'delivery' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7 + */ + prev: string | null + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2OrganizationsBySlugWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data?: { + attributes: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | 'project.v1.paused' + | 'project.v1.created' + | 'project.v1.restored' + | 'project.v1.transferred' + | 'project.v1.removed' + | 'project.v1.restarted' + | 'project.v1.status.changed' + | 'project.v1.backup.started' + | 'project.v1.branch.created' + | 'project.v1.branch.updated' + | 'project.v1.branch.removed' + | 'organization.v1.member.invitation.created' + | 'organization.v1.member.invitation.canceled' + | 'organization.v1.member.added' + | 'organization.v1.member.removed' + | 'organization.v1.member.role.assigned' + | 'organization.v1.member.role.removed' + | 'organization.v1.member.role.updated' + | 'organization.v1.billing.plan.upgraded' + | 'organization.v1.billing.plan.downgraded' + | 'project.v1.branch.deleted' + } + /** + * @description Resource type. + * @constant + */ + type: 'event' + } + } + } + } + responses: { + /** @description Event published */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + id: string + /** + * @description Resource type. + * @constant + */ + type: 'ingress' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.endpoint.test.disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Endpoint is disabled' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.endpoint.test.wrong_event_type' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Provided event type is not subscribed to by the endpoint' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + 'v2-list-log-drains': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ListLogDrainsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to fetch log drains */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-create-log-drain': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['CreateLogDrainRequestOpenApi'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['LogDrainResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to create a log drain */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-update-log-drain': { + parameters: { + query?: never + header?: never + path: { + /** @description Log drains identifier */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['UpdateLogDrainRequestOpenApi'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['LogDrainResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to update log drain */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-delete-log-drain': { + parameters: { + query?: never + header?: never + path: { + /** @description Log drains identifier */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to delete a log drain */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-get-project-config': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ProjectConfigResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-list-private-link-associations': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListPrivateLinkAssociationsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to retrieve AWS accounts for project */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-create-private-link-association': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2CreatePrivateLinkAssociationRequest'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2PrivateLinkAssociationResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description This feature requires the Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to add AWS account to PrivateLink share */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-delete-private-link-association': { + parameters: { + query?: never + header?: never + path: { + /** @description AWS account ID used in PrivateLink association */ + aws_account_id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to remove AWS account from PrivateLink share */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-delete-private-link-association-for-database': { + parameters: { + query?: never + header?: never + path: { + /** @description AWS account ID used in PrivateLink association */ + aws_account_id: string + /** @description Identifier of the read replica this PrivateLink association targets */ + database_identifier: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Failed to remove AWS account from PrivateLink share */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-transfer-a-project': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2TransferProjectBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-preview-a-project-transfer': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2TransferProjectBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2PreviewProjectTransferResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of a delivery (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Delivery details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of the attempt. + */ + attempt_timestamp: string + event: { + /** @description Final data sent to the consumer. */ + payload: { + /** + * @description Organization slug + * @example tsrqponmlkjihgfedcba + */ + organization_slug: string + project_ref: string | null + } & { + [key: string]: unknown + } + /** + * Format: date-time + * @description Timestamp of event publication. + */ + timestamp: string + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | 'project.v1.paused' + | 'project.v1.created' + | 'project.v1.restored' + | 'project.v1.transferred' + | 'project.v1.removed' + | 'project.v1.restarted' + | 'project.v1.status.changed' + | 'project.v1.backup.started' + | 'project.v1.branch.created' + | 'project.v1.branch.updated' + | 'project.v1.branch.removed' + | 'organization.v1.member.invitation.created' + | 'organization.v1.member.invitation.canceled' + | 'organization.v1.member.added' + | 'organization.v1.member.removed' + | 'organization.v1.member.role.assigned' + | 'organization.v1.member.role.removed' + | 'organization.v1.member.role.updated' + | 'organization.v1.billing.plan.upgraded' + | 'organization.v1.billing.plan.downgraded' + | 'project.v1.branch.deleted' + } + /** + * Format: uuid + * @description Identifier of the event, which triggered the delivery (UUID v7). + */ + event_id: string + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + response_body: + | ( + | { + [key: string]: string + } + | string + ) + | null + /** @description HTTP status code of the response, `0` if unavailable. */ + response_code: number + /** @description HTTP headers of the response, `{}` if unavailable. */ + response_headers: { + [key: string]: string + } | null + /** + * @description Status of the delivery attempt. + * @enum {string} + */ + status: 'pending' | 'success' | 'failure' | 'skipped' + } + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'delivery' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description DeliveryNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.delivery' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Delivery not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of a delivery (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Delivery details */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + id: string + /** + * @description Resource type. + * @constant + */ + type: 'ingress' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description DeliveryNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.delivery' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Delivery not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: { + /** @description Up to how many records to return. */ + 'page[limit]'?: string + /** @description Offset for offset-based pagination. + * + * Offset should be dividable by `page[limit]` without a reminder (`offset % limit === 0`), otherwise it will cause weird behavior when used on a frontend. */ + 'page[offset]'?: string + } + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Collection of endpoints */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=30 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0 + */ + prev: string | null + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data: { + attributes: { + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description?: string | null + /** + * @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. + * @default true + */ + enabled?: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** @description Secret key to use when signing. All events will be signed according to the [Standard Webhooks](https://www.standardwebhooks.com/) specification. */ + signing_secret: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + responses: { + /** @description Created endpoint */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Deleted endpoints */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + }[] + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Deleted endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data: { + attributes: { + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description?: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled?: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types?: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** @description Secret key to use when signing. All events will be signed according to the [Standard Webhooks](https://www.standardwebhooks.com/) specification. */ + signing_secret?: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url?: string + } + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + responses: { + /** @description Updated endpoint details */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of endpoint's creation. + */ + created_at: string + /** + * Format: uuid + * @description ID of the user who created the endpoint. + */ + created_by: string + /** + * @description Additional request headers to pass when performing HTTP request location defined by `url`. Both keys and values must be strings and a valid HTTP headers. + * @example { + * "Authorization": "Bearer example_token" + * } + */ + custom_headers?: { + [key: string]: string + } | null + /** @description Optional description for the endpoint. */ + description: string | null + /** @description Whether the endpoint is enabled or not - disabled endpoints won't emit any events. */ + enabled: boolean + /** + * @description List of subscribed events for which to receive the webhook event. + * @example [ + * { + * "type": "v1.project.paused" + * } + * ] + */ + event_types: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | '*' + }[] + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * Format: uri + * @description Publicly available URL where to send the events, must use a domain and be resolvable to a non-reserved IP address. + * @example https://mydomain.com/path/to/handler + */ + url: string + } + /** + * Format: uuid + * @description Identifier of an endpoint (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'endpoint' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: { + /** @description Cursor in cursor-based pagination to return up to `page[size]` records after (exclusive) the entry specified by this query param. */ + 'page[after]'?: string + /** @description Cursor in cursor-based pagination to return up to `page[size]` records before (exclusive) the entry specified by this query param. */ + 'page[before]'?: string + /** @description Up to how many records to return. */ + 'page[size]'?: string + } + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description List of deliveries */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + attributes: { + /** + * Format: date-time + * @description Timestamp of the attempt. + */ + attempt_timestamp: string + /** + * Format: uuid + * @description Identifier of the event, which triggered the delivery (UUID v7). + */ + event_id: string + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + response_body: + | ( + | { + [key: string]: string + } + | string + ) + | null + /** @description HTTP status code of the response, `0` if unavailable. */ + response_code: number + /** @description HTTP headers of the response, `{}` if unavailable. */ + response_headers: { + [key: string]: string + } | null + /** + * @description Status of the delivery attempt. + * @enum {string} + */ + status: 'pending' | 'success' | 'failure' | 'skipped' + } + /** + * Format: uuid + * @description Identifier of a delivery (UUID v7). + */ + id: string + /** + * @description Resource type. + * @constant + */ + type: 'delivery' + }[] + links: { + /** + * @description URL path to the first page if available. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10 + */ + first?: string | null + /** + * @description URL path to the last page if available. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295 + */ + last?: string | null + /** + * @description URL path to the next page. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4 + */ + next: string | null + /** + * @description URL path to the previous page. + * @example /v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7 + */ + prev: string | null + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + allV2ProjectsByRefWebhooks: { + parameters: { + query?: never + header?: never + path: { + /** @description Identifier of an endpoint (UUID v7). */ + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': { + data?: { + attributes: { + /** + * @description Webhook event type. + * @enum {string} + */ + type: + | 'v1.project.paused' + | 'v1.project.created' + | 'v1.project.restored' + | 'v1.project.transferred' + | 'v1.project.removed' + | 'v1.project.restarted' + | 'v1.project.status.changed' + | 'v1.project.backup.started' + | 'v1.project.branch.created' + | 'v1.project.branch.updated' + | 'v1.project.branch.removed' + | 'v1.organization.member.invitation.created' + | 'v1.organization.member.invitation.canceled' + | 'v1.organization.member.added' + | 'v1.organization.member.removed' + | 'v1.organization.member.role.assigned' + | 'v1.organization.member.role.removed' + | 'v1.organization.member.role.updated' + | 'v1.organization.billing.plan.upgraded' + | 'v1.organization.billing.plan.downgraded' + | 'project.v1.paused' + | 'project.v1.created' + | 'project.v1.restored' + | 'project.v1.transferred' + | 'project.v1.removed' + | 'project.v1.restarted' + | 'project.v1.status.changed' + | 'project.v1.backup.started' + | 'project.v1.branch.created' + | 'project.v1.branch.updated' + | 'project.v1.branch.removed' + | 'organization.v1.member.invitation.created' + | 'organization.v1.member.invitation.canceled' + | 'organization.v1.member.added' + | 'organization.v1.member.removed' + | 'organization.v1.member.role.assigned' + | 'organization.v1.member.role.removed' + | 'organization.v1.member.role.updated' + | 'organization.v1.billing.plan.upgraded' + | 'organization.v1.billing.plan.downgraded' + | 'project.v1.branch.deleted' + } + /** + * @description Resource type. + * @constant + */ + type: 'event' + } + } + } + } + responses: { + /** @description Event published */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + data: { + id: string + /** + * @description Resource type. + * @constant + */ + type: 'ingress' + } + } + } + } + /** @description Multiple error responses */ + 400: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'bad_request.endpoint.test.disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Endpoint is disabled' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.endpoint.test.wrong_event_type' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Provided event type is not subscribed to by the endpoint' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_slug' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid organization slug' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'bad_request.invalid_ref' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Bad Request: Invalid project ref' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericUnauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'unauthorized' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Unauthorized' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description Multiple error responses */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: + | { + /** @constant */ + code: 'forbidden.permission_denied' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Permission denied' + meta?: { + [key: string]: unknown + } + } + | { + /** @constant */ + code: 'forbidden.access_disabled' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Forbidden: Access disabled' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description EndpointNotFound */ + 404: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'not_found.endpoint' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Not Found: Endpoint not found' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericRequestTimeout */ + 408: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'request_timeout' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Request Timeout' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericTooManyRequests */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'too_many_requests' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Too Many Requests' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + /** @description GenericInternalServerError */ + 500: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': { + error: { + /** @constant */ + code: 'internal_server_error' + description?: string + id?: string + issues?: components['schemas']['APIErrorObject'][] + links?: { + [key: string]: { + describedby?: string + href: string + meta?: { + [key: string]: unknown + } + rel?: string + title?: string + type?: string + } + } + /** @constant */ + message: 'Internal Server Error' + meta?: { + [key: string]: unknown + } + } + $defs: { + APIErrorObject: components['schemas']['APIErrorObject'] + } + } + } + } + } + } + 'v2-list-all-workers': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2ListWorkersResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-get-a-worker': { + parameters: { + query?: never + header?: never + path: { + name: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2WorkerResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-delete-a-worker': { + parameters: { + query?: never + header?: never + path: { + name: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-deploy-a-worker': { + parameters: { + query?: never + header?: never + path: { + name: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V2DeployWorkerRequest'] + } + } + responses: { + 202: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2WorkerResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } + 'v2-create-worker-upload': { + parameters: { + query?: never + header?: never + path: { + name: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V2WorkerUploadResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ErrorResponseBody'] + } + } + } + } +} diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index 622b9dd1b784a..5b5b673b49555 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -520,23 +520,6 @@ export interface paths { patch?: never trace?: never } - '/platform/feedback/docs': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - get?: never - put?: never - /** Send feedback on docs */ - post: operations['SendFeedbackController_sendDocsFeedback'] - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } '/platform/feedback/downgrade': { parameters: { query?: never @@ -683,6 +666,26 @@ export interface paths { patch: operations['GitHubConnectionsController_updateGitHubConnection'] trace?: never } + '/platform/integrations/github/connections/{connection_id}/config': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Gets the Supabase config of a connected GitHub repository + * @description Reads `supabase/config.toml` from the workdir of the connected repository and returns it as JSON. + */ + get: operations['GitHubConnectionsController_getGitHubConnectionConfig'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/platform/integrations/github/repositories': { parameters: { query?: never @@ -1984,11 +1987,9 @@ export interface paths { } /** Gets the given organization's tax ID */ get: operations['TaxIdsController_getTaxId'] - /** Creates or updates a tax ID for the given organization */ - put: operations['TaxIdsController_updateTaxId'] + put?: never post?: never - /** Delete the tax ID with the given ID */ - delete: operations['TaxIdsController_deleteTaxId'] + delete?: never options?: never head?: never patch?: never @@ -2592,6 +2593,24 @@ export interface paths { patch?: never trace?: never } + '/platform/projects/{ref}/analytics/endpoints/logs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Gets project's logs from the unified logs stream */ + get: operations['LogsController_getProjectLogsViaGetNew'] + put?: never + /** Gets project's logs from the unified logs stream */ + post: operations['LogsController_getProjectLogsViaPostNew'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/platform/projects/{ref}/analytics/endpoints/logs.all': { parameters: { query?: never @@ -2599,10 +2618,16 @@ export interface paths { path?: never cookie?: never } - /** Gets project's logs */ + /** + * Gets project's logs from legacy logs tables + * @deprecated + */ get: operations['LogsController_getProjectLogsViaGet'] put?: never - /** Gets project's logs */ + /** + * Gets project's logs from legacy logs tables + * @deprecated + */ post: operations['LogsController_getProjectLogsViaPost'] delete?: never options?: never @@ -2617,10 +2642,16 @@ export interface paths { path?: never cookie?: never } - /** Gets project's logs from the ClickHouse-backed endpoint */ + /** + * Gets project's logs from the unified logs stream + * @deprecated + */ get: operations['LogsController_getProjectLogsOtelViaGet'] put?: never - /** Gets project's logs from the ClickHouse-backed endpoint */ + /** + * Gets project's logs from the unified logs stream + * @deprecated + */ post: operations['LogsController_getProjectLogsOtelViaPost'] delete?: never options?: never @@ -2767,6 +2798,26 @@ export interface paths { patch?: never trace?: never } + '/platform/projects/{ref}/analytics/metrics': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * Scrape a project's metrics + * @description Prometheus scrape endpoint. Returns metrics of a customer project in the Prometheus open exposition format. Replaces `/customer/v1/privileged/metrics`. + */ + get: operations['scrape-project-metrics'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/platform/projects/{ref}/api-keys/temporary': { parameters: { query?: never @@ -3394,7 +3445,7 @@ export interface paths { post?: never /** * Remove AWS account from PrivateLink share for the project - * @description Removes an AWS account from the project's PrivateLink configuration. Cleans up associated AWS resources. + * @description Removes an AWS account from the project's PrivateLink configuration (targeting the primary database). Cleans up associated AWS resources. */ delete: operations['ProjectPrivateLinkController_removeAwsAccountFromPrivateLink'] options?: never @@ -3402,6 +3453,26 @@ export interface paths { patch?: never trace?: never } + '/platform/projects/{ref}/privatelink/associations/aws-account/{aws_account_id}/database/{database_identifier}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + post?: never + /** + * Remove AWS account from a specific database PrivateLink share for the project + * @description Removes an AWS account from the project's PrivateLink configuration for the given read replica. Cleans up associated AWS resources. + */ + delete: operations['ProjectPrivateLinkController_removeAwsAccountFromPrivateLinkForDatabase'] + options?: never + head?: never + patch?: never + trace?: never + } '/platform/projects/{ref}/resize': { parameters: { query?: never @@ -3504,57 +3575,6 @@ export interface paths { patch?: never trace?: never } - '/platform/projects/{ref}/run-lints/{name}': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Run project lint by name */ - get: operations['ProjectRunLintsController_runLintByName'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } - '/platform/projects/{ref}/run-lints/leaked-service-key': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Run project leaked service key lint */ - get: operations['ProjectRunLintsController_runLeakedServiceKeyLint'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } - '/platform/projects/{ref}/run-lints/no-backup-admin': { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - /** Run project backup admin lint */ - get: operations['ProjectRunLintsController_runAuthBackupAdminLint'] - put?: never - post?: never - delete?: never - options?: never - head?: never - patch?: never - trace?: never - } '/platform/projects/{ref}/service-versions': { parameters: { query?: never @@ -4104,7 +4124,7 @@ export interface paths { } /** * Estimate replication cost for a publication - * @description Estimate the cost of replicating a publication's tables. Returns the flat per-pipeline fee, a per-table breakdown of the one-time initial-copy cost derived from the tables’ on-disk size, and the usage-based streaming rate. Requires bearer auth and an active, healthy project. + * @description Estimate the cost of replicating a publication's tables. Returns the hourly (and projected monthly) per-pipeline fee, a per-table breakdown of the one-time initial-copy cost derived from the tables’ on-disk size, and the usage-based streaming rate. Requires bearer auth and an active, healthy project. */ get: operations['ReplicationSourcesController_getCostEstimate'] put?: never @@ -4539,6 +4559,40 @@ export interface paths { patch?: never trace?: never } + '/platform/storage/{ref}/cdn/purge-bucket': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Purges CDN cache for an entire bucket */ + post: operations['StorageCdnController_purgeBucketCache'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/storage/{ref}/cdn/purge-object': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + get?: never + put?: never + /** Purges CDN cache for a single object */ + post: operations['StorageCdnController_purgeObjectCache'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/platform/storage/{ref}/credentials': { parameters: { query?: never @@ -4903,90 +4957,220 @@ export interface paths { patch?: never trace?: never } - '/platform/workflow-runs': { + '/platform/warehouse/{ref}/catalog': { parameters: { query?: never header?: never path?: never cookie?: never } - /** Get a list of workflow runs */ - get: operations['WorkflowRunController_listWorkflowRuns'] + /** + * Get Warehouse catalog access + * @description Return whether external Warehouse catalog access is enabled and credentials when enabled. + */ + get: operations['WarehouseController_getCatalog'] put?: never - post?: never + /** + * Update Warehouse catalog access + * @description Enable or disable external Warehouse catalog access for the project. + */ + post: operations['WarehouseController_updateCatalog'] delete?: never options?: never head?: never patch?: never trace?: never } - '/platform/workflow-runs/{workflow_run_id}/logs': { + '/platform/warehouse/{ref}/refresh-schema': { parameters: { query?: never header?: never path?: never cookie?: never } - /** Get the logs of a workflow run */ - get: operations['WorkflowRunController_getWorkflowRunLogs'] + get?: never put?: never - post?: never + /** + * Refresh the Warehouse foreign schema + * @description Reinstall the project Warehouse FDW schema asynchronously without restarting replication or waiting for a table copy. + */ + post: operations['WarehouseController_refreshSchema'] delete?: never options?: never head?: never patch?: never trace?: never } -} -export type webhooks = Record -export interface components { - schemas: { - AccessControlPermission: { - actions: string[] | null - condition: - | ( - | string - | number - | boolean - | unknown[] - | { - [key: string]: unknown - } - ) - | null - organization_id: number | null - organization_slug: string - project_ids: number[] | null - project_refs: string[] | null - resources: string[] | null - restrictive: boolean | null + '/platform/warehouse/{ref}/setup-status': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never } - AccessToken: { - created_at: string - expires_at: string | null - id: number - last_used_at: string | null - name: string - /** @enum {string} */ - scope?: 'V0' - token_alias: string + /** + * Get Warehouse setup status + * @description Return the async Warehouse setup status for the project. Overall completion follows the replication pipeline and table copy state; project database FDW markers are informational. + */ + get: operations['WarehouseController_getSetupStatus'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/warehouse/{ref}/tables': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never } - AccountRequestDetailsDto: { - email: string - email_matches: boolean - expires_at: string - id: string - linked_organization?: { - id: number - name: string - slug: string - } - /** @enum {string} */ - status: 'pending' | 'complete' | 'expired' | 'error' + /** + * List Warehouse linked tables + * @description List tables copied to Warehouse for the project. Requires bearer auth and an active, healthy project. + */ + get: operations['WarehouseController_getTables'] + put?: never + /** + * Copy a table to Warehouse + * @description Ensure the project Warehouse pipeline exists, add the table to its publication, and start syncing. Warehouse FDW installation is opt-in. + */ + post: operations['WarehouseController_linkTable'] + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/warehouse/{ref}/tables/{schema}/{name}': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never } - AddAwsAccountToPrivateLinkBody: { - account_name?: string + get?: never + put?: never + post?: never + /** + * Detach a table from Warehouse + * @description Remove the table from the Warehouse publication so it stops syncing. Existing DuckLake data is left in place. + */ + delete: operations['WarehouseController_detachTable'] + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/warehouse/{ref}/tables/{schema}/{name}/snapshots': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** + * List Warehouse snapshots for a table + * @description Return available DuckLake snapshots for a Warehouse-linked table. The snapshots are read from the Warehouse FDW in the project database. + */ + get: operations['WarehouseController_getTableSnapshots'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/workflow-runs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Get a list of workflow runs */ + get: operations['WorkflowRunController_listWorkflowRuns'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } + '/platform/workflow-runs/{workflow_run_id}/logs': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Get the logs of a workflow run */ + get: operations['WorkflowRunController_getWorkflowRunLogs'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } +} +export type webhooks = Record +export interface components { + schemas: { + AccessControlPermission: { + actions: string[] | null + condition: + | ( + | string + | number + | boolean + | unknown[] + | { + [key: string]: unknown + } + ) + | null + organization_id: number | null + organization_slug: string + project_ids: number[] | null + project_refs: string[] | null + resources: string[] | null + restrictive: boolean | null + } + AccessToken: { + created_at: string + expires_at: string | null + id: number + last_used_at: string | null + name: string + /** @enum {string} */ + scope?: 'V0' + token_alias: string + } + AccountRequestDetailsDto: { + email: string + email_matches: boolean + expires_at: string + id: string + linked_organization?: { + id: number + name: string + slug: string + } + /** @enum {string} */ + status: 'pending' | 'complete' | 'expired' | 'error' + } + AddAwsAccountToPrivateLinkBody: { + account_name?: string aws_account_id: string + /** @description Identifier of the read replica this PrivateLink share should target. Omit to target the primary database. */ + database_identifier?: string } AnalyticsResponse: { error?: @@ -5020,6 +5204,9 @@ export interface components { } method: string name: string + params?: { + [key: string]: unknown + } route: string status: number } @@ -5027,10 +5214,24 @@ export interface components { app_id?: string app_name?: string email?: string + /** @description Only present when token_type=app */ + installation_id?: string ip?: string + /** @description JWT issuer. Only present for branching service JWTs */ + jwt_issuer?: string + /** @description JWT subject. Only present for branching service JWTs */ + jwt_subject?: string oauth_app_id?: string oauth_app_name?: string + /** @description Organization whose grant was used. Only present when token_type=oauth */ + organization_id?: string + /** @description GoTrue login session. Only present when token_type=jwt */ + session_id?: string + /** @description Access token alias, as shown in the dashboard. Only present when token_type=v0, token_type=v1 or token_type=scoped_pat */ + token_alias?: string token_hash?: string + /** @description Only present when token_type=scoped_pat */ + token_scope?: string token_type: string user_id?: string } @@ -5041,60 +5242,6 @@ export interface components { }[] retention_period: number } - AuthBackupAdminLintResponse: { - lints: { - cache_key: string - categories: ('PERFORMANCE' | 'SECURITY')[] - description: string - detail: string - /** @enum {string} */ - facing: 'EXTERNAL' - /** @enum {string} */ - level: 'ERROR' | 'WARN' | 'INFO' - metadata?: { - entity?: string - fkey_columns?: number[] - fkey_name?: string - name?: string - schema?: string - /** @enum {string} */ - type?: 'table' | 'view' | 'auth' | 'function' | 'extension' | 'compliance' - } - /** @enum {string} */ - name: - | 'unindexed_foreign_keys' - | 'auth_users_exposed' - | 'auth_rls_initplan' - | 'no_primary_key' - | 'unused_index' - | 'multiple_permissive_policies' - | 'policy_exists_rls_disabled' - | 'rls_enabled_no_policy' - | 'duplicate_index' - | 'security_definer_view' - | 'function_search_path_mutable' - | 'rls_disabled_in_public' - | 'extension_in_public' - | 'rls_references_user_metadata' - | 'materialized_view_in_api' - | 'foreign_table_in_api' - | 'unsupported_reg_types' - | 'auth_otp_long_expiry' - | 'auth_otp_short_length' - | 'ssl_not_enforced' - | 'network_restrictions_not_set' - | 'password_requirements_min_length' - | 'pitr_not_enabled' - | 'auth_leaked_password_protection' - | 'auth_insufficient_mfa_options' - | 'auth_password_policy_missing' - | 'leaked_service_key' - | 'no_backup_admin' - | 'vulnerable_postgres_version' - remediation: string - title: string - }[] - } BackendConnectionTest: { 'connected?': boolean reason: string @@ -5131,7 +5278,7 @@ export interface components { clear_tax_id?: true dry_run?: boolean tax_id?: { - country?: string + country: string type: string value: string } @@ -5220,6 +5367,81 @@ export interface components { CopyObjectResponse: { path: string } + CostEstimateResponse: { + /** + * @description Currency of all amounts + * @example usd + * @enum {string} + */ + currency: 'usd' + /** @description Recurring per-pipeline cost */ + pipeline: { + /** + * @description Hourly rate charged per active pipeline + * @example 0.053 + */ + hourly_cost: number + /** + * @description Projected monthly cost for an active pipeline, based on an average 730-hour month. Pipelines are billed hourly, so this is an estimate, not a metered amount. + * @example 38.69 + */ + monthly_cost: number + } + /** @description Usage-based streaming cost, expressed as a rate */ + streaming: { + /** + * @description Usage-based streaming rate per GB. Actual cost depends on the change volume. + * @example 3 + */ + rate_per_gb: number + } + /** @description One-time cost for the initial table copy */ + table_copy: { + /** + * @description One-time initial-copy rate per GB + * @example 0.6 + */ + rate_per_gb: number + /** @description Per-table initial-copy cost estimate */ + tables: { + /** + * @description Estimated on-disk size of the table in bytes + * @example 10960896 + */ + estimated_bytes: number + /** + * @description Estimated one-time initial-copy cost for the table, in the response currency + * @example 0.01 + */ + estimated_cost: number + /** + * @description Whether this table has a row filter. The estimate does not account for how many rows the filter excludes, so the actual replicated volume may be lower than shown. + * @example false + */ + is_row_filtered: boolean + /** + * @description Table name + * @example orders + */ + name: string + /** + * @description Table schema + * @example public + */ + schema: string + }[] + /** + * @description Total estimated bytes across all tables + * @example 11911168 + */ + total_bytes: number + /** + * @description Total estimated one-time initial-copy cost + * @example 0.01 + */ + total_cost: number + } + } CreateAccessTokenBody: { /** Format: date-time */ expires_at?: string @@ -5389,12 +5611,7 @@ export interface components { workdir: string } CreateInvitationBody: { - /** - * Format: email - * @deprecated - */ - email?: string - emails?: string[] + emails: string[] require_sso?: boolean role_id: number role_scoped_projects?: string[] @@ -5566,7 +5783,7 @@ export interface components { payment_method?: string size?: string tax_id?: { - country?: string + country: string type: string value: string } @@ -5579,37 +5796,6 @@ export interface components { | 'tier_enterprise' | 'tier_platform' } - CreateOrganizationResponse: - | { - pending_payment_intent_secret: string | null - } - | { - billing_email: string | null - /** @enum {string|null} */ - billing_partner: 'fly' | 'aws_marketplace' | 'vercel_marketplace' | null - id: number - integration_source: string | null - is_owner: boolean - name: string - opt_in_tags: string[] - organization_missing_address: boolean - organization_missing_tax_id: boolean - organization_requires_mfa: boolean - plan: { - /** @enum {string} */ - id: 'free' | 'pro' | 'team' | 'enterprise' | 'platform' - name: string - } - restriction_data: { - [key: string]: string - } | null - /** @enum {string|null} */ - restriction_status: 'grace_period' | 'grace_period_over' | 'restricted' | null - slug: string - stripe_customer_id: string | null - subscription_id: string | null - usage_billing_enabled: boolean - } CreatePipelineResponse: { /** * @description Pipeline id @@ -5631,6 +5817,8 @@ export interface components { | 'members_write' | 'organization_projects_read' | 'organization_projects_create' + | 'platform_webhooks_organization_read' + | 'platform_webhooks_organization_write' | 'project_admin_read' | 'project_admin_write' | 'action_runs_read' @@ -5700,6 +5888,10 @@ export interface components { | 'storage_config_write' | 'vanity_subdomain_read' | 'vanity_subdomain_write' + | 'platform_webhooks_projects_read' + | 'platform_webhooks_projects_write' + | 'workers_read' + | 'workers_write' )[] } CreatePlatformAppResponse: { @@ -5728,9 +5920,9 @@ export interface components { CreateProjectBody: { auth_site_url?: string /** @enum {string} */ - cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + cloud_provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' custom_supabase_internal_requests?: { - ami: { + ami?: { /** * @description Exact AWS instance type to provision (e.g. `t3.nano`, `t4g.nano`). Hard pin — no ODCR fallback. Only for internal use; rejected for user-facing requests in production. * @enum {string} @@ -5740,16 +5932,68 @@ export interface components { | 't3a.nano' | 't3.nano' | 't4g.micro' + | 't3a.micro' + | 't3.micro' | 't4g.small' + | 't3a.small' + | 't3.small' | 't4g.medium' + | 't3a.medium' + | 't3.medium' | 'm6g.medium' + | 'm7g.medium' + | 'm8g.medium' + | 'm9g.medium' + | 'c6g.medium' | 'm6g.large' + | 'm6a.large' + | 'm6i.large' + | 'm7i.large' + | 'm8i.large' + | 'm7a.large' + | 'm8a.large' | 'm6g.xlarge' + | 'm6a.xlarge' + | 'm6i.xlarge' + | 'm7i.xlarge' + | 'm8i.xlarge' + | 'm7a.xlarge' + | 'm8a.xlarge' | 'm6g.2xlarge' + | 'm6a.2xlarge' + | 'm6i.2xlarge' + | 'm7i.2xlarge' + | 'm8i.2xlarge' + | 'm7a.2xlarge' + | 'm8a.2xlarge' | 'm6g.4xlarge' + | 'm6a.4xlarge' + | 'm6i.4xlarge' + | 'm7i.4xlarge' + | 'm8i.4xlarge' + | 'm7a.4xlarge' + | 'm8a.4xlarge' | 'm6g.8xlarge' + | 'm6a.8xlarge' + | 'm6i.8xlarge' + | 'm7i.8xlarge' + | 'm8i.8xlarge' + | 'm7a.8xlarge' + | 'm8a.8xlarge' | 'm6g.12xlarge' + | 'm6a.12xlarge' + | 'm6i.12xlarge' + | 'm7i.12xlarge' + | 'm8i.12xlarge' + | 'm7a.12xlarge' + | 'm8a.12xlarge' | 'm6g.16xlarge' + | 'm6a.16xlarge' + | 'm6i.16xlarge' + | 'm7i.16xlarge' + | 'm8i.16xlarge' + | 'm7a.16xlarge' + | 'm8a.16xlarge' | 'm8g.24xlarge' | 'c8g.24xlarge' | 'r8g.24xlarge' @@ -5767,6 +6011,26 @@ export interface components { [key: string]: string } } + warehouse_fdw?: { + /** @description AWS ACM Private CA ARN used by the worker to issue per-project warehouse FDW client certificates. Defaults to the worker environment configuration when omitted. */ + client_certificate_authority_arn?: string + /** @description Optional URI SAN to place in the issued client certificate. Defaults to spiffe://supabase//postgres//. */ + client_certificate_identity_uri?: string + client_certificate_ttl_days?: number + connect_timeout_ms?: number + enabled?: boolean + endpoint: string + jwt_audience?: string + jwt_issuer?: string + jwt_kid: string + jwt_ttl_secs?: number + request_timeout_ms?: number + /** @description Optional legacy input. The platform derives the runtime AWS Secrets Manager prefix from the project ref as warehouse-fdw/. */ + secret_prefix?: string + secret_region?: string + stream_idle_timeout_ms?: number + tls_domain_name?: string + } } data_api_exposed_schemas?: string[] data_api_revoke_default_privileges?: boolean @@ -5815,7 +6079,29 @@ export interface components { /** @description Provider region selection. Only one of db_region or region_selection can be specified. */ region_selection?: | { - code: string + /** + * @description The selected region code must be valid for the specified cloud provider. + * @enum {string} + */ + code: + | 'us-east-1' + | 'us-east-2' + | 'us-west-1' + | 'us-west-2' + | 'ap-east-1' + | 'ap-southeast-1' + | 'ap-northeast-1' + | 'ap-northeast-2' + | 'ap-southeast-2' + | 'eu-west-1' + | 'eu-west-2' + | 'eu-west-3' + | 'eu-north-1' + | 'eu-central-1' + | 'eu-central-2' + | 'ca-central-1' + | 'ap-south-1' + | 'sa-east-1' /** @enum {string} */ type: 'specific' } @@ -6167,7 +6453,7 @@ export interface components { private_key_passphrase?: string | null /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string | null /** @@ -6177,7 +6463,7 @@ export interface components { schema: string /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user: string } @@ -6479,7 +6765,7 @@ export interface components { private_key_passphrase?: string | null /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string | null /** @@ -6489,7 +6775,7 @@ export interface components { schema: string /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user: string } @@ -6530,7 +6816,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -6605,7 +6891,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Source id @@ -6645,7 +6931,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -6720,7 +7006,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Destination id @@ -6769,6 +7055,8 @@ export interface components { | 'members_write' | 'organization_projects_read' | 'organization_projects_create' + | 'platform_webhooks_organization_read' + | 'platform_webhooks_organization_write' | 'project_admin_read' | 'project_admin_write' | 'action_runs_read' @@ -6838,6 +7126,10 @@ export interface components { | 'storage_config_write' | 'vanity_subdomain_read' | 'vanity_subdomain_write' + | 'platform_webhooks_projects_read' + | 'platform_webhooks_projects_write' + | 'workers_read' + | 'workers_write' )[] project_refs?: string[] } @@ -6891,46 +7183,13 @@ export interface components { metadata_xml_url: string user_name_mapping?: string[] } - CreateSSOProviderResponse: - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file: string - /** Format: uri */ - metadata_xml_url?: string - user_name_mapping?: string[] - } - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file?: string - metadata_xml_url: string - user_name_mapping?: string[] - } CreateStorageAnalyticsBucketBody: { bucketName: string } CreateStorageBucketBody: { allowed_mime_types?: string[] file_size_limit?: number + /** @description Storage bucket id */ id: string public: boolean /** @enum {string} */ @@ -6948,11 +7207,6 @@ export interface components { CreateStorageVectorBucketBody: { bucketName: string } - CreateTaxIdBody: { - country?: string - type: string - value: string - } CreateTenantSourceResponse: { /** * @description Source id @@ -6977,7 +7231,7 @@ export interface components { parent_id?: string | null project_id: number } - CreateUserReponse: { + CreateUserResponse: { aud?: string banned_until?: string confirmation_sent_at?: string @@ -7055,7 +7309,6 @@ export interface components { } CreditRedemptionResponse: { amount_cents: number - /** Format: date-time */ credits_expire_at: string | null } CreditsTopUpRequest: { @@ -7112,7 +7365,7 @@ export interface components { } DatabaseDetailResponse: { /** @enum {string} */ - cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + cloud_provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' /** @default null */ connection_string_read_only?: string | null /** @default null */ @@ -7325,7 +7578,6 @@ export interface components { logo_uri?: string redirect_uris: string[] response_types?: string[] - /** @default organizations:read projects:read projects:write database:write database:read analytics:read secrets:read edge_functions:read edge_functions:write environment:read environment:write storage:read */ scope?: string token_endpoint_auth_method?: string } @@ -7346,71 +7598,26 @@ export interface components { private: number shared: number } - GetJwtSecretUpdateStatus: { - update_status: { - change_tracking_id: string - /** @enum {number} */ - error?: 0 | 1 | 2 | 3 | 4 | 5 - /** @enum {number} */ + GetGitHubConnectionConfigResponse: { + /** @description JSON representation of the parsed `supabase/config.toml`. Its shape is owned by the Supabase CLI and is passed through as-is. */ + config: { + [key: string]: unknown + } + /** @description Path of the config file within the connected repository, relative to its root. */ + path: string + /** @description Git ref the config was read from, or `null` when the default branch of the connected repository was used. */ + ref: string | null + /** @description Blob SHA of the config file, to detect changes between requests. */ + sha: string + } + GetJwtSecretUpdateStatus: { + update_status: { + change_tracking_id: string + error?: 0 | 1 | 2 | 3 | 4 | 5 progress: 0 | 1 | 2 | 3 | 4 | 5 - /** @enum {number} */ status: 0 | 1 | 2 } | null } - GetLeakedServiceKeyLintResponse: { - lints: { - cache_key: string - categories: ('PERFORMANCE' | 'SECURITY')[] - description: string - detail: string - /** @enum {string} */ - facing: 'EXTERNAL' - /** @enum {string} */ - level: 'ERROR' | 'WARN' | 'INFO' - metadata?: { - entity?: string - fkey_columns?: number[] - fkey_name?: string - name?: string - schema?: string - /** @enum {string} */ - type?: 'table' | 'view' | 'auth' | 'function' | 'extension' | 'compliance' - } - /** @enum {string} */ - name: - | 'unindexed_foreign_keys' - | 'auth_users_exposed' - | 'auth_rls_initplan' - | 'no_primary_key' - | 'unused_index' - | 'multiple_permissive_policies' - | 'policy_exists_rls_disabled' - | 'rls_enabled_no_policy' - | 'duplicate_index' - | 'security_definer_view' - | 'function_search_path_mutable' - | 'rls_disabled_in_public' - | 'extension_in_public' - | 'rls_references_user_metadata' - | 'materialized_view_in_api' - | 'foreign_table_in_api' - | 'unsupported_reg_types' - | 'auth_otp_long_expiry' - | 'auth_otp_short_length' - | 'ssl_not_enforced' - | 'network_restrictions_not_set' - | 'password_requirements_min_length' - | 'pitr_not_enabled' - | 'auth_leaked_password_protection' - | 'auth_insufficient_mfa_options' - | 'auth_password_policy_missing' - | 'leaked_service_key' - | 'no_backup_admin' - | 'vulnerable_postgres_version' - remediation: string - title: string - }[] - } GetOAuthAuthorizationResponse: { approved_at?: string approved_organization_slug?: string @@ -7495,13 +7702,19 @@ export interface components { integration: { name: string } - /** @description Any JSON-serializable value */ - metadata: unknown + metadata: components['schemas']['GetOrganizationIntegrationResponseJsonValue'] organization: { slug: string } updated_at: string } + /** @description Any JSON-serializable value */ + GetOrganizationIntegrationResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['GetOrganizationIntegrationResponseJsonValue'][] + | { + [key: string]: components['schemas']['GetOrganizationIntegrationResponseJsonValue'] + } GetPlatformAppInstallationResponse: { /** Format: uuid */ app_id: string @@ -7541,6 +7754,19 @@ export interface components { private_link_associations: { account_name?: string aws_account_id: string + /** @description Identifier of the database this PrivateLink share targets - the project ref for the primary, or the read replica identifier. */ + database_identifier: string + /** + * @description Whether this PrivateLink share targets the primary database or a read replica. + * @enum {string} + */ + database_type: 'PRIMARY' | 'READ_REPLICA' + /** @description ARN of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_arn?: string + /** @description ID of the AWS VPC Lattice resource configuration backing this PrivateLink share. */ + resource_access_manager_resource_config_id?: string + /** @description ARN of the AWS Resource Access Manager resource share for this association. */ + resource_access_manager_share_arn?: string /** * Format: date-time * @description The time and date at which the AWS Resource Share Association was requested from Supabase. `null` means that the association was not yet requested while the PrivateLink Association is pending. @@ -7750,40 +7976,6 @@ export interface components { } path: string[] } - GetSSOProviderResponse: - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file: string - /** Format: uri */ - metadata_xml_url?: string - user_name_mapping?: string[] - } - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file?: string - metadata_xml_url: string - user_name_mapping?: string[] - } GetStorageCredentialsResponse: { data: { created_at: string @@ -7799,7 +7991,7 @@ export interface components { }[] billing_cycle_anchor: number /** @enum {string} */ - billing_partner?: 'fly' | 'aws_marketplace' | 'vercel_marketplace' + billing_partner?: 'aws_marketplace' | 'vercel_marketplace' billing_via_partner: boolean current_period_end: number current_period_start: number @@ -7854,8 +8046,7 @@ export interface components { | 'auth_mfa_web_authn_default' | 'log_drain_default' | 'etl_pipeline_default' - /** @description Any JSON-serializable value */ - meta?: unknown + meta?: components['schemas']['GetSubscriptionResponseJsonValue'] name: string price: number price_description: string @@ -7869,7 +8060,6 @@ export interface components { ref: string }[] scheduled_plan_change: { - /** Format: date-time */ at: string /** @enum {string} */ target_plan: 'free' | 'pro' | 'team' | 'enterprise' | 'platform' @@ -7877,6 +8067,13 @@ export interface components { } | null usage_billing_enabled: boolean } + /** @description Any JSON-serializable value */ + GetSubscriptionResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['GetSubscriptionResponseJsonValue'][] + | { + [key: string]: components['schemas']['GetSubscriptionResponseJsonValue'] + } GetUserContentByIdResponse: { content: { [key: string]: unknown @@ -7964,13 +8161,19 @@ export interface components { integration: { name: string } - /** @description Any JSON-serializable value */ - metadata: unknown + metadata: components['schemas']['GetUserOrganizationIntegrationResponseJsonValue'] organization: { slug: string } updated_at: string } + /** @description Any JSON-serializable value */ + GetUserOrganizationIntegrationResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['GetUserOrganizationIntegrationResponseJsonValue'][] + | { + [key: string]: components['schemas']['GetUserOrganizationIntegrationResponseJsonValue'] + } GetVercelProjectsResponse: { pagination: { count: number @@ -8380,14 +8583,14 @@ export interface components { tls?: boolean } description?: string - id: number - metadata: { + readonly id: number + readonly metadata: { project_ref: string /** @enum {string} */ type: 'log-drain' } | null name: string - token: string + readonly token: string /** @enum {string} */ type: | 'postgres' @@ -8402,7 +8605,7 @@ export interface components { | 'last9' | 'otlp' | 'syslog' - user_id: number + readonly user_id: number } LinkClazarBuyerBody: { buyer_id: string @@ -8437,6 +8640,7 @@ export interface components { | 'storage.image_transformations' | 'storage.vector_buckets' | 'storage.iceberg_catalog' + | 'storage.purge_cache' | 'security.audit_logs_days' | 'security.questionnaire' | 'security.soc2_report' @@ -8486,6 +8690,8 @@ export interface components { | 'integrations.github_connections' | 'dedicated_pooler' | 'observability.dashboard_advanced_metrics' + | 'api.members.invitations' + | 'api.members.roles' /** @enum {string} */ type: 'boolean' | 'numeric' | 'set' } @@ -8678,6 +8884,7 @@ export interface components { is_sensitive: boolean } Member: { + avatar_url: string | null gotrue_id: string is_sso_user: boolean | null metadata: { @@ -8736,18 +8943,23 @@ export interface components { 'table-uuid'?: string } NotificationResponse: { - /** @description Any JSON-serializable value */ - data: unknown + data: components['schemas']['NotificationResponseJsonValue'] id: string inserted_at: string - /** @description Any JSON-serializable value */ - meta: unknown + meta: components['schemas']['NotificationResponseJsonValue'] name: string /** @enum {string} */ priority: 'Critical' | 'Warning' | 'Info' /** @enum {string} */ status: 'new' | 'seen' | 'archived' } + /** @description Any JSON-serializable value */ + NotificationResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['NotificationResponseJsonValue'][] + | { + [key: string]: components['schemas']['NotificationResponseJsonValue'] + } NotificationsSummary: { has_critical: boolean has_warning: boolean @@ -8887,7 +9099,7 @@ export interface components { OrganizationResponse: { billing_email: string | null /** @enum {string|null} */ - billing_partner: 'fly' | 'aws_marketplace' | 'vercel_marketplace' | null + billing_partner: 'aws_marketplace' | 'vercel_marketplace' | null id: number integration_source: string | null is_owner: boolean @@ -8943,7 +9155,7 @@ export interface components { } OrganizationSlugAvailableVersionsBody: { /** @enum {string} */ - provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' region: string } OrganizationSlugAvailableVersionsResponse: { @@ -8958,7 +9170,7 @@ export interface components { OrganizationSlugResponse: { billing_email: string | null /** @enum {string|null} */ - billing_partner: 'fly' | 'aws_marketplace' | 'vercel_marketplace' | null + billing_partner: 'aws_marketplace' | 'vercel_marketplace' | null has_oriole_project: boolean id: number integration_source: string | null @@ -8988,6 +9200,7 @@ export interface components { egress_storage: number egress_supavisor: number } | null + /** Format: date */ date: string /** @enum {string} */ metric: @@ -9037,6 +9250,8 @@ export interface components { | 'IPV4' | 'LOG_DRAIN' | 'ETL_PIPELINE' + | 'ETL_REPLICATED_DATA' + | 'ETL_COPY_BACKFILL_DATA' | 'LOG_INGESTION' | 'LOG_QUERYING' | 'LOG_STORAGE' @@ -9102,6 +9317,8 @@ export interface components { | 'IPV4' | 'LOG_DRAIN' | 'ETL_PIPELINE' + | 'ETL_REPLICATED_DATA' + | 'ETL_COPY_BACKFILL_DATA' | 'LOG_INGESTION' | 'LOG_QUERYING' | 'LOG_STORAGE' @@ -9241,6 +9458,22 @@ export interface components { } } } + PlanGateErrorBody: { + /** @description Present on entitlement denials. Other errors with this status code (validation, billing state) carry only message. */ + error?: { + /** + * @description Machine-readable marker for plan-gated denials + * @enum {string} + */ + code: 'entitlement_required' + /** @description Entitlement feature key that failed the check */ + feature: string + /** @description Billing page URL for the organization, present when the org is resolvable */ + upgrade_url?: string + } + /** @description Human-readable explanation of the plan gate */ + message: string + } PlansResponse: { plans: { /** @enum {string} */ @@ -9507,7 +9740,7 @@ export interface components { state?: string | null } tax_id?: { - country?: string + country: string type: string value: string } @@ -9682,23 +9915,7 @@ export interface components { } ProfileResponse: { auth0_id: string - disabled_features: ( - | 'organizations:create' - | 'organizations:delete' - | 'organization_members:create' - | 'organization_members:delete' - | 'projects:create' - | 'projects:transfer' - | 'project_auth:all' - | 'project_storage:all' - | 'project_edge_function:all' - | 'profile:update' - | 'billing:account_data' - | 'billing:credits' - | 'billing:invoices' - | 'billing:payment_methods' - | 'realtime:all' - )[] + disabled_features: string[] first_name: string | null free_project_limit: number | null gotrue_id: string @@ -9753,8 +9970,7 @@ export interface components { | 'auth_mfa_web_authn_default' | 'log_drain_default' | 'etl_pipeline_default' - /** @description Any JSON-serializable value */ - meta?: unknown + meta?: components['schemas']['ProjectAddonsResponseJsonValue'] name: string price: number price_description: string @@ -9806,8 +10022,7 @@ export interface components { | 'auth_mfa_web_authn_default' | 'log_drain_default' | 'etl_pipeline_default' - /** @description Any JSON-serializable value */ - meta?: unknown + meta?: components['schemas']['ProjectAddonsResponseJsonValue'] name: string price: number price_description: string @@ -9818,6 +10033,13 @@ export interface components { } }[] } + /** @description Any JSON-serializable value */ + ProjectAddonsResponseJsonValue: + | ((string | number | boolean) | null) + | components['schemas']['ProjectAddonsResponseJsonValue'][] + | { + [key: string]: components['schemas']['ProjectAddonsResponseJsonValue'] + } ProjectClonedResponse: { source_project_ref: string target_disk_size_gb: number @@ -9992,6 +10214,15 @@ export interface components { PublicUrlResponse: { publicUrl: string } + PurgeBucketCacheBody: { + /** @description Storage bucket id */ + bucket_id: string + } + PurgeObjectCacheBody: { + /** @description Storage bucket id */ + bucket_id: string + path: string + } PutOAuthAppResponse: { client_id: string created_at: string @@ -10057,7 +10288,7 @@ export interface components { | 'sa-east-1' name: string /** @enum {string} */ - provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -10095,7 +10326,7 @@ export interface components { | 'sa-east-1' name: string /** @enum {string} */ - provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -10267,7 +10498,7 @@ export interface components { database: string /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string /** @@ -10277,7 +10508,7 @@ export interface components { schema: string /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user: string } @@ -10456,7 +10687,7 @@ export interface components { database: string /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string /** @@ -10466,7 +10697,7 @@ export interface components { schema: string /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user: string } @@ -10526,7 +10757,7 @@ export interface components { * @example reserved * @enum {string} */ - wal_status?: 'extended' | 'lost' | 'reserved' | 'unknown' | 'unreserved' + wal_status?: 'reserved' | 'extended' | 'unreserved' | 'lost' | 'unknown' /** * @description Write lag expressed in milliseconds. * @example 1500 @@ -10646,7 +10877,7 @@ export interface components { * @example reserved * @enum {string} */ - wal_status?: 'extended' | 'lost' | 'reserved' | 'unknown' | 'unreserved' + wal_status?: 'reserved' | 'extended' | 'unreserved' | 'lost' | 'unknown' /** * @description Write lag expressed in milliseconds. * @example 1500 @@ -10688,7 +10919,7 @@ export interface components { * @example info * @enum {string} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ @@ -10834,7 +11065,7 @@ export interface components { * @example info * @enum {string} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ @@ -10995,81 +11226,6 @@ export interface components { name: string } } - CostEstimateResponse: { - /** - * @description Currency of all amounts - * @example usd - * @enum {string} - */ - currency: 'usd' - /** @description Recurring per-pipeline cost */ - pipeline: { - /** - * @description Hourly rate charged per active pipeline - * @example 0.053 - */ - hourly_cost: number - /** - * @description Projected monthly cost for an active pipeline, based on an average 730-hour month. Pipelines are billed hourly, so this is an estimate, not a metered amount. - * @example 38.69 - */ - monthly_cost: number - } - /** @description Usage-based streaming cost, expressed as a rate */ - streaming: { - /** - * @description Usage-based streaming rate per GB. Actual cost depends on the change volume. - * @example 3 - */ - rate_per_gb: number - } - /** @description One-time cost for the initial table copy */ - table_copy: { - /** - * @description One-time initial-copy rate per GB - * @example 0.6 - */ - rate_per_gb: number - /** @description Per-table initial-copy cost estimate */ - tables: { - /** - * @description Estimated on-disk size of the table in bytes - * @example 10960896 - */ - estimated_bytes: number - /** - * @description Estimated one-time initial-copy cost for the table, in the response currency - * @example 0.01 - */ - estimated_cost: number - /** - * @description Whether this table has a row filter. The estimate does not account for how many rows the filter excludes, so the actual replicated volume may be lower than shown. - * @example false - */ - is_row_filtered: boolean - /** - * @description Table name - * @example orders - */ - name: string - /** - * @description Table schema - * @example public - */ - schema: string - }[] - /** - * @description Total estimated bytes across all tables - * @example 11911168 - */ - total_bytes: number - /** - * @description Total estimated one-time initial-copy cost - * @example 0.01 - */ - total_cost: number - } - } ReplicationPublicationsResponse: { /** @description List of publications */ publications: { @@ -11308,73 +11464,12 @@ export interface components { table_id: number }[] } - RunLintByNameResponse: { - lints: { - cache_key: string - categories: ('PERFORMANCE' | 'SECURITY')[] - description: string - detail: string - /** @enum {string} */ - facing: 'EXTERNAL' - /** @enum {string} */ - level: 'ERROR' | 'WARN' | 'INFO' - metadata?: { - entity?: string - fkey_columns?: number[] - fkey_name?: string - name?: string - schema?: string - /** @enum {string} */ - type?: 'table' | 'view' | 'auth' | 'function' | 'extension' | 'compliance' - } - /** @enum {string} */ - name: - | 'unindexed_foreign_keys' - | 'auth_users_exposed' - | 'auth_rls_initplan' - | 'no_primary_key' - | 'unused_index' - | 'multiple_permissive_policies' - | 'policy_exists_rls_disabled' - | 'rls_enabled_no_policy' - | 'duplicate_index' - | 'security_definer_view' - | 'function_search_path_mutable' - | 'rls_disabled_in_public' - | 'extension_in_public' - | 'rls_references_user_metadata' - | 'materialized_view_in_api' - | 'foreign_table_in_api' - | 'unsupported_reg_types' - | 'auth_otp_long_expiry' - | 'auth_otp_short_length' - | 'ssl_not_enforced' - | 'network_restrictions_not_set' - | 'password_requirements_min_length' - | 'pitr_not_enabled' - | 'auth_leaked_password_protection' - | 'auth_insufficient_mfa_options' - | 'auth_password_policy_missing' - | 'leaked_service_key' - | 'no_backup_admin' - | 'vulnerable_postgres_version' - remediation: string - title: string - }[] - } RunQueryBody: { /** @default false */ disable_statement_timeout?: boolean parameters?: unknown[] query: string } - SendDocsFeedbackBody: { - feedback?: string - isHelpful: boolean - page: string - team?: string - title: string - } SendExitSurveyBody: { additionalFeedback?: string exitAction?: string @@ -11494,6 +11589,9 @@ export interface components { imageTransformation: { enabled: boolean } + purgeCache: { + enabled: boolean + } s3Protocol: { enabled: boolean } @@ -11654,7 +11752,7 @@ export interface components { } TelemetryFeatureFlagBody: { feature_flag_name: string - feature_flag_value?: unknown + feature_flag_value: unknown } TelemetryGroupsIdentityBody: { organization_slug?: string @@ -11710,9 +11808,7 @@ export interface components { UpcomingInvoice: { amount_projected?: number amount_total: number - /** Format: date-time */ billing_cycle_end: string - /** Format: date-time */ billing_cycle_start: string currency: string customer_balance: number @@ -11773,9 +11869,7 @@ export interface components { is_read_replica?: boolean } period?: { - /** Format: date-time */ end: string - /** Format: date-time */ start: string } proration: boolean @@ -11831,6 +11925,8 @@ export interface components { | 'IPV4' | 'LOG_DRAIN' | 'ETL_PIPELINE' + | 'ETL_REPLICATED_DATA' + | 'ETL_COPY_BACKFILL_DATA' | 'LOG_INGESTION' | 'LOG_QUERYING' | 'LOG_STORAGE' @@ -12367,6 +12463,8 @@ export interface components { | 'members_write' | 'organization_projects_read' | 'organization_projects_create' + | 'platform_webhooks_organization_read' + | 'platform_webhooks_organization_write' | 'project_admin_read' | 'project_admin_write' | 'action_runs_read' @@ -12436,6 +12534,10 @@ export interface components { | 'storage_config_write' | 'vanity_subdomain_read' | 'vanity_subdomain_write' + | 'platform_webhooks_projects_read' + | 'platform_webhooks_projects_write' + | 'workers_read' + | 'workers_write' )[] } UpdatePlatformAppInstallationResponse: { @@ -12471,6 +12573,7 @@ export interface components { UpdatePostgrestConfigBody: { db_extra_search_path?: string db_pool?: number + db_pool_acquisition_timeout?: number db_schema?: string max_rows?: number } @@ -12478,6 +12581,8 @@ export interface components { db_extra_search_path: string /** @description If `null`, the value is automatically configured based on compute size. */ db_pool: number | null + /** @description If `null`, the value is automatically configured to 10. */ + db_pool_acquisition_timeout: number | null db_schema: string max_rows: number } @@ -12807,7 +12912,7 @@ export interface components { private_key_passphrase?: string | null /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string | null /** @@ -12817,7 +12922,7 @@ export interface components { schema?: string | null /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user?: string | null } @@ -13115,7 +13220,7 @@ export interface components { private_key_passphrase?: string | null /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string | null /** @@ -13125,7 +13230,7 @@ export interface components { schema?: string | null /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user?: string | null } @@ -13166,7 +13271,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -13190,7 +13295,7 @@ export interface components { */ memory_refresh_interval_ms?: number | null /** - * @description Publication name. Omission preserves the stored value; ETL rejects clearing it with `null`. + * @description Publication name. Omission preserves the stored value; Pipelines rejects clearing it with `null`. * @example pub_orders */ publication_name?: string | null @@ -13241,7 +13346,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Source id @@ -13281,7 +13386,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -13305,7 +13410,7 @@ export interface components { */ memory_refresh_interval_ms?: number | null /** - * @description Publication name. Omission preserves the stored value; ETL rejects clearing it with `null`. + * @description Publication name. Omission preserves the stored value; Pipelines rejects clearing it with `null`. * @example pub_orders */ publication_name?: string | null @@ -13356,7 +13461,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Destination id @@ -13432,40 +13537,6 @@ export interface components { metadata_xml_url: string user_name_mapping?: string[] } - UpdateSSOProviderResponse: - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file: string - /** Format: uri */ - metadata_xml_url?: string - user_name_mapping?: string[] - } - | { - /** @default [] */ - domains?: string[] - email_mapping: string[] - enabled: boolean - first_name_mapping?: string[] - /** Format: uri */ - idjag_issuer_url?: string | null - join_org_on_signup_enabled: boolean - /** @enum {string} */ - join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' - last_name_mapping?: string[] - metadata_xml_file?: string - metadata_xml_url: string - user_name_mapping?: string[] - } UpdateStorageBucketBody: { allowed_mime_types?: string[] | null file_size_limit?: number | null @@ -13494,6 +13565,9 @@ export interface components { imageTransformation?: { enabled: boolean } + purgeCache?: { + enabled: boolean + } s3Protocol?: { enabled: boolean } @@ -13537,7 +13611,7 @@ export interface components { UpdateUserBody: { ban_duration?: string } - UpdateUserReponse: { + UpdateUserResponse: { aud?: string banned_until?: string confirmation_sent_at?: string @@ -13584,6 +13658,10 @@ export interface components { env_sync_targets?: ('production' | 'preview' | 'development')[] public_env_var_prefix?: string } + UpdateWarehouseCatalogBody: { + /** @description Whether external catalog access should be enabled */ + enabled: boolean + } UpsertContentBody: { content?: { [key: string]: unknown @@ -13594,7 +13672,6 @@ export interface components { * @default false */ favorite?: boolean - /** Format: uuid */ folder_id?: (null | (string | null)) | null id?: string name: string @@ -13613,6 +13690,9 @@ export interface components { } method: string name: string + params?: { + [key: string]: unknown + } route: string status: number } @@ -13620,10 +13700,24 @@ export interface components { app_id?: string app_name?: string email?: string + /** @description Only present when token_type=app */ + installation_id?: string ip?: string + /** @description JWT issuer. Only present for branching service JWTs */ + jwt_issuer?: string + /** @description JWT subject. Only present for branching service JWTs */ + jwt_subject?: string oauth_app_id?: string oauth_app_name?: string + /** @description Organization whose grant was used. Only present when token_type=oauth */ + organization_id?: string + /** @description GoTrue login session. Only present when token_type=jwt */ + session_id?: string + /** @description Access token alias, as shown in the dashboard. Only present when token_type=v0, token_type=v1 or token_type=scoped_pat */ + token_alias?: string token_hash?: string + /** @description Only present when token_type=scoped_pat */ + token_scope?: string token_type: string user_id?: string } @@ -14010,7 +14104,7 @@ export interface components { private_key_passphrase?: string | null /** * @description Optional Snowflake role - * @example ETL_ROLE + * @example PIPELINES_ROLE */ role?: string | null /** @@ -14020,7 +14114,7 @@ export interface components { schema: string /** * @description Snowflake user configured for key-pair authentication - * @example ETL_USER + * @example PIPELINES_USER */ user: string } @@ -14056,7 +14150,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -14131,7 +14225,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Source id @@ -14171,7 +14265,7 @@ export interface components { * @example info * @enum {string|null} */ - log_level?: 'debug' | 'error' | 'info' | 'trace' | 'warn' | null + log_level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | null /** @description Maximum number of copy connections per table */ max_copy_connections_per_table?: number | null /** @description Maximum number of table sync workers */ @@ -14246,7 +14340,7 @@ export interface components { /** @enum {string} */ type: 'skip_tables' } - | (never | null) + | never } /** * @description Source id @@ -14275,45 +14369,316 @@ export interface components { /** @enum {string} */ result: 'success' } - WorkflowRunResponse: { - branch_id: string - check_run_id: number | null - created_at: string - git_config?: unknown - id: string - /** @enum {string} */ - status: - | 'CREATING_PROJECT' - | 'RUNNING_MIGRATIONS' - | 'MIGRATIONS_PASSED' - | 'MIGRATIONS_FAILED' - | 'FUNCTIONS_DEPLOYED' - | 'FUNCTIONS_FAILED' - updated_at: string - workdir: string | null - } - } - responses: never - parameters: never - requestBodies: never - headers: never - pathItems: never -} -export type $defs = Record -export interface operations { - GoTrueConfigController_getGoTrueConfig: { - parameters: { - query?: never - header?: never - path: { - /** @description Project ref */ - ref: string + WarehouseCatalogResponse: { + /** @description External catalog credentials. Present only when enabled. */ + credentials?: { + /** + * @description DuckLake catalog Postgres URL + * @example postgres://postgres:@db.example.supabase.co:5432/postgres + */ + catalog_url: string + /** + * @description DuckLake object storage path + * @example s3://warehouse/ + */ + data_path: string + /** + * @description DuckLake metadata schema in the catalog database + * @example ducklake + */ + metadata_schema: string + /** @description S3 access key id */ + s3_access_key_id: string + /** + * @description S3-compatible storage endpoint without protocol + * @example abcjuqabhgwjjutfvtpa.storage.supabase.co/storage/v1/s3 + */ + s3_endpoint: string + /** + * @description S3-compatible storage region + * @example us-east-1 + */ + s3_region: string + /** @description S3 secret access key */ + s3_secret_access_key: string } - cookie?: never + /** @description Whether external catalog access is enabled */ + enabled: boolean } - requestBody?: never - responses: { - 200: { + WarehouseLinkedTable: { + /** + * @description Warehouse-facing table name + * @example warehouse.orders + */ + copy_name: string + /** + * @description Replication lag in milliseconds, when available + * @example 12000 + */ + lag_ms?: number + /** + * Format: date-time + * @description Last sync timestamp, when available + * @example 2026-06-23T17:48:00Z + */ + last_synced_at?: string + /** + * @description Postgres table name + * @example orders + */ + name: string + /** + * @description Postgres schema name + * @example public + */ + schema: string + /** + * @description Warehouse copy sync state derived from replication status + * @example live + * @enum {string} + */ + state: 'syncing' | 'live' | 'error' + /** + * @description Warehouse table size in bytes, when available + * @example 197912092672 + */ + warehouse_size_bytes?: number + } + WarehouseLinkTableBody: { + /** + * @description Whether to configure and install the Warehouse FDW in the project database. Defaults to false. + * @example false + */ + install_fdw?: boolean + /** + * @description Postgres table name + * @example orders + */ + name: string + /** + * @description Postgres schema name + * @example public + */ + schema: string + } + WarehouseSetupStatusResponse: { + /** @description Project database FDW setup markers used to derive the Warehouse FDW phase */ + fdw_status: { + /** + * @description Whether fdw_warehouse is available to install on the project database instance + * @example true + */ + extension_available: boolean + /** + * @description Whether the fdw_warehouse extension exists in the project database + * @example true + */ + extension_installed: boolean + /** + * @description Whether the Warehouse foreign schema import has exposed the Warehouse snapshots table + * @example true + */ + foreign_schema_imported: boolean + /** + * @description Whether the local Warehouse schema exists in the project database + * @example true + */ + schema_created: boolean + /** + * @description Whether the Warehouse foreign server exists in the project database + * @example true + */ + server_configured: boolean + /** + * @description Whether the Warehouse foreign data wrapper exists in the project database + * @example true + */ + wrapper_installed: boolean + } + /** + * @description Warehouse replication pipeline id when it exists + * @example 101 + */ + pipeline_id?: number + /** + * @description Overall Warehouse setup status derived from replication state + * @example copying + * @enum {string} + */ + setup_status: 'not_started' | 'setting_up' | 'copying' | 'complete' | 'error' + /** @description Warehouse setup phases in execution order */ + steps: { + /** + * @description Best-effort progress or error message derived from Warehouse state + * @example Pending initial copy: public.orders:copying_table + */ + message?: string + /** + * @description Observable Warehouse setup phase + * @example warehouse_copy + * @enum {string} + */ + name: 'warehouse_pipeline' | 'warehouse_copy' | 'warehouse_fdw' + /** + * @description Derived Warehouse setup step status + * @example running + * @enum {string} + */ + status: 'waiting' | 'running' | 'completed' | 'skipped' | 'error' + }[] + /** @description Warehouse linked tables and replication-derived sync state */ + tables: { + /** + * @description Warehouse-facing table name + * @example warehouse.orders + */ + copy_name: string + /** + * @description Replication lag in milliseconds, when available + * @example 12000 + */ + lag_ms?: number + /** + * Format: date-time + * @description Last sync timestamp, when available + * @example 2026-06-23T17:48:00Z + */ + last_synced_at?: string + /** + * @description Postgres table name + * @example orders + */ + name: string + /** + * @description Postgres schema name + * @example public + */ + schema: string + /** + * @description Warehouse copy sync state derived from replication status + * @example live + * @enum {string} + */ + state: 'syncing' | 'live' | 'error' + /** + * @description Warehouse table size in bytes, when available + * @example 197912092672 + */ + warehouse_size_bytes?: number + }[] + } + WarehouseTableSnapshotsResponse: { + /** @description Available Warehouse snapshots for the project catalog. */ + snapshots: { + /** + * @description Snapshot author, when available. + * @example postgres + */ + author: string | null + /** @description Snapshot change metadata returned by the Warehouse FDW. */ + changes: string | null + /** @description Additional snapshot commit metadata returned by the Warehouse FDW. */ + commit_extra_info: string | null + /** @description Snapshot commit message, when available. */ + commit_message: string | null + /** + * @description DuckLake schema version. Returned as a string because the source value is bigint. + * @example 7 + */ + schema_version: string | null + /** + * @description DuckLake snapshot id. Returned as a string because the source value is bigint. + * @example 42 + */ + snapshot_id: string + /** + * @description Snapshot timestamp returned by the Warehouse FDW. + * @example 2026-06-24 08:00:00+00 + */ + snapshot_time: string | null + }[] + } + WarehouseTablesResponse: { + /** @description Tables with Warehouse copies */ + tables: { + /** + * @description Warehouse-facing table name + * @example warehouse.orders + */ + copy_name: string + /** + * @description Replication lag in milliseconds, when available + * @example 12000 + */ + lag_ms?: number + /** + * Format: date-time + * @description Last sync timestamp, when available + * @example 2026-06-23T17:48:00Z + */ + last_synced_at?: string + /** + * @description Postgres table name + * @example orders + */ + name: string + /** + * @description Postgres schema name + * @example public + */ + schema: string + /** + * @description Warehouse copy sync state derived from replication status + * @example live + * @enum {string} + */ + state: 'syncing' | 'live' | 'error' + /** + * @description Warehouse table size in bytes, when available + * @example 197912092672 + */ + warehouse_size_bytes?: number + }[] + } + WorkflowRunResponse: { + branch_id: string + check_run_id: number | null + created_at: string + git_config?: unknown + id: string + /** @enum {string} */ + status: + | 'CREATING_PROJECT' + | 'RUNNING_MIGRATIONS' + | 'MIGRATIONS_PASSED' + | 'MIGRATIONS_FAILED' + | 'FUNCTIONS_DEPLOYED' + | 'FUNCTIONS_FAILED' + updated_at: string + workdir: string | null + } + } + responses: never + parameters: never + requestBodies: never + headers: never + pathItems: never +} +export type $defs = Record +export interface operations { + GoTrueConfigController_getGoTrueConfig: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { headers: { [name: string]: unknown } @@ -14791,7 +15156,7 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['CreateUserReponse'] + 'application/json': components['schemas']['CreateUserResponse'] } } /** @description Unauthorized */ @@ -14827,8 +15192,12 @@ export interface operations { UsersController_deleteUserById: { parameters: { query?: { - /** @description Boolean string, true or false */ - soft_delete?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + soft_delete?: string } header?: never path: { @@ -14898,7 +15267,7 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['UpdateUserReponse'] + 'application/json': components['schemas']['UpdateUserResponse'] } } /** @description Unauthorized */ @@ -15587,7 +15956,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -15853,36 +16224,6 @@ export interface operations { } } } - SendFeedbackController_sendDocsFeedback: { - parameters: { - query?: never - header?: never - path?: never - cookie?: never - } - requestBody: { - content: { - 'application/json': components['schemas']['SendDocsFeedbackBody'] - } - } - responses: { - 201: { - headers: { - [name: string]: unknown - } - content: { - 'application/json': components['schemas']['SendFeedbackResponse'] - } - } - /** @description Failed to send feedback for docs */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } SendFeedbackController_sendExitSurvey: { parameters: { query?: never @@ -16137,6 +16478,7 @@ export interface operations { parameters: { query: { organization_id: number + project_ref?: string } header?: never path?: never @@ -16247,6 +16589,58 @@ export interface operations { } } } + GitHubConnectionsController_getGitHubConnectionConfig: { + parameters: { + query?: { + /** @description Git branch, tag or commit SHA to read the config from. Defaults to the default branch of the connected repository. */ + ref?: string + } + header?: never + path: { + connection_id: number + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GetGitHubConnectionConfigResponse'] + } + } + /** @description Not allowed to read the config of this connection */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description GitHub connection not found, or the repository has no config file */ + 404: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description The config file could not be parsed as TOML */ + 422: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get the Supabase config of the connected GitHub repository */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } GitHubRepositoriesController_listRepositories: { parameters: { query?: never @@ -16522,7 +16916,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -16582,7 +16978,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -17004,7 +17402,35 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['CreateOrganizationResponse'] + 'application/json': + | { + pending_payment_intent_secret: string | null + } + | { + billing_email: string | null + billing_partner: ('aws_marketplace' | 'vercel_marketplace') | null + id: number + integration_source: string | null + is_owner: boolean + name: string + opt_in_tags: string[] + organization_missing_address: boolean + organization_missing_tax_id: boolean + organization_requires_mfa: boolean + plan: { + /** @enum {string} */ + id: 'free' | 'pro' | 'team' | 'enterprise' | 'platform' + name: string + } + restriction_data: { + [key: string]: string + } | null + restriction_status: ('grace_period' | 'grace_period_over' | 'restricted') | null + slug: string + stripe_customer_id: string | null + subscription_id: string | null + usage_billing_enabled: boolean + } } } /** @description Unexpected error creating an organization */ @@ -17247,7 +17673,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -19333,7 +19761,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { @@ -19383,7 +19813,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { @@ -19433,7 +19865,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Unauthorized */ 401: { @@ -19808,7 +20242,14 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['CreateInvitationResponse'] + 'application/json': { + failed: { + /** Format: email */ + email: string + error: string + }[] + succeeded: string[] + } | null } } /** @description Unauthorized */ @@ -20036,7 +20477,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -20873,7 +21316,38 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['GetSSOProviderResponse'] + 'application/json': + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping?: string[] + } + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping?: string[] + } } } /** @description Unauthorized */ @@ -20920,7 +21394,38 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['UpdateSSOProviderResponse'] + 'application/json': + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping?: string[] + } + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping?: string[] + } } } /** @description Unauthorized */ @@ -20967,7 +21472,38 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['CreateSSOProviderResponse'] + 'application/json': + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping?: string[] + } + | { + /** @default [] */ + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping?: string[] + idjag_issuer_url?: string | null + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping?: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping?: string[] + } } } /** @description Unauthorized */ @@ -20982,7 +21518,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -21091,108 +21629,6 @@ export interface operations { } } } - TaxIdsController_updateTaxId: { - parameters: { - query?: never - header?: never - path: { - /** @description Organization slug */ - slug: string - } - cookie?: never - } - requestBody: { - content: { - 'application/json': components['schemas']['CreateTaxIdBody'] - } - } - responses: { - 200: { - headers: { - [name: string]: unknown - } - content: { - 'application/json': components['schemas']['TaxIdResponse'] - } - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Failed to create the tax ID */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } - TaxIdsController_deleteTaxId: { - parameters: { - query?: never - header?: never - path: { - /** @description Organization slug */ - slug: string - } - cookie?: never - } - requestBody?: never - responses: { - 204: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Failed to delete the tax ID */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } OrgUsageController_getOrgUsage: { parameters: { query?: { @@ -21351,7 +21787,35 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['CreateOrganizationResponse'] + 'application/json': + | { + pending_payment_intent_secret: string | null + } + | { + billing_email: string | null + billing_partner: ('aws_marketplace' | 'vercel_marketplace') | null + id: number + integration_source: string | null + is_owner: boolean + name: string + opt_in_tags: string[] + organization_missing_address: boolean + organization_missing_tax_id: boolean + organization_requires_mfa: boolean + plan: { + /** @enum {string} */ + id: 'free' | 'pro' | 'team' | 'enterprise' | 'platform' + name: string + } + restriction_data: { + [key: string]: string + } | null + restriction_status: ('grace_period' | 'grace_period_over' | 'restricted') | null + slug: string + stripe_customer_id: string | null + subscription_id: string | null + usage_billing_enabled: boolean + } } } 202: { @@ -22064,6 +22528,7 @@ export interface operations { | 'storage.image_transformations' | 'storage.vector_buckets' | 'storage.iceberg_catalog' + | 'storage.purge_cache' | 'security.audit_logs_days' | 'security.questionnaire' | 'security.soc2_report' @@ -22113,6 +22578,8 @@ export interface operations { | 'integrations.github_connections' | 'dedicated_pooler' | 'observability.dashboard_advanced_metrics' + | 'api.members.invitations' + | 'api.members.roles' } header?: never path?: never @@ -22726,9 +23193,9 @@ export interface operations { ApiKeysLastUsedController_getApiKeysLastUsed: { parameters: { query?: { - iso_timestamp_start?: string - iso_timestamp_end?: string days?: string + iso_timestamp_end?: string + iso_timestamp_start?: string } header?: never path: { @@ -22988,6 +23455,115 @@ export interface operations { } } } + LogsController_getProjectLogsViaGetNew: { + parameters: { + query?: { + iso_timestamp_end?: string + iso_timestamp_start?: string + lql?: string + sql?: string + } + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['AnalyticsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get project's logs */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + LogsController_getProjectLogsViaPostNew: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['GetProjectLogsBody'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['AnalyticsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get project's logs */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } LogsController_getProjectLogsViaGet: { parameters: { query?: { @@ -23554,7 +24130,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -23793,11 +24371,11 @@ export interface operations { } } } - ApiKeysController_createTemporaryApiKey: { + 'scrape-project-metrics': { parameters: { - query: { - authorization_exp: string - claims: string + query?: { + /** @description Project service to include in the scrape. Valid values are `database`. Defaults to `database`. */ + services?: string } header?: never path: { @@ -23808,13 +24386,68 @@ export interface operations { } requestBody?: never responses: { - /** @description Temporary API key */ - 201: { + /** @description Prometheus / OpenMetrics text exposition */ + 200: { headers: { [name: string]: unknown } content: { - 'application/json': components['schemas']['TemporaryApiKeyResponse'] + 'application/openmetrics-text': string + 'text/plain': string + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to fetch project's metrics */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + ApiKeysController_createTemporaryApiKey: { + parameters: { + query: { + authorization_exp: string + claims: string + } + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Temporary API key */ + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['TemporaryApiKeyResponse'] } } /** @description Unauthorized */ @@ -24778,8 +25411,12 @@ export interface operations { parameters: { query?: { cursor?: string - /** @description Boolean string, true or false */ - favorite?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + favorite?: string limit?: string name?: string sort_by?: 'name' | 'inserted_at' @@ -25847,65 +26484,68 @@ export interface operations { | 'physical_replication_lag_physical_replication_lag_seconds' | 'pg_stat_database_num_backends' | 'max_db_connections' - attributes?: ( - | 'cpu_usage' - | 'cpu_usage_busy_system' - | 'cpu_usage_busy_user' - | 'cpu_usage_busy_iowait' - | 'cpu_usage_busy_irqs' - | 'cpu_usage_busy_other' - | 'cpu_usage_busy_idle' - | 'max_cpu_usage' - | 'avg_cpu_usage' - | 'ram_usage' - | 'ram_usage_total' - | 'ram_usage_available' - | 'ram_usage_used' - | 'ram_usage_free' - | 'ram_usage_cache_and_buffers' - | 'ram_usage_swap' - | 'ram_commit_used' - | 'ram_commit_limit' - | 'swap_usage' - | 'client_connections_pgbouncer' - | 'network_receive_bytes' - | 'network_transmit_bytes' - | 'pgbouncer_pools_client_active_connections' - | 'supavisor_connections_active' - | 'client_connections_postgres' - | 'client_connections_authenticator' - | 'client_connections_supabase_auth_admin' - | 'client_connections_supabase_storage_admin' - | 'client_connections_supabase_admin' - | 'client_connections_other' - | 'realtime_connections_connected' - | 'realtime_channel_joins' - | 'realtime_channel_events' - | 'realtime_channel_presence_events' - | 'realtime_channel_db_events' - | 'realtime_authorization_rls_execution_time' - | 'realtime_read_authorization_rls_execution_time' - | 'realtime_write_authorization_rls_execution_time' - | 'realtime_payload_size' - | 'realtime_replication_connection_lag' - | 'realtime_sum_connections_connected' - | 'disk_io_budget' - | 'disk_io_consumption' - | 'disk_io_usage' - | 'disk_iops_read' - | 'disk_iops_write' - | 'disk_bytes_read' - | 'disk_bytes_written' - | 'pg_database_size' - | 'disk_fs_size' - | 'disk_fs_avail' - | 'disk_fs_used' - | 'disk_fs_used_wal' - | 'disk_fs_used_system' - | 'physical_replication_lag_physical_replication_lag_seconds' - | 'pg_stat_database_num_backends' - | 'max_db_connections' - )[] + /** @description Comma-separated list of enums or array of enums. */ + attributes?: + | string + | ( + | 'cpu_usage' + | 'cpu_usage_busy_system' + | 'cpu_usage_busy_user' + | 'cpu_usage_busy_iowait' + | 'cpu_usage_busy_irqs' + | 'cpu_usage_busy_other' + | 'cpu_usage_busy_idle' + | 'max_cpu_usage' + | 'avg_cpu_usage' + | 'ram_usage' + | 'ram_usage_total' + | 'ram_usage_available' + | 'ram_usage_used' + | 'ram_usage_free' + | 'ram_usage_cache_and_buffers' + | 'ram_usage_swap' + | 'ram_commit_used' + | 'ram_commit_limit' + | 'swap_usage' + | 'client_connections_pgbouncer' + | 'network_receive_bytes' + | 'network_transmit_bytes' + | 'pgbouncer_pools_client_active_connections' + | 'supavisor_connections_active' + | 'client_connections_postgres' + | 'client_connections_authenticator' + | 'client_connections_supabase_auth_admin' + | 'client_connections_supabase_storage_admin' + | 'client_connections_supabase_admin' + | 'client_connections_other' + | 'realtime_connections_connected' + | 'realtime_channel_joins' + | 'realtime_channel_events' + | 'realtime_channel_presence_events' + | 'realtime_channel_db_events' + | 'realtime_authorization_rls_execution_time' + | 'realtime_read_authorization_rls_execution_time' + | 'realtime_write_authorization_rls_execution_time' + | 'realtime_payload_size' + | 'realtime_replication_connection_lag' + | 'realtime_sum_connections_connected' + | 'disk_io_budget' + | 'disk_io_consumption' + | 'disk_io_usage' + | 'disk_iops_read' + | 'disk_iops_write' + | 'disk_bytes_read' + | 'disk_bytes_written' + | 'pg_database_size' + | 'disk_fs_size' + | 'disk_fs_avail' + | 'disk_fs_used' + | 'disk_fs_used_wal' + | 'disk_fs_used_system' + | 'physical_replication_lag_physical_replication_lag_seconds' + | 'pg_stat_database_num_backends' + | 'max_db_connections' + )[] databaseIdentifier?: string endDate: string interval?: '1m' | '5m' | '10m' | '30m' | '1h' | '1d' @@ -26432,7 +27072,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -26514,6 +27156,64 @@ export interface operations { } } } + ProjectPrivateLinkController_removeAwsAccountFromPrivateLinkForDatabase: { + parameters: { + query?: never + header?: never + path: { + aws_account_id: string + database_identifier: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Scheduled AWS PrivateLink resources to be removed. */ + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Invalid AWS account ID format or association does not have a valid status for deletion. */ + 400: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to remove AWS account from PrivateLink share */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } ResizeController_resizeDatabase: { parameters: { query?: never @@ -26548,7 +27248,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -26824,41 +27526,11 @@ export interface operations { } } } - ProjectRunLintsController_runLintByName: { + ProjectServiceVersionsController_getServiceVersions: { parameters: { query?: never header?: never path: { - name: - | 'unindexed_foreign_keys' - | 'auth_users_exposed' - | 'auth_rls_initplan' - | 'no_primary_key' - | 'unused_index' - | 'multiple_permissive_policies' - | 'policy_exists_rls_disabled' - | 'rls_enabled_no_policy' - | 'duplicate_index' - | 'security_definer_view' - | 'function_search_path_mutable' - | 'rls_disabled_in_public' - | 'extension_in_public' - | 'rls_references_user_metadata' - | 'materialized_view_in_api' - | 'foreign_table_in_api' - | 'unsupported_reg_types' - | 'auth_otp_long_expiry' - | 'auth_otp_short_length' - | 'ssl_not_enforced' - | 'network_restrictions_not_set' - | 'password_requirements_min_length' - | 'pitr_not_enabled' - | 'auth_leaked_password_protection' - | 'auth_insufficient_mfa_options' - | 'auth_password_policy_missing' - | 'leaked_service_key' - | 'no_backup_admin' - | 'vulnerable_postgres_version' /** @description Project ref */ ref: string } @@ -26871,7 +27543,7 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['RunLintByNameResponse'] + 'application/json': components['schemas']['ServiceVersions'] } } /** @description Unauthorized */ @@ -26897,7 +27569,7 @@ export interface operations { } } } - ProjectRunLintsController_runLeakedServiceKeyLint: { + SettingsController_getProjectSettings: { parameters: { query?: never header?: never @@ -26914,7 +27586,7 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['GetLeakedServiceKeyLintResponse'] + 'application/json': components['schemas']['ProjectSettingsResponse'] } } /** @description Unauthorized */ @@ -26938,9 +27610,16 @@ export interface operations { } content?: never } + /** @description Failed to retrieve project's settings */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } } } - ProjectRunLintsController_runAuthBackupAdminLint: { + SensitivityController_updateProjectSensitivity: { parameters: { query?: never header?: never @@ -26950,14 +27629,18 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['MarkSensitiveBody'] + } + } responses: { 200: { headers: { [name: string]: unknown } content: { - 'application/json': components['schemas']['AuthBackupAdminLintResponse'] + 'application/json': components['schemas']['ProjectSensitivityResponse'] } } /** @description Unauthorized */ @@ -26981,9 +27664,16 @@ export interface operations { } content?: never } + /** @description Failed to update project */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } } } - ProjectServiceVersionsController_getServiceVersions: { + ProjectStatusController_getStatus: { parameters: { query?: never header?: never @@ -26999,9 +27689,7 @@ export interface operations { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['ServiceVersions'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -27024,9 +27712,16 @@ export interface operations { } content?: never } + /** @description Failed to get project's status */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } } } - SettingsController_getProjectSettings: { + ProjectTransferController_transferProject: { parameters: { query?: never header?: never @@ -27036,15 +27731,17 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['TransferProjectBody'] + } + } responses: { - 200: { + 201: { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['ProjectSettingsResponse'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -27067,16 +27764,9 @@ export interface operations { } content?: never } - /** @description Failed to retrieve project's settings */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } } } - SensitivityController_updateProjectSensitivity: { + ProjectTransferController_previewTransfer: { parameters: { query?: never header?: never @@ -27088,16 +27778,16 @@ export interface operations { } requestBody: { content: { - 'application/json': components['schemas']['MarkSensitiveBody'] + 'application/json': components['schemas']['TransferProjectBody'] } } responses: { - 200: { + 201: { headers: { [name: string]: unknown } content: { - 'application/json': components['schemas']['ProjectSensitivityResponse'] + 'application/json': components['schemas']['PreviewProjectTransferResponse'] } } /** @description Unauthorized */ @@ -27121,156 +27811,9 @@ export interface operations { } content?: never } - /** @description Failed to update project */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } } } - ProjectStatusController_getStatus: { - parameters: { - query?: never - header?: never - path: { - /** @description Project ref */ - ref: string - } - cookie?: never - } - requestBody?: never - responses: { - 200: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Failed to get project's status */ - 500: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } - ProjectTransferController_transferProject: { - parameters: { - query?: never - header?: never - path: { - /** @description Project ref */ - ref: string - } - cookie?: never - } - requestBody: { - content: { - 'application/json': components['schemas']['TransferProjectBody'] - } - } - responses: { - 201: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } - ProjectTransferController_previewTransfer: { - parameters: { - query?: never - header?: never - path: { - /** @description Project ref */ - ref: string - } - cookie?: never - } - requestBody: { - content: { - 'application/json': components['schemas']['TransferProjectBody'] - } - } - responses: { - 201: { - headers: { - [name: string]: unknown - } - content: { - 'application/json': components['schemas']['PreviewProjectTransferResponse'] - } - } - /** @description Unauthorized */ - 401: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Forbidden action */ - 403: { - headers: { - [name: string]: unknown - } - content?: never - } - /** @description Rate limit exceeded */ - 429: { - headers: { - [name: string]: unknown - } - content?: never - } - } - } - ProjectWakeController_wakeUpProject: { + ProjectWakeController_wakeUpProject: { parameters: { query?: never header?: never @@ -27316,7 +27859,7 @@ export interface operations { ProjectsController_getRegions: { parameters: { query: { - cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' | 'AWS_NIMBUS' + cloud_provider: 'AWS' | 'AWS_K8S' | 'AWS_NIMBUS' desired_instance_size?: | 'micro' | 'small' @@ -27437,6 +27980,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27492,6 +28044,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27549,6 +28110,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27604,6 +28174,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27726,6 +28305,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27777,6 +28365,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -27952,6 +28549,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28060,6 +28666,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28111,6 +28726,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28201,7 +28825,7 @@ export interface operations { } } } - ReplicationPipelinesController_rollbackTables: { + ReplicationPipelinesController_restartPipeline: { parameters: { query?: never header?: never @@ -28213,20 +28837,14 @@ export interface operations { } cookie?: never } - requestBody: { - content: { - 'application/json': components['schemas']['RollbackTablesBody'] - } - } + requestBody?: never responses: { - /** @description New table states after rollback. */ - 200: { + /** @description Pipeline restart accepted. */ + 202: { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['RollbackTablesResponse'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -28235,6 +28853,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28242,6 +28869,13 @@ export interface operations { } content?: never } + /** @description Pipeline is not running. */ + 409: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Rate limit exceeded */ 429: { headers: { @@ -28249,7 +28883,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while rolling back tables. */ + /** @description Unexpected error while restarting pipeline. */ 500: { headers: { [name: string]: unknown @@ -28258,7 +28892,7 @@ export interface operations { } } } - ReplicationPipelinesController_startPipeline: { + ReplicationPipelinesController_rollbackTables: { parameters: { query?: never header?: never @@ -28270,22 +28904,37 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['RollbackTablesBody'] + } + } responses: { - /** @description Pipeline started. */ + /** @description New table states after rollback. */ 200: { headers: { [name: string]: unknown } - content?: never - } - /** @description Unauthorized */ + content: { + 'application/json': components['schemas']['RollbackTablesResponse'] + } + } + /** @description Unauthorized */ 401: { headers: { [name: string]: unknown } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28300,7 +28949,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while starting pipeline. */ + /** @description Unexpected error while rolling back tables. */ 500: { headers: { [name: string]: unknown @@ -28309,7 +28958,7 @@ export interface operations { } } } - ReplicationPipelinesController_restartPipeline: { + ReplicationPipelinesController_startPipeline: { parameters: { query?: never header?: never @@ -28323,8 +28972,8 @@ export interface operations { } requestBody?: never responses: { - /** @description Pipeline restart accepted. */ - 202: { + /** @description Pipeline started. */ + 200: { headers: { [name: string]: unknown } @@ -28337,15 +28986,17 @@ export interface operations { } content?: never } - /** @description Forbidden action */ - 403: { + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } - /** @description Pipeline is not running. */ - 409: { + /** @description Forbidden action */ + 403: { headers: { [name: string]: unknown } @@ -28358,7 +29009,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while restarting pipeline. */ + /** @description Unexpected error while starting pipeline. */ 500: { headers: { [name: string]: unknown @@ -28448,6 +29099,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28556,6 +29216,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28718,7 +29387,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -28796,13 +29467,11 @@ export interface operations { } } } - ReplicationSourcesController_getCostEstimate: { + ReplicationSourcesController_createPublication: { parameters: { query?: never header?: never path: { - /** @description Publication name */ - publication_name: string /** @description Project ref */ ref: string /** @description Source id */ @@ -28810,16 +29479,18 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['CreateReplicationPublicationBody'] + } + } responses: { - /** @description Cost estimate for replicating the publication. */ + /** @description Publication created. */ 200: { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['CostEstimateResponse'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -28828,6 +29499,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28842,7 +29522,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while estimating replication cost. */ + /** @description Unexpected error while creating publication. */ 500: { headers: { [name: string]: unknown @@ -28851,11 +29531,13 @@ export interface operations { } } } - ReplicationSourcesController_createPublication: { + ReplicationSourcesController_updatePublication: { parameters: { query?: never header?: never path: { + /** @description Publication name */ + publication_name: string /** @description Project ref */ ref: string /** @description Source id */ @@ -28865,11 +29547,11 @@ export interface operations { } requestBody: { content: { - 'application/json': components['schemas']['CreateReplicationPublicationBody'] + 'application/json': components['schemas']['UpdateReplicationPublicationBody'] } } responses: { - /** @description Publication created. */ + /** @description Publication updated. */ 200: { headers: { [name: string]: unknown @@ -28883,6 +29565,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28897,7 +29588,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while creating publication. */ + /** @description Unexpected error while updating publication. */ 500: { headers: { [name: string]: unknown @@ -28906,7 +29597,7 @@ export interface operations { } } } - ReplicationSourcesController_updatePublication: { + ReplicationSourcesController_deletePublication: { parameters: { query?: never header?: never @@ -28920,13 +29611,9 @@ export interface operations { } cookie?: never } - requestBody: { - content: { - 'application/json': components['schemas']['UpdateReplicationPublicationBody'] - } - } + requestBody?: never responses: { - /** @description Publication updated. */ + /** @description Publication deleted. */ 200: { headers: { [name: string]: unknown @@ -28940,6 +29627,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -28947,6 +29643,13 @@ export interface operations { } content?: never } + /** @description Source not found. */ + 404: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Rate limit exceeded */ 429: { headers: { @@ -28954,7 +29657,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while updating publication. */ + /** @description Unexpected error while deleting publication. */ 500: { headers: { [name: string]: unknown @@ -28963,7 +29666,7 @@ export interface operations { } } } - ReplicationSourcesController_deletePublication: { + ReplicationSourcesController_getCostEstimate: { parameters: { query?: never header?: never @@ -28979,12 +29682,14 @@ export interface operations { } requestBody?: never responses: { - /** @description Publication deleted. */ + /** @description Cost estimate for replicating the publication. */ 200: { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['CostEstimateResponse'] + } } /** @description Unauthorized */ 401: { @@ -29000,13 +29705,6 @@ export interface operations { } content?: never } - /** @description Source not found. */ - 404: { - headers: { - [name: string]: unknown - } - content?: never - } /** @description Rate limit exceeded */ 429: { headers: { @@ -29014,7 +29712,7 @@ export interface operations { } content?: never } - /** @description Unexpected error while deleting publication. */ + /** @description Unexpected error while estimating replication cost. */ 500: { headers: { [name: string]: unknown @@ -29102,6 +29800,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -29172,7 +29879,9 @@ export interface operations { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } } /** @description Forbidden action */ 403: { @@ -29383,7 +30092,7 @@ export interface operations { query?: never header?: never path: { - /** @description Analytics Bucket ID */ + /** @description Storage bucket id */ id: string /** @description Project ref */ ref: string @@ -29435,7 +30144,7 @@ export interface operations { query?: never header?: never path: { - /** @description Analytics Bucket ID */ + /** @description Storage bucket id */ id: string /** @description Project ref */ ref: string @@ -29487,7 +30196,7 @@ export interface operations { query?: never header?: never path: { - /** @description Analytics Bucket ID */ + /** @description Storage bucket id */ id: string /** @description Project ref */ ref: string @@ -29700,8 +30409,12 @@ export interface operations { StorageAnalyticsBucketNamespaceTableController_dropTable: { parameters: { query?: { - /** @description Boolean string, true or false */ - purge?: boolean + /** @description Boolean string. + * + * Truthy values: `true`, `1`, `yes`, `on`, `y`, `enabled` + * + * Falsy values: `false`, `0`, `no`, `off`, `n`, `disabled` */ + purge?: string } header?: never path: { @@ -30608,7 +31321,7 @@ export interface operations { } } } - StorageS3CredentialsController_getAllCredentials: { + StorageCdnController_purgeBucketCache: { parameters: { query?: never header?: never @@ -30618,15 +31331,17 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['PurgeBucketCacheBody'] + } + } responses: { - 200: { + 201: { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['GetStorageCredentialsResponse'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -30635,6 +31350,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -30649,7 +31373,7 @@ export interface operations { } content?: never } - /** @description Failed to get project storage credentials */ + /** @description Failed to purge CDN cache for bucket */ 500: { headers: { [name: string]: unknown @@ -30658,7 +31382,7 @@ export interface operations { } } } - StorageS3CredentialsController_createCredential: { + StorageCdnController_purgeObjectCache: { parameters: { query?: never header?: never @@ -30670,7 +31394,7 @@ export interface operations { } requestBody: { content: { - 'application/json': components['schemas']['CreateStorageCredentialBody'] + 'application/json': components['schemas']['PurgeObjectCacheBody'] } } responses: { @@ -30678,9 +31402,7 @@ export interface operations { headers: { [name: string]: unknown } - content: { - 'application/json': components['schemas']['CreateStorageCredentialResponse'] - } + content?: never } /** @description Unauthorized */ 401: { @@ -30689,6 +31411,15 @@ export interface operations { } content?: never } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } /** @description Forbidden action */ 403: { headers: { @@ -30703,7 +31434,7 @@ export interface operations { } content?: never } - /** @description Failed to create project storage credential */ + /** @description Failed to purge CDN cache for object */ 500: { headers: { [name: string]: unknown @@ -30712,13 +31443,11 @@ export interface operations { } } } - StorageS3CredentialsController_deleteCredential: { + StorageS3CredentialsController_getAllCredentials: { parameters: { query?: never header?: never path: { - /** @description Storage credential id */ - id: string /** @description Project ref */ ref: string } @@ -30726,11 +31455,13 @@ export interface operations { } requestBody?: never responses: { - 204: { + 200: { headers: { [name: string]: unknown } - content?: never + content: { + 'application/json': components['schemas']['GetStorageCredentialsResponse'] + } } /** @description Unauthorized */ 401: { @@ -30753,7 +31484,7 @@ export interface operations { } content?: never } - /** @description Failed to delete project storage credential */ + /** @description Failed to get project storage credentials */ 500: { headers: { [name: string]: unknown @@ -30762,11 +31493,9 @@ export interface operations { } } } - StorageVectorBucketsController_getBuckets: { + StorageS3CredentialsController_createCredential: { parameters: { - query?: { - nextToken?: string - } + query?: never header?: never path: { /** @description Project ref */ @@ -30774,14 +31503,18 @@ export interface operations { } cookie?: never } - requestBody?: never + requestBody: { + content: { + 'application/json': components['schemas']['CreateStorageCredentialBody'] + } + } responses: { - 200: { + 201: { headers: { [name: string]: unknown } content: { - 'application/json': components['schemas']['StorageVectorBucketsResponse'] + 'application/json': components['schemas']['CreateStorageCredentialResponse'] } } /** @description Unauthorized */ @@ -30805,7 +31538,7 @@ export interface operations { } content?: never } - /** @description Failed to get list of vector buckets */ + /** @description Failed to create project storage credential */ 500: { headers: { [name: string]: unknown @@ -30814,23 +31547,21 @@ export interface operations { } } } - StorageVectorBucketsController_createBucket: { + StorageS3CredentialsController_deleteCredential: { parameters: { query?: never header?: never path: { + /** @description Storage credential id */ + id: string /** @description Project ref */ ref: string } cookie?: never } - requestBody: { - content: { - 'application/json': components['schemas']['CreateStorageVectorBucketBody'] - } - } + requestBody?: never responses: { - 201: { + 204: { headers: { [name: string]: unknown } @@ -30857,7 +31588,7 @@ export interface operations { } content?: never } - /** @description Failed to create vector bucket */ + /** @description Failed to delete project storage credential */ 500: { headers: { [name: string]: unknown @@ -30866,12 +31597,13 @@ export interface operations { } } } - StorageVectorBucketIdController_getBucket: { + StorageVectorBucketsController_getBuckets: { parameters: { - query?: never + query?: { + nextToken?: string + } header?: never path: { - id: string /** @description Project ref */ ref: string } @@ -30884,7 +31616,7 @@ export interface operations { [name: string]: unknown } content: { - 'application/json': components['schemas']['StorageVectorBucketResponse'] + 'application/json': components['schemas']['StorageVectorBucketsResponse'] } } /** @description Unauthorized */ @@ -30908,7 +31640,7 @@ export interface operations { } content?: never } - /** @description Failed to get bucket */ + /** @description Failed to get list of vector buckets */ 500: { headers: { [name: string]: unknown @@ -30917,19 +31649,122 @@ export interface operations { } } } - StorageVectorBucketIdController_deleteBucket: { + StorageVectorBucketsController_createBucket: { parameters: { query?: never header?: never path: { - id: string /** @description Project ref */ ref: string } cookie?: never } - requestBody?: never - responses: { + requestBody: { + content: { + 'application/json': components['schemas']['CreateStorageVectorBucketBody'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to create vector bucket */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + StorageVectorBucketIdController_getBucket: { + parameters: { + query?: never + header?: never + path: { + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['StorageVectorBucketResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get bucket */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + StorageVectorBucketIdController_deleteBucket: { + parameters: { + query?: never + header?: never + path: { + id: string + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { 200: { headers: { [name: string]: unknown @@ -31500,6 +32335,465 @@ export interface operations { } } } + WarehouseController_getCatalog: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse catalog access. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseCatalogResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while retrieving Warehouse catalog. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_updateCatalog: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['UpdateWarehouseCatalogBody'] + } + } + responses: { + /** @description Warehouse catalog access updated. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseCatalogResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while updating Warehouse catalog. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_refreshSchema: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse foreign schema refresh accepted. */ + 202: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while refreshing the Warehouse foreign schema. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_getSetupStatus: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse setup status. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseSetupStatusResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while retrieving Warehouse setup status. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_getTables: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse linked tables. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseTablesResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while listing Warehouse tables. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_linkTable: { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['WarehouseLinkTableBody'] + } + } + responses: { + /** @description Warehouse table link accepted. */ + 202: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseLinkedTable'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while linking Warehouse table. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_detachTable: { + parameters: { + query?: never + header?: never + path: { + /** @description Postgres table name */ + name: string + /** @description Project ref */ + ref: string + /** @description Postgres schema name */ + schema: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse table detached. */ + 204: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description This feature requires the Pro, Team, or Enterprise organization plan. */ + 402: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['PlanGateErrorBody'] + } + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while detaching Warehouse table. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + WarehouseController_getTableSnapshots: { + parameters: { + query?: { + /** @description Maximum number of snapshots to return. */ + limit?: number + } + header?: never + path: { + /** @description Postgres table name */ + name: string + /** @description Project ref */ + ref: string + /** @description Postgres schema name */ + schema: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Warehouse snapshots. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['WarehouseTableSnapshotsResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unexpected error while listing Warehouse snapshots. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } WorkflowRunController_listWorkflowRuns: { parameters: { query?: { diff --git a/packages/ui-patterns/src/Chart/charts/chart-bar.tsx b/packages/ui-patterns/src/Chart/charts/chart-bar.tsx index 79c0f16f512ea..e81034adabb74 100644 --- a/packages/ui-patterns/src/Chart/charts/chart-bar.tsx +++ b/packages/ui-patterns/src/Chart/charts/chart-bar.tsx @@ -73,6 +73,9 @@ export interface ChartBarProps { } } +// [Joshen] JFYI - shouldn't rely on xKey's value to determine if its a time-based format +// Preferably provide an additional param like xFormat to be more deterministic + export const ChartBar = ({ data, xKey = 'timestamp', diff --git a/packages/ui-patterns/src/Chart/charts/chart-line.tsx b/packages/ui-patterns/src/Chart/charts/chart-line.tsx index 1811933d845a0..a2571ff78c540 100644 --- a/packages/ui-patterns/src/Chart/charts/chart-line.tsx +++ b/packages/ui-patterns/src/Chart/charts/chart-line.tsx @@ -84,6 +84,9 @@ export interface ChartLineProps { referenceLines?: ChartReferenceLine[] } +// [Joshen] JFYI - shouldn't rely on xKey's value to determine if its a time-based format +// Preferably provide an additional param like xFormat to be more deterministic + export const ChartLine = ({ data, xKey = 'timestamp', @@ -305,7 +308,7 @@ export const ChartLine = ({ fillOpacity={fillOpacity} stroke={lineColor} strokeWidth={strokeWidth} - stackId={`stack-${key}`} + stackId={keysToRender.length > 1 ? `stack-${key}` : undefined} /> ) })}