Merge branch 'master' into claude/dreamy-herschel-9ea1e3

This commit is contained in:
Jordi Enric committed 2026-05-05 16:25:26 +02:00
commit caa1db43b2
386 files changed
+79841 -65082

No files matched your search

-22
View File
@@ -126,17 +126,6 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: []
},
"admonition-description-only": {
name: "admonition-description-only",
type: "components:example",
registryDependencies: ["admonition"],
component: React.lazy(() => import("@/registry/default/example/admonition-description-only")),
source: "",
files: ["registry/default/example/admonition-description-only.tsx"],
category: "undefined",
subcategory: "undefined",
chunks: []
},
"admonition-warning": {
name: "admonition-warning",
type: "components:example",
@@ -148,17 +137,6 @@ export const Index: Record<string, any> = {
subcategory: "undefined",
chunks: []
},
"admonition-success": {
name: "admonition-success",
type: "components:example",
registryDependencies: ["admonition"],
component: React.lazy(() => import("@/registry/default/example/admonition-success")),
source: "",
files: ["registry/default/example/admonition-success.tsx"],
category: "undefined",
subcategory: "undefined",
chunks: []
},
"admonition-destructive": {
name: "admonition-destructive",
type: "components:example",
+4 -5
View File
@@ -1,20 +1,19 @@
'use client'
import { ThemeProvider } from 'common'
import { Provider as JotaiProvider } from 'jotai'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import { ThemeProviderProps } from 'next-themes/dist/types'
import { TooltipProvider } from 'ui'
import { MobileSidebarProvider } from '@/context/mobile-sidebar-context'
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
export function Providers({ children }: { children: React.ReactNode }) {
return (
<JotaiProvider>
<NextThemesProvider {...props}>
<ThemeProvider>
<TooltipProvider delayDuration={0}>
<MobileSidebarProvider>{children}</MobileSidebarProvider>
</TooltipProvider>
</NextThemesProvider>
</ThemeProvider>
</JotaiProvider>
)
}
+3 -7
View File
@@ -4,7 +4,7 @@ import '@/styles/globals.css'
import type { Metadata, Viewport } from 'next'
import { customFont, sourceCodePro } from './fonts'
import { ThemeProvider } from './Providers'
import { Providers } from './Providers'
import { Toaster } from './toaster'
const className = `${customFont.variable} ${sourceCodePro.variable}`
@@ -131,16 +131,12 @@ export default async function Layout({ children }: RootLayoutProps) {
/>
</head>
<body>
<ThemeProvider
themes={['dark', 'light', 'classic-dark']}
defaultTheme="system"
enableSystem
>
<Providers>
<div vaul-drawer-wrapper="">
<div className="relative flex min-h-screen flex-col bg-background">{children}</div>
</div>
<Toaster />
</ThemeProvider>
</Providers>
</body>
</html>
)
@@ -15,12 +15,6 @@ Admonition provides focus for situations that require a callout.
Use Admonition instead of [Alert](../components/alert) unless you specifically need the primitives. If in doubt, stick with Admonition.
Use `title` for the heading slot and `description` for short body copy. The `description` should always end in a period.
Use `children` instead of `description` when the body needs rich React or MDX content such as links, lists, or multiple paragraphs, and this cannot be achieved via a React Fragment as a `description` value.
Avoid `label` in new code. It is a legacy alias for `title` that still exists for older docs content.
## Usage
```tsx
@@ -53,7 +47,7 @@ Only ever use the `primary` (green) button `type` on a `default` Admonition. Eve
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Responsive
## Responsive
Resize your browser to see the button(s) change `layout` based on the Admonition’s width.
@@ -85,24 +79,6 @@ AlertError for example rolls up consistent error handling and support contact me
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Description only
You may omit the title when the Admonition is short and sits near a heading that already provides enough context. Do not do the inverse: a title-only Admonition usually reads like an incomplete sentence and should include supporting description copy.
<ComponentPreview
name="admonition-description-only"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Success
Use `success` strictly for positive, completed states where the user does not need to take corrective action.
<ComponentPreview
name="admonition-success"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]"
/>
### Sandwiched
Some [Card](../components/card) or [Dialog](../components/dialog) instances may need to include callout information in-between core content. Admonition can be used ‘full-bleed’ in these cases by removing borders and radii.
+2 -1
View File
@@ -20,6 +20,7 @@
"@hookform/resolvers": "^3.1.1",
"@tanstack/react-table": "^8.21.3",
"contentlayer2": "0.4.6",
"common": "workspace:*",
"date-fns": "^2.30.0",
"dayjs": "1.11.13",
"eslint-config-supabase": "workspace:*",
@@ -29,7 +30,7 @@
"markdown-wasm": "^1.2.0",
"next": "catalog:",
"next-contentlayer2": "0.4.6",
"next-themes": "^0.3.0",
"next-themes": "catalog:",
"react": "catalog:",
"react-data-grid": "7.0.0-beta.47",
"react-day-picker": "^9.11.1",
@@ -1,10 +0,0 @@
import { Admonition } from 'ui-patterns/admonition'
export default function AdmonitionDescriptionOnly() {
return (
<Admonition
type="default"
description="Changes to these settings can take a few minutes to appear across all projects."
/>
)
}
@@ -1,11 +0,0 @@
import { Admonition } from 'ui-patterns/admonition'
export default function AdmonitionSuccess() {
return (
<Admonition
type="success"
title="Success"
description="Your connection has been confirmed. You can now close this tab."
/>
)
}
@@ -24,7 +24,7 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
Input,
Input_Shadcn_ as Input,
Table,
TableBody,
TableCell,
@@ -196,7 +196,7 @@ export default function DataTableDemo() {
placeholder="Filter by email"
value={(table.getColumn('email')?.getFilterValue() as string) ?? ''}
onChange={(event) => table.getColumn('email')?.setFilterValue(event.target.value)}
className="max-w-sm"
className="max-w-xs"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -1,4 +1,4 @@
import { Button, Checkbox, Input, Textarea } from 'ui'
import { Button, Checkbox, Input_Shadcn_ as Input, Textarea } from 'ui'
import {
Field,
FieldDescription,
@@ -1,4 +1,4 @@
import { Input } from 'ui'
import { Input_Shadcn_ as Input } from 'ui'
import {
Field,
FieldDescription,
@@ -1,4 +1,4 @@
import { Input } from 'ui'
import { Input_Shadcn_ as Input } from 'ui'
import {
Field,
FieldDescription,
@@ -1,4 +1,4 @@
import { Button, Input, Textarea } from 'ui'
import { Button, Input_Shadcn_ as Input, Textarea } from 'ui'
import {
Field,
FieldContent,
@@ -12,7 +12,7 @@ import {
FormItem,
FormLabel,
FormMessage,
Input,
Input_Shadcn_ as Input,
} from 'ui'
import { z } from 'zod'
@@ -8,7 +8,9 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
Input,
InputGroup,
InputGroupAddon,
InputGroupInput,
Table,
TableBody,
TableCell,
@@ -68,12 +70,16 @@ export default function PageLayoutList() {
<div className="w-full space-y-4">
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-2 flex-wrap">
<div className="flex flex-col lg:flex-row lg:items-center gap-2">
<Input
placeholder="Search for a function"
size="tiny"
icon={<Search />}
className="w-full lg:w-52"
/>
<InputGroup>
<InputGroupInput
placeholder="Search for a function"
size="tiny"
className="w-full lg:w-52"
/>
<InputGroupAddon>
<Search />
</InputGroupAddon>
</InputGroup>
</div>
<Button type="primary">Create a new function</Button>
</div>
-12
View File
@@ -25,24 +25,12 @@ export const examples: Registry = [
registryDependencies: ['admonition'],
files: ['example/admonition-button.tsx'],
},
{
name: 'admonition-description-only',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-description-only.tsx'],
},
{
name: 'admonition-warning',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-warning.tsx'],
},
{
name: 'admonition-success',
type: 'components:example',
registryDependencies: ['admonition'],
files: ['example/admonition-success.tsx'],
},
{
name: 'admonition-destructive',
type: 'components:example',
+1 -1
View File
@@ -5,7 +5,7 @@
@import './../../../packages/ui/build/css/themes/classic-dark.css';
@import './../../../packages/ui/build/css/themes/light.css';
@config '../tailwind.config.cjs';
@config '../tailwind.config.js';
@import 'config/typography.css';
File renamed without changes.
+86 -5
View File
@@ -1,14 +1,15 @@
import { promises as fs } from 'fs'
import path from 'path'
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { BASE_PATH, IS_PRODUCTION, PROD_URL } from '~/lib/constants'
import { NextResponse } from 'next/server'
export async function GET(_request: Request, { params }: { params: Promise<{ slug: string[] }> }) {
export async function GET(request: Request, { params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params
const baseDir = path.join(process.cwd(), 'public/docs/guides')
const filePath = path.join(baseDir, `${slug.join('/')}.md`)
if (!filePath.startsWith(baseDir + path.sep) && filePath !== baseDir) {
return new NextResponse('Not found', { status: 404 })
return notFoundResponse(request, slug)
}
try {
@@ -20,6 +21,86 @@ export async function GET(_request: Request, { params }: { params: Promise<{ slu
},
})
} catch {
return new NextResponse('Not found', { status: 404 })
return notFoundResponse(request, slug)
}
}
/**
* Resolves the docs base URL from trusted sources only.
* Avoids host-header-driven SSRF from request origin.
*/
function resolveDocsBaseUrl() {
if (IS_PRODUCTION) return PROD_URL
if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}${BASE_PATH}`
if (process.env.NEXT_PUBLIC_SITE_URL) return `${process.env.NEXT_PUBLIC_SITE_URL}${BASE_PATH}`
return undefined
}
async function notFoundResponse(_request: Request, slug: string[]) {
const baseUrl = resolveDocsBaseUrl()
const query = slug.join(' ').replace(/[_-]/g, ' ')
const suggestions = baseUrl ? await searchForSuggestions(baseUrl, query) : []
const markdown = buildNotFoundMarkdown(slug, suggestions)
return new NextResponse(markdown, {
status: 404,
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
'Cache-Control': 'no-store',
},
})
}
interface SearchSuggestion {
title: string
href: string
}
async function searchForSuggestions(baseUrl: string, query: string): Promise<SearchSuggestion[]> {
try {
const response = await fetch(`${baseUrl}/api/graphql`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query SearchDocs($query: String!) {
searchDocs(query: $query, limit: 5) {
nodes {
title
href
}
}
}
`,
variables: { query },
}),
})
if (!response.ok) return []
const data = await response.json()
return (data?.data?.searchDocs?.nodes ?? []).filter(
(n: Partial<SearchSuggestion>): n is SearchSuggestion => !!n.title && !!n.href
)
} catch {
return []
}
}
function buildNotFoundMarkdown(slug: string[], suggestions: SearchSuggestion[]): string {
const pagePath = slug.join('/')
const suggestionsMd =
suggestions.length > 0
? `## You might be looking for...\n\n${suggestions
.map(({ title, href }) => `- [${title}](${href}.md)`)
.join('\n')}\n`
: ''
return `# 404 - Page Not Found
The page \`/docs/guides/${pagePath}.md\` does not exist.
${suggestionsMd}
See also: [Changelog](https://supabase.com/changelog.md)
`
}
@@ -1,6 +1,8 @@
import { useState } from 'react'
import { Button, Input } from 'ui'
import { Button, Input_Shadcn_ as Input } from 'ui'
import { Admonition } from 'ui-patterns/admonition'
import { Input as DataInput } from 'ui-patterns/DataInputs/Input'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
function base64URL(value: string) {
return globalThis.btoa(value).replace(/[=]/g, '').replace(/[+]/g, '-').replace(/[\/]/g, '_')
@@ -105,30 +107,45 @@ const AppleSecretGenerator = () => {
return (
<div className="flex flex-col gap-3">
<Input
<FormItemLayout
isReactForm={false}
layout="vertical"
label="Account ID"
description="Found in the upper-right corner of Apple Developer Center."
labelOptional="required"
placeholder="Apple Developer account ID, 10 alphanumeric digits"
descriptionText="Found in the upper-right corner of Apple Developer Center."
value={teamID}
onChange={(e) => setTeamID(e.target.value.trim())}
/>
<Input
>
<Input
placeholder="Apple Developer account ID, 10 alphanumeric digits"
value={teamID}
onChange={(e) => setTeamID(e.target.value.trim())}
/>
</FormItemLayout>
<FormItemLayout
isReactForm={false}
layout="vertical"
label="Service ID"
description="Found under Certificates, Identifiers & Profiles in Apple Developer Center."
labelOptional="required"
placeholder="ID of the service, example: com.example.app.service"
descriptionText="Found under Certificates, Identifiers & Profiles in Apple Developer Center."
value={serviceID}
onChange={(e) => setServiceID(e.target.value.trim())}
/>
<Input
>
<Input
placeholder="ID of the service, example: com.example.app.service"
value={serviceID}
onChange={(e) => setServiceID(e.target.value.trim())}
/>
</FormItemLayout>
<FormItemLayout
isReactForm={false}
layout="vertical"
label="Key ID"
description="If the file you select does not preserve the original name from Apple Developer Center, please enter the key ID."
labelOptional="(optional)"
placeholder="Extracted from filename, AuthKey_XXXXXXXXXX.p8"
descriptionText="If the file you select does not preserve the original name from Apple Developer Center, please enter the key ID."
value={keyID}
onChange={(e) => setKeyID(e.target.value.trim())}
/>
>
<Input
placeholder="Extracted from filename, AuthKey_XXXXXXXXXX.p8"
value={keyID}
onChange={(e) => setKeyID(e.target.value.trim())}
/>
</FormItemLayout>
<div>
<input
type="file"
@@ -176,14 +193,14 @@ const AppleSecretGenerator = () => {
{secretKey && (
<>
<div style={{ height: '1rem' }} />
<Input
<FormItemLayout
isReactForm={false}
layout="vertical"
label="Secret Key"
value={secretKey}
descriptionText={`Valid until: ${expiresAt}. Make sure you generate a new one before then!`}
reveal
copy
size="medium"
/>
description={`Valid until: ${expiresAt}. Make sure you generate a new one before then!`}
>
<DataInput value={secretKey} copy reveal />
</FormItemLayout>
</>
)}
</div>
@@ -2,7 +2,7 @@ import { X } from 'lucide-react'
import Link from 'next/link'
import React, { useState } from 'react'
import { extensions } from 'shared-data'
import { Badge, Input } from 'ui'
import { Badge, Input_Shadcn_ as Input } from 'ui'
import { GlassPanel } from 'ui-patterns/GlassPanel'
type Extension = {
+5 -5
View File
@@ -1,13 +1,13 @@
'use client'
import { ChevronRight, Play, Sparkles } from 'lucide-react'
import Link from 'next/link'
import { useTheme } from 'next-themes'
// End of third-party imports
import { isFeatureEnabled, useBreakpoint } from 'common'
import { ChevronRight, Play, Sparkles } from 'lucide-react'
import { useTheme } from 'next-themes'
import Link from 'next/link'
import { cn, IconBackground } from 'ui'
import { IconPanel } from 'ui-patterns/IconPanel'
import { getCustomContent } from '../lib/custom-content/getCustomContent'
import DocsCoverLogo from './DocsCoverLogo'
@@ -41,7 +41,7 @@ const HomePageCover = (props) => {
const iconSize = isXs ? 'sm' : 'lg'
const { homepageHeading } = getCustomContent(['homepage:heading'])
const { resolvedTheme } = useTheme()
const isLightMode = resolvedTheme !== 'dark'
const isLightMode = !resolvedTheme?.includes('dark')
const frameworks = [
{
@@ -60,11 +60,12 @@ interface WebhookPayload {
serve(async (req) => {
const payload: WebhookPayload = await req.json()
const soRecord = payload.record
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
const supabaseAdminClient = createClient<Database>(
// Supabase API URL - env var exported by default when deployed.
Deno.env.get('SUPABASE_URL') ?? '',
// Supabase API SERVICE ROLE KEY - env var exported by default when deployed.
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
// Supabase API SECRET KEY - env var exported by default when deployed.
Deno.env.get(SUPABASE_SECRET_KEYS['default']) ?? ''
)
// Construct image url from storage
+1 -1
View File
@@ -88,7 +88,7 @@ Future<void> main() async {
final auth0 = Auth0('AUTH0_DOMAIN', 'AUTH0_CLIENT_ID');
await Supabase.initialize(
url: 'https://<supabase-project>.supabase.co',
anonKey: 'SUPABASE_PUBLISHABLE_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
accessToken: () async {
final credentials = await auth0.credentialsManager.credentials();
return credentials.idToken;
+1 -1
View File
@@ -89,7 +89,7 @@ import 'package:supabase_flutter/supabase_flutter.dart';
Future<void> main() async {
await Supabase.initialize(
url: 'https://<supabase-project>.supabase.co',
anonKey: 'SUPABASE_PUBLISHABLE_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
accessToken: () async {
final session = await Amplify.Auth.fetchAuthSession();
final cognitoSession = session as CognitoAuthSession;
+1 -1
View File
@@ -56,7 +56,7 @@ import 'package:supabase_flutter/supabase_flutter.dart';
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_PUBLISHABLE_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
accessToken: () async {
final token = await ClerkAuth.of(context).sessionToken();
return token.jwt;
@@ -49,7 +49,7 @@ Creating a client for the Web is as easy as passing the `accessToken` async func
```dart
await Supabase.initialize(
url: supabaseUrl,
anonKey: supabaseKey,
publishableKey: publishableKey,
debug: false,
accessToken: () async {
final token = await FirebaseAuth.instance.currentUser?.getIdToken();
+4 -4
View File
@@ -171,7 +171,7 @@ See the [`@supabase/server` docs](https://github.com/supabase/server) for the fu
</Admonition>
### Authenticated user calls
### Authenticated user calls [#authenticated-user-calls-with-server-sdk]
`allow: 'user'` pairs with `verify_jwt = true`. The platform validates the JWT, and the SDK hands you `ctx.supabase` already scoped to the caller.
@@ -186,7 +186,7 @@ export default {
}
```
### Service-to-service calls
### Service-to-service calls [#service-to-service-calls-with-server-sdk]
`allow: 'secret:<name>'` validates the `apikey` header against the named secret key from your [dashboard](/dashboard/project/_/settings/api-keys) and gives you `ctx.supabaseAdmin` for privileged work. The `<name>` matches the name you gave the key. Keep `verify_jwt = false`.
@@ -209,11 +209,11 @@ Create a named secret key for each caller in the [**Settings > API keys**](/dash
</Admonition>
### Public functions
### Public functions [#public-functions-with-server-sdk]
The SDK adds nothing to a truly public function. Use the raw pattern from the previous section. If you need a Supabase client anyway, `allow: 'always'` with `verify_jwt = false` skips every check and treats every caller as anonymous.
### External webhooks
### External webhooks [#external-webhooks-with-server-sdk]
Use `allow: 'always'` to skip the SDK's credential check, then verify the provider's signature inside the handler. Keep `verify_jwt = false`.
@@ -117,10 +117,10 @@ console.log(`Function "elevenlabs-scribe-bot" up and running!`)
const elevenLabsClient = new ElevenLabsClient({
apiKey: Deno.env.get('ELEVENLABS_API_KEY') || '',
})
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
const supabase = createClient(
Deno.env.get('SUPABASE_URL') || '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') || ''
Deno.env.get(SUPABASE_SECRET_KEYS['default']) || ''
)
async function scribe({
@@ -61,3 +61,57 @@ with check (
bucket_id = 'cats' and storage.extension(name) = 'png'
);
```
### `storage.allow_only_operation()`
Returns `true` when the current Storage API operation exactly matches the provided operation name.
This is useful when a single SQL privilege such as `SELECT` is used by multiple Storage actions, but you want a policy to apply to only one of them, such as object listing versus object download.
The current operation names are defined in [`src/http/routes/operations.ts`](https://github.com/supabase/storage/blob/master/src/http/routes/operations.ts).
Storage normalizes operation names before comparing them, so both of the following forms are treated as equivalent:
- `storage.object.list`
- `object.list`
The comparison remains exact after normalization. Partial values such as `object` do not match `object.list`. If the current operation is not set, or the input is empty, the function returns `false`.
**Usage**
This example demonstrates how you would allow authenticated users to list only their own objects:
```sql
create policy "Allow users to list their own objects"
on storage.objects
for select
to authenticated
using (
storage.allow_only_operation('object.list')
and owner_id = (select auth.uid()::text)
);
```
### `storage.allow_any_operation()`
Returns `true` when the current Storage API operation exactly matches any operation in the provided array.
Use this when the same policy should apply to a small set of Storage actions.
**Usage**
This example demonstrates how you would allow authenticated users to list their own objects and read their own authenticated objects:
```sql
create policy "Allow users to list and read their own authenticated objects"
on storage.objects
for select
to authenticated
using (
storage.allow_any_operation(ARRAY[
'object.list',
'storage.object.get_authenticated'
])
and owner_id = (select auth.uid()::text)
);
```
@@ -16,6 +16,8 @@ By default Storage does not allow any uploads to buckets without RLS policies. Y
You can find the documentation for the storage schema [here](/docs/guides/storage/schema/design) , and to simplify the process of crafting your policies, you can utilize these [helper functions](/docs/guides/storage/schema/helper-functions) .
If you need different `SELECT` policies for different Storage actions, such as listing objects versus reading authenticated objects, use the operation-aware helpers `storage.allow_only_operation()` and `storage.allow_any_operation()` documented in [Storage Helper Functions](/docs/guides/storage/schema/helper-functions).
<Admonition type="note">
The RLS policies required for different operations are documented [here](/docs/reference/javascript/storage-createbucket)
@@ -0,0 +1,27 @@
---
title = "Database: \"Error: too many connections for database \"postgres\"\""
topics = [ "database" ]
keywords = []
---
When getting an error where your connections are overwhelmed `Error: too many connections for database "postgres"`
## Why this occurs
This issue occurs when `datconnlimit` gets modified. The default value for `datconnlimit` is -1.
https://www.postgresql.org/docs/current/catalog-pg-database.html
## To check and resolve
1. **Check the value for `datconnlimit` using the query below**
```bash
select datconnlimit from pg_database where datname='postgres';
```
- If the value you see is 0 or any other value other than -1, proceed with the next step.
2. **Update `datconnlimit` to DEFAULT**
```bash
ALTER DATABASE postgres CONNECTION LIMIT DEFAULT;
```
+6 -6
View File
@@ -44,7 +44,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart main.dart
await Supabase.initialize(
url: supabaseUrl,
anonKey: supabaseKey,
publishableKey: publishableKey,
authFlowType: AuthFlowType.pkce,
storageRetryAttempts: 10,
realtimeClientOptions: const RealtimeClientOptions(
@@ -59,7 +59,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart main.dart
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_ANON_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
authOptions: const FlutterAuthClientOptions(
authFlowType: AuthFlowType.pkce,
),
@@ -295,7 +295,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_ANON_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
authFlowType: AuthFlowType.implicit, // set to implicit by default
);
```
@@ -305,7 +305,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_ANON_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
authOptions: FlutterAuthClientOptions(
authFlowType: AuthFlowType.pkce, // set to pkce by default
)
@@ -339,7 +339,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_ANON_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
authCallbackUrlHostname: 'auth-callback',
);
```
@@ -349,7 +349,7 @@ We have brought numerous updates behind the scenes to make the SDK work more int
```dart
await Supabase.initialize(
url: 'SUPABASE_URL',
anonKey: 'SUPABASE_ANON_KEY',
publishableKey: 'SUPABASE_PUBLISHABLE_KEY',
);
```
@@ -88,7 +88,7 @@ With TypeScript, `supabase-js` detects things like `not null` constraints and [g
const supabase = createClient<Database>(
process.env.SUPABASE_URL,
process.env.SUPABASE_ANON_KEY
process.env.SUPABASE_PUBLISHABLE_KEY
)
```
@@ -43,7 +43,7 @@ _Optionally_ if you are using custom configuration with `createClient` then foll
<TabPanel id="1.0x" label="Before">
```ts src/supabaseClient.ts
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {
schema: 'custom',
persistSession: false,
})
@@ -53,7 +53,7 @@ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
<TabPanel id="2.0x" label="After">
```ts src/supabaseClient.ts
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
const supabase = createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {
db: {
schema: 'custom',
},
+1 -1
View File
@@ -24,7 +24,7 @@ function GlobalProviders({ children }: PropsWithChildren) {
<DevToolbarProvider apiUrl={API_URL}>
<PageTelemetry />
<ScrollRestoration />
<ThemeProvider defaultTheme="system" enableSystem disableTransitionOnChange>
<ThemeProvider>
<TooltipProvider delayDuration={0}>
<DocsCommandProvider>
<div className="flex flex-col">
File diff suppressed because it is too large. Load diff
+2 -3
View File
@@ -93,7 +93,7 @@
"next": "^15.5.15",
"next-mdx-remote": "^6.0.0",
"next-plugin-yaml": "^1.0.1",
"next-themes": "^0.3.0",
"next-themes": "catalog:",
"nuqs": "^1.19.1",
"openai": "^4.75.1",
"openapi-fetch": "0.12.4",
@@ -119,7 +119,7 @@
"unist-builder": "^3.0.1",
"unist-util-filter": "^4.0.1",
"unist-util-visit": "^4.1.2",
"uuid": "^9.0.1",
"uuid": "^14.0.0",
"valtio": "catalog:",
"yaml": "^2.8.1",
"zod": "catalog:"
@@ -144,7 +144,6 @@
"@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-dom": "catalog:",
"@types/unist": "^2.0.6",
"@types/uuid": "^10.0.0",
"@redocly/cli": "^2.25.3",
"amaro": "^1.1.5",
"api-types": "workspace:*",
+4
View File
@@ -35,6 +35,7 @@ Beng Eu
Benjamin Coenen
Bo Lu
Bobbie Soedirgo
Brad Gyger
Brendan Stephens
Brent Newson
Carel de Waal
@@ -59,6 +60,7 @@ Colum Ferry
Craig Cannon
Cuong Do
Dane Harrigan
Daniel Mitterdorfer
Daniel Velázquez Lara
Danny White
Dave Wilson
@@ -140,6 +142,7 @@ Jordi Enric
José Luis Ledesma
Joshen Lim
Julien Goux
Kai M
Kalleby Santos
Kanishk Dudeja
Kamil Ogórek
@@ -171,6 +174,7 @@ Marcus Weiner
Margarita Sandomirskaia
Mark Burggraf
Matthew Hambright
Matt Hudson
Matt Johnston
Matt Rossman
Matthias Luft
+114 -40
View File
@@ -1920,7 +1920,7 @@
"200": {
"description": "",
"content": {
"application/json": { "schema": { "$ref": "#/components/schemas/JitAccessResponse" } }
"application/json": { "schema": { "$ref": "#/components/schemas/JitStateResponse" } }
}
},
"401": { "description": "Unauthorized" },
@@ -1964,7 +1964,7 @@
"200": {
"description": "",
"content": {
"application/json": { "schema": { "$ref": "#/components/schemas/JitAccessResponse" } }
"application/json": { "schema": { "$ref": "#/components/schemas/JitStateResponse" } }
}
},
"401": { "description": "Unauthorized" },
@@ -6857,6 +6857,45 @@
"x-oauth-scope": "database:read"
}
},
"/v1/projects/{ref}/database/backups/restore": {
"post": {
"operationId": "v1-restore-physical-backup",
"parameters": [
{
"name": "ref",
"required": true,
"in": "path",
"description": "Project ref",
"schema": {
"minLength": 20,
"maxLength": 20,
"pattern": "^[a-z]+$",
"example": "abcdefghijklmnopqrst",
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": { "schema": { "$ref": "#/components/schemas/V1RestoreBackupBody" } }
}
},
"responses": {
"201": { "description": "" },
"401": { "description": "Unauthorized" },
"403": { "description": "Forbidden action" },
"429": { "description": "Rate limit exceeded" }
},
"security": [{ "bearer": [] }, { "fga_permissions": ["backups_write"] }],
"summary": "Restores a physical backup for a database",
"tags": ["Database"],
"x-badges": [{ "name": "OAuth scope: database:write", "position": "after" }],
"x-endpoint-owners": ["infra"],
"x-internal": true,
"x-oauth-scope": "database:write"
}
},
"/v1/projects/{ref}/database/backups/undo": {
"post": {
"operationId": "v1-undo",
@@ -8306,44 +8345,33 @@
"required": ["custom_hostname"],
"example": { "custom_hostname": "docs.example.com" }
},
"JitAccessResponse": {
"type": "object",
"properties": {
"user_id": { "type": "string", "format": "uuid" },
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": { "type": "string", "minLength": 1 },
"expires_at": { "type": "number" },
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": { "cidr": { "type": "string" } },
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": { "cidr": { "type": "string" } },
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
"JitStateResponse": {
"discriminator": { "propertyName": "state" },
"oneOf": [
{
"type": "object",
"properties": {
"state": { "type": "string", "enum": ["enabled", "disabled"] },
"appliedSuccessfully": { "type": "boolean" }
},
"required": ["state"]
},
{
"type": "object",
"properties": {
"state": { "type": "string", "enum": ["unavailable"] },
"unavailableReason": {
"type": "string",
"enum": [
"manual_migration_required",
"postgres_upgrade_required",
"temporarily_unavailable"
]
}
},
"required": ["state", "unavailableReason"]
}
},
"required": ["user_id", "user_roles"]
]
},
"JitAccessRequestRequest": {
"type": "object",
@@ -10674,6 +10702,45 @@
"properties": { "message": { "type": "string" } },
"required": ["message"]
},
"JitAccessResponse": {
"type": "object",
"properties": {
"user_id": { "type": "string", "format": "uuid" },
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": { "type": "string", "minLength": 1 },
"expires_at": { "type": "number" },
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": { "cidr": { "type": "string" } },
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": { "cidr": { "type": "string" } },
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
}
},
"required": ["user_id", "user_roles"]
},
"AuthorizeJitAccessBody": {
"type": "object",
"properties": {
@@ -11988,6 +12055,7 @@
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"is_physical_backup": { "type": "boolean" },
"status": {
"type": "string",
@@ -11995,7 +12063,7 @@
},
"inserted_at": { "type": "string" }
},
"required": ["is_physical_backup", "status", "inserted_at"]
"required": ["id", "is_physical_backup", "status", "inserted_at"]
}
},
"physical_backup_data": {
@@ -12031,6 +12099,12 @@
},
"required": ["name", "status", "completed_on"]
},
"V1RestoreBackupBody": {
"type": "object",
"properties": { "id": { "type": "integer" } },
"required": ["id"],
"example": { "id": 12345 }
},
"V1UndoBody": {
"type": "object",
"properties": { "name": { "type": "string", "maxLength": 20 } },
+3 -1
View File
@@ -1,7 +1,7 @@
clispec: '001'
info:
id: cli
version: 2.95.4
version: 2.98.1
title: Supabase CLI
language: sh
source: https://github.com/supabase/cli
@@ -548,6 +548,8 @@ commands:
> It is recommended to have at least 7GB of RAM to start all services.
Health checks are automatically added to verify the started containers. Use `--ignore-health-check` flag to ignore these errors.
> If the CLI is running inside a dev container with the Docker socket bind-mounted, set the `SUPABASE_SERVICES_HOSTNAME` environment variable to the hostname reachable from inside that container, such as `host.docker.internal`.
examples:
- id: basic-usage
name: Basic usage
File diff suppressed because it is too large. Load diff
@@ -23,7 +23,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 96,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L96"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L96"
}
],
"type": {
@@ -42,7 +42,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 97,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L97"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L97"
}
],
"type": {
@@ -61,7 +61,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 98,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L98"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L98"
}
],
"type": {
@@ -80,7 +80,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 99,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L99"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L99"
}
],
"type": {
@@ -99,7 +99,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 100,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L100"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L100"
}
],
"type": {
@@ -118,7 +118,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 101,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L101"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L101"
}
],
"type": {
@@ -137,7 +137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 102,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L102"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L102"
}
],
"type": {
@@ -156,7 +156,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 103,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L103"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L103"
}
],
"type": {
@@ -175,7 +175,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 104,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L104"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L104"
}
],
"type": {
@@ -194,7 +194,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 105,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L105"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L105"
}
],
"type": {
@@ -213,7 +213,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 106,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L106"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L106"
}
],
"type": {
@@ -232,7 +232,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 107,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L107"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L107"
}
],
"type": {
@@ -251,7 +251,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 108,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L108"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L108"
}
],
"type": {
@@ -270,7 +270,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 109,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L109"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L109"
}
],
"type": {
@@ -289,7 +289,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 110,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L110"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L110"
}
],
"type": {
@@ -309,7 +309,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 95,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L95"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L95"
}
]
},
@@ -339,7 +339,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L44"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"signatures": [
@@ -372,7 +372,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -393,7 +393,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L44"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"parameters": [
@@ -436,7 +436,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 52,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L52"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L52"
}
],
"type": {
@@ -665,7 +665,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 51,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L51"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L51"
}
],
"type": {
@@ -702,7 +702,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 53,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L53"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L53"
}
],
"type": {
@@ -725,7 +725,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 50,
"character": 7,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L50"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L50"
}
]
}
@@ -755,7 +755,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 19,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L19"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L19"
}
],
"type": {
@@ -984,7 +984,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 17,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L17"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L17"
}
],
"type": {
@@ -1020,7 +1020,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 18,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L18"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L18"
}
],
"type": {
@@ -1043,7 +1043,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L16"
}
],
"type": {
@@ -1062,7 +1062,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L202"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"signatures": [
@@ -1094,7 +1094,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -1490,7 +1490,7 @@
},
{
"tag": "@example",
"name": "Example 7",
"name": "Standalone client invoke",
"content": [
{
"kind": "code",
@@ -1505,7 +1505,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L202"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"typeParameters": [
@@ -1604,7 +1604,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"signatures": [
@@ -1627,7 +1627,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -1648,7 +1648,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"parameters": [
@@ -1696,7 +1696,7 @@
],
"categories": [
{
"title": "Functions",
"title": "Edge Functions",
"children": [2, 31, 28]
},
{
@@ -1709,7 +1709,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 15,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L15"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L15"
}
]
},
@@ -1750,7 +1750,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L32"
}
],
"signatures": [
@@ -1765,7 +1765,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L32"
}
],
"parameters": [
@@ -1836,7 +1836,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -1855,7 +1855,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -1870,7 +1870,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1893,7 +1893,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1912,7 +1912,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1931,7 +1931,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1951,7 +1951,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -1979,7 +1979,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 30,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L30"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L30"
}
],
"extendedTypes": [
@@ -2048,7 +2048,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L58"
}
],
"signatures": [
@@ -2063,7 +2063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L58"
}
],
"parameters": [
@@ -2111,7 +2111,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2137,7 +2137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2154,7 +2154,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2177,7 +2177,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2196,7 +2196,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2215,7 +2215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2235,7 +2235,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2273,7 +2273,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 57,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L57"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L57"
}
],
"extendedTypes": [
@@ -2322,7 +2322,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L90"
}
],
"signatures": [
@@ -2337,7 +2337,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L90"
}
],
"parameters": [
@@ -2385,7 +2385,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2411,7 +2411,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2428,7 +2428,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2451,7 +2451,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2470,7 +2470,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2489,7 +2489,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2509,7 +2509,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2547,7 +2547,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 89,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L89"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L89"
}
],
"extendedTypes": [
@@ -2596,7 +2596,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L74"
}
],
"signatures": [
@@ -2611,7 +2611,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L74"
}
],
"parameters": [
@@ -2659,7 +2659,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2685,7 +2685,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2702,7 +2702,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2725,7 +2725,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2744,7 +2744,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2763,7 +2763,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2783,7 +2783,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2821,7 +2821,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 73,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L73"
}
],
"extendedTypes": [
@@ -2844,7 +2844,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L113"
}
],
"type": {
@@ -2877,7 +2877,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 129,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L129"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L129"
}
],
"type": {
@@ -2986,7 +2986,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"type": {
@@ -3002,7 +3002,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"indexSignatures": [
@@ -3017,7 +3017,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"parameters": [
@@ -3063,7 +3063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 121,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L121"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L121"
}
],
"type": {
@@ -3113,7 +3113,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 125,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L125"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L125"
}
],
"type": {
@@ -3144,7 +3144,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 140,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L140"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L140"
}
],
"type": {
@@ -3178,7 +3178,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 145,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L145"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L145"
}
],
"type": {
@@ -3198,7 +3198,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 36,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L113"
}
]
}
@@ -3215,7 +3215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L16"
}
],
"typeParameters": [
@@ -23,7 +23,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 96,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L96"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L96"
}
],
"type": {
@@ -42,7 +42,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 97,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L97"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L97"
}
],
"type": {
@@ -61,7 +61,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 98,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L98"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L98"
}
],
"type": {
@@ -80,7 +80,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 99,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L99"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L99"
}
],
"type": {
@@ -99,7 +99,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 100,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L100"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L100"
}
],
"type": {
@@ -118,7 +118,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 101,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L101"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L101"
}
],
"type": {
@@ -137,7 +137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 102,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L102"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L102"
}
],
"type": {
@@ -156,7 +156,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 103,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L103"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L103"
}
],
"type": {
@@ -175,7 +175,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 104,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L104"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L104"
}
],
"type": {
@@ -194,7 +194,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 105,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L105"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L105"
}
],
"type": {
@@ -213,7 +213,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 106,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L106"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L106"
}
],
"type": {
@@ -232,7 +232,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 107,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L107"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L107"
}
],
"type": {
@@ -251,7 +251,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 108,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L108"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L108"
}
],
"type": {
@@ -270,7 +270,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 109,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L109"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L109"
}
],
"type": {
@@ -289,7 +289,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 110,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L110"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L110"
}
],
"type": {
@@ -309,7 +309,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 95,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L95"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L95"
}
]
},
@@ -339,7 +339,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L44"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"signatures": [
@@ -372,7 +372,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -393,7 +393,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 44,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L44"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L44"
}
],
"parameters": [
@@ -436,7 +436,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 52,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L52"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L52"
}
],
"type": {
@@ -665,7 +665,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 51,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L51"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L51"
}
],
"type": {
@@ -702,7 +702,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 53,
"character": 6,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L53"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L53"
}
],
"type": {
@@ -725,7 +725,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 50,
"character": 7,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L50"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L50"
}
]
}
@@ -755,7 +755,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 19,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L19"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L19"
}
],
"type": {
@@ -984,7 +984,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 17,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L17"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L17"
}
],
"type": {
@@ -1020,7 +1020,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 18,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L18"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L18"
}
],
"type": {
@@ -1043,7 +1043,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L16"
}
],
"type": {
@@ -1062,7 +1062,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L202"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"signatures": [
@@ -1094,7 +1094,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -1490,7 +1490,7 @@
},
{
"tag": "@example",
"name": "Example 7",
"name": "Standalone client invoke",
"content": [
{
"kind": "code",
@@ -1505,7 +1505,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 202,
"character": 8,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L202"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L202"
}
],
"typeParameters": [
@@ -1604,7 +1604,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"signatures": [
@@ -1627,7 +1627,7 @@
"content": [
{
"kind": "text",
"text": "Functions"
"text": "Edge Functions"
}
]
},
@@ -1648,7 +1648,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 73,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L73"
}
],
"parameters": [
@@ -1696,7 +1696,7 @@
],
"categories": [
{
"title": "Functions",
"title": "Edge Functions",
"children": [2, 31, 28]
},
{
@@ -1709,7 +1709,7 @@
"fileName": "packages/core/functions-js/src/FunctionsClient.ts",
"line": 15,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/FunctionsClient.ts#L15"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/FunctionsClient.ts#L15"
}
]
},
@@ -1750,7 +1750,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L32"
}
],
"signatures": [
@@ -1765,7 +1765,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 32,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L32"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L32"
}
],
"parameters": [
@@ -1836,7 +1836,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -1855,7 +1855,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -1870,7 +1870,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1893,7 +1893,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1912,7 +1912,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1931,7 +1931,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -1951,7 +1951,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -1979,7 +1979,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 30,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L30"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L30"
}
],
"extendedTypes": [
@@ -2048,7 +2048,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L58"
}
],
"signatures": [
@@ -2063,7 +2063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 58,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L58"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L58"
}
],
"parameters": [
@@ -2111,7 +2111,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2137,7 +2137,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2154,7 +2154,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2177,7 +2177,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2196,7 +2196,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2215,7 +2215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2235,7 +2235,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2273,7 +2273,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 57,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L57"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L57"
}
],
"extendedTypes": [
@@ -2322,7 +2322,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L90"
}
],
"signatures": [
@@ -2337,7 +2337,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 90,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L90"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L90"
}
],
"parameters": [
@@ -2385,7 +2385,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2411,7 +2411,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2428,7 +2428,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2451,7 +2451,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2470,7 +2470,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2489,7 +2489,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2509,7 +2509,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2547,7 +2547,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 89,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L89"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L89"
}
],
"extendedTypes": [
@@ -2596,7 +2596,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L74"
}
],
"signatures": [
@@ -2611,7 +2611,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 74,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L74"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L74"
}
],
"parameters": [
@@ -2659,7 +2659,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 31,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L31"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L31"
}
],
"type": {
@@ -2685,7 +2685,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"signatures": [
@@ -2702,7 +2702,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2725,7 +2725,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 45,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2744,7 +2744,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 28,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2763,7 +2763,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
],
"type": {
@@ -2783,7 +2783,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 38,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L38"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L38"
}
]
}
@@ -2821,7 +2821,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 73,
"character": 13,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L73"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L73"
}
],
"extendedTypes": [
@@ -2844,7 +2844,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L113"
}
],
"type": {
@@ -2877,7 +2877,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 129,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L129"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L129"
}
],
"type": {
@@ -2986,7 +2986,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"type": {
@@ -3002,7 +3002,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"indexSignatures": [
@@ -3017,7 +3017,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 117,
"character": 14,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L117"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L117"
}
],
"parameters": [
@@ -3063,7 +3063,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 121,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L121"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L121"
}
],
"type": {
@@ -3113,7 +3113,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 125,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L125"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L125"
}
],
"type": {
@@ -3144,7 +3144,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 140,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L140"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L140"
}
],
"type": {
@@ -3178,7 +3178,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 145,
"character": 2,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L145"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L145"
}
],
"type": {
@@ -3198,7 +3198,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 113,
"character": 36,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L113"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L113"
}
]
}
@@ -3215,7 +3215,7 @@
"fileName": "packages/core/functions-js/src/types.ts",
"line": 16,
"character": 12,
"url": "https://github.com/supabase/supabase-js/blob/2f11f49ffbfe0b4a9ecd3a550c67916e05f10745/packages/core/functions-js/src/types.ts#L16"
"url": "https://github.com/supabase/supabase-js/blob/84a729bdd73e808f5158b4e1ec07bc14af42c1ae/packages/core/functions-js/src/types.ts#L16"
}
],
"typeParameters": [
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -5380,59 +5380,42 @@
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"minLength": 1
},
"expires_at": {
"type": "number"
},
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
}
"discriminator": {
"propertyName": "state"
},
"required": ["user_id", "user_roles"]
"oneOf": [
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["enabled", "disabled"]
},
"appliedSuccessfully": {
"type": "boolean"
}
},
"required": ["state"]
},
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["unavailable"]
},
"unavailableReason": {
"type": "string",
"enum": [
"manual_migration_required",
"postgres_upgrade_required",
"temporarily_unavailable"
]
}
},
"required": ["state", "unavailableReason"]
}
]
}
}
}
@@ -5512,59 +5495,42 @@
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"minLength": 1
},
"expires_at": {
"type": "number"
},
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
}
"discriminator": {
"propertyName": "state"
},
"required": ["user_id", "user_roles"]
"oneOf": [
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["enabled", "disabled"]
},
"appliedSuccessfully": {
"type": "boolean"
}
},
"required": ["state"]
},
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["unavailable"]
},
"unavailableReason": {
"type": "string",
"enum": [
"manual_migration_required",
"postgres_upgrade_required",
"temporarily_unavailable"
]
}
},
"required": ["state", "unavailableReason"]
}
]
}
}
}
@@ -21176,6 +21142,9 @@
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"is_physical_backup": {
"type": "boolean"
},
@@ -21194,7 +21163,7 @@
"type": "string"
}
},
"required": ["is_physical_backup", "status", "inserted_at"]
"required": ["id", "is_physical_backup", "status", "inserted_at"]
}
},
"physical_backup_data": {
@@ -21506,6 +21475,78 @@
"x-oauth-scope": "database:read"
}
},
"/v1/projects/{ref}/database/backups/restore": {
"post": {
"operationId": "v1-restore-physical-backup",
"parameters": [
{
"name": "ref",
"required": true,
"in": "path",
"description": "Project ref",
"schema": {
"minLength": 20,
"maxLength": 20,
"pattern": "^[a-z]+$",
"example": "abcdefghijklmnopqrst",
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": ["id"],
"example": {
"id": 12345
}
}
}
}
},
"responses": {
"201": {
"description": ""
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden action"
},
"429": {
"description": "Rate limit exceeded"
}
},
"security": [
{
"bearer": []
},
{
"fga_permissions": ["backups_write"]
}
],
"summary": "Restores a physical backup for a database",
"tags": ["Database"],
"x-badges": [
{
"name": "OAuth scope: database:write",
"position": "after"
}
],
"x-endpoint-owners": ["infra"],
"x-internal": true,
"x-oauth-scope": "database:write"
}
},
"/v1/projects/{ref}/database/backups/undo": {
"post": {
"operationId": "v1-undo",
@@ -24010,60 +24051,43 @@
"custom_hostname": "docs.example.com"
}
},
"JitAccessResponse": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"minLength": 1
},
"expires_at": {
"type": "number"
},
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
}
"JitStateResponse": {
"discriminator": {
"propertyName": "state"
},
"required": ["user_id", "user_roles"]
"oneOf": [
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["enabled", "disabled"]
},
"appliedSuccessfully": {
"type": "boolean"
}
},
"required": ["state"]
},
{
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": ["unavailable"]
},
"unavailableReason": {
"type": "string",
"enum": [
"manual_migration_required",
"postgres_upgrade_required",
"temporarily_unavailable"
]
}
},
"required": ["state", "unavailableReason"]
}
]
},
"JitAccessRequestRequest": {
"type": "object",
@@ -28501,6 +28525,61 @@
},
"required": ["message"]
},
"JitAccessResponse": {
"type": "object",
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"user_roles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string",
"minLength": 1
},
"expires_at": {
"type": "number"
},
"allowed_networks": {
"type": "object",
"properties": {
"allowed_cidrs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
},
"allowed_cidrs_v6": {
"type": "array",
"items": {
"type": "object",
"properties": {
"cidr": {
"type": "string"
}
},
"required": ["cidr"]
}
}
}
}
},
"required": ["role"]
}
}
},
"required": ["user_id", "user_roles"]
},
"AuthorizeJitAccessBody": {
"type": "object",
"properties": {
@@ -30657,6 +30736,9 @@
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"is_physical_backup": {
"type": "boolean"
},
@@ -30668,7 +30750,7 @@
"type": "string"
}
},
"required": ["is_physical_backup", "status", "inserted_at"]
"required": ["id", "is_physical_backup", "status", "inserted_at"]
}
},
"physical_backup_data": {
@@ -30730,6 +30812,18 @@
},
"required": ["name", "status", "completed_on"]
},
"V1RestoreBackupBody": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": ["id"],
"example": {
"id": 12345
}
},
"V1UndoBody": {
"type": "object",
"properties": {
File diff suppressed because it is too large. Load diff
+1
View File
@@ -2,6 +2,7 @@
@import './../../../packages/ui/build/css/source/global.css';
@import './../../../packages/ui/build/css/themes/dark.css';
@import './../../../packages/ui/build/css/themes/faux-classic-dark.css';
@import './../../../packages/ui/build/css/themes/light.css';
@config '../tailwind.config.cjs';
+1
View File
@@ -30,6 +30,7 @@
"VERCEL",
"VERCEL_ENV",
"VERCEL_GIT_COMMIT_SHA",
"VERCEL_URL",
// These envs are used in the packages
"NEXT_PUBLIC_STORAGE_KEY",
"NEXT_PUBLIC_AUTH_DEBUG_KEY",
+6 -7
View File
@@ -1,25 +1,24 @@
'use client'
import { AuthProvider, ThemeProvider } from 'common'
import { Provider as JotaiProvider } from 'jotai'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
import { ThemeProviderProps } from 'next-themes/dist/types'
import { PropsWithChildren } from 'react'
import { TooltipProvider } from 'ui'
import { FrameworkProvider } from '@/context/framework-context'
import { MobileMenuProvider } from '@/context/mobile-menu-context'
import { AuthProvider } from 'common'
import { TooltipProvider } from 'ui'
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
export function Providers({ children }: PropsWithChildren) {
return (
<AuthProvider>
<JotaiProvider>
<NextThemesProvider {...props}>
<ThemeProvider>
<MobileMenuProvider>
<FrameworkProvider>
<TooltipProvider delayDuration={0}>{children}</TooltipProvider>
</FrameworkProvider>
</MobileMenuProvider>
</NextThemesProvider>
</ThemeProvider>
</JotaiProvider>
</AuthProvider>
)
+3 -7
View File
@@ -6,7 +6,7 @@ import { FeatureFlagProvider, TelemetryTagManager } from 'common'
import { genFaviconData } from 'common/MetaFavicons/app-router'
import { Inter } from 'next/font/google'
import { ThemeProvider } from './Providers'
import { Providers } from './Providers'
import { Toaster } from './toaster'
import { API_URL } from '@/lib/constants'
@@ -47,14 +47,10 @@ export default async function Layout({ children }: RootLayoutProps) {
<body className={`${inter.className} antialiased`}>
<TelemetryTagManager />
<FeatureFlagProvider API_URL={API_URL}>
<ThemeProvider
themes={['dark', 'light', 'classic-dark']}
defaultTheme="system"
enableSystem
>
<Providers>
{children}
<Toaster />
</ThemeProvider>
</Providers>
</FeatureFlagProvider>
</body>
</html>
+1 -1
View File
@@ -23,7 +23,7 @@
"lucide-react": "*",
"next": "catalog:",
"next-contentlayer2": "0.4.6",
"next-themes": "^0.3.0",
"next-themes": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
"react-wrap-balancer": "^1.1.0",
+1
View File
@@ -2,6 +2,7 @@
@import './../../../packages/ui/build/css/source/global.css';
@import './../../../packages/ui/build/css/themes/dark.css';
@import './../../../packages/ui/build/css/themes/classic-dark.css';
@import './../../../packages/ui/build/css/themes/light.css';
@config '../tailwind.config.js';
@@ -5,7 +5,7 @@ import {
Button,
Card,
Checkbox,
Input,
Input_Shadcn_ as Input,
Label_Shadcn_ as Label,
Separator,
Switch,
+9 -33
View File
@@ -1,12 +1,12 @@
{
"rules": {
"react-hooks/exhaustive-deps": 182,
"react-hooks/exhaustive-deps": 179,
"import/no-anonymous-default-export": 57,
"@tanstack/query/exhaustive-deps": 12,
"@typescript-eslint/no-explicit-any": 1056,
"@typescript-eslint/no-explicit-any": 1042,
"no-restricted-imports": 0,
"no-restricted-exports": 267,
"react/no-unstable-nested-components": 57,
"no-restricted-exports": 255,
"react/no-unstable-nested-components": 51,
"studio/require-safe-sql-fragment": 158
},
"ruleFiles": {
@@ -45,7 +45,6 @@
"components/interfaces/Database/Replication/ReplicationDiagram/index.tsx": 1,
"components/interfaces/DiskManagement/DiskManagementForm.tsx": 1,
"components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx": 1,
"components/interfaces/GraphQL/GraphiQL.tsx": 1,
"components/interfaces/Integrations/CronJobs/CreateCronJobSheet/CreateCronJobSheet.tsx": 1,
"components/interfaces/Integrations/Queues/QueuesSettings.tsx": 1,
"components/interfaces/Integrations/Queues/SingleQueue/QueueSettings.tsx": 1,
@@ -89,7 +88,6 @@
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.tsx": 2,
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx": 2,
"components/interfaces/TableGridEditor/TableGridEditor.tsx": 2,
"components/interfaces/UnifiedLogs/ServiceFlow/components/ServiceFlowHeader.tsx": 2,
"components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx": 1,
"components/layouts/ProjectLayout/ConnectingState.tsx": 1,
@@ -218,9 +216,8 @@
},
"@typescript-eslint/no-explicit-any": {
"components/grid/SupabaseGrid.tsx": 1,
"components/grid/SupabaseGrid.utils.ts": 4,
"components/grid/SupabaseGrid.utils.ts": 2,
"components/grid/components/common/MonacoEditor.tsx": 3,
"components/grid/components/editor/BooleanEditor.tsx": 1,
"components/grid/components/editor/JsonEditor.tsx": 2,
"components/grid/components/editor/SelectEditor.tsx": 1,
"components/grid/components/editor/TextEditor.tsx": 1,
@@ -328,7 +325,7 @@
"components/interfaces/Organization/BillingSettings/CostControl/SpendCapSidePanel.tsx": 2,
"components/interfaces/Organization/BillingSettings/CreditTopUp.tsx": 2,
"components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx": 1,
"components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx": 2,
"components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx": 1,
"components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx": 1,
"components/interfaces/Organization/BillingSettings/Subscription/SubscriptionPlanUpdateDialog.tsx": 6,
"components/interfaces/Organization/BillingSettings/Subscription/UpgradeModal.tsx": 3,
@@ -388,8 +385,6 @@
"components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx": 2,
"components/interfaces/Settings/Database/NetworkRestrictions/AddRestrictionModal.tsx": 1,
"components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.utils.ts": 2,
"components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx": 1,
"components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx": 1,
"components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx": 1,
"components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceNode.tsx": 1,
"components/interfaces/Settings/Logs/LogSelectionRenderers/DefaultPreviewSelectionRenderer.tsx": 1,
@@ -465,12 +460,12 @@
"components/interfaces/UnifiedLogs/ServiceFlow/config/fieldHelpers.ts": 3,
"components/interfaces/UnifiedLogs/ServiceFlow/types.ts": 10,
"components/interfaces/UnifiedLogs/ServiceFlow/utils/storageUtils.ts": 3,
"components/interfaces/UnifiedLogs/UnifiedLogs.queries.ts": 5,
"components/interfaces/UnifiedLogs/UnifiedLogs.queries.ts": 4,
"components/interfaces/UnifiedLogs/UnifiedLogs.tsx": 8,
"components/interfaces/UnifiedLogs/UnifiedLogs.utils.ts": 1,
"components/interfaces/UnifiedLogs/components/DownloadLogsButton.tsx": 1,
"components/interfaces/UnifiedLogs/components/LogsListPanel.tsx": 1,
"components/layouts/AccountLayout/WithSidebar.tsx": 3,
"components/layouts/AccountLayout/WithSidebar.tsx": 2,
"components/layouts/DocsLayout/DocsLayout.tsx": 2,
"components/layouts/IntegrationsLayout/Integrations.utils.ts": 2,
"components/layouts/Navigation/LayoutHeader/BreadcrumbsView.tsx": 2,
@@ -486,7 +481,6 @@
"components/layouts/SQLEditorLayout/SQLEditorNavV2/SearchList.tsx": 1,
"components/layouts/TableEditorLayout/EntityListItem.tsx": 1,
"components/layouts/TableEditorLayout/TableEditorMenu.tsx": 1,
"components/layouts/Tabs/NewTab.tsx": 1,
"components/to-be-cleaned/KeyMap.tsx": 3,
"components/ui/AIAssistantPanel/AIAssistant.utils.ts": 1,
"components/ui/AIAssistantPanel/DisplayBlockRenderer.tsx": 1,
@@ -534,7 +528,6 @@
"components/ui/SchemaComboBox.tsx": 1,
"components/ui/SchemaSelector.tsx": 1,
"components/ui/SqlEditor.tsx": 6,
"components/ui/TwoOptionToggle.tsx": 4,
"components/ui/ui.types.ts": 1,
"data/ai/check-api-key-query.ts": 1,
"data/ai/rate-message-mutation.ts": 1,
@@ -593,7 +586,7 @@
"data/replication/restart-pipeline-helper.ts": 2,
"data/replication/rollback-tables-mutation.ts": 1,
"data/reports/database-charts.ts": 4,
"data/reports/v2/auth.config.ts": 16,
"data/reports/v2/auth.config.ts": 15,
"data/reports/v2/edge-functions.config.ts": 9,
"data/reports/v2/reports.types.ts": 2,
"data/sql/execute-sql-query.ts": 5,
@@ -710,7 +703,6 @@
"components/interfaces/Database/EnumeratedTypes/EnumeratedTypeValueRow.tsx": 1,
"components/interfaces/Database/Extensions/ExtensionCardSkeleton.tsx": 1,
"components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx": 1,
"components/interfaces/Database/Indexes/Indexes.tsx": 1,
"components/interfaces/Database/Migrations/Migrations.tsx": 1,
"components/interfaces/Database/Privileges/PrivilegesHead.tsx": 1,
"components/interfaces/Database/Privileges/PrivilegesTable.tsx": 1,
@@ -727,10 +719,8 @@
"components/interfaces/Docs/Snippets.ts": 1,
"components/interfaces/Functions/CommandRender.tsx": 1,
"components/interfaces/Functions/EdgeFunctionOverview/EdgeFunctionOverview.tsx": 1,
"components/interfaces/Functions/EdgeFunctionSecrets/AddNewSecretForm.tsx": 1,
"components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecret.tsx": 1,
"components/interfaces/Functions/FunctionsNav.tsx": 1,
"components/interfaces/GraphQL/GraphiQL.tsx": 1,
"components/interfaces/Home/ProjectUsage.tsx": 1,
"components/interfaces/Integrations/CronJobs/CronJobsEmptyState.tsx": 1,
"components/interfaces/Integrations/CronJobs/CronSyntaxChart.tsx": 1,
@@ -738,9 +728,7 @@
"components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx": 1,
"components/interfaces/Integrations/Wrappers/InputField.tsx": 1,
"components/interfaces/Integrations/Wrappers/WrapperTableEditor.tsx": 1,
"components/interfaces/Linter/LintDetail.tsx": 1,
"components/interfaces/Linter/LintPageTabs.tsx": 1,
"components/interfaces/Linter/LinterDataGrid.tsx": 1,
"components/interfaces/Linter/LinterFilters.tsx": 1,
"components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingBreakdown.tsx": 1,
"components/interfaces/Organization/BillingSettings/BillingEmail.tsx": 1,
@@ -786,8 +774,6 @@
"components/interfaces/Reports/ReportStickyNav.tsx": 1,
"components/interfaces/Reports/ReportWidget.tsx": 1,
"components/interfaces/Reports/Reports.tsx": 1,
"components/interfaces/RoleImpersonationSelector/RoleImpersonationRadio.tsx": 1,
"components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx": 1,
"components/interfaces/SQLEditor/DownloadSnippetModal.tsx": 1,
"components/interfaces/SQLEditor/InlineWidget.tsx": 1,
"components/interfaces/SQLEditor/MonacoEditor.tsx": 1,
@@ -797,9 +783,6 @@
"components/interfaces/SQLEditor/UtilityPanel/ReadOnlyBadge.tsx": 1,
"components/interfaces/SQLEditor/UtilityPanel/Results.tsx": 1,
"components/interfaces/SQLEditor/UtilityPanel/SavingIndicator.tsx": 1,
"components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx": 1,
"components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx": 1,
"components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx": 1,
"components/interfaces/SQLEditor/hooks.ts": 1,
"components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx": 1,
"components/interfaces/Settings/Addons/IPv4SidePanel.tsx": 1,
@@ -852,7 +835,6 @@
"components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetImportConfiguration.tsx": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetTextInput.tsx": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetPreviewGrid.tsx": 1,
"components/interfaces/TableGridEditor/ViewEntityAutofixSecurityModal.tsx": 1,
"components/layouts/APIKeys/APIKeysLayout.tsx": 1,
"components/layouts/AccountLayout/AccountLayout.tsx": 1,
"components/layouts/AdvisorsLayout/AdvisorsLayout.tsx": 1,
@@ -927,7 +909,6 @@
"components/ui/ShimmerLine.tsx": 1,
"components/ui/SparkBar.tsx": 1,
"components/ui/SqlEditor.tsx": 1,
"components/ui/TwoOptionToggle.tsx": 1,
"data/prefetchers/PrefetchableLink.tsx": 1,
"hooks/analytics/useDbQuery.tsx": 1,
"hooks/analytics/useLogsPreview.tsx": 1,
@@ -954,16 +935,13 @@
"components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx": 1,
"components/interfaces/Linter/LintPageTabs.tsx": 1,
"components/interfaces/Linter/LinterDataGrid.tsx": 3,
"components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx": 1,
"components/interfaces/Organization/Usage/UsageBarChart.tsx": 1,
"components/interfaces/ProjectAPIDocs/FirstLevelNav.tsx": 1,
"components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx": 1,
"components/interfaces/Settings/Logs/LogSelection.tsx": 1,
"components/interfaces/Settings/Logs/LogTable.tsx": 3,
"components/interfaces/Settings/Logs/LogsFormatters.tsx": 2,
"components/interfaces/Settings/Logs/PreviewFilterPanelWithUniversal.tsx": 1,
"components/interfaces/Storage/StoragePolicies/StoragePoliciesEditPolicyModal.tsx": 1,
"components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx": 2,
"components/interfaces/UnifiedLogs/components/LogTypeIcon.tsx": 5,
"components/layouts/Navigation/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx": 1,
"components/layouts/Navigation/NavigationBar/NavigationIconLink.tsx": 1,
@@ -977,8 +955,6 @@
"components/ui/Charts/ComposedChart.utils.tsx": 3,
"components/ui/ErrorBoundary/ErrorBoundary.tsx": 1,
"components/ui/NoPermission.tsx": 1,
"components/ui/SqlEditor.tsx": 1,
"pages/integrations/vercel/[slug]/deploy-button/new-project.tsx": 1,
"pages/project/[ref]/observability/database.tsx": 1
},
"studio/require-safe-sql-fragment": {
@@ -20,7 +20,6 @@ import { useSqlFilterGenerateMutation } from '@/data/ai/sql-filter-mutation'
import { useTableEditorTableStateSnapshot } from '@/state/table-editor-table'
export interface FilterPopoverProps {
portal?: boolean
isRefetching?: boolean
}
@@ -17,7 +17,7 @@ import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { FilterPopover } from '@/components/ui/FilterPopover'
import {
TIMESTAMP_MICROS_PER_MS,
type V2AuditLog,
type AuditLog,
} from '@/data/organizations/organization-audit-logs-query'
import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
import { useProfileAuditLogsQuery } from '@/data/profile/profile-audit-logs-query'
@@ -35,7 +35,7 @@ export const AuditLogs = () => {
to: currentTime.toISOString(),
})
const [selectedLog, setSelectedLog] = useState<V2AuditLog>()
const [selectedLog, setSelectedLog] = useState<AuditLog>()
const [filters, setFilters] = useState<{ projects: string[] }>({
projects: [],
})
@@ -1,12 +1,12 @@
import type { V2AuditLog } from '@/data/organizations/organization-audit-logs-query'
import type { AuditLog } from '@/data/organizations/organization-audit-logs-query'
export function sortAuditLogs(logs: V2AuditLog[], descending: boolean): V2AuditLog[] {
export function sortAuditLogs(logs: AuditLog[], descending: boolean): AuditLog[] {
return [...logs].sort((a, b) =>
descending ? b.timestamp - a.timestamp : a.timestamp - b.timestamp
)
}
export function filterByProjects(logs: V2AuditLog[], projectRefs: string[]): V2AuditLog[] {
export function filterByProjects(logs: AuditLog[], projectRefs: string[]): AuditLog[] {
if (projectRefs.length === 0) return logs
return logs.filter((log) => projectRefs.includes(log.project_ref ?? ''))
}
@@ -8,11 +8,11 @@ import {
} from '@/components/ui/Forms/FormSection'
import {
TIMESTAMP_MICROS_PER_MS,
type V2AuditLog,
type AuditLog,
} from '@/data/organizations/organization-audit-logs-query'
interface LogDetailsPanelProps {
selectedLog?: V2AuditLog
selectedLog?: AuditLog
onClose: () => void
}
@@ -18,6 +18,11 @@ import {
FormField,
FormLabel,
Input_Shadcn_,
Select_Shadcn_,
SelectContent_Shadcn_,
SelectItem_Shadcn_,
SelectTrigger_Shadcn_,
SelectValue_Shadcn_,
Separator,
Sheet,
SheetClose,
@@ -62,6 +67,9 @@ const FormSchema = z.object({
.array()
.min(1, 'At least one redirect URI is required'),
client_type: z.enum(['public', 'confidential']).default('confidential'),
token_endpoint_auth_method: z
.enum(['client_secret_basic', 'client_secret_post', 'none'])
.default('client_secret_basic'),
client_id: z.string().optional(),
client_secret: z.string().optional(),
logo_uri: z.string().optional(),
@@ -74,6 +82,7 @@ const initialValues = {
type: 'manual' as const,
redirect_uris: [{ value: '' }],
client_type: 'confidential' as const,
token_endpoint_auth_method: 'client_secret_basic' as const,
client_id: '',
client_secret: '',
logo_uri: '',
@@ -140,6 +149,11 @@ export const CreateOrUpdateOAuthAppSheet = ({
? appToEdit.redirect_uris.map((uri) => ({ value: uri }))
: [{ value: '' }],
client_type: appToEdit.client_type,
token_endpoint_auth_method:
(appToEdit.token_endpoint_auth_method as
| 'client_secret_basic'
| 'client_secret_post'
| 'none') || 'client_secret_basic',
client_id: appToEdit.client_id,
client_secret: '****************************************************************',
logo_uri: appToEdit.logo_uri || undefined,
@@ -184,10 +198,12 @@ export const CreateOrUpdateOAuthAppSheet = ({
}
if (isEditMode && appToEdit) {
const payload: UpdateOAuthClientParams = {
const payload: UpdateOAuthClientParams & { token_endpoint_auth_method?: string } = {
client_name: data.name,
redirect_uris: validRedirectUris,
logo_uri: uploadedLogoUri,
token_endpoint_auth_method:
data.client_type === 'public' ? 'none' : data.token_endpoint_auth_method,
}
updateOAuthApp({
@@ -197,12 +213,18 @@ export const CreateOrUpdateOAuthAppSheet = ({
...payload,
})
} else {
const payload: CreateOAuthClientParams & { logo_uri?: string; client_type?: string } = {
const payload: CreateOAuthClientParams & {
logo_uri?: string
client_type?: string
token_endpoint_auth_method?: string
} = {
client_name: data.name,
client_uri: '',
client_type: data.client_type,
redirect_uris: validRedirectUris,
logo_uri: uploadedLogoUri || undefined,
token_endpoint_auth_method:
data.client_type === 'public' ? 'none' : data.token_endpoint_auth_method,
}
createOAuthApp({
@@ -438,15 +460,50 @@ export const CreateOrUpdateOAuthAppSheet = ({
<FormControl>
<Switch
checked={field.value === 'public'}
onCheckedChange={(checked) =>
field.onChange(checked ? 'public' : 'confidential')
}
onCheckedChange={(checked) => {
const newType = checked ? 'public' : 'confidential'
field.onChange(newType)
form.setValue(
'token_endpoint_auth_method',
newType === 'public' ? 'none' : 'client_secret_basic'
)
}}
disabled={isEditMode}
/>
</FormControl>
</FormItemLayout>
)}
/>
{form.watch('client_type') === 'confidential' && (
<FormField
control={form.control}
name="token_endpoint_auth_method"
render={({ field }) => (
<FormItemLayout
label="Token Endpoint Auth Method"
description="How the client authenticates with the token endpoint. The client secret is included in either the Authorization header or the request body."
className="px-5"
>
<FormControl>
<Select_Shadcn_ value={field.value} onValueChange={field.onChange}>
<SelectTrigger_Shadcn_ className="text-sm">
<SelectValue_Shadcn_ />
</SelectTrigger_Shadcn_>
<SelectContent_Shadcn_>
<SelectItem_Shadcn_ value="client_secret_basic" className="text-sm">
HTTP Basic Auth header (client_secret_basic)
</SelectItem_Shadcn_>
<SelectItem_Shadcn_ value="client_secret_post" className="text-sm">
Request body (client_secret_post)
</SelectItem_Shadcn_>
</SelectContent_Shadcn_>
</Select_Shadcn_>
</FormControl>
</FormItemLayout>
)}
/>
)}
</form>
</Form>
</SheetSection>
@@ -1,4 +1,3 @@
import type { PostgresPolicy } from '@supabase/postgres-meta'
import { useParams } from 'common'
import { isEmpty } from 'lodash'
import Link from 'next/link'
@@ -11,6 +10,7 @@ import {
PolicyTableRow,
PolicyTableRowProps,
} from '@/components/interfaces/Auth/Policies/PolicyTableRow'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import { ProtectedSchemaWarning } from '@/components/interfaces/Database/ProtectedSchemaWarning'
import { NoSearchResults } from '@/components/ui/NoSearchResults'
import { useDatabasePolicyDeleteMutation } from '@/data/database-policies/database-policy-delete-mutation'
@@ -25,7 +25,7 @@ interface PoliciesProps {
isLocked: boolean
visibleTableIds: Set<number>
onSelectCreatePolicy: (table: string) => void
onSelectEditPolicy: (policy: PostgresPolicy) => void
onSelectEditPolicy: (policy: Policy) => void
onResetSearch?: () => void
}
@@ -83,13 +83,13 @@ export const Policies = ({
)
const onSelectEditPolicy = useCallback(
(policy: PostgresPolicy) => {
(policy: Policy) => {
onSelectEditPolicyAI(policy)
},
[onSelectEditPolicyAI]
)
const onSelectDeletePolicy = useCallback((policy: PostgresPolicy) => {
const onSelectDeletePolicy = useCallback((policy: Policy) => {
setSelectedPolicyToDelete(policy)
}, [])
@@ -1,13 +1,13 @@
import type { PostgresPolicy } from '@supabase/postgres-meta'
import type { PropsWithChildren } from 'react'
import { createContext, useCallback, useContext, useMemo } from 'react'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import type { ResponseError } from '@/types'
type TableKey = `${string}.${string}`
type PoliciesDataContextValue = {
getPoliciesForTable: (schema: string, table: string) => PostgresPolicy[]
getPoliciesForTable: (schema: string, table: string) => Array<Policy>
isPoliciesLoading: boolean
isPoliciesError: boolean
policiesError?: ResponseError | Error
@@ -23,7 +23,7 @@ export const usePoliciesData = () => {
}
type PoliciesDataProviderProps = {
policies: PostgresPolicy[]
policies: Array<Policy>
isPoliciesLoading: boolean
isPoliciesError: boolean
policiesError?: ResponseError | Error
@@ -39,7 +39,7 @@ export const PoliciesDataProvider = ({
exposedSchemas,
}: PropsWithChildren<PoliciesDataProviderProps>) => {
const policiesByTable = useMemo(() => {
const map = new Map<TableKey, PostgresPolicy[]>()
const map = new Map<TableKey, Array<Policy>>()
for (const policy of policies) {
const key = `${policy.schema}.${policy.table}` satisfies TableKey
@@ -1,3 +1,4 @@
import { ident } from '@supabase/pg-meta/src/pg-format'
import type { PostgresPolicy } from '@supabase/postgres-meta'
import { isEqual } from 'lodash'
@@ -65,7 +66,7 @@ export const generateCreatePolicyQuery = ({
using?: string
check?: string
}) => {
const querySkeleton = `create policy "${name}" on "${schema}"."${table}" as ${behavior} for ${command} to ${roles}`
const querySkeleton = `create policy ${ident(name)} on ${ident(schema)}.${ident(table)} as ${behavior} for ${command} to ${roles}`
const query =
command === 'insert'
? `${querySkeleton} with check (${check});`
@@ -1,4 +1,3 @@
import type { PostgresPolicy } from '@supabase/postgres-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { noop } from 'lodash'
import { Edit, MoreVertical, Trash } from 'lucide-react'
@@ -17,6 +16,7 @@ import {
} from 'ui'
import { generatePolicyUpdateSQL } from './PolicyTableRow.utils'
import type { Policy } from './PolicyTableRow.utils'
import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
import { DropdownMenuItemTooltip } from '@/components/ui/DropdownMenuItemTooltip'
import { useAuthConfigQuery } from '@/data/auth/auth-config-query'
@@ -26,9 +26,9 @@ import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
interface PolicyRowProps {
policy: PostgresPolicy
onSelectEditPolicy: (policy: PostgresPolicy) => void
onSelectDeletePolicy: (policy: PostgresPolicy) => void
policy: Policy
onSelectEditPolicy: (policy: Policy) => void
onSelectDeletePolicy: (policy: Policy) => void
isLocked?: boolean
}
@@ -1,7 +1,13 @@
import { ident, joinSqlFragments, safeSql, type SafeSqlFragment } from '@supabase/pg-meta'
import { PostgresPolicy } from '@supabase/postgres-meta'
import type { TableApiAccessData } from '@/data/privileges/table-api-access-query'
export type Policy = Omit<PostgresPolicy, 'definition' | 'check'> & {
definition: SafeSqlFragment | null
check: SafeSqlFragment | null
}
/**
* Single classifier for the RLS page's per-table admonition state. Shares the
* "granted / custom / revoked" grant semantics used by the Data API settings
@@ -61,21 +67,22 @@ export function getTableAdmonitionMessage(status: TableDataApiStatus): string |
}
}
export const generatePolicyUpdateSQL = (policy: PostgresPolicy) => {
let expression = ''
if (policy.definition !== null && policy.definition !== undefined) {
expression += `using (${policy.definition})${
policy.check === null || policy.check === undefined ? ';' : ''
}\n`
export const generatePolicyUpdateSQL = (policy: Policy): SafeSqlFragment => {
const parts: Array<SafeSqlFragment> = []
if (policy.definition != null) {
const semicolon = policy.check == null ? safeSql`;` : safeSql``
parts.push(safeSql`using (${policy.definition})${semicolon}`)
}
if (policy.check !== null && policy.check !== undefined) {
expression += `with check (${policy.check});\n`
if (policy.check != null) {
parts.push(safeSql`with check (${policy.check});`)
}
return `
alter policy "${policy.name}"
on "${policy.schema}"."${policy.table}"
to ${policy.roles.join(', ')}
${expression}
`.trim()
const expression = parts.length > 0 ? joinSqlFragments(parts, '\n') : safeSql``
return safeSql`
alter policy ${ident(policy.name)}
on ${ident(policy.schema)}.${ident(policy.table)}
to ${joinSqlFragments(policy.roles.map(ident), ', ')}
${expression}`
}
@@ -1,4 +1,3 @@
import type { PostgresPolicy } from '@supabase/postgres-meta'
import { useParams } from 'common'
import { noop } from 'lodash'
import { memo, useMemo } from 'react'
@@ -19,6 +18,7 @@ import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader'
import { usePoliciesData } from '../PoliciesDataContext'
import { PolicyRow } from './PolicyRow'
import type { PolicyTable } from './PolicyTableRow.types'
import type { Policy } from './PolicyTableRow.utils'
import { getTableAdmonitionMessage, getTableDataApiStatus } from './PolicyTableRow.utils'
import { PolicyTableRowHeader } from './PolicyTableRowHeader'
import AlertError from '@/components/ui/AlertError'
@@ -31,8 +31,8 @@ export interface PolicyTableRowProps {
isLocked: boolean
onSelectToggleRLS: (table: PolicyTable) => void
onSelectCreatePolicy: (table: PolicyTable) => void
onSelectEditPolicy: (policy: PostgresPolicy) => void
onSelectDeletePolicy: (policy: PostgresPolicy) => void
onSelectEditPolicy: (policy: Policy) => void
onSelectDeletePolicy: (policy: Policy) => void
}
const PolicyTableRowComponent = ({
@@ -1,24 +1,43 @@
import { UntrustedSqlFragment } from '@supabase/pg-meta'
import { Loader2 } from 'lucide-react'
import { Badge, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import CodeEditor from '@/components/ui/CodeEditor/CodeEditor'
export const InferredSQLViewer = ({ sql }: { sql: string }) => {
export const InferredSQLViewer = ({
sql,
isLoading = false,
}: {
sql: UntrustedSqlFragment | undefined
isLoading?: boolean
}) => {
return (
<>
<div className="flex items-center justify-between px-4 py-2">
<p className="text-sm">Inferred SQL:</p>
<Tooltip>
<TooltipTrigger>
<Badge variant="warning">Generated</Badge>
</TooltipTrigger>
<TooltipContent side="bottom" align="end" className="w-64 text-center">
This query is inferred from client library code with the help of the Assistant and may
not guarantee correctness.
</TooltipContent>
</Tooltip>
<div className="flex items-center gap-x-2">
<p className="text-sm">Inferred SQL:</p>
{isLoading && <Loader2 size={14} className="animate-spin text-foreground-lighter" />}
</div>
<div className="flex items-center gap-x-2">
<Tooltip>
<TooltipTrigger>
<Badge variant="warning">Generated</Badge>
</TooltipTrigger>
<TooltipContent side="bottom" align="end" className="w-64 text-center">
This query is inferred from client library code with the help of the Assistant and may
not guarantee correctness.
</TooltipContent>
</Tooltip>
</div>
</div>
<div className="h-44 relative">
<CodeEditor isReadOnly id="inferred-sql" language="pgsql" value={sql} />
{isLoading && !sql ? (
<div className="flex h-full items-center justify-center bg-surface-100 text-foreground-lighter">
<Loader2 size={20} className="animate-spin" />
</div>
) : (
<CodeEditor isReadOnly id="inferred-sql" language="pgsql" value={sql ?? ''} />
)}
</div>
</>
)
@@ -1,4 +1,3 @@
import { type PostgresPolicy } from '@supabase/postgres-meta'
import { Check, ChevronDown, Edit, X } from 'lucide-react'
import { useMemo } from 'react'
import {
@@ -9,13 +8,14 @@ import {
WarningIcon,
} from 'ui'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
interface RLSTableCardProps {
table: { schema: string; name: string; isRLSEnabled: boolean }
role?: string
policies: PostgresPolicy[]
handleSelectEditPolicy: (policy: PostgresPolicy) => void
policies: Policy[]
handleSelectEditPolicy: (policy: Policy) => void
}
export const RLSTableCard = ({
@@ -157,8 +157,8 @@ const TableAccessPolicySummary = ({
policies,
handleSelectEditPolicy,
}: {
policies: PostgresPolicy[]
handleSelectEditPolicy: (policy: PostgresPolicy) => void
policies: Policy[]
handleSelectEditPolicy: (policy: Policy) => void
}) => {
return (
<div className="border rounded-sm mt-4">
@@ -1,5 +1,4 @@
import { type PostgresPolicy } from '@supabase/postgres-meta'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import { type User } from '@/data/auth/users-infinite-query'
import { type ParseSQLQueryResponse } from '@/data/misc/parse-query-mutation'
@@ -7,7 +6,7 @@ export type ParseQueryResults = {
tables: {
schema: string
table: string
tablePolicies: PostgresPolicy[]
tablePolicies: Array<Policy>
isRLSEnabled: boolean
}[]
operation: ParseSQLQueryResponse['operation']
@@ -1,4 +1,3 @@
import { type PostgresPolicy } from '@supabase/postgres-meta'
import {
Badge,
cn,
@@ -12,13 +11,15 @@ import { Admonition } from 'ui-patterns'
import { Results } from '../../SQLEditor/UtilityPanel/Results'
import { RLSTableCard } from './RLSTableCard'
import { ParseQueryResults } from './RLSTester.types'
import { deriveRLSTestState } from './RLSTesterResults.utils'
import { useTestQueryRLS } from './useTestQueryRLS'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
interface RLSTesterResultsProps {
results: Object[]
autoLimit: boolean
parseQueryResults: ParseQueryResults
handleSelectEditPolicy: (policy: PostgresPolicy) => void
handleSelectEditPolicy: (policy: Policy) => void
}
export const RLSTesterResults = ({
@@ -29,16 +30,12 @@ export const RLSTesterResults = ({
}: RLSTesterResultsProps) => {
const { limit } = useTestQueryRLS()
const isServiceRole = parseQueryResults?.role === undefined
const tableWithRLSEnabledButNoPolicies = parseQueryResults?.tables.find(
(x) => x.isRLSEnabled && x.tablePolicies.length === 0
)
const tableWithRLSEnabledWithPolicyFalse = parseQueryResults?.tables.find(
(x) => x.isRLSEnabled && x.tablePolicies.some((y) => y.definition === 'false')
)
const noAccessToData =
!isServiceRole && (!!tableWithRLSEnabledButNoPolicies || !!tableWithRLSEnabledWithPolicyFalse)
const {
isServiceRole,
tableWithRLSEnabledButNoPolicies,
tableWithRLSEnabledWithPolicyFalse,
noAccessToData,
} = deriveRLSTestState(parseQueryResults)
return (
<div className="p-5 pt-4">
@@ -0,0 +1,20 @@
import type { ParseQueryResults } from './RLSTester.types'
export function deriveRLSTestState(parseQueryResults: ParseQueryResults | undefined) {
const isServiceRole = parseQueryResults?.role === undefined
const tableWithRLSEnabledButNoPolicies = parseQueryResults?.tables.find(
(x) => x.isRLSEnabled && x.tablePolicies.length === 0
)
const tableWithRLSEnabledWithPolicyFalse = parseQueryResults?.tables.find(
(x) => x.isRLSEnabled && x.tablePolicies.some((y) => y.definition === 'false')
)
const noAccessToData =
!isServiceRole && (!!tableWithRLSEnabledButNoPolicies || !!tableWithRLSEnabledWithPolicyFalse)
return {
isServiceRole,
tableWithRLSEnabledButNoPolicies,
tableWithRLSEnabledWithPolicyFalse,
noAccessToData,
}
}
@@ -1,4 +1,9 @@
import { type PostgresPolicy } from '@supabase/postgres-meta'
import {
acceptUntrustedSql,
safeSql,
type SafeSqlFragment,
type UntrustedSqlFragment,
} from '@supabase/pg-meta'
import {
Select,
SelectContent,
@@ -10,7 +15,7 @@ import {
} from '@ui/components/shadcn/ui/select'
import { LOCAL_STORAGE_KEYS } from 'common'
import { Code } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import {
Button,
DialogSectionSeparator,
@@ -31,13 +36,14 @@ import { RLSTesterEmptyState } from './RLSTesterEmptyState'
import { RLSTesterResults } from './RLSTesterResults'
import { RoleSelector } from './RoleSelector'
import { UserSelector } from './UserSelector'
import { UserSqlEditor } from './UserSqlEditor'
import { useTestQueryRLS } from './useTestQueryRLS'
import { CodeEditor } from '@/components/ui/CodeEditor/CodeEditor'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import { FeaturePreviewBadge } from '@/components/ui/FeaturePreviewBadge'
import { useRoleImpersonationStateSnapshot } from '@/state/role-impersonation-state'
interface RLSTesterSheetProps {
handleSelectEditPolicy: (policy: PostgresPolicy) => void
handleSelectEditPolicy: (policy: Policy) => void
}
export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps) => {
@@ -47,28 +53,53 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps)
const [selectedOption, setSelectedOption] = useState<'anon' | 'authenticated'>('anon')
const [format, setFormat] = useState<'sql' | 'lib'>('sql')
const [inferredSQL, setInferredSQL] = useState<string>()
const [inferredSQL, setInferredSQL] = useState<UntrustedSqlFragment>()
const [value, setValue] = useState<string>('')
const [value, setValue] = useState<SafeSqlFragment>(safeSql``)
const [results, setResults] = useState<Object[] | null>(null)
const [autoLimit, setAutoLimit] = useState(false)
const [parseQueryResults, setParseQueryResults] = useState<ParseQueryResults>()
const { testQuery, isLoading, executeSqlError, parseQueryError, parseClientCodeError } =
useTestQueryRLS()
const {
testQuery,
inferSQLFromLib,
isLoading,
isInferring,
executeSqlError,
parseQueryError,
parseClientCodeError,
} = useTestQueryRLS()
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const handleValueChange = (sql: SafeSqlFragment) => {
setValue(sql)
if (format !== 'lib') return
if (debounceRef.current !== null) clearTimeout(debounceRef.current)
if (!sql) return
debounceRef.current = setTimeout(() => {
inferSQLFromLib(sql, setInferredSQL)
}, 1500)
}
const executionCallbacks = {
option: selectedOption,
onExecuteSQL: ({ result, isAutoLimit }: { result: Object[] | null; isAutoLimit: boolean }) => {
setResults(result)
setAutoLimit(isAutoLimit)
},
onParseQuery: setParseQueryResults,
}
const onRunQuery = async () => {
await testQuery({
option: selectedOption,
format,
value,
onInferSQL: setInferredSQL,
onParseQuery: setParseQueryResults,
onExecuteSQL: ({ result, isAutoLimit }) => {
setResults(result)
setAutoLimit(isAutoLimit)
},
})
if (format === 'lib') {
if (!inferredSQL) return
await testQuery({ value: acceptUntrustedSql(inferredSQL), ...executionCallbacks })
} else {
await testQuery({ value, ...executionCallbacks })
}
}
useEffect(() => {
@@ -110,7 +141,17 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps)
<div className="flex items-center justify-between px-5 py-2">
<p className="text-sm">Query</p>
<div className="flex items-center gap-x-2">
<Select value={format} onValueChange={(x) => setFormat(x as 'sql' | 'lib')}>
<Select
value={format}
onValueChange={(x) => {
const newFormat = x as 'sql' | 'lib'
setFormat(newFormat)
if (newFormat !== 'lib') {
setInferredSQL(undefined)
if (debounceRef.current !== null) clearTimeout(debounceRef.current)
}
}}
>
<SelectTrigger size="tiny">
<SelectValue />
</SelectTrigger>
@@ -126,21 +167,20 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps)
</div>
<div className="h-40 relative">
<CodeEditor
<UserSqlEditor
id="rls-tester"
language="pgsql"
value={value}
placeholder={
format === 'sql'
? 'select * from table;'
: 'SQL will be inferred from client library code'
? safeSql`select * from table;`
: safeSql`SQL will be inferred from client library code`
}
onInputChange={(val) => setValue(val ?? '')}
onChange={handleValueChange}
actions={{
runQuery: {
enabled: open,
callback: () => {
if (!isLoading) onRunQuery()
if (!isInferring && !isLoading) onRunQuery()
},
},
}}
@@ -148,10 +188,10 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps)
</div>
</SheetSection>
{format === 'lib' && !!inferredSQL && (
{format === 'lib' && (
<div>
<DialogSectionSeparator />
<InferredSQLViewer sql={inferredSQL} />
<InferredSQLViewer sql={inferredSQL} isLoading={isInferring} />
</div>
)}
@@ -214,7 +254,12 @@ export const RLSTesterSheet = ({ handleSelectEditPolicy }: RLSTesterSheetProps)
<Button type="default" disabled={isLoading} onClick={() => setOpen(false)}>
Cancel
</Button>
<Button type="primary" loading={isLoading} onClick={onRunQuery}>
<Button
type="primary"
loading={isInferring || isLoading}
disabled={format === 'lib' && !inferredSQL}
onClick={onRunQuery}
>
Run query
</Button>
</div>
@@ -0,0 +1,28 @@
import { rawSql, type SafeSqlFragment } from '@supabase/pg-meta'
import type { ComponentProps } from 'react'
import { CodeEditor } from '@/components/ui/CodeEditor/CodeEditor'
interface UserSqlEditorProps {
id: string
value: SafeSqlFragment
placeholder?: SafeSqlFragment
actions?: ComponentProps<typeof CodeEditor>['actions']
onChange: (sql: SafeSqlFragment) => void
}
/**
* Wraps CodeEditor for user-authored SQL. The rawSql boundary lives here — any
* text the user types is immediately promoted to SafeSqlFragment so callers
* never handle plain strings.
*/
export const UserSqlEditor = ({ value, onChange, ...props }: UserSqlEditorProps) => {
return (
<CodeEditor
language="pgsql"
value={value}
onInputChange={(val) => onChange(rawSql(val ?? ''))}
{...props}
/>
)
}
@@ -0,0 +1,199 @@
import type { SafeSqlFragment } from '@supabase/pg-meta'
import { screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import type { ParseQueryResults } from '@/components/interfaces/Auth/RLSTester/RLSTester.types'
import { RLSTesterResults } from '@/components/interfaces/Auth/RLSTester/RLSTesterResults'
import { render } from '@/tests/helpers'
vi.mock('@/components/interfaces/Auth/RLSTester/useTestQueryRLS', () => ({
useTestQueryRLS: () => ({ limit: 100 }),
}))
vi.mock('@/components/interfaces/Auth/RLSTester/RLSTableCard', () => ({
RLSTableCard: () => <div data-testid="rls-table-card" />,
}))
vi.mock('@/components/interfaces/SQLEditor/UtilityPanel/Results', () => ({
Results: () => <div data-testid="results" />,
}))
const sql = (s: string) => s as unknown as SafeSqlFragment
const makePolicy = (definition: string | null = null): Policy =>
({ definition: definition !== null ? sql(definition) : null }) as Policy
const makeTable = (
overrides?: Partial<ParseQueryResults['tables'][number]>
): ParseQueryResults['tables'][number] => ({
schema: 'public',
table: 'items',
isRLSEnabled: true,
tablePolicies: [],
...overrides,
})
const defaultProps = {
results: [],
autoLimit: false,
handleSelectEditPolicy: vi.fn(),
}
describe('RLSTesterResults', () => {
describe('access badge', () => {
it('shows "No access" badge when table has RLS enabled but no policies', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [makeTable()],
operation: 'SELECT',
role: 'anon',
}}
/>
)
expect(screen.getByText('No access')).toBeInTheDocument()
})
it('shows "No access" badge when a policy definition is false', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [makeTable({ tablePolicies: [makePolicy('false')] })],
operation: 'SELECT',
role: 'anon',
}}
/>
)
expect(screen.getByText('No access')).toBeInTheDocument()
})
it('shows "Has access" badge when results are empty and user has access', () => {
render(
<RLSTesterResults
{...defaultProps}
results={[]}
parseQueryResults={{
tables: [makeTable({ tablePolicies: [makePolicy('auth.uid() = user_id')] })],
operation: 'SELECT',
role: 'authenticated',
}}
/>
)
expect(screen.getByText('Has access')).toBeInTheDocument()
})
it('shows "Can access" badge when results are returned', () => {
render(
<RLSTesterResults
{...defaultProps}
results={[{ id: 1 }]}
parseQueryResults={{
tables: [makeTable({ tablePolicies: [makePolicy('auth.uid() = user_id')] })],
operation: 'SELECT',
role: 'authenticated',
}}
/>
)
expect(screen.getByText('Can access')).toBeInTheDocument()
})
})
describe('policy admonitions', () => {
it('shows service role admonition for postgres role', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [makeTable()],
operation: 'SELECT',
role: undefined,
}}
/>
)
expect(screen.getByText(/bypasses all RLS policies/)).toBeInTheDocument()
})
it('shows "no policies" admonition when RLS is enabled but no policies exist', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [makeTable({ table: 'profiles', tablePolicies: [] })],
operation: 'SELECT',
role: 'anon',
}}
/>
)
expect(screen.getByText(/no policies set up/)).toBeInTheDocument()
expect(screen.getByText(/public.profiles/)).toBeInTheDocument()
})
it('shows "policy false" admonition when a policy evaluates to false', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [makeTable({ table: 'secrets', tablePolicies: [makePolicy('false')] })],
operation: 'SELECT',
role: 'anon',
}}
/>
)
expect(screen.getByText(/evaluates to/)).toBeInTheDocument()
expect(screen.getByText(/public.secrets/)).toBeInTheDocument()
})
})
describe('"Ran as" section', () => {
it('shows postgres for service role', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [],
operation: 'SELECT',
role: undefined,
}}
/>
)
expect(screen.getAllByText('postgres').length).toBeGreaterThan(0)
})
it('shows "an Anonymous user" for anon role', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [],
operation: 'SELECT',
role: 'anon',
}}
/>
)
expect(screen.getByText('an Anonymous user')).toBeInTheDocument()
expect(screen.getByText('Not logged in user')).toBeInTheDocument()
})
it('shows user email and ID when a user is present', () => {
render(
<RLSTesterResults
{...defaultProps}
parseQueryResults={{
tables: [],
operation: 'SELECT',
role: 'authenticated',
user: {
id: 'user-123',
email: 'alice@example.com',
} as any,
}}
/>
)
expect(screen.getByText('alice@example.com')).toBeInTheDocument()
expect(screen.getByText('ID: user-123')).toBeInTheDocument()
})
})
})
@@ -0,0 +1,192 @@
import type { SafeSqlFragment } from '@supabase/pg-meta'
import { describe, expect, it } from 'vitest'
import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
import type { ParseQueryResults } from '@/components/interfaces/Auth/RLSTester/RLSTester.types'
import { deriveRLSTestState } from '@/components/interfaces/Auth/RLSTester/RLSTesterResults.utils'
const sql = (s: string) => s as unknown as SafeSqlFragment
const makePolicy = (definition: string | null = null): Policy =>
({ definition: definition !== null ? sql(definition) : null }) as Policy
const makeTable = (
overrides?: Partial<ParseQueryResults['tables'][number]>
): ParseQueryResults['tables'][number] => ({
schema: 'public',
table: 'items',
isRLSEnabled: true,
tablePolicies: [],
...overrides,
})
const makeResults = (overrides?: Partial<ParseQueryResults>): ParseQueryResults => ({
tables: [],
operation: 'SELECT',
role: 'anon',
...overrides,
})
describe('deriveRLSTestState', () => {
describe('isServiceRole', () => {
it('is true when parseQueryResults is undefined', () => {
const { isServiceRole } = deriveRLSTestState(undefined)
expect(isServiceRole).toBe(true)
})
it('is true when role is undefined (postgres / service role)', () => {
const { isServiceRole } = deriveRLSTestState(makeResults({ role: undefined }))
expect(isServiceRole).toBe(true)
})
it('is false when role is anon', () => {
const { isServiceRole } = deriveRLSTestState(makeResults({ role: 'anon' }))
expect(isServiceRole).toBe(false)
})
it('is false when role is authenticated', () => {
const { isServiceRole } = deriveRLSTestState(makeResults({ role: 'authenticated' }))
expect(isServiceRole).toBe(false)
})
})
describe('noAccessToData', () => {
it('is false when parseQueryResults is undefined', () => {
const { noAccessToData } = deriveRLSTestState(undefined)
expect(noAccessToData).toBe(false)
})
it('is false for service role even when tables have no policies', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({ role: undefined, tables: [makeTable()] })
)
expect(noAccessToData).toBe(false)
})
it('is false when RLS is disabled on table', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({ tables: [makeTable({ isRLSEnabled: false, tablePolicies: [] })] })
)
expect(noAccessToData).toBe(false)
})
it('is true when RLS is enabled and table has no policies', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({ tables: [makeTable({ isRLSEnabled: true, tablePolicies: [] })] })
)
expect(noAccessToData).toBe(true)
})
it('is true when RLS is enabled and a policy definition is false', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({
tables: [makeTable({ tablePolicies: [makePolicy('false')] })],
})
)
expect(noAccessToData).toBe(true)
})
it('is false when RLS is enabled and policies are valid (not false)', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({
tables: [makeTable({ tablePolicies: [makePolicy('auth.uid() = user_id')] })],
})
)
expect(noAccessToData).toBe(false)
})
it('is false when all tables have RLS disabled regardless of policy state', () => {
const { noAccessToData } = deriveRLSTestState(
makeResults({
tables: [
makeTable({ isRLSEnabled: false, tablePolicies: [] }),
makeTable({
table: 'other',
isRLSEnabled: false,
tablePolicies: [makePolicy('false')],
}),
],
})
)
expect(noAccessToData).toBe(false)
})
})
describe('tableWithRLSEnabledButNoPolicies', () => {
it('is undefined when no tables', () => {
const { tableWithRLSEnabledButNoPolicies } = deriveRLSTestState(makeResults({ tables: [] }))
expect(tableWithRLSEnabledButNoPolicies).toBeUndefined()
})
it('is undefined when RLS disabled', () => {
const { tableWithRLSEnabledButNoPolicies } = deriveRLSTestState(
makeResults({ tables: [makeTable({ isRLSEnabled: false })] })
)
expect(tableWithRLSEnabledButNoPolicies).toBeUndefined()
})
it('is undefined when table has policies', () => {
const { tableWithRLSEnabledButNoPolicies } = deriveRLSTestState(
makeResults({ tables: [makeTable({ tablePolicies: [makePolicy('true')] })] })
)
expect(tableWithRLSEnabledButNoPolicies).toBeUndefined()
})
it('returns the matching table when RLS enabled with no policies', () => {
const table = makeTable({ table: 'profiles', tablePolicies: [] })
const { tableWithRLSEnabledButNoPolicies } = deriveRLSTestState(
makeResults({ tables: [table] })
)
expect(tableWithRLSEnabledButNoPolicies).toEqual(table)
})
it('returns the first matching table among multiple', () => {
const first = makeTable({ table: 'profiles', tablePolicies: [] })
const second = makeTable({ table: 'posts', tablePolicies: [] })
const { tableWithRLSEnabledButNoPolicies } = deriveRLSTestState(
makeResults({ tables: [first, second] })
)
expect(tableWithRLSEnabledButNoPolicies).toEqual(first)
})
})
describe('tableWithRLSEnabledWithPolicyFalse', () => {
it('is undefined when no tables', () => {
const { tableWithRLSEnabledWithPolicyFalse } = deriveRLSTestState(makeResults({ tables: [] }))
expect(tableWithRLSEnabledWithPolicyFalse).toBeUndefined()
})
it('is undefined when RLS disabled even with false policy', () => {
const { tableWithRLSEnabledWithPolicyFalse } = deriveRLSTestState(
makeResults({
tables: [makeTable({ isRLSEnabled: false, tablePolicies: [makePolicy('false')] })],
})
)
expect(tableWithRLSEnabledWithPolicyFalse).toBeUndefined()
})
it('is undefined when no policy has definition of false', () => {
const { tableWithRLSEnabledWithPolicyFalse } = deriveRLSTestState(
makeResults({
tables: [makeTable({ tablePolicies: [makePolicy('auth.uid() = user_id')] })],
})
)
expect(tableWithRLSEnabledWithPolicyFalse).toBeUndefined()
})
it('returns the table when a policy definition is exactly "false"', () => {
const table = makeTable({ table: 'secrets', tablePolicies: [makePolicy('false')] })
const { tableWithRLSEnabledWithPolicyFalse } = deriveRLSTestState(
makeResults({ tables: [table] })
)
expect(tableWithRLSEnabledWithPolicyFalse).toEqual(table)
})
it('is undefined when policy definition is null (no definition)', () => {
const { tableWithRLSEnabledWithPolicyFalse } = deriveRLSTestState(
makeResults({ tables: [makeTable({ tablePolicies: [makePolicy(null)] })] })
)
expect(tableWithRLSEnabledWithPolicyFalse).toBeUndefined()
})
})
})
@@ -1,3 +1,4 @@
import { type SafeSqlFragment, type UntrustedSqlFragment } from '@supabase/pg-meta'
import { useState } from 'react'
import { toast } from 'sonner'
@@ -20,7 +21,7 @@ import {
const limit = 100
/**
* [Joshen] Testing a SQL query for it's RLS access involves 3 async steps
* [Joshen] Testing a SQL query for its RLS access involves 3 async steps
* 0. (Optional) Inferring client library code to SQL query via the AI Assistant
* 1. Parsing the provided SQL query to retrieve its operation type + tables involved
* 2. Checking for tables involved if they've got RLS enabled
@@ -48,10 +49,26 @@ export const useTestQueryRLS = () => {
onError: () => {},
})
const { mutateAsync: parseClientCode, error: parseClientCodeError } = useParseClientCodeMutation({
const {
mutateAsync: parseClientCode,
isPending: isInferring,
error: parseClientCodeError,
} = useParseClientCodeMutation({
onError: () => {},
})
const inferSQLFromLib = async (
value: string,
onInferSQL: (unchecked_sql: UntrustedSqlFragment) => void
) => {
const { unchecked_sql, valid } = await parseClientCode({ code: value })
if (valid && unchecked_sql != null) {
onInferSQL(unchecked_sql)
} else {
toast.error('Client library code provided is not valid')
}
}
const { mutateAsync: parseQuery, error: parseQueryError } = useParseSQLQueryMutation({
onError: () => {},
})
@@ -62,17 +79,13 @@ export const useTestQueryRLS = () => {
})
const testQuery = async ({
option,
format,
value,
onInferSQL,
option,
onExecuteSQL,
onParseQuery,
}: {
value: SafeSqlFragment
option: 'anon' | 'authenticated'
format: 'lib' | 'sql'
value: string
onInferSQL: (sql: string) => void
onExecuteSQL: ({
result,
isAutoLimit,
@@ -90,20 +103,9 @@ export const useTestQueryRLS = () => {
try {
setIsLoading(true)
let formattedValue = value
if (format === 'lib') {
const { sql, valid } = await parseClientCode({ code: value })
if (valid && !!sql) {
formattedValue = sql
onInferSQL(sql)
} else {
return toast.error('Client library code provided is not valid')
}
}
const { appendAutoLimit } = checkIfAppendLimitRequired(formattedValue, limit)
const formattedSql = suffixWithLimit(formattedValue, limit)
const { appendAutoLimit } = checkIfAppendLimitRequired(value, limit)
const formattedSql = suffixWithLimit(value, limit)
const data = await parseQuery({ sql: formattedSql })
if (data.operation !== 'SELECT') {
@@ -126,7 +128,8 @@ export const useTestQueryRLS = () => {
(x) =>
x.schema === schema &&
x.table === table &&
x.roles.includes(role?.role ?? '') &&
(x.roles.includes(role?.role ?? '') ||
(x.roles.length === 1 && x.roles[0] === 'public')) &&
x.command === data.operation
)
return {
@@ -175,7 +178,9 @@ export const useTestQueryRLS = () => {
return {
limit,
testQuery,
inferSQLFromLib,
isLoading,
isInferring,
executeSqlError,
parseQueryError,
parseClientCodeError,
@@ -181,7 +181,7 @@ export const UserOverview = ({ user, onDeleteSuccess }: UserOverviewProps) => {
{isBanned ? (
<Admonition
type="warning"
description={`User banned until ${dayjs(user.banned_until).format(DATE_FORMAT)}`}
label={`User banned until ${dayjs(user.banned_until).format(DATE_FORMAT)}`}
className="border-r-0 border-l-0 rounded-none -mt-px [&_svg]:ml-0.5"
/>
) : (
@@ -0,0 +1,248 @@
import { LOCAL_STORAGE_KEYS, useParams } from 'common'
import dayjs from 'dayjs'
import { GitBranchIcon, GitMerge, MoreVertical, Shield } from 'lucide-react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import { toast } from 'sonner'
import {
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from 'ui'
import { TimestampInfo } from 'ui-patterns'
import { useIsPgDeltaDiffEnabled } from '../App/FeaturePreview/FeaturePreviewContext'
import { ReviewWithAI } from '../BranchManagement/ReviewWithAI'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { FeaturePreviewBadge } from '@/components/ui/FeaturePreviewBadge'
import { useBranchUpdateMutation } from '@/data/branches/branch-update-mutation'
import { useBranchesQuery } from '@/data/branches/branches-query'
import { useProjectGitHubConnectionQuery } from '@/data/integrations/github-connections-query'
import { useProjectDetailQuery } from '@/data/projects/project-detail-query'
import { useSendEventMutation } from '@/data/telemetry/send-event-mutation'
import { useBranchMergeDiff } from '@/hooks/branches/useBranchMergeDiff'
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
export const MergeTitle = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const pgDeltaDiffEnabled = useIsPgDeltaDiffEnabled()
const parentProjectRef = project?.parent_project_ref
const { data: branches } = useBranchesQuery(
{ projectRef: parentProjectRef },
{
refetchOnMount: 'always',
refetchOnWindowFocus: true,
staleTime: 0,
}
)
const currentBranch = branches?.find((branch) => branch.project_ref === ref)
const mainBranch = branches?.find((branch) => branch.is_default)
return (
<div className="flex items-center gap-x-4">
<div className="flex items-center gap-x-2">
<span>Merge</span>
<code className="flex items-center text-code-inline gap-x-1.5 px-2 py-1 border border-border">
<GitBranchIcon strokeWidth={1.5} size={14} className="text-foreground-lighter" />
{currentBranch?.name}
</code>
<span>into</span>
<Link href={`/project/${mainBranch?.project_ref}`} className="font-mono inline-flex gap-4">
<code className="flex items-center text-code-inline font-mono gap-x-1.5 px-2 py-1 border border-border">
<Shield strokeWidth={1.5} size={14} className="text-warning" />
{mainBranch?.name || 'main'}
</code>
</Link>
</div>
{pgDeltaDiffEnabled && (
<FeaturePreviewBadge featureKey={LOCAL_STORAGE_KEYS.UI_PREVIEW_PG_DELTA_DIFF} />
)}
</div>
)
}
export const MergeSubtitle = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const parentProjectRef = project?.parent_project_ref
const { data: branches } = useBranchesQuery(
{ projectRef: parentProjectRef },
{
refetchOnMount: 'always',
refetchOnWindowFocus: true,
staleTime: 0,
}
)
const currentBranch = branches?.find((branch) => branch.project_ref === ref)
const subtitle = useMemo(() => {
if (!currentBranch?.created_at) return 'Branch information unavailable'
if (!currentBranch?.review_requested_at) {
return 'Not ready for review'
}
const reviewRequestedTime = dayjs(currentBranch.review_requested_at).fromNow()
return (
<>
Request opened{' '}
<TimestampInfo
className="text-sm"
utcTimestamp={currentBranch.review_requested_at}
label={reviewRequestedTime}
/>
</>
)
}, [currentBranch?.created_at, currentBranch?.review_requested_at])
return <p className="text-foreground-lighter text-sm">{subtitle}</p>
}
export const MergeActions = ({
isWorkflowRunning,
isSubmitting,
onSelectMerge,
}: {
isWorkflowRunning: boolean
isSubmitting: boolean
onSelectMerge: () => void
}) => {
const router = useRouter()
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const { data: selectedOrg } = useSelectedOrganizationQuery()
const { mutate: sendEvent } = useSendEventMutation()
const { mutate: updateBranch, isPending: isUpdating } = useBranchUpdateMutation({
onError: (error) => {
toast.error(`Failed to update branch: ${error.message}`)
},
})
const parentProjectRef = project?.parent_project_ref
const { data: parentProject } = useProjectDetailQuery({ ref: parentProjectRef })
const { data: ghConnection } = useProjectGitHubConnectionQuery({ ref: parentProjectRef })
const { data: branches } = useBranchesQuery(
{ projectRef: parentProjectRef },
{
refetchOnMount: 'always',
refetchOnWindowFocus: true,
staleTime: 0,
}
)
const currentBranch = branches?.find((branch) => branch.project_ref === ref)
const mainBranch = branches?.find((branch) => branch.is_default)
const {
diffContent,
isBranchOutOfDateOverall,
isLoading: isCombinedDiffLoading,
hasChanges: combinedHasChanges,
} = useBranchMergeDiff({
currentBranchRef: ref,
parentProjectRef,
currentBranchConnectionString: project?.connectionString || undefined,
parentBranchConnectionString: parentProject?.connectionString || undefined,
currentBranchCreatedAt: currentBranch?.created_at,
})
const isMergeDisabled =
!combinedHasChanges ||
isCombinedDiffLoading ||
isBranchOutOfDateOverall ||
isWorkflowRunning ||
(!!ghConnection && Boolean(mainBranch?.git_branch))
return (
<div className="flex items-end gap-2">
<ReviewWithAI
currentBranch={currentBranch}
mainBranch={mainBranch}
parentProjectRef={parentProjectRef}
diffContent={diffContent}
disabled={!currentBranch || !mainBranch || isCombinedDiffLoading}
/>
{isMergeDisabled ? (
<ButtonTooltip
tooltip={{
content: {
side: 'bottom',
text: !combinedHasChanges
? 'No changes to merge'
: isWorkflowRunning
? 'Workflow is currently running'
: !!ghConnection && Boolean(mainBranch?.git_branch)
? 'Deploy to production from GitHub is enabled'
: 'Unable to merge at this time',
},
}}
type="primary"
loading={isSubmitting}
disabled={isMergeDisabled}
onClick={onSelectMerge}
icon={<GitMerge size={16} strokeWidth={1.5} className="text-brand" />}
>
Merge branch
</ButtonTooltip>
) : (
<Button
type="primary"
loading={isSubmitting}
onClick={onSelectMerge}
icon={<GitMerge size={16} strokeWidth={1.5} className="text-brand" />}
>
Merge branch
</Button>
)}
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button type="default" loading={isUpdating} className="px-1.5" icon={<MoreVertical />} />
</DropdownMenuTrigger>
<DropdownMenuContent side="bottom" align="end" className="w-52">
<DropdownMenuItem
className="gap-x-2"
onClick={() => {
if (!ref || !parentProjectRef) return
updateBranch(
{
branchRef: ref,
projectRef: parentProjectRef,
requestReview: false,
},
{
onSuccess: () => {
toast.success('Successfully closed merge request')
router.push(`/project/${project?.ref}/branches?tab=prs`)
sendEvent({
action: 'branch_close_merge_request_button_clicked',
groups: {
project: parentProjectRef ?? 'Unknown',
organization: selectedOrg?.slug ?? 'Unknown',
},
})
},
}
)
}}
>
Close this merge request
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}
@@ -1,6 +1,9 @@
import { useParams } from 'common'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useMemo, useRef } from 'react'
import { Button } from 'ui'
import { Admonition } from 'ui-patterns'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import type {
@@ -14,11 +17,13 @@ import { ConnectSheetStep } from './ConnectSheetStep'
import { CopyPromptAdmonition } from './CopyPromptAdmonition'
import { getConnectionStrings } from './DatabaseSettings.utils'
import { getAddons } from '@/components/interfaces/Billing/Subscription/Subscription.utils'
import { DocsButton } from '@/components/ui/DocsButton'
import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
import { usePgbouncerConfigQuery } from '@/data/database/pgbouncer-config-query'
import { useSupavisorConfigurationQuery } from '@/data/database/supavisor-configuration-query'
import { useProjectAddonsQuery } from '@/data/subscriptions/project-addons-query'
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
import { DOCS_URL } from '@/lib/constants'
import { pluckObjectFields } from '@/lib/helpers'
interface ConnectStepsSectionProps {
@@ -145,9 +150,25 @@ function StepContent({
}
export function ConnectStepsSection({ steps, state, projectKeys }: ConnectStepsSectionProps) {
const { ref } = useParams()
const stepsContainerRef = useRef<HTMLDivElement | null>(null)
const connectionStringPooler = useConnectionStringPooler()
const { data: ipv4Addon } = useProjectAddonsQuery(
{ projectRef: ref },
{
select: (data) => {
const selectedAddons = data?.selected_addons ?? []
return selectedAddons.find((addon) => addon.type === 'ipv4')
},
}
)
const showIpv4AddonNotice =
state.mode === 'direct' &&
!ipv4Addon &&
(state.connectionMethod === 'direct' ||
(state.connectionMethod === 'transaction' && !state.useSharedPooler))
if (steps.length === 0) return null
return (
@@ -157,6 +178,20 @@ export function ConnectStepsSection({ steps, state, projectKeys }: ConnectStepsS
<CopyPromptAdmonition stepsContainerRef={stepsContainerRef} />
{showIpv4AddonNotice && (
<Admonition
type="default"
title={`${state.connectionMethod === 'direct' ? 'Direct connections use' : 'Transaction pooler uses'} IPv6 by default`}
description="Enable the dedicated IPv4 address add-on to connect from IPv4-only networks"
actions={[
<Button asChild key="addon" type="default">
<Link href={`/project/${ref}/settings/addons?panel=ipv4`}>Enable IPv4 add-on</Link>
</Button>,
<DocsButton key="docs" href={`${DOCS_URL}/guides/platform/ipv4-address`} />,
]}
/>
)}
<div className="mt-6" ref={stepsContainerRef}>
{steps.map((step, index) => (
<ConnectSheetStep
@@ -1,6 +1,6 @@
import { Edit, MoreVertical, Search, Trash } from 'lucide-react'
import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import {
Button,
@@ -26,15 +26,21 @@ import EditEnumeratedTypeSidePanel from './EditEnumeratedTypeSidePanel'
import AlertError from '@/components/ui/AlertError'
import { DocsButton } from '@/components/ui/DocsButton'
import SchemaSelector from '@/components/ui/SchemaSelector'
import { Shortcut } from '@/components/ui/Shortcut'
import { useEnumeratedTypeDeleteMutation } from '@/data/enumerated-types/enumerated-type-delete-mutation'
import { useEnumeratedTypesQuery } from '@/data/enumerated-types/enumerated-types-query'
import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useIsProtectedSchema } from '@/hooks/useProtectedSchemas'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
export const EnumeratedTypes = () => {
const { data: project } = useSelectedProjectQuery()
const [search, setSearch] = useState('')
const [schemaSelectorOpen, setSchemaSelectorOpen] = useState(false)
const searchInputRef = useRef<HTMLInputElement>(null)
const { selectedSchema, setSelectedSchema } = useQuerySchemaState()
const {
@@ -80,6 +86,19 @@ export const EnumeratedTypes = () => {
const { isSchemaLocked } = useIsProtectedSchema({ schema: selectedSchema })
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search enumerated types' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setSearch('')
})
const onConfirmDeleteType = () => {
if (typeToDelete === undefined) return console.error('No enumerated type selected')
if (project?.ref === undefined) return console.error('Project ref required')
@@ -112,18 +131,29 @@ export const EnumeratedTypes = () => {
<div className="space-y-4">
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-2 flex-wrap">
<div className="flex flex-col lg:flex-row lg:items-center gap-2 flex-wrap">
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={setSelectedSchema}
/>
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_FOCUS_SCHEMA}
onTrigger={() => setSchemaSelectorOpen(true)}
side="bottom"
tooltipOpen={schemaSelectorOpen ? false : undefined}
>
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={setSelectedSchema}
open={schemaSelectorOpen}
onOpenChange={setSchemaSelectorOpen}
/>
</Shortcut>
<Input
ref={searchInputRef}
size="tiny"
value={search}
className="w-full lg:w-52"
onChange={(e) => setSearch(e.target.value)}
onKeyDown={onSearchInputEscape(search, setSearch)}
placeholder="Search for a type"
icon={<Search />}
/>
@@ -132,13 +162,20 @@ export const EnumeratedTypes = () => {
<div className="flex items-center gap-2">
<DocsButton href="https://www.postgresql.org/docs/current/datatype-enum.html" />
{!isSchemaLocked && (
<Button
className="ml-auto flex-1"
type="primary"
onClick={() => setShowCreateTypePanel(true)}
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_NEW_ITEM}
label="Create new enumerated type"
onTrigger={() => setShowCreateTypePanel(true)}
side="bottom"
>
Create type
</Button>
<Button
className="ml-auto flex-1"
type="primary"
onClick={() => setShowCreateTypePanel(true)}
>
Create type
</Button>
</Shortcut>
)}
</div>
</div>
@@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { isNull, partition } from 'lodash'
import { AlertCircle, Search } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import {
Card,
Input,
@@ -23,11 +23,28 @@ import { NoSearchResults } from '@/components/ui/NoSearchResults'
import { useDatabaseExtensionsQuery } from '@/data/database-extensions/database-extensions-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
export const Extensions = () => {
const { filter } = useParams()
const { data: project } = useSelectedProjectQuery()
const [filterString, setFilterString] = useState<string>('')
const searchInputRef = useRef<HTMLInputElement>(null)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search extensions' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setFilterString('')
})
const { data = [], isPending: isLoading } = useDatabaseExtensionsQuery({
projectRef: project?.ref,
@@ -63,10 +80,12 @@ export const Extensions = () => {
<>
<div className="mb-4">
<Input
inputRef={searchInputRef}
size="tiny"
placeholder="Search for an extension"
value={filterString}
onChange={(e) => setFilterString(e.target.value)}
onKeyDown={onSearchInputEscape(filterString, setFilterString)}
className="w-52"
icon={<Search />}
/>
@@ -1,9 +1,19 @@
import { safeSql } from '@supabase/pg-meta'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Search } from 'lucide-react'
import { parseAsBoolean, parseAsJson, parseAsString, useQueryState } from 'nuqs'
import { useEffect } from 'react'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import { AiIconAnimation, Card, Table, TableBody, TableHead, TableHeader, TableRow } from 'ui'
import {
AiIconAnimation,
Button,
Card,
Table,
TableBody,
TableHead,
TableHeader,
TableRow,
} from 'ui'
import { Input } from 'ui-patterns/DataInputs/Input'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
@@ -20,20 +30,24 @@ import ProductEmptyState from '@/components/to-be-cleaned/ProductEmptyState'
import AlertError from '@/components/ui/AlertError'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import SchemaSelector from '@/components/ui/SchemaSelector'
import { Shortcut } from '@/components/ui/Shortcut'
import { TextConfirmModal } from '@/components/ui/TextConfirmModalWrapper'
import { useDatabaseFunctionDeleteMutation } from '@/data/database-functions/database-functions-delete-mutation'
import type { DatabaseFunction } from '@/data/database-functions/database-functions-query'
import type { SavedDatabaseFunction } from '@/data/database-functions/database-functions-query'
import { useDatabaseFunctionsQuery } from '@/data/database-functions/database-functions-query'
import { useSchemasQuery } from '@/data/database/schemas-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useIsProtectedSchema } from '@/hooks/useProtectedSchemas'
import { onSearchInputEscape } from '@/lib/keyboard'
import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state'
import { useEditorPanelStateSnapshot } from '@/state/editor-panel-state'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state'
const createFunctionSnippet = `create function function_name()
const createFunctionSnippet = safeSql`create function function_name()
returns void
language plpgsql
as $$
@@ -66,7 +80,7 @@ export const FunctionsList = () => {
}
}
const duplicateFunction = (fn: DatabaseFunction) => {
const duplicateFunction = (fn: SavedDatabaseFunction) => {
if (isInlineEditorEnabled) {
const dupFn = {
...fn,
@@ -81,7 +95,7 @@ export const FunctionsList = () => {
}
}
const editFunction = (fn: DatabaseFunction) => {
const editFunction = (fn: SavedDatabaseFunction) => {
setSelectedFunctionIdToDuplicate(null)
if (isInlineEditorEnabled) {
setEditorPanelValue(fn.complete_statement)
@@ -107,6 +121,9 @@ export const FunctionsList = () => {
parseAsJson(selectFilterSchema.parse)
)
const [schemaSelectorOpen, setSchemaSelectorOpen] = useState(false)
const searchInputRef = useRef<HTMLInputElement>(null)
const { can: canCreateFunctions } = useAsyncCheckPermissions(
PermissionAction.TENANT_SQL_ADMIN_WRITE,
'functions'
@@ -114,6 +131,23 @@ export const FunctionsList = () => {
const { isSchemaLocked } = useIsProtectedSchema({ schema: selectedSchema })
const canAddFunctions = canCreateFunctions && !isSchemaLocked
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search functions' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setFilterString('')
setReturnTypeFilter(null)
setSecurityFilter(null)
})
// [Joshen] This is to preload the data for the Schema Selector
useSchemasQuery({
projectRef: project?.ref,
@@ -236,23 +270,34 @@ export const FunctionsList = () => {
<div className="w-full space-y-4">
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-2 flex-wrap">
<div className="flex flex-col lg:flex-row lg:items-center gap-2">
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={(schema) => {
setFilterString('')
setSelectedSchema(schema)
}}
/>
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_FOCUS_SCHEMA}
onTrigger={() => setSchemaSelectorOpen(true)}
side="bottom"
tooltipOpen={schemaSelectorOpen ? false : undefined}
>
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={(schema) => {
setFilterString('')
setSelectedSchema(schema)
}}
open={schemaSelectorOpen}
onOpenChange={setSchemaSelectorOpen}
/>
</Shortcut>
<Input
ref={searchInputRef}
placeholder="Search for a function"
size="tiny"
icon={<Search />}
value={filterString}
className="w-full lg:w-52"
onChange={(e) => setFilterString(e.target.value)}
onKeyDown={onSearchInputEscape(filterString, setFilterString)}
/>
<ReportsSelectFilter
label="Return Type"
@@ -275,21 +320,31 @@ export const FunctionsList = () => {
<div className="flex items-center gap-x-2">
{!isSchemaLocked && (
<>
<ButtonTooltip
disabled={!canCreateFunctions}
onClick={() => createFunction()}
className="grow"
tooltip={{
content: {
side: 'bottom',
text: !canCreateFunctions
? 'You need additional permissions to create functions'
: undefined,
},
}}
>
Create a new function
</ButtonTooltip>
{canAddFunctions ? (
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_NEW_ITEM}
label="Create new function"
onTrigger={() => createFunction()}
side="bottom"
>
<Button className="grow" onClick={() => createFunction()}>
Create a new function
</Button>
</Shortcut>
) : (
<ButtonTooltip
disabled
className="grow"
tooltip={{
content: {
side: 'bottom',
text: 'You need additional permissions to create functions',
},
}}
>
Create a new function
</ButtonTooltip>
)}
<ButtonTooltip
type="default"
disabled={!canCreateFunctions}
@@ -2,7 +2,7 @@ import { useParams } from 'common'
import { sortBy } from 'lodash'
import { AlertCircle, Search, Trash } from 'lucide-react'
import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs'
import { useEffect } from 'react'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import {
Button,
@@ -24,18 +24,24 @@ import { CreateIndexSidePanel } from './CreateIndexSidePanel'
import AlertError from '@/components/ui/AlertError'
import CodeEditor from '@/components/ui/CodeEditor/CodeEditor'
import SchemaSelector from '@/components/ui/SchemaSelector'
import { Shortcut } from '@/components/ui/Shortcut'
import { useDatabaseIndexDeleteMutation } from '@/data/database-indexes/index-delete-mutation'
import { useIndexesQuery, type DatabaseIndex } from '@/data/database-indexes/indexes-query'
import { useSchemasQuery } from '@/data/database/schemas-query'
import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { useIsProtectedSchema } from '@/hooks/useProtectedSchemas'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
export const Indexes = () => {
const { data: project } = useSelectedProjectQuery()
const { schema: urlSchema, table } = useParams()
const [search, setSearch] = useQueryState('search', parseAsString.withDefault(''))
const [schemaSelectorOpen, setSchemaSelectorOpen] = useState(false)
const searchInputRef = useRef<HTMLInputElement>(null)
const { selectedSchema, setSelectedSchema } = useQuerySchemaState()
const {
@@ -84,6 +90,19 @@ export const Indexes = () => {
const { isSchemaLocked } = useIsProtectedSchema({ schema: selectedSchema })
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search indexes' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setSearch('')
})
const sortedIndexes = sortBy(allIndexes ?? [], (index) => index.name.toLocaleLowerCase())
const indexes =
search.length > 0
@@ -138,32 +157,51 @@ export const Indexes = () => {
</div>
)}
{isSuccessSchemas && (
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={setSelectedSchema}
/>
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_FOCUS_SCHEMA}
onTrigger={() => setSchemaSelectorOpen(true)}
side="bottom"
tooltipOpen={schemaSelectorOpen ? false : undefined}
>
<SchemaSelector
className="w-full lg:w-[180px]"
size="tiny"
showError={false}
selectedSchemaName={selectedSchema}
onSelectSchema={setSelectedSchema}
open={schemaSelectorOpen}
onOpenChange={setSchemaSelectorOpen}
/>
</Shortcut>
)}
<Input
ref={searchInputRef}
size="tiny"
value={search}
className="w-full lg:w-52"
onChange={(e) => setSearch(e.target.value)}
onKeyDown={onSearchInputEscape(search, setSearch)}
placeholder="Search for an index"
icon={<Search />}
/>
{!isSchemaLocked && (
<Button
className="ml-auto grow lg:grow-0"
type="primary"
onClick={() => setShowCreateIndex(true)}
disabled={!isSuccessSchemas}
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_NEW_ITEM}
label="Create new index"
onTrigger={() => setShowCreateIndex(true)}
options={{ enabled: isSuccessSchemas }}
side="bottom"
>
Create index
</Button>
<Button
className="ml-auto grow lg:grow-0"
type="primary"
onClick={() => setShowCreateIndex(true)}
disabled={!isSuccessSchemas}
>
Create index
</Button>
</Shortcut>
)}
</div>
@@ -1,6 +1,6 @@
import { SupportCategories } from '@supabase/shared-types/out/constants'
import { Search } from 'lucide-react'
import { useState } from 'react'
import { useRef, useState } from 'react'
import {
Button,
Card,
@@ -28,10 +28,24 @@ import { DatabaseMigration, useMigrationsQuery } from '@/data/database/migration
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { DOCS_URL } from '@/lib/constants'
import { formatMigrationVersionLabel, parseMigrationVersion } from '@/lib/migration-utils'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
const Migrations = () => {
const [search, setSearch] = useState('')
const [selectedMigration, setSelectedMigration] = useState<DatabaseMigration>()
const searchInputRef = useRef<HTMLInputElement>(null)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search migrations' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => setSearch(''))
const { data: project } = useSelectedProjectQuery()
const {
@@ -96,6 +110,7 @@ const Migrations = () => {
{data.length > 0 && (
<div className="flex flex-col gap-y-4">
<Input
ref={searchInputRef}
size="tiny"
placeholder="Search for a migration"
value={search}
@@ -27,3 +27,21 @@ export const PublicationSkeleton = ({ index }: PublicationSkeletonProps) => {
</TableRow>
)
}
export const PublicationTablesSkeleton = ({ index }: PublicationSkeletonProps) => {
return (
<TableRow>
<TableCell style={{ width: '35%' }}>
<ShimmeringLoader className="h-4 w-24 my-0.5 p-0" delayIndex={index} />
</TableCell>
<TableCell className="hidden lg:table-cell" style={{ width: '15%' }}>
<ShimmeringLoader className="h-4 w-14 my-0.5 p-0" delayIndex={index} />
</TableCell>
<TableCell className="px-4 py-3 pr-2">
<div className="flex">
<ShimmeringLoader className="h-6 w-12 p-0" delayIndex={index} />
</div>
</TableCell>
</TableRow>
)
}
@@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { AlertCircle, Info, Search } from 'lucide-react'
import Link from 'next/link'
import { useState } from 'react'
import { useRef, useState } from 'react'
import { toast } from 'sonner'
import {
Button,
@@ -29,6 +29,9 @@ import { useDatabasePublicationsQuery } from '@/data/database-publications/datab
import { useDatabasePublicationUpdateMutation } from '@/data/database-publications/database-publications-update-mutation'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
interface PublicationEvent {
event: string
@@ -39,6 +42,20 @@ export const PublicationsList = () => {
const { ref } = useParams()
const { data: project } = useSelectedProjectQuery()
const [filterString, setFilterString] = useState<string>('')
const searchInputRef = useRef<HTMLInputElement>(null)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search publications' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setFilterString('')
})
const {
data = [],
@@ -95,27 +112,27 @@ export const PublicationsList = () => {
return (
<>
<div className="mb-4">
<div className="flex items-center justify-between">
<div className="flex items-center">
<Input
size="tiny"
icon={<Search />}
className="w-48"
placeholder="Search for a publication"
value={filterString}
onChange={(e) => setFilterString(e.target.value)}
<div className="flex items-center justify-between">
<div className="flex items-center">
<Input
ref={searchInputRef}
size="tiny"
icon={<Search />}
className="w-48"
placeholder="Search for a publication"
value={filterString}
onChange={(e) => setFilterString(e.target.value)}
onKeyDown={onSearchInputEscape(filterString, setFilterString)}
/>
</div>
{isPermissionsLoaded && !canUpdatePublications && (
<div className="w-[500px]">
<InformationBox
icon={<AlertCircle className="text-foreground-light" strokeWidth={2} />}
title="You need additional permissions to update database publications"
/>
</div>
{isPermissionsLoaded && !canUpdatePublications && (
<div className="w-[500px]">
<InformationBox
icon={<AlertCircle className="text-foreground-light" strokeWidth={2} />}
title="You need additional permissions to update database publications"
/>
</div>
)}
</div>
)}
</div>
<div className="w-full overflow-hidden overflow-x-auto">
@@ -144,6 +161,18 @@ export const PublicationsList = () => {
</TableRow>
)}
{!isLoading && publications.length === 0 && (
<TableRow>
<TableCell colSpan={7}>
<NoSearchResults
searchString={filterString}
onResetFilter={() => setFilterString('')}
className="border-none !p-0"
/>
</TableCell>
</TableRow>
)}
{isSuccess &&
publications.map((x) => (
<TableRow key={x.name}>
@@ -204,14 +233,6 @@ export const PublicationsList = () => {
</Card>
</div>
{!isLoading && publications.length === 0 && (
<NoSearchResults
searchString={filterString}
onResetFilter={() => setFilterString('')}
className="rounded-t-none border-t-0"
/>
)}
<ConfirmationModal
visible={toggleListenEventValue !== null}
title={`Confirm to toggle sending ${toggleListenEventValue?.event.event.toLowerCase()} events`}
@@ -1,31 +1,43 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useParams } from 'common'
import { ChevronLeft, Search } from 'lucide-react'
import Link from 'next/link'
import { useMemo, useState } from 'react'
import { Card, LogoLoader, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
import { Search } from 'lucide-react'
import { useMemo, useRef, useState } from 'react'
import { Card, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from 'ui'
import { Admonition } from 'ui-patterns'
import { Input } from 'ui-patterns/DataInputs/Input'
import { PublicationTablesSkeleton } from './PublicationSkeleton'
import { PublicationsTableItem } from './PublicationsTableItem'
import AlertError from '@/components/ui/AlertError'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { AlertError } from '@/components/ui/AlertError'
import { NoSearchResults } from '@/components/ui/NoSearchResults'
import { useDatabasePublicationsQuery } from '@/data/database-publications/database-publications-query'
import { useTablesQuery } from '@/data/tables/tables-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
export const PublicationsTables = () => {
const { ref, id } = useParams()
const { id } = useParams()
const { data: project } = useSelectedProjectQuery()
const [filterString, setFilterString] = useState<string>('')
const searchInputRef = useRef<HTMLInputElement>(null)
const { can: canUpdatePublications, isLoading: isLoadingPermissions } = useAsyncCheckPermissions(
PermissionAction.TENANT_SQL_ADMIN_WRITE,
'publications'
)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search publications' }
)
const { data: publications = [] } = useDatabasePublicationsQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
@@ -53,87 +65,89 @@ export const PublicationsTables = () => {
<>
<div className="mb-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<ButtonTooltip
asChild
type="outline"
icon={<ChevronLeft />}
style={{ padding: '5px' }}
tooltip={{ content: { side: 'bottom', text: 'Go back to publications list' } }}
>
<Link href={`/project/${ref}/database/publications`} />
</ButtonTooltip>
<div>
<Input
size="tiny"
placeholder="Search for a table"
value={filterString}
onChange={(e) => setFilterString(e.target.value)}
icon={<Search />}
className="w-48"
/>
</div>
</div>
<Input
size="tiny"
ref={searchInputRef}
icon={<Search />}
className="w-48"
placeholder="Search for a table"
value={filterString}
onChange={(e) => setFilterString(e.target.value)}
onKeyDown={onSearchInputEscape(filterString, setFilterString)}
/>
{!isLoadingPermissions && !canUpdatePublications && (
<Admonition
type="note"
className="w-[500px]"
title="You need additional permissions to update database replications"
/>
)}
</div>
</div>
{!isLoadingPermissions && !canUpdatePublications && (
<Admonition
type="warning"
className="mb-4 w-full"
description="You need additional permissions to update database replications."
/>
)}
<Card>
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Schema</TableHead>
<TableHead className="hidden lg:table-cell">Description</TableHead>
{/*
We've disabled All tables toggle for publications.
See https://github.com/supabase/supabase/pull/7233.
*/}
<TableHead />
</TableRow>
</TableHeader>
<TableBody>
{(isLoading || isLoadingPermissions) &&
Array.from({ length: 2 }).map((_, i) => (
<PublicationTablesSkeleton key={i} index={i} />
))}
{(isLoading || isLoadingPermissions) && (
<div className="mt-8">
<LogoLoader />
</div>
)}
{isError && (
<TableRow>
<TableCell colSpan={4}>
<AlertError error={error} subject="Failed to retrieve tables" />
</TableCell>
</TableRow>
)}
{isError && <AlertError error={error} subject="Failed to retrieve tables" />}
{!isLoading && !isLoadingPermissions && tables.length === 0 && (
<TableRow>
<TableCell colSpan={4}>
<NoSearchResults
className="border-none !p-0"
searchString={filterString}
onResetFilter={() => setFilterString('')}
/>
</TableCell>
</TableRow>
)}
{isSuccess &&
(tables.length === 0 ? (
<NoSearchResults searchString={filterString} onResetFilter={() => setFilterString('')} />
) : (
<Card>
<Table>
<TableHeader>
{isSuccess ? (
!!selectedPublication ? (
tables.map((table) => (
<PublicationsTableItem
key={table.id}
table={table}
selectedPublication={selectedPublication}
/>
))
) : (
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Schema</TableHead>
<TableHead className="hidden lg:table-cell">Description</TableHead>
{/*
We've disabled All tables toggle for publications.
See https://github.com/supabase/supabase/pull/7233.
*/}
<TableHead />
<TableCell colSpan={4}>
<p>The selected publication with ID {id} cannot be found</p>
<p className="text-foreground-light">
Head back to the list of publications to select one from there
</p>
</TableCell>
</TableRow>
</TableHeader>
<TableBody>
{!!selectedPublication ? (
tables.map((table) => (
<PublicationsTableItem
key={table.id}
table={table}
selectedPublication={selectedPublication}
/>
))
) : (
<TableRow>
<TableCell colSpan={4}>
<p>The selected publication with ID {id} cannot be found</p>
<p className="text-foreground-light">
Head back to the list of publications to select one from there
</p>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</Card>
))}
)
) : null}
</TableBody>
</Table>
</Card>
</>
)
}
@@ -653,26 +653,21 @@ export const AnalyticsBucketFields = ({
</p>
{isSuccessKeys && keyNoLongerExists && (
<Admonition
type="warning"
title="Unable to find access key ID in project"
description={
<>
Please select another key or create a new set, as this destination will
not work otherwise. S3 access keys can be managed in your{' '}
<InlineLink href={`/project/${projectRef}/storage/files/settings`}>
storage settings
</InlineLink>
.
</>
}
/>
<Admonition type="warning" title="Unable to find access key ID in project">
<p className="leading-normal!">
Please select another key or create a new set, as this destination will not
work otherwise. S3 access keys can be managed in your{' '}
<InlineLink href={`/project/${projectRef}/storage/files/settings`}>
storage settings
</InlineLink>
</p>
</Admonition>
)}
{s3AccessKeyId === CREATE_NEW_KEY && (
<Admonition
type="default"
description="A new set of S3 access keys will be created."
title="A new set of S3 access keys will be created"
/>
)}
</div>
@@ -738,7 +733,7 @@ export const AnalyticsBucketFields = ({
layout="horizontal"
label="S3 Secret Access Key"
className="relative"
description="The secret key corresponding to your selected access key ID."
description="The secret key corresponding to your selected access key ID"
>
<FormControl>
<Input_Shadcn_
@@ -36,6 +36,7 @@ import {
} from './useIsETLPrivateAlpha'
import { AlertError } from '@/components/ui/AlertError'
import { DocsButton } from '@/components/ui/DocsButton'
import { Shortcut } from '@/components/ui/Shortcut'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { useReplicationDestinationsQuery } from '@/data/replication/destinations-query'
import { replicationKeys } from '@/data/replication/keys'
@@ -44,6 +45,8 @@ import { useReplicationPipelinesQuery } from '@/data/replication/pipelines-query
import { useReplicationSourcesQuery } from '@/data/replication/sources-query'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { DOCS_URL } from '@/lib/constants'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
export const Destinations = () => {
const queryClient = useQueryClient()
@@ -65,6 +68,7 @@ export const Destinations = () => {
: null
const prefetchedRef = useRef(false)
const searchInputRef = useRef<HTMLInputElement>(null)
const [filterString, setFilterString] = useState<string>('')
const [statusRefetchInterval, setStatusRefetchInterval] = useState<number | false>(5000)
const [showDisableExternalReplicationDialog, setShowDisableExternalReplicationDialog] =
@@ -143,6 +147,17 @@ export const Destinations = () => {
setDestinationType(newDestinationDefaultType)
}
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search destinations' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => setFilterString(''))
useEffect(() => {
if (
projectRef &&
@@ -190,6 +205,7 @@ export const Destinations = () => {
<div className="flex items-center justify-between">
<div className="flex items-center">
<Input
ref={searchInputRef}
placeholder="Filter destinations"
size="tiny"
icon={<Search />}
@@ -209,14 +225,22 @@ export const Destinations = () => {
/>
</div>
<div className="flex items-center gap-x-2">
<Button
type="default"
icon={<Plus />}
disabled={!newDestinationDefaultType}
onClick={openDestinationPanel}
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_NEW_ITEM}
label="Add destination"
onTrigger={openDestinationPanel}
options={{ enabled: !!newDestinationDefaultType }}
side="bottom"
>
Add destination
</Button>
<Button
type="default"
icon={<Plus />}
disabled={!newDestinationDefaultType}
onClick={openDestinationPanel}
>
Add destination
</Button>
</Shortcut>
<DocsButton href={`${DOCS_URL}/guides/database/replication`} />
{canDisableExternalReplication && (
<DropdownMenu>
@@ -136,7 +136,7 @@ export const RestoreToNewProject = () => {
return (
<Admonition
type="default"
description="Restoring to new projects is temporarily not available for AWS (Revamped) projects."
title="Restoring to new projects is temporarily not available for AWS (Revamped) projects"
/>
)
}
@@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { partition, sortBy } from 'lodash'
import { Plus, Search, X } from 'lucide-react'
import { parseAsBoolean, parseAsString, useQueryState } from 'nuqs'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import { Badge, Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import { Input } from 'ui-patterns/DataInputs/Input'
@@ -14,12 +14,16 @@ import { RoleRowSkeleton } from './RoleRowSkeleton'
import { SUPABASE_ROLES } from './Roles.constants'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { NoSearchResults } from '@/components/ui/NoSearchResults'
import { Shortcut } from '@/components/ui/Shortcut'
import { SparkBar } from '@/components/ui/SparkBar'
import { useDatabaseRoleDeleteMutation } from '@/data/database-roles/database-role-delete-mutation'
import { useDatabaseRolesQuery } from '@/data/database-roles/database-roles-query'
import { useMaxConnectionsQuery } from '@/data/database/max-connections-query'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { onSearchInputEscape } from '@/lib/keyboard'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
import { useShortcut } from '@/state/shortcuts/useShortcut'
type SUPABASE_ROLE = (typeof SUPABASE_ROLES)[number]
@@ -28,12 +32,27 @@ export const RolesList = () => {
const [filterString, setFilterString] = useState('')
const [filterType, setFilterType] = useState<'all' | 'active'>('all')
const searchInputRef = useRef<HTMLInputElement>(null)
const { can: canUpdateRoles } = useAsyncCheckPermissions(
PermissionAction.TENANT_SQL_ADMIN_WRITE,
'roles'
)
useShortcut(
SHORTCUT_IDS.LIST_PAGE_FOCUS_SEARCH,
() => {
searchInputRef.current?.focus()
searchInputRef.current?.select()
},
{ label: 'Search roles' }
)
useShortcut(SHORTCUT_IDS.LIST_PAGE_RESET_FILTERS, () => {
setFilterString('')
setFilterType('all')
})
const { data: maxConnData } = useMaxConnectionsQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
@@ -107,12 +126,14 @@ export const RolesList = () => {
<div className="mb-4 flex items-center justify-between gap-2 flex-wrap">
<div className="flex items-center space-x-4">
<Input
ref={searchInputRef}
size="tiny"
className="w-52"
placeholder="Search for a role"
icon={<Search />}
value={filterString}
onChange={(event) => setFilterString(event.target.value)}
onKeyDown={onSearchInputEscape(filterString, setFilterString)}
actions={
filterString && (
<Button
@@ -191,22 +212,36 @@ export const RolesList = () => {
))}
</TooltipContent>
</Tooltip>
<ButtonTooltip
type="primary"
disabled={!canUpdateRoles}
icon={<Plus size={12} />}
onClick={() => setIsCreatingRole(true)}
tooltip={{
content: {
side: 'bottom',
text: !canUpdateRoles
? 'You need additional permissions to add a new role'
: undefined,
},
}}
>
Add role
</ButtonTooltip>
{canUpdateRoles ? (
<Shortcut
id={SHORTCUT_IDS.LIST_PAGE_NEW_ITEM}
label="Add new role"
onTrigger={() => setIsCreatingRole(true)}
side="bottom"
>
<Button
type="primary"
icon={<Plus size={12} />}
onClick={() => setIsCreatingRole(true)}
>
Add role
</Button>
</Shortcut>
) : (
<ButtonTooltip
type="primary"
disabled
icon={<Plus size={12} />}
tooltip={{
content: {
side: 'bottom',
text: 'You need additional permissions to add a new role',
},
}}
>
Add role
</ButtonTooltip>
)}
</div>
</div>
Loaded 100 of 386 files, more files were not shown because too many files have changed in this diff. Show more