@@ -62,48 +70,93 @@ const LangSelector = ({
>
Bash
- {selectedLang == 'bash' && (
-
+ {selectedLang == 'bash' && !isLoadingAPIKeys && apiKeys && apiKeys.length > 0 && (
+
- Project API key :
+ Project API key:
-
+
- <>
- setShowApiKey(DEFAULT_KEY)}>
- hide
-
- {anonApiKey && (
-
- setShowApiKey({
- key: anonApiKey.api_key ?? '-',
- name: 'anon (public)',
- })
- }
- >
- anon (public)
-
+
+ setSelectedApiKey(DEFAULT_KEY)}
+ >
+ Hide keys
+
+
+ {publishableKeys.length > 0 && (
+ <>
+
+ Publishable keys
+ {publishableKeys.map((key) => {
+ const value = key.api_key
+ return (
+
+ setSelectedApiKey({
+ name: `Publishable key: ${key.name}`,
+ key: value,
+ })
+ }
+ >
+ {key.name}
+
+ )
+ })}
+ >
)}
- {canReadServiceKey && (
-
- setShowApiKey({
- key: serviceApiKey?.api_key ?? '-',
- name: 'service_role (secret)',
- })
- }
- >
- service_role (secret)
-
+
+ {secretKeys.length > 0 && (
+ <>
+
+ Secret keys
+ {secretKeys.map((key) => {
+ const value = key.prefix + '...'
+ return (
+
+ setSelectedApiKey({ name: `Secret key: ${key.name}`, key: value })
+ }
+ >
+ {key.name}
+
+ )
+ })}
+ >
)}
- >
+
+
+
+
+ JWT-based legacy keys
+ {legacyKeys.map((key) => {
+ const value = key.api_key
+ return (
+
+ setSelectedApiKey({ name: `Legacy key: ${key.name}`, key: value })
+ }
+ >
+ {key.name}
+
+ )
+ })}
+
+
diff --git a/apps/studio/data/config/project-settings-v2-query.ts b/apps/studio/data/config/project-settings-v2-query.ts
index b76d50f85f945..9b8d65e071d41 100644
--- a/apps/studio/data/config/project-settings-v2-query.ts
+++ b/apps/studio/data/config/project-settings-v2-query.ts
@@ -63,6 +63,9 @@ export const useProjectSettingsV2Query =
(
)
}
+/**
+ * @deprecated Use api-keys-query instead!
+ */
export const getAPIKeys = (settings?: ProjectSettings) => {
const anonKey = (settings?.service_api_keys ?? []).find((x) => x.tags === 'anon')
const serviceKey = (settings?.service_api_keys ?? []).find((x) => x.tags === 'service_role')
diff --git a/apps/studio/pages/project/[ref]/api/index.tsx b/apps/studio/pages/project/[ref]/api/index.tsx
index 9e34e08a2b7d0..b324749bdb1bd 100644
--- a/apps/studio/pages/project/[ref]/api/index.tsx
+++ b/apps/studio/pages/project/[ref]/api/index.tsx
@@ -3,13 +3,13 @@ import { useState } from 'react'
import { GeneralContent, ResourceContent, RpcContent } from 'components/interfaces/Docs'
import LangSelector from 'components/interfaces/Docs/LangSelector'
+import DefaultLayout from 'components/layouts/DefaultLayout'
import DocsLayout from 'components/layouts/DocsLayout/DocsLayout'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query'
import { useProjectJsonSchemaQuery } from 'data/docs/project-json-schema-query'
import { snakeToCamel } from 'lib/helpers'
import type { NextPageWithLayout } from 'types'
-import DefaultLayout from 'components/layouts/DefaultLayout'
const PageConfig: NextPageWithLayout = () => {
return
@@ -29,7 +29,7 @@ const DocView = () => {
const { ref: projectRef, page, resource, rpc } = useParams()
const [selectedLang, setSelectedLang] = useState('js')
- const [showApiKey, setShowApiKey] = useState(DEFAULT_KEY)
+ const [selectedApikey, setSelectedApiKey] = useState(DEFAULT_KEY)
const { data: settings, error: settingsError } = useProjectSettingsV2Query({ projectRef })
const {
@@ -112,9 +112,9 @@ const DocView = () => {
@@ -124,7 +124,7 @@ const DocView = () => {
selectedLang={selectedLang}
resourceId={resource}
resources={resources}
- showApiKey={showApiKey.key}
+ showApiKey={selectedApikey.key}
refreshDocs={refreshDocs}
/>
) : rpc ? (
@@ -133,11 +133,15 @@ const DocView = () => {
rpcId={rpc}
paths={paths}
rpcs={rpcs}
- showApiKey={showApiKey.key}
+ showApiKey={selectedApikey.key}
refreshDocs={refreshDocs}
/>
) : (
-
+
)}
From ae9ce3d01015e64815b5b8013dde889e830aec7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?=
Date: Tue, 24 Jun 2025 11:23:56 +0800
Subject: [PATCH 3/5] fix: payment method selection (#36623)
---
.../Subscription/SubscriptionPlanUpdateDialog.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/SubscriptionPlanUpdateDialog.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/SubscriptionPlanUpdateDialog.tsx
index 1fa2c2d6af279..5dafba5472326 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/SubscriptionPlanUpdateDialog.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/SubscriptionPlanUpdateDialog.tsx
@@ -554,7 +554,7 @@ export const SubscriptionPlanUpdateDialog = ({
{}}
+ onSelectPaymentMethod={(pm) => setSelectedPaymentMethod(pm)}
createPaymentMethodInline={
subscriptionPreview.pending_subscription_flow === true
}
From 4e3264dc45d11a8a8e795e1d170a3c2758a6e6db Mon Sep 17 00:00:00 2001
From: Terry Sutton
Date: Tue, 24 Jun 2025 01:05:10 -0230
Subject: [PATCH 4/5] Update nextjs logo (#36620)
* Update nextjs logo
* Update link for Next.js subscription and Auth example
---------
Co-authored-by: Joshen Lim
---
apps/studio/components/interfaces/Home/Home.constants.ts | 2 +-
apps/studio/public/img/libraries/nextjs-dark-icon.svg | 4 +---
apps/studio/public/img/libraries/nextjs-icon.svg | 4 +---
3 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/apps/studio/components/interfaces/Home/Home.constants.ts b/apps/studio/components/interfaces/Home/Home.constants.ts
index dc3aa38e38750..46181f40fdcc9 100644
--- a/apps/studio/components/interfaces/Home/Home.constants.ts
+++ b/apps/studio/components/interfaces/Home/Home.constants.ts
@@ -63,7 +63,7 @@ export const EXAMPLE_PROJECTS = [
framework: 'nextjs',
title: 'Next.js Subscription and Auth',
description: 'The all-in-one starter kit for high-performance SaaS applications.',
- url: 'https://github.com/vercel/nextjs-subscription-payments',
+ url: 'https://github.com/nextjs/saas-starter',
type: 'app',
},
{
diff --git a/apps/studio/public/img/libraries/nextjs-dark-icon.svg b/apps/studio/public/img/libraries/nextjs-dark-icon.svg
index 99afa3413d30f..60ef95ea6b075 100644
--- a/apps/studio/public/img/libraries/nextjs-dark-icon.svg
+++ b/apps/studio/public/img/libraries/nextjs-dark-icon.svg
@@ -1,3 +1 @@
-
+
\ No newline at end of file
diff --git a/apps/studio/public/img/libraries/nextjs-icon.svg b/apps/studio/public/img/libraries/nextjs-icon.svg
index c45d6e63fb907..60ef95ea6b075 100644
--- a/apps/studio/public/img/libraries/nextjs-icon.svg
+++ b/apps/studio/public/img/libraries/nextjs-icon.svg
@@ -1,3 +1 @@
-
+
\ No newline at end of file
From 8c8110a34cd3cba51b5b4a5d10e1650b2c79e617 Mon Sep 17 00:00:00 2001
From: Alaister Young
Date: Tue, 24 Jun 2025 12:01:33 +0800
Subject: [PATCH 5/5] chore: disable role impersonation for edge functions
(#36599)
* chore: disable role impersonation for edge functions
* allow service role and anon
---
.../EdgeFunctionTesterSheet.tsx | 12 +++++-
.../RoleImpersonationPopover.tsx | 7 +++-
.../RoleImpersonationSelector.tsx | 39 ++++++++++++-------
3 files changed, 41 insertions(+), 17 deletions(-)
diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx
index 11cd1dd9e04c1..7c65503db22ec 100644
--- a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx
+++ b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx
@@ -15,7 +15,10 @@ import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { IS_PLATFORM } from 'lib/constants'
import { prettifyJSON } from 'lib/helpers'
import { getRoleImpersonationJWT } from 'lib/role-impersonation'
-import { useGetImpersonatedRoleState } from 'state/role-impersonation-state'
+import {
+ RoleImpersonationStateContextProvider,
+ useGetImpersonatedRoleState,
+} from 'state/role-impersonation-state'
import {
Badge,
Button,
@@ -416,7 +419,12 @@ export const EdgeFunctionTesterSheet = ({ visible, onClose }: EdgeFunctionTester
-
+ {/* [Alaister]: We're using a fresh context here as edge functions don't allow impersonating users. */}
+
+
+