Skip to content

Commit 72ee2d3

Browse files
authored
Merge pull request #299 from simplyblock/apikeys-pgconfig-fix
Apikeys pgconfig fix
2 parents e5ba136 + b01b1c1 commit 72ee2d3

6 files changed

Lines changed: 99 additions & 61 deletions

File tree

apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,31 @@ export const ConnectionPooling = () => {
151151
if (isSuccess) resetForm()
152152
}, [isSuccess])
153153

154-
const onSubmit = (values: FormValues) => {
155-
if (!slug || !ref || !branch) return
156-
// FIXME: using a locally typed version because the current PgbouncerConfigurationUpdateVariables is not typed correctly ideally we would want to use that one
157-
const payload: PgBouncerPayload = {
158-
slug: slug,
159-
ref: ref,
154+
const onSubmit = (values: FormValues) => {
155+
if (!slug || !ref || !branch || !data) return
156+
157+
// 1. Merge the original data with the form values
158+
const payload = {
159+
...data, // Include all original fields the backend might require
160+
slug,
161+
ref,
160162
branchId: branch,
161-
...values,
163+
164+
// 2. Explicitly map the form values to ensure nulls are preserved
165+
// instead of dropping them if they evaluate to undefined
166+
default_pool_size: values.default_pool_size,
167+
max_client_conn: values.max_client_conn ?? null,
168+
reserve_pool_size: values.reserve_pool_size ?? null,
169+
server_idle_timeout: values.server_idle_timeout ?? null,
170+
server_lifetime: values.server_lifetime ?? null,
171+
query_wait_timeout: values.query_wait_timeout ?? null,
162172
}
163173

174+
// 3. Remove the fields that PgBouncerPayload explicitly omits
175+
// (in case the backend rejects the request if they are present)
176+
delete (payload as any).pgbouncer_enabled
177+
delete (payload as any).pool_mode
178+
164179
updateConfig(payload as any, {
165180
onSuccess: () => {
166181
toast.success('PgBouncer configuration updated')
@@ -169,6 +184,8 @@ export const ConnectionPooling = () => {
169184
})
170185
}
171186

187+
188+
172189
const connectionPoolingUnavailable = data?.pool_mode === null
173190

174191
return (

apps/studio/components/interfaces/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ const BranchSidebarLinks = () => {
485485
<SideBarNavLink
486486
key={`settings-routes-${i}`}
487487
route={route}
488-
active={pathParts.includes("settings")}
488+
active={pathParts.includes("settings") && !pathParts.includes("database")}
489489
/>
490490
))}
491491
</SidebarGroup>

apps/studio/components/layouts/APIKeys/APIKeysLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const ApiKeysLayout = ({ children }: PropsWithChildren) => {
2424
<PageLayout
2525
title="API Keys"
2626
subtitle="Configure API keys to securely control access to your project"
27-
navigationItems={navigationItems}
27+
// navigationItems={navigationItems}
2828
>
2929
<ScaffoldContainer className="flex flex-col py-8 gap-8" bottomPadding>
3030
{children}

apps/studio/data/database/pgbouncer-config-update-mutation.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@ export type PgbouncerConfigurationUpdateVariables = {
1010
ref: string
1111
slug: string
1212
branchId: string
13-
} & Pick<
14-
components['schemas']['UpdatePgbouncerConfigBody'],
15-
'default_pool_size' | 'max_client_conn' | 'ignore_startup_parameters'
16-
>
13+
} & components['schemas']['UpdatePgbouncerConfigBody']
1714

1815
export async function updatePgbouncerConfiguration({
1916
slug,
2017
ref,
2118
branchId,
22-
default_pool_size,
23-
max_client_conn,
24-
ignore_startup_parameters,
19+
...body
2520
}: PgbouncerConfigurationUpdateVariables) {
2621
if (!slug) return console.error('Organization slug is required')
2722
if (!ref) return console.error('Project ref is required')
@@ -37,11 +32,7 @@ export async function updatePgbouncerConfiguration({
3732
branch: branchId,
3833
},
3934
},
40-
body: {
41-
default_pool_size,
42-
max_client_conn,
43-
ignore_startup_parameters,
44-
},
35+
body,
4536
}
4637
)
4738

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,43 @@
1+
import {
2+
ApiKeysCreateCallout,
3+
ApiKeysFeedbackBanner,
4+
} from 'components/interfaces/APIKeys/ApiKeysIllustrations'
5+
import { useApiKeysVisibility } from 'components/interfaces/APIKeys/hooks/useApiKeysVisibility'
6+
import { PublishableAPIKeys } from 'components/interfaces/APIKeys/PublishableAPIKeys'
7+
import { SecretAPIKeys } from 'components/interfaces/APIKeys/SecretAPIKeys'
18
import ApiKeysLayout from 'components/layouts/APIKeys/APIKeysLayout'
29
import DefaultLayout from 'components/layouts/DefaultLayout'
310
import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'
4-
import { DisplayApiSettings } from 'components/ui/ProjectSettings'
11+
import { DisableInteraction } from 'components/ui/DisableInteraction'
512
import type { NextPageWithLayout } from 'types'
13+
import { Separator } from 'ui'
614

7-
const ApiKeysLegacyPage: NextPageWithLayout = () => {
8-
return <DisplayApiSettings showTitle={false} showNotice={false} />
15+
// const ApiKeysLegacyPage: NextPageWithLayout = () => {
16+
// return <DisplayApiSettings showTitle={false} showNotice={false} />
17+
// }
18+
19+
const ApiKeysNewPage: NextPageWithLayout = () => {
20+
const { shouldDisableUI, canInitApiKeys } = useApiKeysVisibility()
21+
22+
return (
23+
<>
24+
{canInitApiKeys && <ApiKeysCreateCallout />}
25+
<ApiKeysFeedbackBanner />
26+
<DisableInteraction disabled={shouldDisableUI} className="flex flex-col gap-8">
27+
<PublishableAPIKeys />
28+
<Separator />
29+
<SecretAPIKeys />
30+
</DisableInteraction>
31+
</>
32+
)
933
}
1034

11-
ApiKeysLegacyPage.getLayout = (page) => (
35+
ApiKeysNewPage.getLayout = (page) => (
1236
<DefaultLayout>
1337
<SettingsLayout>
1438
<ApiKeysLayout>{page}</ApiKeysLayout>
1539
</SettingsLayout>
1640
</DefaultLayout>
1741
)
1842

19-
export default ApiKeysLegacyPage
43+
export default ApiKeysNewPage
Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
1-
import {
2-
ApiKeysCreateCallout,
3-
ApiKeysFeedbackBanner,
4-
} from 'components/interfaces/APIKeys/ApiKeysIllustrations'
5-
import { useApiKeysVisibility } from 'components/interfaces/APIKeys/hooks/useApiKeysVisibility'
6-
import { PublishableAPIKeys } from 'components/interfaces/APIKeys/PublishableAPIKeys'
7-
import { SecretAPIKeys } from 'components/interfaces/APIKeys/SecretAPIKeys'
8-
import ApiKeysLayout from 'components/layouts/APIKeys/APIKeysLayout'
9-
import DefaultLayout from 'components/layouts/DefaultLayout'
10-
import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'
11-
import { DisableInteraction } from 'components/ui/DisableInteraction'
12-
import type { NextPageWithLayout } from 'types'
13-
import { Separator } from 'ui'
1+
// This page is currently not in use. It was the original page for API Keys settings, but has been replaced by a new page at the same route. The old page is kept here for reference and potential future use, but is not exported or used in the app.
2+
// const ApiKeysLegacyPage: NextPageWithLayout = () => {
3+
// return <DisplayApiSettings showTitle={false} showNotice={false} />
4+
// }
145

15-
const ApiKeysNewPage: NextPageWithLayout = () => {
16-
const { shouldDisableUI, canInitApiKeys } = useApiKeysVisibility()
6+
// duplicate of the new page at the same route, but with the old API keys display component. This is kept for reference and potential future use, but is not exported or used in the app.
7+
// import {
8+
// ApiKeysCreateCallout,
9+
// ApiKeysFeedbackBanner,
10+
// } from 'components/interfaces/APIKeys/ApiKeysIllustrations'
11+
// import { useApiKeysVisibility } from 'components/interfaces/APIKeys/hooks/useApiKeysVisibility'
12+
// import { PublishableAPIKeys } from 'components/interfaces/APIKeys/PublishableAPIKeys'
13+
// import { SecretAPIKeys } from 'components/interfaces/APIKeys/SecretAPIKeys'
14+
// import ApiKeysLayout from 'components/layouts/APIKeys/APIKeysLayout'
15+
// import DefaultLayout from 'components/layouts/DefaultLayout'
16+
// import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'
17+
// import { DisableInteraction } from 'components/ui/DisableInteraction'
18+
// import type { NextPageWithLayout } from 'types'
19+
// import { Separator } from 'ui'
1720

18-
return (
19-
<>
20-
{canInitApiKeys && <ApiKeysCreateCallout />}
21-
<ApiKeysFeedbackBanner />
22-
<DisableInteraction disabled={shouldDisableUI} className="flex flex-col gap-8">
23-
<PublishableAPIKeys />
24-
<Separator />
25-
<SecretAPIKeys />
26-
</DisableInteraction>
27-
</>
28-
)
29-
}
21+
// const ApiKeysNewPage: NextPageWithLayout = () => {
22+
// const { shouldDisableUI, canInitApiKeys } = useApiKeysVisibility()
3023

31-
ApiKeysNewPage.getLayout = (page) => (
32-
<DefaultLayout>
33-
<SettingsLayout>
34-
<ApiKeysLayout>{page}</ApiKeysLayout>
35-
</SettingsLayout>
36-
</DefaultLayout>
37-
)
24+
// return (
25+
// <>
26+
// {canInitApiKeys && <ApiKeysCreateCallout />}
27+
// <ApiKeysFeedbackBanner />
28+
// <DisableInteraction disabled={shouldDisableUI} className="flex flex-col gap-8">
29+
// <PublishableAPIKeys />
30+
// <Separator />
31+
// <SecretAPIKeys />
32+
// </DisableInteraction>
33+
// </>
34+
// )
35+
// }
3836

39-
export default ApiKeysNewPage
37+
// ApiKeysNewPage.getLayout = (page) => (
38+
// <DefaultLayout>
39+
// <SettingsLayout>
40+
// <ApiKeysLayout>{page}</ApiKeysLayout>
41+
// </SettingsLayout>
42+
// </DefaultLayout>
43+
// )
44+
45+
// export default ApiKeysNewPage

0 commit comments

Comments
 (0)