-
-
-
Managing secrets
+ <>
+
+
+ Local development & CLI
+
+
+
+
Local secrets and environment variables can be loaded in either of the following two
@@ -386,9 +385,50 @@ export const FunctionsSecretsEmptyStateLocal = () => {
-
-
-
-
+
+
+
+
+
+ Self-Hosted Supabase
+
+
+
+
+
+
+ Change settings in
+
+ .env file
+
+ and
+
+ docker-compose.yml
+
+ at
+ functions
+ service
+
+
+ Secrets can also be loaded at runtime by injecting them into
+
+ main/index.ts file
+
+
+
+
+ >
)
}
diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet.tsx
index 53e4232800d..a836fbc2d25 100644
--- a/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet.tsx
+++ b/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet.tsx
@@ -1,13 +1,8 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
-import { parseAsString, useQueryState } from 'nuqs'
-import { useEffect, useState } from 'react'
-import { SubmitHandler, useForm } from 'react-hook-form'
-import { toast } from 'sonner'
-
import { useWatch } from '@ui/components/shadcn/ui/form'
import { useParams } from 'common'
-import EnableExtensionModal from 'components/interfaces/Database/Extensions/EnableExtensionModal'
+import { EnableExtensionModal } from 'components/interfaces/Database/Extensions/EnableExtensionModal'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { getDatabaseCronJob } from 'data/database-cron-jobs/database-cron-job-query'
import { useDatabaseCronJobCreateMutation } from 'data/database-cron-jobs/database-cron-jobs-create-mutation'
@@ -17,11 +12,15 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
+import { parseAsString, useQueryState } from 'nuqs'
+import { useEffect, useState } from 'react'
+import { SubmitHandler, useForm } from 'react-hook-form'
+import { toast } from 'sonner'
import {
Button,
- Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
+ Form_Shadcn_,
Input_Shadcn_,
RadioGroupStacked,
RadioGroupStackedItem,
@@ -34,6 +33,7 @@ import {
} from 'ui'
import { Admonition } from 'ui-patterns/admonition'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+
import { CRONJOB_DEFINITIONS } from '../CronJobs.constants'
import { buildCronQuery, buildHttpRequestCommand, parseCronJobCommand } from '../CronJobs.utils'
import { EdgeFunctionSection } from '../EdgeFunctionSection'
@@ -43,9 +43,9 @@ import { HttpRequestSection } from '../HttpRequestSection'
import { SqlFunctionSection } from '../SqlFunctionSection'
import { SqlSnippetSection } from '../SqlSnippetSection'
import {
- FormSchema,
type CreateCronJobForm,
type CronJobType,
+ FormSchema,
} from './CreateCronJobSheet.constants'
import { CronJobScheduleSection } from './CronJobScheduleSection'
diff --git a/apps/studio/components/interfaces/Integrations/Integration/MissingExtensionAlert.tsx b/apps/studio/components/interfaces/Integrations/Integration/MissingExtensionAlert.tsx
index 54526a943fd..d8dbc1312a1 100644
--- a/apps/studio/components/interfaces/Integrations/Integration/MissingExtensionAlert.tsx
+++ b/apps/studio/components/interfaces/Integrations/Integration/MissingExtensionAlert.tsx
@@ -1,7 +1,6 @@
-import { useState } from 'react'
-
-import EnableExtensionModal from 'components/interfaces/Database/Extensions/EnableExtensionModal'
+import { EnableExtensionModal } from 'components/interfaces/Database/Extensions/EnableExtensionModal'
import { DatabaseExtension } from 'data/database-extensions/database-extensions-query'
+import { useState } from 'react'
import { Button } from 'ui'
export const MissingExtensionAlert = ({ extension }: { extension: DatabaseExtension }) => {
diff --git a/apps/studio/components/interfaces/LogDrains/LogDrainDestinationSheetForm.tsx b/apps/studio/components/interfaces/LogDrains/LogDrainDestinationSheetForm.tsx
index f612b62df4f..dbaf733022e 100644
--- a/apps/studio/components/interfaces/LogDrains/LogDrainDestinationSheetForm.tsx
+++ b/apps/studio/components/interfaces/LogDrains/LogDrainDestinationSheetForm.tsx
@@ -1,34 +1,31 @@
import { zodResolver } from '@hookform/resolvers/zod'
+import { IS_PLATFORM, useFlag, useParams } from 'common'
+import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query'
+import { DOCS_URL } from 'lib/constants'
import { useTrack } from 'lib/telemetry/track'
import { TrashIcon } from 'lucide-react'
import Link from 'next/link'
import { ReactNode, useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
-import { z } from 'zod'
-
-import { IS_PLATFORM, useFlag, useParams } from 'common'
-import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query'
-import { DOCS_URL } from 'lib/constants'
import {
Button,
- cn,
- Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
FormItem_Shadcn_,
FormLabel_Shadcn_,
FormMessage_Shadcn_,
+ Form_Shadcn_,
Input_Shadcn_,
RadioGroupCard,
RadioGroupCardItem,
- Select_Shadcn_,
SelectContent_Shadcn_,
SelectGroup_Shadcn_,
SelectItem_Shadcn_,
SelectLabel_Shadcn_,
SelectTrigger_Shadcn_,
SelectValue_Shadcn_,
+ Select_Shadcn_,
Sheet,
SheetContent,
SheetFooter,
@@ -36,9 +33,12 @@ import {
SheetSection,
SheetTitle,
Switch,
+ cn,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { InfoTooltip } from 'ui-patterns/info-tooltip'
+import { z } from 'zod'
+
import { urlRegex } from '../Auth/Auth.constants'
import { DATADOG_REGIONS, LOG_DRAIN_TYPES, LogDrainType } from './LogDrains.constants'
@@ -91,9 +91,14 @@ const formUnion = z.discriminatedUnion('type', [
}),
z.object({
type: z.literal('s3'),
- }),
- z.object({
- type: z.literal('axiom'),
+ s3_bucket: z.string().min(1, { message: 'Bucket name is required' }),
+ storage_region: z.string().min(1, { message: 'Region is required' }),
+ access_key_id: z.string().min(1, { message: 'Access Key ID is required' }),
+ secret_access_key: z.string().min(1, { message: 'Secret Access Key is required' }),
+ batch_timeout: z.coerce
+ .number()
+ .int({ message: 'Batch timeout must be an integer' })
+ .min(1, { message: 'Batch timeout must be a positive integer' }),
}),
z.object({
type: z.literal('sentry'),
@@ -102,6 +107,11 @@ const formUnion = z.discriminatedUnion('type', [
.min(1, { message: 'Sentry DSN is required' })
.refine((dsn) => dsn.startsWith('https://'), 'Sentry DSN must start with https://'),
}),
+ z.object({
+ type: z.literal('axiom'),
+ api_token: z.string().min(1, { message: 'API token is required' }),
+ dataset_name: z.string().min(1, { message: 'Dataset name is required' }),
+ }),
])
const formSchema = z
@@ -120,7 +130,6 @@ function LogDrainFormItem({
formControl,
placeholder,
type,
- defaultValue,
}: {
value: string
label: string
@@ -128,7 +137,6 @@ function LogDrainFormItem({
placeholder?: string
description?: ReactNode
type?: string
- defaultValue?: string
}) {
return (
(
-
+
)}
@@ -178,6 +181,8 @@ export function LogDrainDestinationSheetForm({
const DEFAULT_HEADERS = mode === 'create' ? CREATE_DEFAULT_HEADERS : defaultConfig?.headers || {}
const sentryEnabled = useFlag('SentryLogDrain')
+ const s3Enabled = useFlag('S3logdrain')
+ const axiomEnabled = useFlag('axiomLogDrain')
const { ref } = useParams()
const { data: logDrains } = useLogDrainsQuery({
@@ -203,6 +208,13 @@ export function LogDrainDestinationSheetForm({
username: defaultConfig?.username || '',
password: defaultConfig?.password || '',
dsn: defaultConfig?.dsn || '',
+ s3_bucket: defaultConfig?.s3_bucket || '',
+ storage_region: defaultConfig?.storage_region || '',
+ access_key_id: defaultConfig?.access_key_id || '',
+ secret_access_key: defaultConfig?.secret_access_key || '',
+ batch_timeout: defaultConfig?.batch_timeout ?? 3000,
+ dataset_name: defaultConfig?.dataset_name || '',
+ api_token: defaultConfig?.api_token || '',
},
})
@@ -290,10 +302,7 @@ export function LogDrainDestinationSheetForm({
form.handleSubmit(onSubmit)(e)
track('log_drain_save_button_clicked', {
- destination: form.getValues('type') as Exclude<
- LogDrainType,
- 'elastic' | 'postgres' | 'bigquery' | 'clickhouse' | 's3' | 'axiom'
- >,
+ destination: form.getValues('type'),
})
}}
>
@@ -327,18 +336,21 @@ export function LogDrainDestinationSheetForm({
{LOG_DRAIN_TYPES.find((t) => t.value === type)?.name}
- {LOG_DRAIN_TYPES.filter((t) => t.value !== 'sentry' || sentryEnabled).map(
- (type) => (
-
- {type.name}
-
- )
- )}
+ {LOG_DRAIN_TYPES.filter((t) => {
+ if (t.value === 'sentry') return sentryEnabled
+ if (t.value === 's3') return s3Enabled
+ if (t.value === 'axiom') return axiomEnabled
+ return true
+ }).map((type) => (
+
+ {type.name}
+
+ ))}
@@ -517,6 +529,69 @@ export function LogDrainDestinationSheetForm({
/>
)}
+ {type === 's3' && (
+