diff --git a/.github/workflows/docs-mgmt-api-update.yml b/.github/workflows/docs-mgmt-api-update.yml index 7272f722f36..0b8d542d59a 100644 --- a/.github/workflows/docs-mgmt-api-update.yml +++ b/.github/workflows/docs-mgmt-api-update.yml @@ -8,7 +8,7 @@ on: permissions: pull-requests: write - contents: read + contents: write jobs: update-docs: diff --git a/.vale.ini b/.vale.ini deleted file mode 100644 index 1ff9438668a..00000000000 --- a/.vale.ini +++ /dev/null @@ -1,14 +0,0 @@ -StylesPath = './vale/styles' -MinAlertLevel = 'suggestion' - -Vocab = Supabase - -[formats] -mdx = md - -[*] -BasedOnStyles = Vale, Custom -BlockIgnores = (?s) *(.*?), \ -(?s) *(export\s+const\s+\S+\s*=\s*\[.*?\]), \ -(?s) *() -TokenIgnores = (href\s*([=:])\s*['"].*?\1), \ diff --git a/DEVELOPERS.md b/DEVELOPERS.md index ae379939f1d..c41044ceb71 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -65,7 +65,7 @@ To contribute code to [Supabase](https://supabase.com), you must fork the [Supab ### Install dependencies -1. Install the dependencies in the root of the repo. +1. Install the dependencies in the root of the repo: ```sh pnpm install # install dependencies @@ -77,7 +77,7 @@ To contribute code to [Supabase](https://supabase.com), you must fork the [Supab cp apps/www/.env.local.example apps/www/.env.local ``` -3. After that you can run the apps simultaneously with the following. +3. After that you can run the apps simultaneously with the following: ```sh pnpm dev # start all the applications ``` @@ -117,8 +117,8 @@ Installing a package in a specific workspace requires you to move to the workspa For example: -1. `cd apps/studio`: move to the `studio` workspace -2. `pnpm add react`: installs `react` into `studio` workspace +1. `cd apps/studio`: move to the `studio` workspace. +2. `pnpm add react`: installs `react` into `studio` workspace. --- @@ -145,7 +145,7 @@ First, make sure you have the Docker installed on your device. You can download cp .env.example .env ``` -3. Run docker +3. Run docker: ```sh docker compose up @@ -186,9 +186,9 @@ Create a new entry in the [`redirects.js`](https://github.com/supabase/supabase/ We support "federating" docs, meaning doc content can come directly from external repos other than [`supabase/supabase`](https://github.com/supabase/supabase). - It's great for things like client libs who have their own set of docs that we don't want to duplicate on the official Supabase docs (eg. [`supabase/vecs`](https://github.com/supabase/vecs)). -- No duplication or manual steps required - fetches and generates automatically as part of the docs build pipeline -- It's flexible - you can "embed" external docs nearly anywhere at any level in Supabase docs, but they will feel native -- If you are maintaining a repo containing docs that you think could also live in Supabase docs, feel free to create an issue and we can work together to integrate +- No duplication or manual steps required - fetches and generates automatically as part of the docs build pipeline. +- It's flexible - you can "embed" external docs nearly anywhere at any level in Supabase docs, but they will feel native. +- If you are maintaining a repo containing docs that you think could also live in Supabase docs, feel free to create an issue and we can work together to integrate. Federated docs work using Next.js's build pipeline. We use `getStaticProps()` to fetch remote documentation (ie. markdown) at build time which is processed and passed to the respective page within the docs. diff --git a/README.md b/README.md index e74a9fd2814..ee13ffbc323 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,7 @@ Our approach for client libraries is modular. Each sub-library is a standalone i - [Bangla / বাংলা](/i18n/README.bn.md) - [Bulgarian / Български](/i18n/README.bg.md) - [Catalan / Català](/i18n/README.ca.md) +- [Croatian / Hrvatski](/i18n/README.hr.md) - [Czech / čeština](/i18n/README.cs.md) - [Danish / Dansk](/i18n/README.da.md) - [Dutch / Nederlands](/i18n/README.nl.md) diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index e507e711b14..6cba85388af 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -1443,7 +1443,7 @@ export const functions: NavMenuConstant = { url: undefined, items: [ { name: 'Background Tasks', url: '/guides/functions/background-tasks' }, - { name: 'Ephemeral Storage', url: '/guides/functions/ephemeral-storage' }, + { name: 'File Storage', url: '/guides/functions/ephemeral-storage' }, { name: 'WebSockets', url: '/guides/functions/websockets' }, { name: 'Custom Routing', url: '/guides/functions/routing' }, { name: 'Wasm Modules', url: '/guides/functions/wasm' }, diff --git a/apps/docs/content/_partials/project_setup.mdx b/apps/docs/content/_partials/project_setup.mdx index 3d0d9d43288..9b0f3b19adb 100644 --- a/apps/docs/content/_partials/project_setup.mdx +++ b/apps/docs/content/_partials/project_setup.mdx @@ -1,16 +1,16 @@ ## Project setup -Before we start building we're going to set up our Database and API. This is as simple as starting a new Project in Supabase and then creating a "schema" inside the database. +Before you start building you need to set up the Database and API. You can do this by starting a new Project in Supabase and then creating a "schema" inside the database. ### Create a project 1. [Create a new project](https://supabase.com/dashboard) in the Supabase Dashboard. -1. Enter your project details. -1. Wait for the new database to launch. +2. Enter your project details. +3. Wait for the new database to launch. ### Set up the database schema -Now we are going to set up the database schema. We can use the "User Management Starter" quickstart in the SQL Editor, or you can just copy/paste the SQL from below and run it yourself. +Now set up the database schema. You can use the "User Management Starter" quickstart in the SQL Editor, or you can copy/paste the SQL from below and run it. +{/* TODO: discuss */} ```bash supabase link --project-ref @@ -37,6 +37,8 @@ supabase link --project-ref supabase db pull ``` + + @@ -58,7 +60,8 @@ supabase migration new user_management_starter ### Get the API keys Now that you've created some database tables, you are ready to insert data using the auto-generated API. -We just need to get the Project URL and `anon` key from the API settings. + +To do this, you need to get the Project URL and `anon` key from the API settings. 1. Go to the [API Settings](https://supabase.com/dashboard/project/_/settings/api) page in the Dashboard. -1. Find your Project `URL`, `anon`, and `service_role` keys on this page. +2. Find your Project `URL`, `anon`, and `service_role` keys on this page. diff --git a/apps/docs/content/guides/auth/auth-anonymous.mdx b/apps/docs/content/guides/auth/auth-anonymous.mdx index 7c363423ab3..0a4f0b43c2e 100644 --- a/apps/docs/content/guides/auth/auth-anonymous.mdx +++ b/apps/docs/content/guides/auth/auth-anonymous.mdx @@ -269,6 +269,7 @@ using ( true ); RLS policies are permissive by default, which means that they are combined using an "OR" operator when multiple policies are applied. It is important to construct restrictive policies to ensure that the checks for an anonymous user are always enforced when combined with other policies. +Be aware that a single 'restrictive' RLS policy alone will fail unless combined with another policy that returns true, ensuring the combined condition is met. diff --git a/apps/docs/content/guides/auth/passwords.mdx b/apps/docs/content/guides/auth/passwords.mdx index afdfa5b0c0b..961f4cc4c73 100644 --- a/apps/docs/content/guides/auth/passwords.mdx +++ b/apps/docs/content/guides/auth/passwords.mdx @@ -629,7 +629,7 @@ The PKCE flow allows for server-side authentication. Unlike the implicit flow, w Update your reset password email template to send the token hash. See [Email Templates](/docs/guides/auth/auth-email-templates) for how to configure your email templates. -Your signup email template should contain the following HTML: +Your reset password email template should contain the following HTML: ```html

Reset Password

@@ -960,11 +960,11 @@ Consider configuring a custom SMTP server for production. See the [Custom SMTP guide](/docs/guides/auth/auth-smtp) for instructions. -#### Local development with Inbucket +#### Local development with Mailpit -You can test email flows on your local machine. The Supabase CLI automatically captures emails sent locally by using [Inbucket](https://github.com/inbucket/inbucket). +You can test email flows on your local machine. The Supabase CLI automatically captures emails sent locally by using [Mailpit](https://github.com/axllent/mailpit). -In your terminal, run `supabase status` to get the Inbucket URL. Go to this URL in your browser, and follow the instructions to find your emails. +In your terminal, run `supabase status` to get the Mailpit URL. Go to this URL in your browser, and follow the instructions to find your emails. ## With phone diff --git a/apps/docs/content/guides/auth/quickstarts/react-native.mdx b/apps/docs/content/guides/auth/quickstarts/react-native.mdx index ac779e0e5fc..45d125f9074 100644 --- a/apps/docs/content/guides/auth/quickstarts/react-native.mdx +++ b/apps/docs/content/guides/auth/quickstarts/react-native.mdx @@ -71,7 +71,7 @@ hideToc: true ```ts name=lib/supabase.ts - import { AppState } from 'react-native' + import { AppState, Platform } from 'react-native' import 'react-native-url-polyfill/auto' import AsyncStorage from '@react-native-async-storage/async-storage' import { createClient, processLock } from '@supabase/supabase-js' @@ -81,7 +81,7 @@ hideToc: true export const supabase = createClient(supabaseUrl, supabaseAnonKey, { auth: { - storage: AsyncStorage, + ...(Platform.OS !== "web" ? { storage: AsyncStorage } : {}), autoRefreshToken: true, persistSession: true, detectSessionInUrl: false, @@ -94,13 +94,15 @@ hideToc: true // to receive `onAuthStateChange` events with the `TOKEN_REFRESHED` or // `SIGNED_OUT` event if the user's session is terminated. This should // only be registered once. - AppState.addEventListener('change', (state) => { - if (state === 'active') { - supabase.auth.startAutoRefresh() - } else { - supabase.auth.stopAutoRefresh() - } - }) + if (Platform.OS !== "web") { + AppState.addEventListener('change', (state) => { + if (state === 'active') { + supabase.auth.startAutoRefresh() + } else { + supabase.auth.stopAutoRefresh() + } + }) + } ``` diff --git a/apps/docs/content/guides/auth/server-side/nextjs.mdx b/apps/docs/content/guides/auth/server-side/nextjs.mdx index 1b3390e20a6..2cae8e90d46 100644 --- a/apps/docs/content/guides/auth/server-side/nextjs.mdx +++ b/apps/docs/content/guides/auth/server-side/nextjs.mdx @@ -67,7 +67,7 @@ To access Supabase from your Next.js app, you need 2 types of Supabase clients: 1. **Client Component client** - To access Supabase from Client Components, which run in the browser. 1. **Server Component client** - To access Supabase from Server Components, Server Actions, and Route Handlers, which run only on the server. -Create a `utils/supabase` folder with a file for each type of client. Then copy the utility functions for each client type. +Create a `utils/supabase` folder at the root of your project, or inside the `./src` folder if you are using one, with a file for each type of client. Then copy the utility functions for each client type. - -The [official PostGIS documentation](https://postgis.net/documentation/tips/tip-move-postgis-schema/) for relocating the schema will cause issues for Supabase projects. These issues might not be apparent immediately but will eventually surface. To relocate your schema, use the following steps instead. - - - As of PostGIS 2.3 or newer, the PostGIS extension is no longer relocatable from one schema to another. If you need to move it from one schema to another for any reason (e.g. from the public schema to the extensions schema for security reasons), you would normally run a ALTER EXTENSION to relocate the schema. However, you will now to do the following steps: 1. Backup your Database to prevent data loss - You can do this through the [CLI](https://supabase.com/docs/reference/cli/supabase-db-dump) or Postgres backup tools such as [pg_dumpall](https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-ALL) @@ -452,6 +446,28 @@ As of PostGIS 2.3 or newer, the PostGIS extension is no longer relocatable from 4. Restore dropped data via the Backup if necessary from step 1 with your tool of choice. +Alternatively, you can contact the [Supabase Support Team](https://supabase.com/dashboard/support/new) and ask them to run the following SQL on your instance: + +```sql +BEGIN; + UPDATE pg_extension + SET extrelocatable = true + WHERE extname = 'postgis'; + + ALTER EXTENSION postgis + SET SCHEMA extensions; + + ALTER EXTENSION postgis + UPDATE TO "next"; + + ALTER EXTENSION postgis UPDATE; + + UPDATE pg_extension + SET extrelocatable = false + WHERE extname = 'postgis'; +COMMIT; +``` + ## Resources - [Official PostGIS documentation](https://postgis.net/documentation/) diff --git a/apps/docs/content/guides/functions/ephemeral-storage.mdx b/apps/docs/content/guides/functions/ephemeral-storage.mdx index 67336fc6726..0642784ccb4 100644 --- a/apps/docs/content/guides/functions/ephemeral-storage.mdx +++ b/apps/docs/content/guides/functions/ephemeral-storage.mdx @@ -1,21 +1,52 @@ --- id: 'function-ephemeral-storage' -title: 'Ephemeral Storage' -description: 'Read and write from temporary directory' -subtitle: 'Read and write from temporary directory' +title: 'File Storage' +description: 'Use persistent and ephemeral file storage' +subtitle: 'Use persistent and ephemeral file storage' --- -Edge Functions provides ephemeral file storage. You can read and write files to the `/tmp` directory. +Edge Functions provides two flavors of file storage: -This allows you to: +- Persistent - backed by S3 protocol, can read/write from any S3 compatible bucket, including Supabase Storage +- Ephemeral - You can read and write files to the `/tmp` directory. Only suitable for temporary operations + +You can use file storage to: -- Process uploaded files temporarily without permanent storage - Handle complex file transformations and workflows +- Do data migrations between projects +- Process user uploaded files and store them - Unzip archives and process contents before saving to database --- -## Overview +## Persistent Storage + +The persistent storage option is built on top of the S3 protocol. It allows you to mount any S3-compatible bucket, including Supabase Storage Buckets, as a directory for your Edge Functions. +You can perform operations such as reading and writing files to the mounted buckets as you would in a POSIX file system. + +To access an S3 bucket from Edge Functions, you must set the following for environment variables in Edge Function Secrets. + +- `S3FS_ENDPOINT_URL` +- `S3FS_REGION` +- `S3FS_ACCESS_KEY_ID` +- `S3FS_SECRET_ACCESS_KEY` + +[Follow this guide](https://supabase.com/docs/guides/storage/s3/authentication) to enable and create an access key for Supabase Storage S3. + +To access a file path in your mounted bucket from your Edge Function, use the prefix `/s3/YOUR-BUCKET-NAME`. + +```tsx +// read from S3 bucket +const data = await Deno.readFile('/s3/my-bucket/results.csv') + +// make a directory +await Deno.mkdir('/s3/my-bucket/sub-dir') + +// write to S3 bucket +await Deno.writeTextFile('/s3/my-bucket/demo.txt', 'hello world') +``` + +## Ephemeral storage Ephemeral storage will reset on each function invocation. This means the files you write during an invocation can only be read within the same invocation. @@ -128,30 +159,41 @@ Deno.serve(async (req) => { --- -## Limitations +## Using synchronous file APIs -Currently, the synchronous APIs for creating or writing files are not supported: +You can safely use the following synchronous Deno APIs (and their Node counterparts) _during initial script evaluation_: + +- Deno.statSync +- Deno.removeSync +- Deno.writeFileSync +- Deno.writeTextFileSync +- Deno.readFileSync +- Deno.readTextFileSync +- Deno.mkdirSync +- Deno.makeTempDirSync +- Deno.readDirSync + +**Keep in mind** that the sync APIs are available only during initial script evaluation and aren’t supported in callbacks like HTTP handlers or `setTimeout`. ```tsx -// ❌ Not supported -Deno.writeFileSync('/tmp/file.txt', data) -Deno.mkdirSync('/tmp/directory') +Deno.statSync('...') // ✅ -// ✅ Supported -await Deno.writeFile('/tmp/file.txt', data) -await Deno.mkdir('/tmp/directory') -``` +setTimeout(() => { + Deno.statSync('...') // 💣 ERROR! Deno.statSync is blocklisted on the current context +}) -You can use sync variations of read APIs: - -```tsx -// ✅ Supported -const data = Deno.readFileSync('/tmp/file.txt') +Deno.serve(() => { + Deno.statSync('...') // 💣 ERROR! Deno.statSync is blocklisted on the current context +}) ``` --- ## Limits +There are no limits on S3 buckets you mount for Persistent storage. + +Ephemeral Storage: + - Free projects: Up to 256MB of ephemeral storage - Paid projects: Up to 512MB of ephemeral storage diff --git a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx index 384950af5b9..04eb888e4d3 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx @@ -17,27 +17,27 @@ If you get stuck while working through this guide, refer to the [full example on ## Building the app -Let's start building the Angular app from scratch. +Start with building the Angular app from scratch. ### Initialize an Angular app -We can use the [Angular CLI](https://angular.io/cli) to initialize -an app called `supabase-angular`: +You can use the [Angular CLI](https://angular.io/cli) to initialize +an app called `supabase-angular`. The command sets some defaults, that you change to suit your needs: ```bash -npx ng new supabase-angular --routing false --style css --standalone false +npx ng new supabase-angular --routing false --style css --standalone false --zoneless true --ssr false cd supabase-angular ``` -Then let's install the only additional dependency: [supabase-js](https://github.com/supabase/supabase-js) +Then, install the only additional dependency: [supabase-js](https://github.com/supabase/supabase-js) ```bash npm install @supabase/supabase-js ``` -And finally we want to save the environment variables in the `src/environments/environment.ts` file. -All we need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys). -These variables will be exposed on the browser, and that's completely fine since we have [Row Level Security](/docs/guides/auth#row-level-security) enabled on our Database. +Finally, save the environment variables in the `src/environments/environment.ts` file. +All you need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys). +The application exposes these variables in the browser, and that's fine as you have [Row Level Security](/docs/guides/auth#row-level-security) enabled on the Database. <$CodeTabs> @@ -51,7 +51,7 @@ export const environment = { -Now that we have the API credentials in place, let's create a `SupabaseService` with `ng g s supabase` to initialize the Supabase client and implement functions to communicate with the Supabase API. +Now you have the API credentials in place, create a `SupabaseService` with `ng g s supabase` and add the following code to initialize the Supabase client and implement functions to communicate with the Supabase API. <$CodeTabs> @@ -133,37 +133,41 @@ export class SupabaseService { -Optionally, update [src/styles.css](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/angular-user-management/src/styles.css) to style the app. +Optionally, update `src/styles.css` [with the following styles](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/angular-user-management/src/styles.css) to style the app. ### Set up a login component -Let's set up an Angular component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords. -Create an `AuthComponent` with `ng g c auth` Angular CLI command. +Next, set up an Angular component to manage logins and sign ups. The component uses [Magic Links](/docs/guides/auth/auth-email-passwordless#with-magic-link), so users can sign in with their email without using passwords. + +Create an `AuthComponent` with the `ng g c auth` Angular CLI command and add the following code. <$CodeTabs> -```ts name=src/app/auth/auth.component.ts +```ts name=src/app/auth/auth.ts import { Component } from '@angular/core' -import { FormBuilder } from '@angular/forms' +import { FormBuilder, FormGroup } from '@angular/forms' import { SupabaseService } from '../supabase.service' @Component({ selector: 'app-auth', - templateUrl: './auth.component.html', - styleUrls: ['./auth.component.css'], + templateUrl: './auth.html', + styleUrls: ['./auth.css'], + standalone: false, }) export class AuthComponent { - loading = false - - signInForm = this.formBuilder.group({ - email: '', - }) - + signInForm!: FormGroup constructor( private readonly supabase: SupabaseService, private readonly formBuilder: FormBuilder ) {} + loading = false + ngOnInit() { + this.signInForm = this.formBuilder.group({ + email: '', + }) + } + async onSubmit(): Promise { try { this.loading = true @@ -183,7 +187,7 @@ export class AuthComponent { } ``` -```html name=src/app/auth/auth.component.html +```html name=src/app/auth/auth.html

Supabase + Angular

@@ -201,7 +205,7 @@ export class AuthComponent {
@@ -214,38 +218,50 @@ export class AuthComponent { ### Account page Users also need a way to edit their profile details and manage their accounts after signing in. -Create an `AccountComponent` with the `ng g c account` Angular CLI command. +Create an `AccountComponent` with the `ng g c account` Angular CLI command and add the following code. <$CodeTabs> -```ts name=src/app/account/account.component.ts +```ts name=src/app/account/account.ts import { Component, Input, OnInit } from '@angular/core' -import { FormBuilder } from '@angular/forms' +import { FormBuilder, FormGroup } from '@angular/forms' import { AuthSession } from '@supabase/supabase-js' import { Profile, SupabaseService } from '../supabase.service' @Component({ selector: 'app-account', - templateUrl: './account.component.html', - styleUrls: ['./account.component.css'], + templateUrl: './account.html', + styleUrls: ['./account.css'], + standalone: false, }) export class AccountComponent implements OnInit { loading = false profile!: Profile + updateProfileForm!: FormGroup + + get avatarUrl() { + return this.updateProfileForm.value.avatar_url as string + } + async updateAvatar(event: string): Promise { + this.updateProfileForm.patchValue({ + avatar_url: event, + }) + await this.updateProfile() + } @Input() session!: AuthSession - updateProfileForm = this.formBuilder.group({ - username: '', - website: '', - avatar_url: '', - }) - constructor( private readonly supabase: SupabaseService, private formBuilder: FormBuilder - ) {} + ) { + this.updateProfileForm = this.formBuilder.group({ + username: '', + website: '', + avatar_url: '', + }) + } async ngOnInit(): Promise { await this.getProfile() @@ -311,8 +327,9 @@ export class AccountComponent implements OnInit { } ``` -```html name=src/app/account/account.component.html +```html name=src/app/account/account.html
+
@@ -328,7 +345,7 @@ export class AccountComponent implements OnInit {
@@ -342,33 +359,34 @@ export class AccountComponent implements OnInit { ### Launch! -Now that we have all the components in place, let's update `AppComponent`: +Now you have all the components in place, update `AppComponent`: <$CodeTabs> -```ts name=src/app/app.component.ts +```ts name=src/app/app.ts import { Component, OnInit } from '@angular/core' import { SupabaseService } from './supabase.service' @Component({ selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.css'], + templateUrl: './app.html', + styleUrls: ['./app.css'], + standalone: false, }) export class AppComponent implements OnInit { - title = 'angular-user-management' - - session = this.supabase.session - constructor(private readonly supabase: SupabaseService) {} + title = 'angular-user-management' + session: any + ngOnInit() { + this.session = this.supabase.session this.supabase.authChanges((_, session) => (this.session = session)) } } ``` -```html name=src/app/app.component.html +```html name=src/app/app.html
@@ -379,7 +397,7 @@ export class AppComponent implements OnInit { -`app.module.ts` also needs to be modified to include the `ReactiveFormsModule` from the `@angular/forms` package. +You also need to change `app.module.ts` to include the `ReactiveFormsModule` from the `@angular/forms` package. <$CodeTabs> @@ -387,32 +405,33 @@ export class AppComponent implements OnInit { import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' -import { AppComponent } from './app.component' -import { AuthComponent } from './auth/auth.component' -import { AccountComponent } from './account/account.component' +import { AppComponent } from './app' +import { AuthComponent } from './auth/auth' +import { AccountComponent } from './account/account' import { ReactiveFormsModule } from '@angular/forms' -import { AvatarComponent } from './avatar/avatar.component' +import { AvatarComponent } from './avatar/avatar' @NgModule({ declarations: [AppComponent, AuthComponent, AccountComponent, AvatarComponent], imports: [BrowserModule, ReactiveFormsModule], providers: [], bootstrap: [AppComponent], + exports: [AppComponent, AuthComponent, AccountComponent, AvatarComponent], }) export class AppModule {} ``` -Once that's done, run this in a terminal window: +Once that's done, run the application in a terminal: ```bash npm run start ``` -And then open the browser to [localhost:4200](http://localhost:4200) and you should see the completed app. +Open the browser to [localhost:4200](http://localhost:4200) and you should see the completed app. -![Supabase Angular](/docs/img/supabase-angular-demo.png) +![Screenshot of the Supabase Angular application running in a browser](/docs/img/supabase-angular-demo.png) ## Bonus: Profile photos @@ -420,20 +439,21 @@ Every Supabase project is configured with [Storage](/docs/guides/storage) for ma ### Create an upload widget -Let's create an avatar for the user so that they can upload a profile photo. -Create an `AvatarComponent` with `ng g c avatar` Angular CLI command. +Create an avatar for the user so that they can upload a profile photo. +Create an `AvatarComponent` with `ng g c avatar` Angular CLI command and add the following code. <$CodeTabs> -```ts name=src/app/avatar/avatar.component.ts +```ts name=src/app/avatar/avatar.ts import { Component, EventEmitter, Input, Output } from '@angular/core' import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser' import { SupabaseService } from '../supabase.service' @Component({ selector: 'app-avatar', - templateUrl: './avatar.component.html', - styleUrls: ['./avatar.component.css'], + templateUrl: './avatar.html', + styleUrls: ['./avatar.css'], + standalone: false, }) export class AvatarComponent { _avatarUrl: SafeResourceUrl | undefined @@ -490,7 +510,7 @@ export class AvatarComponent { } ``` -```html name=src/app/avatar/avatar.component.html +```html name=src/app/avatar/avatar.html
-```html name=src/app/account.component.html +```html name=src/app/account.html - + ``` @@ -537,11 +557,11 @@ And add an `updateAvatar` function along with an `avatarUrl` getter to the `Acco <$CodeTabs> -```ts name=src/app/account.component.ts +```ts name=src/app/account.ts @Component({ selector: 'app-account', - templateUrl: './account.component.html', - styleUrls: ['./account.component.css'], + templateUrl: './account.html', + styleUrls: ['./account.css'], }) export class AccountComponent implements OnInit { // ... diff --git a/apps/docs/content/guides/local-development.mdx b/apps/docs/content/guides/local-development.mdx index e8ba56d4654..8545ceb1768 100644 --- a/apps/docs/content/guides/local-development.mdx +++ b/apps/docs/content/guides/local-development.mdx @@ -5,6 +5,17 @@ subtitle: Learn how to develop locally and use the Supabase CLI Develop locally while running the Supabase stack on your machine. + + +As a prerequisite, you must install a container runtime compatible with Docker APIs. + +- [Docker Desktop](https://docs.docker.com/desktop/) (macOS, Windows, Linux) +- [Rancher Desktop](https://rancherdesktop.io/) (macOS, Windows, Linux) +- [Podman](https://podman.io/) (macOS, Windows, Linux) +- [OrbStack](https://orbstack.dev/) (macOS) + + + ## Quickstart 1. Install the Supabase CLI: @@ -101,17 +112,6 @@ Develop locally while running the Supabase stack on your machine. - - - As a prerequisite, you must install a container runtime compatible with Docker APIs. - - - [Docker Desktop](https://docs.docker.com/desktop/) (macOS, Windows, Linux) - - [Rancher Desktop](https://rancherdesktop.io/) (macOS, Windows, Linux) - - [Podman](https://podman.io/) (macOS, Windows, Linux) - - [OrbStack](https://orbstack.dev/) (macOS) - - - 4. View your local Supabase instance at [http://localhost:54323](http://localhost:54323). ## Local development diff --git a/apps/docs/content/guides/local-development/cli/getting-started.mdx b/apps/docs/content/guides/local-development/cli/getting-started.mdx index 4240378957e..a65e54431ea 100644 --- a/apps/docs/content/guides/local-development/cli/getting-started.mdx +++ b/apps/docs/content/guides/local-development/cli/getting-started.mdx @@ -217,7 +217,7 @@ Started supabase local development setup. API URL: http://localhost:54321 DB URL: postgresql://postgres:postgres@localhost:54322/postgres Studio URL: http://localhost:54323 - Inbucket URL: http://localhost:54324 + Mailpit URL: http://localhost:54324 anon key: eyJh...... service_role key: eyJh...... diff --git a/apps/docs/content/guides/local-development/cli/testing-and-linting.mdx b/apps/docs/content/guides/local-development/cli/testing-and-linting.mdx index c3c8d2eb9a3..59e8bb4e0d1 100644 --- a/apps/docs/content/guides/local-development/cli/testing-and-linting.mdx +++ b/apps/docs/content/guides/local-development/cli/testing-and-linting.mdx @@ -36,11 +36,11 @@ Edge Functions are powered by Deno, which provides a [native set of testing tool ## Testing Auth emails -The Supabase CLI uses [Inbucket](https://github.com/inbucket/inbucket) to capture emails sent from your local machine. This is useful for testing emails sent from Supabase Auth. +The Supabase CLI uses [Mailpit](https://github.com/axllent/mailpit) to capture emails sent from your local machine. This is useful for testing emails sent from Supabase Auth. -### Accessing Inbucket +### Accessing Mailpit -By default, Inbucket is available at [localhost:54324](http://localhost:54324) when you run `supabase start`. Open this URL in your browser to view the emails. +By default, Mailpit is available at [localhost:54324](http://localhost:54324) when you run `supabase start`. Open this URL in your browser to view the emails. ### Going into production diff --git a/apps/docs/content/guides/platform/access-control.mdx b/apps/docs/content/guides/platform/access-control.mdx index 37b7b85dd52..2483a8f1ddb 100644 --- a/apps/docs/content/guides/platform/access-control.mdx +++ b/apps/docs/content/guides/platform/access-control.mdx @@ -260,20 +260,13 @@ The table below shows the actions each role can take on the resources belonging | | View | | | | | | | List | | | | | | | Run | | | | | -| Events Collections | Create | | | | | -| | Update | | | | | -| | Delete | | | | | -| | View | | | | | -| | List | | | | | -| Warehouse Access Tokens | Create | | | | | -| | Revoke | | | | | -| | List | | | | | | **Branching** | | | | | | -| Enable branching | - | | | | | -| Disable branching | - | | | | | +| Production Branch | Read | | | | | +| | Write | | | | | +| Development Branches | List | | | | | | | Create | | | | | +| | Update | | | | | | | Delete | | | | | -| | List | | | | | [^1]: Available on the Team and Enterprise Plans. [^2]: Sending anonymous data to OpenAI is opt in and can improve Studio AI Assistant's responses. diff --git a/apps/docs/content/guides/platform/backups.mdx b/apps/docs/content/guides/platform/backups.mdx index 64efb201ba5..ae79d74e7cf 100644 --- a/apps/docs/content/guides/platform/backups.mdx +++ b/apps/docs/content/guides/platform/backups.mdx @@ -131,6 +131,14 @@ If you enable PITR, Daily Backups will no longer be taken. PITR provides a finer +When you disable PITR, all new backups will still be taken as physical backups only. Physical backups can still be used for restoration, but they are not available for direct download. If you need to download a backup after PITR is disabled, you’ll need to take a manual [logical backup using the Supabase CLI or pg_dump](https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore#backup-database-using-the-cli). + + + +If PITR has been disabled, logical backups remain available until they pass the backup retention period for your plan. After that window passes, only physical backups will be shown. + + + ### Backup process [#pitr-backup-process] As discussed [here](https://supabase.com/blog/postgresql-physical-logical-backups), PITR is made possible by a combination of taking physical backups of a project, as well as archiving [Write Ahead Log (WAL)](https://www.postgresql.org/docs/current/wal-intro.html) files. Physical backups provide a snapshot of the underlying directory of the database, while WAL files contain records of every change made in the database. diff --git a/apps/docs/content/guides/platform/credits.mdx b/apps/docs/content/guides/platform/credits.mdx index a71d1574de0..625cfc8bd79 100644 --- a/apps/docs/content/guides/platform/credits.mdx +++ b/apps/docs/content/guides/platform/credits.mdx @@ -27,7 +27,7 @@ As an example, if you start a Pro Plan subscription on January 1 and downgrade t ## Credit top-ups -You can top up credits at any time, with a maximum of per top-up. These credits do not expire and are non-refundable. +You can top up credits at any time, with a maximum of per top-up. These credits do not expire and are non-refundable. If you have any outstanding invoices, we’ll automatically use your credits to pay them off. Any remaining credits will be applied to future invoices. diff --git a/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx b/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx index 809d4e38b26..063eecdbad5 100644 --- a/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx +++ b/apps/docs/content/guides/platform/migrating-to-supabase/firestore-data.mdx @@ -1,6 +1,6 @@ --- id: 'firestore-data' -title: 'Migrated from Firebase Firestore to Supabase' +title: 'Migrate from Firebase Firestore to Supabase' description: 'Migrate your Firebase Firestore database to a Supabase Postgres database.' subtitle: 'Migrate your Firebase Firestore database to a Supabase Postgres database.' --- diff --git a/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx b/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx index fd3644ed209..f26c2f72814 100644 --- a/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx +++ b/apps/docs/content/guides/platform/migrating-within-supabase/backup-restore.mdx @@ -227,7 +227,7 @@ supabase db diff --linked --schema auth,storage > changes.sql The new project has the old project's Storage buckets, but the Storage objects need to be migrated manually. Use this script to move storage objects from one project to another. ```js -// npm install @supabase/supabase-js@1 +// npm install @supabase/supabase-js@2 const { createClient } = require('@supabase/supabase-js') const OLD_PROJECT_URL = 'https://xxx.supabase.co' @@ -238,7 +238,9 @@ const NEW_PROJECT_SERVICE_KEY = 'new-project-service-key-yyy' ;(async () => { const oldSupabaseRestClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY, { - schema: 'storage', + db: { + schema: 'storage', + }, }) const oldSupabaseClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY) const newSupabaseClient = createClient(NEW_PROJECT_URL, NEW_PROJECT_SERVICE_KEY) diff --git a/apps/docs/content/guides/queues/pgmq.mdx b/apps/docs/content/guides/queues/pgmq.mdx index fa4f840a37c..d5c01326e8f 100644 --- a/apps/docs/content/guides/queues/pgmq.mdx +++ b/apps/docs/content/guides/queues/pgmq.mdx @@ -207,7 +207,7 @@ select * from pgmq.send_batch( #### `read` -Read 1 or more messages from a queue. The VT specifies the delay in seconds between reading and the message becoming invisible to other consumers. +Read 1 or more messages from a queue. The VT specifies the duration of time in seconds that the message is invisible to other consumers. At the end of that duration, the message is visible again and could be read by other consumers. {/* prettier-ignore */} ```sql diff --git a/apps/docs/content/guides/storage/s3/authentication.mdx b/apps/docs/content/guides/storage/s3/authentication.mdx index b6a09be5555..55c5102fcce 100644 --- a/apps/docs/content/guides/storage/s3/authentication.mdx +++ b/apps/docs/content/guides/storage/s3/authentication.mdx @@ -25,6 +25,14 @@ This is all the information you need to connect to Supabase Storage using any S3 Storage S3 Access keys + + +For optimal performance when uploading large files you should always use the direct storage hostname. This provides several performance enhancements that will greatly improve performance when uploading large files. + +Instead of `https://project-id.supabase.co` use `https://project-id.storage.supabase.co` + + + @@ -86,7 +94,7 @@ const { const client = new S3Client({ forcePathStyle: true, region: 'project_region', - endpoint: 'https://project_ref.supabase.co/storage/v1/s3', + endpoint: 'https://project_ref.storage.supabase.co/storage/v1/s3', credentials: { accessKeyId: 'project_ref', secretAccessKey: 'anonKey', diff --git a/apps/docs/content/guides/storage/uploads/resumable-uploads.mdx b/apps/docs/content/guides/storage/uploads/resumable-uploads.mdx index d12d1cc6924..a7ac47b3031 100644 --- a/apps/docs/content/guides/storage/uploads/resumable-uploads.mdx +++ b/apps/docs/content/guides/storage/uploads/resumable-uploads.mdx @@ -14,6 +14,14 @@ The resumable upload method is recommended when: Supabase Storage implements the [TUS protocol](https://tus.io/) to enable resumable uploads. TUS stands for The Upload Server and is an open protocol for supporting resumable uploads. The protocol allows the upload process to be resumed from where it left off in case of interruptions. This method can be implemented using the [`tus-js-client`](https://github.com/tus/tus-js-client) library, or other client-side libraries like [Uppy](https://uppy.io/docs/tus/) that support the TUS protocol. + + +For optimal performance when uploading large files you should always use the direct storage hostname. This provides several performance enhancements that will greatly improve performance when uploading large files. + +Instead of `https://project-id.supabase.co` use `https://project-id.storage.supabase.co` + + + { var upload = new tus.Upload(file, { - endpoint: `https://${projectId}.supabase.co/storage/v1/upload/resumable`, + // Supabase TUS endpoint (with direct storage hostname) + endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`, retryDelays: [0, 3000, 5000, 10000, 20000], headers: { authorization: `Bearer ${session.access_token}`, @@ -125,7 +134,7 @@ Supabase Storage implements the [TUS protocol](https://tus.io/) to enable resuma // Initialize Uppy instance only once const [uppy] = useState(() => new Uppy()); // Initialize Supabase client with project URL and anon key - const supabase = createClient(projectURL, anonKey); + const supabase = createClient(`https://${projectId}.supabase.co`, anonKey); useEffect(() => { const initializeUppy = async () => { @@ -135,7 +144,8 @@ Supabase Storage implements the [TUS protocol](https://tus.io/) to enable resuma } = await supabase.auth.getSession(); uppy.use(Tus, { - endpoint: `${projectURL}/storage/v1/upload/resumable`, // Supabase TUS endpoint + // Supabase TUS endpoint (with direct storage hostname) + endpoint: `https://${projectId}.storage.supabase.co/storage/v1/upload/resumable`, retryDelays: [0, 3000, 5000, 10000, 20000], // Retry delays for resumable uploads headers: { authorization: `Bearer ${session?.access_token}`, // User session access token diff --git a/apps/docs/public/humans.txt b/apps/docs/public/humans.txt index 4a367b66d20..58db9f6a50c 100644 --- a/apps/docs/public/humans.txt +++ b/apps/docs/public/humans.txt @@ -26,6 +26,7 @@ Chris Caruso Chris Chandler Chris Copplestone Chris Gwilliams +Chris Martin Chris Stockton Chris Ward Craig Cannon @@ -40,6 +41,7 @@ Divit D Eduardo Gurgel Egor Romanov Eleftheria Trivyzaki +Emmett Folger Etienne Stalmans Fabrizio Fenoglio Felipe Stival @@ -83,6 +85,7 @@ Manan Gupta Margarita Sandomirskaia Mark Burggraf Monica Khoury +Mykhailo Mischa Lieibenson Nyannyacha Oli R Pamela Chia @@ -106,6 +109,7 @@ Stanislav M Stephen Morgan Steve Chavez Stojan Dimitrovski +Sugu Sougoumarane Supun Sudaraka Kalidasa Taryn King Terry Sutton diff --git a/apps/docs/spec/api_v1_openapi.json b/apps/docs/spec/api_v1_openapi.json index 370f302ea3d..81dd92764b4 100644 --- a/apps/docs/spec/api_v1_openapi.json +++ b/apps/docs/spec/api_v1_openapi.json @@ -7,7 +7,13 @@ "summary": "Get database branch config", "description": "Fetches configurations of the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -28,7 +34,13 @@ "summary": "Update database branch config", "description": "Updates the configuration of the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], "requestBody": { "required": true, @@ -53,7 +65,13 @@ "summary": "Delete a database branch", "description": "Deletes the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -76,8 +94,20 @@ "summary": "Pushes a database branch", "description": "Pushes the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], + "requestBody": { + "required": true, + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BranchActionBody" } } + } + }, "responses": { "201": { "description": "", @@ -99,8 +129,20 @@ "summary": "Merges a database branch", "description": "Merges the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], + "requestBody": { + "required": true, + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BranchActionBody" } } + } + }, "responses": { "201": { "description": "", @@ -122,8 +164,20 @@ "summary": "Resets a database branch", "description": "Resets the specified database branch", "parameters": [ - { "name": "branch_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + } ], + "requestBody": { + "required": true, + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BranchActionBody" } } + } + }, "responses": { "201": { "description": "", @@ -139,6 +193,37 @@ "security": [{ "bearer": [] }] } }, + "/v1/branches/{branch_id}/diff": { + "get": { + "operationId": "v1-diff-a-branch", + "summary": "[Beta] Diffs a database branch", + "description": "Diffs the specified database branch", + "parameters": [ + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "included_schemas", + "required": false, + "in": "query", + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "content": { "text/plain": { "schema": { "type": "string" } } }, + "description": "" + }, + "500": { "description": "Failed to diff database branch" } + }, + "tags": ["Environments"], + "security": [{ "bearer": [] }] + } + }, "/v1/projects": { "get": { "operationId": "v1-list-all-projects", @@ -168,9 +253,7 @@ "requestBody": { "required": true, "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/V1CreateProjectBodyDto" } - } + "application/json": { "schema": { "$ref": "#/components/schemas/V1CreateProjectBody" } } } }, "responses": { @@ -216,7 +299,7 @@ "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/CreateOrganizationV1Dto" } + "schema": { "$ref": "#/components/schemas/CreateOrganizationV1" } } } }, @@ -241,23 +324,16 @@ "summary": "[Beta] Authorize user through oauth", "parameters": [ { - "name": "code_challenge_method", - "required": false, + "name": "client_id", + "required": true, "in": "query", - "schema": { "enum": ["plain", "sha256", "S256"], "type": "string" } + "schema": { "format": "uuid", "type": "string" } }, - { - "name": "code_challenge", - "required": false, - "in": "query", - "schema": { "type": "string" } - }, - { "name": "state", "required": false, "in": "query", "schema": { "type": "string" } }, { "name": "response_type", "required": true, "in": "query", - "schema": { "type": "string" } + "schema": { "enum": ["code", "token", "id_token token"], "type": "string" } }, { "name": "redirect_uri", @@ -265,9 +341,35 @@ "in": "query", "schema": { "type": "string" } }, - { "name": "client_id", "required": true, "in": "query", "schema": { "type": "string" } } + { "name": "scope", "required": false, "in": "query", "schema": { "type": "string" } }, + { "name": "state", "required": false, "in": "query", "schema": { "type": "string" } }, + { + "name": "response_mode", + "required": false, + "in": "query", + "schema": { "type": "string" } + }, + { + "name": "code_challenge", + "required": false, + "in": "query", + "schema": { "type": "string" } + }, + { + "name": "code_challenge_method", + "required": false, + "in": "query", + "schema": { "enum": ["plain", "sha256", "S256"], "type": "string" } + }, + { + "name": "organization_slug", + "required": false, + "in": "query", + "description": "Organization slug", + "schema": { "pattern": "^[\\w-]+$", "type": "string" } + } ], - "responses": { "303": { "description": "" } }, + "responses": { "204": { "description": "" } }, "tags": ["OAuth"], "security": [{ "oauth2": ["read"] }] } @@ -308,7 +410,7 @@ "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/OAuthRevokeTokenBodyDto" } + "schema": { "$ref": "#/components/schemas/OAuthRevokeTokenBody" } } } }, @@ -317,11 +419,75 @@ "security": [{ "oauth2": ["write"] }] } }, + "/v1/oauth/authorize/project-claim": { + "get": { + "operationId": "v1-oauth-authorize-project-claim", + "x-internal": true, + "summary": "Authorize user through oauth and claim a project", + "description": "Initiates the OAuth authorization flow for the specified provider. After successful authentication, the user can claim ownership of the specified project.", + "parameters": [ + { + "name": "project_ref", + "required": true, + "in": "query", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "client_id", + "required": true, + "in": "query", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "response_type", + "required": true, + "in": "query", + "schema": { "enum": ["code", "token", "id_token token"], "type": "string" } + }, + { + "name": "redirect_uri", + "required": true, + "in": "query", + "schema": { "type": "string" } + }, + { "name": "state", "required": false, "in": "query", "schema": { "type": "string" } }, + { + "name": "response_mode", + "required": false, + "in": "query", + "schema": { "type": "string" } + }, + { + "name": "code_challenge", + "required": false, + "in": "query", + "schema": { "type": "string" } + }, + { + "name": "code_challenge_method", + "required": false, + "in": "query", + "schema": { "enum": ["plain", "sha256", "S256"], "type": "string" } + } + ], + "responses": { "204": { "description": "" } }, + "tags": ["OAuth"], + "security": [{ "bearer": [] }] + } + }, "/v1/snippets": { "get": { "operationId": "v1-list-all-snippets", "summary": "Lists SQL snippets for the logged in user", "parameters": [ + { + "name": "project_ref", + "required": false, + "in": "query", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "cursor", "required": false, "in": "query", "schema": { "type": "string" } }, { "name": "limit", @@ -340,12 +506,6 @@ "required": false, "in": "query", "schema": { "enum": ["asc", "desc"], "type": "string" } - }, - { - "name": "project_ref", - "required": false, - "in": "query", - "schema": { "type": "string" } } ], "responses": { @@ -391,8 +551,20 @@ "operationId": "v1-get-project-api-keys", "summary": "Get project api keys", "parameters": [ - { "name": "reveal", "required": false, "in": "query", "schema": { "type": "boolean" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + } ], "responses": { "200": { @@ -412,11 +584,23 @@ "security": [{ "bearer": [] }] }, "post": { - "operationId": "createApiKey", - "summary": "[Alpha] Creates a new API key for the project", + "operationId": "v1-create-project-api-key", + "summary": "Creates a new API key for the project", "parameters": [ - { "name": "reveal", "required": false, "in": "query", "schema": { "type": "boolean" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + } ], "requestBody": { "required": true, @@ -437,14 +621,92 @@ "security": [{ "bearer": [] }] } }, + "/v1/projects/{ref}/api-keys/legacy": { + "get": { + "operationId": "v1-get-project-legacy-api-keys", + "summary": "Check whether JWT based legacy (anon, service_role) API keys are enabled. This API endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/LegacyApiKeysResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Secrets"], + "security": [{ "bearer": [] }] + }, + "put": { + "operationId": "v1-update-project-legacy-api-keys", + "summary": "Disable or re-enable JWT based legacy (anon, service_role) API keys. This API endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "enabled", + "required": true, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/LegacyApiKeysResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Secrets"], + "security": [{ "bearer": [] }] + } + }, "/v1/projects/{ref}/api-keys/{id}": { "patch": { - "operationId": "updateApiKey", - "summary": "[Alpha] Updates an API key for the project", + "operationId": "v1-update-project-api-key", + "summary": "Updates an API key for the project", "parameters": [ - { "name": "reveal", "required": false, "in": "query", "schema": { "type": "boolean" } }, - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + } ], "requestBody": { "required": true, @@ -465,12 +727,29 @@ "security": [{ "bearer": [] }] }, "get": { - "operationId": "getApiKey", - "summary": "[Alpha] Get API key", + "operationId": "v1-get-project-api-key", + "summary": "Get API key", "parameters": [ - { "name": "reveal", "required": false, "in": "query", "schema": { "type": "boolean" } }, - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + } ], "responses": { "200": { @@ -485,12 +764,37 @@ "security": [{ "bearer": [] }] }, "delete": { - "operationId": "deleteApiKey", - "summary": "[Alpha] Deletes an API key for the project", + "operationId": "v1-delete-project-api-key", + "summary": "Deletes an API key for the project", "parameters": [ - { "name": "reveal", "required": false, "in": "query", "schema": { "type": "boolean" } }, - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + }, + { + "name": "was_compromised", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + }, + { "name": "reason", "required": false, "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { @@ -511,7 +815,13 @@ "summary": "List all database branches", "description": "Returns all database branches of the specified project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -536,7 +846,13 @@ "summary": "Create a database branch", "description": "Creates a database branch from the specified project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -562,7 +878,13 @@ "summary": "Disables preview branching", "description": "Disables preview branching for the specified project", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "" }, @@ -573,6 +895,35 @@ "security": [{ "bearer": [] }] } }, + "/v1/projects/{ref}/branches/{name}": { + "get": { + "operationId": "v1-get-a-branch", + "summary": "Get a database branch", + "description": "Fetches the specified database branch by its name.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { "name": "name", "required": true, "in": "path", "schema": { "type": "string" } } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/BranchResponse" } } + } + }, + "403": { "description": "" }, + "500": { "description": "Failed to fetch database branch" } + }, + "tags": ["Environments"], + "security": [{ "bearer": [] }] + } + }, "/v1/projects/{ref}/custom-hostname": { "get": { "operationId": "v1-get-hostname-config", @@ -583,7 +934,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -610,7 +961,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -632,7 +983,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -669,7 +1020,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -698,7 +1049,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -722,7 +1073,13 @@ "operationId": "v1-list-all-network-bans", "summary": "[Beta] Gets project's network bans", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "201": { @@ -740,12 +1097,47 @@ "security": [{ "bearer": [] }] } }, + "/v1/projects/{ref}/network-bans/retrieve/enriched": { + "post": { + "operationId": "v1-list-all-network-bans-enriched", + "summary": "[Beta] Gets project's network bans with additional information about which databases they affect", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/NetworkBanResponseEnriched" } + } + } + }, + "403": { "description": "" }, + "500": { "description": "Failed to retrieve project's enriched network bans" } + }, + "tags": ["Projects"], + "security": [{ "bearer": [] }] + } + }, "/v1/projects/{ref}/network-bans": { "delete": { "operationId": "v1-delete-network-bans", "summary": "[Beta] Remove network bans.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -769,7 +1161,13 @@ "operationId": "v1-get-network-restrictions", "summary": "[Beta] Gets project's network restrictions", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -792,7 +1190,13 @@ "operationId": "v1-update-network-restrictions", "summary": "[Beta] Updates project's network restrictions", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -823,7 +1227,13 @@ "operationId": "v1-get-pgsodium-config", "summary": "[Beta] Gets project's pgsodium config", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -844,7 +1254,13 @@ "operationId": "v1-update-pgsodium-config", "summary": "[Beta] Updates project's pgsodium config. Updating the root_key can cause all data encrypted with the older key to become inaccessible.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -880,7 +1296,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -907,7 +1323,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -944,7 +1360,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -971,7 +1387,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -995,7 +1411,13 @@ "summary": "List all secrets", "description": "Returns all secrets you've previously added to the specified project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1020,17 +1442,18 @@ "summary": "Bulk create secrets", "description": "Creates multiple secrets and adds them to the specified project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, "content": { - "application/json": { - "schema": { - "type": "array", - "items": { "$ref": "#/components/schemas/CreateSecretBody" } - } - } + "application/json": { "schema": { "$ref": "#/components/schemas/CreateSecretBody" } } } }, "responses": { @@ -1046,7 +1469,13 @@ "summary": "Bulk delete secrets", "description": "Deletes all secrets with the given names from the specified project", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1055,10 +1484,7 @@ } }, "responses": { - "200": { - "description": "", - "content": { "application/json": { "schema": { "type": "object" } } } - }, + "200": { "description": "" }, "403": { "description": "" }, "500": { "description": "Failed to delete secrets with given names" } }, @@ -1071,7 +1497,13 @@ "operationId": "v1-get-ssl-enforcement-config", "summary": "[Beta] Get project's SSL enforcement configuration.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1092,7 +1524,13 @@ "operationId": "v1-update-ssl-enforcement-config", "summary": "[Beta] Update project's SSL enforcement configuration.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1130,7 +1568,13 @@ "in": "query", "schema": { "default": "public", "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1153,7 +1597,13 @@ "operationId": "v1-get-vanity-subdomain-config", "summary": "[Beta] Gets current vanity subdomain config", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1174,7 +1624,13 @@ "operationId": "v1-deactivate-vanity-subdomain-config", "summary": "[Beta] Deletes a project's vanity subdomain configuration", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "" }, @@ -1190,7 +1646,13 @@ "operationId": "v1-check-vanity-subdomain-availability", "summary": "[Beta] Checks vanity subdomain availability", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1219,7 +1681,13 @@ "operationId": "v1-activate-vanity-subdomain-config", "summary": "[Beta] Activates a vanity subdomain for a project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1248,7 +1716,13 @@ "operationId": "v1-upgrade-postgres-version", "summary": "[Beta] Upgrades the project's Postgres version", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1277,7 +1751,13 @@ "operationId": "v1-get-postgres-upgrade-eligibility", "summary": "[Beta] Returns the project's eligibility for upgrades", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1300,13 +1780,19 @@ "operationId": "v1-get-postgres-upgrade-status", "summary": "[Beta] Gets the latest status of the project's upgrade", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "tracking_id", "required": false, "in": "query", "schema": { "type": "string" } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + } ], "responses": { "200": { @@ -1334,7 +1820,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1363,7 +1849,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1380,7 +1866,13 @@ "operationId": "v1-setup-a-read-replica", "summary": "[Beta] Set up a read replica", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1404,7 +1896,13 @@ "operationId": "v1-remove-a-read-replica", "summary": "[Beta] Remove a read replica", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1433,13 +1931,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } - }, - { - "name": "timeout_ms", - "required": false, - "in": "query", - "schema": { "minimum": 0, "maximum": 10000, "type": "integer" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, { "name": "services", @@ -1452,6 +1944,12 @@ "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"] } } + }, + { + "name": "timeout_ms", + "required": false, + "in": "query", + "schema": { "minimum": 0, "maximum": 10000, "type": "integer" } } ], "responses": { @@ -1473,12 +1971,72 @@ "security": [{ "bearer": [] }] } }, + "/v1/projects/{ref}/config/auth/signing-keys/legacy": { + "post": { + "operationId": "v1-create-legacy-signing-key", + "summary": "Set up the project's existing JWT secret as an in_use JWT signing key. This endpoint will be removed in the future always check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/SigningKeyResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Auth"], + "security": [{ "bearer": [] }] + }, + "get": { + "operationId": "v1-get-legacy-signing-key", + "summary": "Get the signing key information for the JWT secret imported as signing key for this project. This endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/SigningKeyResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Auth"], + "security": [{ "bearer": [] }] + } + }, "/v1/projects/{ref}/config/auth/signing-keys": { "post": { - "operationId": "createSigningKeyForProject", - "summary": "[Alpha] Create a new signing key for the project in standby status", + "operationId": "v1-create-project-signing-key", + "summary": "Create a new signing key for the project in standby status", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1490,10 +2048,10 @@ }, "responses": { "201": { - "description": "[Alpha] Create a new signing key for the project in standby status", + "description": "", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/CreateSigningKeyBody" } + "schema": { "$ref": "#/components/schemas/SigningKeyResponse" } } } }, @@ -1503,10 +2061,16 @@ "security": [{ "bearer": [] }] }, "get": { - "operationId": "listSigningKeysForProject", - "summary": "[Alpha] List all signing keys for the project", + "operationId": "v1-get-project-signing-keys", + "summary": "List all signing keys for the project", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1525,11 +2089,22 @@ }, "/v1/projects/{ref}/config/auth/signing-keys/{id}": { "get": { - "operationId": "getSigningKeyForProject", - "summary": "[Alpha] Get information about a signing key", + "operationId": "v1-get-project-signing-key", + "summary": "Get information about a signing key", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1546,11 +2121,22 @@ "security": [{ "bearer": [] }] }, "delete": { - "operationId": "deleteSigningKey", - "summary": "[Alpha] Remove a signing key from a project, where the status is previously_used", + "operationId": "v1-remove-project-signing-key", + "summary": "Remove a signing key from a project. Only possible if the key has been in revoked status for a while.", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -1567,11 +2153,22 @@ "security": [{ "bearer": [] }] }, "patch": { - "operationId": "patchSigningKey", - "summary": "[Alpha] Update a signing key, mainly its status", + "operationId": "v1-update-project-signing-key", + "summary": "Update a signing key, mainly its status", "parameters": [ - { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + }, + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -1606,7 +2203,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1633,7 +2230,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -1663,7 +2260,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1690,7 +2287,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -1727,7 +2324,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1747,7 +2344,7 @@ }, "/v1/projects/{ref}/config/database/pooler": { "get": { - "operationId": "getSupavisorConfig", + "operationId": "v1-get-pooler-config", "summary": "Gets project's supavisor config", "parameters": [ { @@ -1755,7 +2352,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1776,7 +2373,7 @@ "security": [{ "bearer": [] }] }, "patch": { - "operationId": "updateSupavisorConfig", + "operationId": "v1-update-pooler-config", "summary": "Updates project's supavisor config", "parameters": [ { @@ -1784,7 +2381,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -1821,7 +2418,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1848,7 +2445,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -1877,7 +2474,7 @@ }, "/v1/projects/{ref}/config/auth/third-party-auth": { "post": { - "operationId": "createTPAForProject", + "operationId": "v1-create-project-tpa-integration", "summary": "Creates a new third-party auth integration", "parameters": [ { @@ -1885,7 +2482,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -1909,7 +2506,7 @@ "security": [{ "bearer": [] }] }, "get": { - "operationId": "listTPAForProject", + "operationId": "v1-list-project-tpa-integrations", "summary": "Lists all third-party auth integrations", "parameters": [ { @@ -1917,7 +2514,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -1940,7 +2537,7 @@ }, "/v1/projects/{ref}/config/auth/third-party-auth/{tpa_id}": { "delete": { - "operationId": "deleteTPAForProject", + "operationId": "v1-delete-project-tpa-integration", "summary": "Removes a third-party auth integration", "parameters": [ { @@ -1948,9 +2545,14 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, - { "name": "tpa_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "tpa_id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -1965,7 +2567,7 @@ "security": [{ "bearer": [] }] }, "get": { - "operationId": "getTPAForProject", + "operationId": "v1-get-project-tpa-integration", "summary": "Get a third-party integration", "parameters": [ { @@ -1973,9 +2575,14 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, - { "name": "tpa_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "tpa_id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -2000,7 +2607,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { "200": { "description": "" }, "403": { "description": "" } }, @@ -2013,7 +2620,13 @@ "operationId": "v1-list-available-restore-versions", "summary": "Lists available restore versions for the given project", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -2035,16 +2648,14 @@ "operationId": "v1-restore-a-project", "summary": "Restores the given project", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/RestoreProjectBodyDto" } - } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } - }, + ], "responses": { "200": { "description": "" }, "403": { "description": "" } }, "tags": ["Projects"], "security": [{ "bearer": [] }] @@ -2055,7 +2666,13 @@ "operationId": "v1-cancel-a-project-restoration", "summary": "Cancels the given project restoration", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "" }, "403": { "description": "" } }, "tags": ["Projects"], @@ -2067,33 +2684,46 @@ "operationId": "v1-list-project-addons", "summary": "Lists project addons", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ListProjectAddonsResponseDto" } + "schema": { "$ref": "#/components/schemas/ListProjectAddonsResponse" } } } }, "403": { "description": "" }, "500": { "description": "Failed to list project addons" } }, + "tags": ["Billing"], "security": [{ "bearer": [] }] }, "patch": { "operationId": "v1-apply-project-addon", "summary": "Applies project addon", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ApplyProjectAddonBodyDto" } + "schema": { "$ref": "#/components/schemas/ApplyProjectAddonBody" } } } }, @@ -2102,6 +2732,7 @@ "403": { "description": "" }, "500": { "description": "Failed to apply project addon" } }, + "tags": ["Billing"], "security": [{ "bearer": [] }] } }, @@ -2110,83 +2741,311 @@ "operationId": "v1-remove-project-addon", "summary": "Removes project addon", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "addon_variant", "required": true, "in": "path", - "schema": { - "enum": [ - "ci_micro", - "ci_small", - "ci_medium", - "ci_large", - "ci_xlarge", - "ci_2xlarge", - "ci_4xlarge", - "ci_8xlarge", - "ci_12xlarge", - "ci_16xlarge", - "cd_default", - "pitr_7", - "pitr_14", - "pitr_28", - "ipv4_default" - ], - "type": "string" - } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + "oneOf": [ + { + "type": "string", + "enum": [ + "ci_micro", + "ci_small", + "ci_medium", + "ci_large", + "ci_xlarge", + "ci_2xlarge", + "ci_4xlarge", + "ci_8xlarge", + "ci_12xlarge", + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" + ] + }, + { "type": "string", "enum": ["cd_default"] }, + { "type": "string", "enum": ["pitr_7", "pitr_14", "pitr_28"] }, + { "type": "string", "enum": ["ipv4_default"] } + ], + "schema": {} + } ], "responses": { "200": { "description": "" }, "403": { "description": "" }, "500": { "description": "Failed to remove project addon" } }, + "tags": ["Billing"], "security": [{ "bearer": [] }] } }, - "/v1/projects/{ref}/analytics/endpoints/logs.all": { + "/v1/projects/{ref}/claim-token": { "get": { - "operationId": "getLogs", - "summary": "Gets project's logs", + "operationId": "v1-get-project-claim-token", + "x-internal": true, + "summary": "Gets project claim token", "parameters": [ { - "name": "iso_timestamp_end", - "required": false, - "in": "query", - "schema": { "type": "string" } - }, - { - "name": "iso_timestamp_start", - "required": false, - "in": "query", - "schema": { "type": "string" } - }, - { "name": "sql", "required": false, "in": "query", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/V1AnalyticsResponse" } + "schema": { "$ref": "#/components/schemas/ProjectClaimTokenResponse" } } } }, "403": { "description": "" } }, + "tags": ["Projects"], + "security": [{ "bearer": [] }] + }, + "post": { + "operationId": "v1-create-project-claim-token", + "x-internal": true, + "summary": "Creates project claim token", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/CreateProjectClaimTokenResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Projects"], + "security": [{ "bearer": [] }] + }, + "delete": { + "operationId": "v1-delete-project-claim-token", + "x-internal": true, + "summary": "Revokes project claim token", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { "204": { "description": "" }, "403": { "description": "" } }, + "tags": ["Projects"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/advisors/performance": { + "get": { + "operationId": "v1-get-performance-advisors", + "summary": "Gets project performance advisors.", + "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", + "deprecated": true, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1ProjectAdvisorsResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Advisors"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/advisors/security": { + "get": { + "operationId": "v1-get-security-advisors", + "summary": "Gets project security advisors.", + "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", + "deprecated": true, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "lint_type", + "required": false, + "in": "query", + "schema": { "enum": ["sql"], "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1ProjectAdvisorsResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Advisors"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/analytics/endpoints/logs.all": { + "get": { + "operationId": "v1-get-project-logs", + "summary": "Gets project's logs", + "description": "Executes a SQL query on the project's logs.\n\nEither the 'iso_timestamp_start' and 'iso_timestamp_end' parameters must be provided.\nIf both are not provided, only the last 1 minute of logs will be queried.\nThe timestamp range must be no more than 24 hours and is rounded to the nearest minute. If the range is more than 24 hours, a validation error will be thrown.\n", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { "name": "sql", "required": false, "in": "query", "schema": { "type": "string" } }, + { + "name": "iso_timestamp_start", + "required": false, + "in": "query", + "schema": { "format": "date-time", "type": "string" } + }, + { + "name": "iso_timestamp_end", + "required": false, + "in": "query", + "schema": { "format": "date-time", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/AnalyticsResponse" } } + } + }, + "403": { "description": "" } + }, + "tags": ["Analytics"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/analytics/endpoints/usage.api-counts": { + "get": { + "operationId": "v1-get-project-usage-api-count", + "summary": "Gets project's usage api counts", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "interval", + "required": false, + "in": "query", + "schema": { + "enum": ["15min", "30min", "1hr", "3hr", "1day", "3day", "7day"], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/AnalyticsResponse" } } + } + }, + "403": { "description": "" }, + "500": { "description": "Failed to get project's usage api counts" } + }, + "tags": ["Analytics"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/analytics/endpoints/usage.api-requests-count": { + "get": { + "operationId": "v1-get-project-usage-request-count", + "summary": "Gets project's usage api requests count", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/AnalyticsResponse" } } + } + }, + "500": { "description": "Failed to get project's usage api requests count" } + }, "tags": ["Analytics"], "security": [{ "bearer": [] }] } }, "/v1/projects/{ref}/database/migrations": { "get": { - "operationId": "v1-list-migrations", + "operationId": "v1-list-migration-history", "summary": "[Beta] List applied migration versions", "description": "Only available to selected partner OAuth apps", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -2208,18 +3067,72 @@ "summary": "[Beta] Apply a database migration", "description": "Only available to selected partner OAuth apps", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } - ], - "responses": { - "200": { - "description": "", - "content": { "application/json": { "schema": { "type": "object" } } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, + { + "name": "Idempotency-Key", + "required": false, + "in": "header", + "description": "A unique key to ensure the same migration is tracked only once.", + "schema": { "type": "string" } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1CreateMigrationBody" } + } + } + }, + "responses": { + "200": { "description": "" }, "403": { "description": "" }, "500": { "description": "Failed to apply database migration" } }, "tags": ["Database"], "security": [{ "bearer": [] }] + }, + "put": { + "operationId": "v1-upsert-a-migration", + "summary": "[Beta] Upsert a database migration without applying", + "description": "Only available to selected partner OAuth apps", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "Idempotency-Key", + "required": false, + "in": "header", + "description": "A unique key to ensure the same migration is tracked only once.", + "schema": { "type": "string" } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1UpsertMigrationBody" } + } + } + }, + "responses": { + "200": { "description": "" }, + "403": { "description": "" }, + "500": { "description": "Failed to upsert database migration" } + }, + "tags": ["Database"], + "security": [{ "bearer": [] }] } }, "/v1/projects/{ref}/database/query": { @@ -2227,7 +3140,13 @@ "operationId": "v1-run-a-query", "summary": "[Beta] Run sql query", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -2236,10 +3155,7 @@ } }, "responses": { - "201": { - "description": "", - "content": { "application/json": { "schema": { "type": "object" } } } - }, + "201": { "description": "" }, "403": { "description": "" }, "500": { "description": "Failed to run sql query" } }, @@ -2257,7 +3173,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -2271,19 +3187,25 @@ }, "/v1/projects/{ref}/database/context": { "get": { - "operationId": "getDatabaseMetadata", + "operationId": "v1-get-database-metadata", "summary": "Gets database metadata for the given project.", "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", "deprecated": true, "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { "description": "", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/GetProjectDbMetadataResponseDto" } + "schema": { "$ref": "#/components/schemas/GetProjectDbMetadataResponse" } } } }, @@ -2299,7 +3221,13 @@ "summary": "List all functions", "description": "Returns all functions you've previously added to the specified project.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "responses": { "200": { @@ -2324,12 +3252,45 @@ "summary": "Create a function", "description": "This endpoint is deprecated - use the deploy endpoint. Creates a function and adds it to the specified project.", "deprecated": true, + "requestBody": { + "required": true, + "content": { + "application/vnd.denoland.eszip": { + "schema": { "type": "string", "format": "binary" } + }, + "application/json": { + "schema": { "$ref": "#/components/schemas/V1CreateFunctionBody" } + } + } + }, "parameters": [ { - "name": "import_map_path", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "slug", "required": false, "in": "query", - "schema": { "type": "string" } + "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } + }, + { "name": "name", "required": false, "in": "query", "schema": { "type": "string" } }, + { + "name": "verify_jwt", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + }, + { + "name": "import_map", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } }, { "name": "entrypoint_path", @@ -2338,32 +3299,18 @@ "schema": { "type": "string" } }, { - "name": "import_map", + "name": "import_map_path", "required": false, "in": "query", - "schema": { "type": "boolean" } + "schema": { "type": "string" } }, { - "name": "verify_jwt", + "name": "ezbr_sha256", "required": false, "in": "query", - "schema": { "type": "boolean" } - }, - { "name": "name", "required": false, "in": "query", "schema": { "type": "string" } }, - { "name": "slug", "required": false, "in": "query", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/V1CreateFunctionBody" } - }, - "application/vnd.denoland.eszip": { - "schema": { "$ref": "#/components/schemas/V1CreateFunctionBody" } - } + "schema": { "type": "string" } } - }, + ], "responses": { "201": { "description": "", @@ -2382,16 +3329,19 @@ "summary": "Bulk update functions", "description": "Bulk update functions. It will create a new function or replace existing. The operation is idempotent. NOTE: You will need to manually bump the version.", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, "content": { "application/json": { - "schema": { - "type": "array", - "items": { "$ref": "#/components/schemas/BulkUpdateFunctionBody" } - } + "schema": { "$ref": "#/components/schemas/BulkUpdateFunctionBody" } } } }, @@ -2417,14 +3367,26 @@ "summary": "Deploy a function", "description": "A new endpoint to deploy functions. It will create if function does not exist.", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "slug", + "required": false, + "in": "query", + "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } + }, { "name": "bundleOnly", "required": false, "in": "query", + "description": "Boolean string, true or false", "schema": { "type": "boolean" } - }, - { "name": "slug", "required": false, "in": "query", "schema": { "type": "string" } }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + } ], "requestBody": { "required": true, @@ -2456,13 +3418,20 @@ "summary": "Retrieve a function", "description": "Retrieves a function with the specified slug and project.", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + } ], "responses": { "200": { @@ -2483,12 +3452,52 @@ "operationId": "v1-update-a-function", "summary": "Update a function", "description": "Updates a function with the specified slug and project.", + "requestBody": { + "required": true, + "content": { + "application/vnd.denoland.eszip": { + "schema": { "type": "string", "format": "binary" } + }, + "application/json": { + "schema": { "$ref": "#/components/schemas/V1UpdateFunctionBody" } + } + } + }, "parameters": [ { - "name": "import_map_path", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "function_slug", + "required": true, + "in": "path", + "description": "Function slug", + "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } + }, + { + "name": "slug", "required": false, "in": "query", - "schema": { "type": "string" } + "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } + }, + { "name": "name", "required": false, "in": "query", "schema": { "type": "string" } }, + { + "name": "verify_jwt", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } + }, + { + "name": "import_map", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { "type": "boolean" } }, { "name": "entrypoint_path", @@ -2497,37 +3506,18 @@ "schema": { "type": "string" } }, { - "name": "import_map", + "name": "import_map_path", "required": false, "in": "query", - "schema": { "type": "boolean" } + "schema": { "type": "string" } }, { - "name": "verify_jwt", + "name": "ezbr_sha256", "required": false, "in": "query", - "schema": { "type": "boolean" } - }, - { "name": "name", "required": false, "in": "query", "schema": { "type": "string" } }, - { - "name": "function_slug", - "required": true, - "in": "path", - "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/V1UpdateFunctionBody" } - }, - "application/vnd.denoland.eszip": { - "schema": { "$ref": "#/components/schemas/V1UpdateFunctionBody" } - } + "schema": { "type": "string" } } - }, + ], "responses": { "200": { "description": "", @@ -2546,13 +3536,20 @@ "summary": "Delete a function", "description": "Deletes a function with the specified slug from the specified project.", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + } ], "responses": { "200": { "description": "" }, @@ -2569,16 +3566,28 @@ "summary": "Retrieve a function body", "description": "Retrieves a function body for the specified slug and project.", "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, { "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } - }, - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + } ], "responses": { - "200": { "description": "" }, + "200": { + "description": "", + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/StreamableFile" } } + } + }, "403": { "description": "" }, "500": { "description": "Failed to retrieve function body with given slug" } }, @@ -2596,7 +3605,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -2628,7 +3637,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "requestBody": { @@ -2661,7 +3670,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -2690,9 +3699,14 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, - { "name": "provider_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "provider_id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -2720,9 +3734,14 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, - { "name": "provider_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "provider_id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + } ], "requestBody": { "required": true, @@ -2756,9 +3775,14 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } }, - { "name": "provider_id", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "provider_id", + "required": true, + "in": "path", + "schema": { "format": "uuid", "type": "string" } + } ], "responses": { "200": { @@ -2788,7 +3812,7 @@ "required": true, "in": "path", "description": "Project ref", - "schema": { "minLength": 20, "maxLength": 20, "type": "string" } + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } } ], "responses": { @@ -2810,7 +3834,13 @@ "operationId": "v1-restore-pitr-backup", "summary": "Restores a PITR backup for a database", "parameters": [ - { "name": "ref", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } ], "requestBody": { "required": true, @@ -2823,12 +3853,113 @@ "security": [{ "bearer": [] }] } }, + "/v1/projects/{ref}/database/backups/restore-point": { + "post": { + "operationId": "v1-create-restore-point", + "x-internal": true, + "summary": "Initiates a creation of a restore point for a database", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1RestorePointPostBody" } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1RestorePointResponse" } + } + } + } + }, + "tags": ["Database"], + "security": [{ "bearer": [] }] + }, + "get": { + "operationId": "v1-get-restore-point", + "x-internal": true, + "summary": "Get restore points for project", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "name", + "required": false, + "in": "query", + "schema": { "maxLength": 20, "type": "string" } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/V1RestorePointResponse" } + } + } + }, + "403": { "description": "" }, + "500": { "description": "Failed to get requested restore points" } + }, + "tags": ["Database"], + "security": [{ "bearer": [] }] + } + }, + "/v1/projects/{ref}/database/backups/undo": { + "post": { + "operationId": "v1-undo", + "x-internal": true, + "summary": "Initiates an undo to a given restore point", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { "minLength": 20, "maxLength": 20, "pattern": "^[a-z]+$", "type": "string" } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { "schema": { "$ref": "#/components/schemas/V1UndoBody" } } + } + }, + "responses": { "201": { "description": "" }, "403": { "description": "" } }, + "tags": ["Database"], + "security": [{ "bearer": [] }] + } + }, "/v1/organizations/{slug}/members": { "get": { "operationId": "v1-list-organization-members", "summary": "List members of an organization", "parameters": [ - { "name": "slug", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { "pattern": "^[\\w-]+$", "type": "string" } + } ], "responses": { "200": { @@ -2853,7 +3984,13 @@ "operationId": "v1-get-an-organization", "summary": "Gets information about the organization", "parameters": [ - { "name": "slug", "required": true, "in": "path", "schema": { "type": "string" } } + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { "pattern": "^[\\w-]+$", "type": "string" } + } ], "responses": { "200": { @@ -2869,6 +4006,54 @@ "tags": ["Organizations"], "security": [{ "bearer": [] }] } + }, + "/v1/organizations/{slug}/project-claim/{token}": { + "get": { + "operationId": "v1-get-organization-project-claim", + "x-internal": true, + "summary": "Gets project details for the specified organization and claim token", + "parameters": [ + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { "pattern": "^[\\w-]+$", "type": "string" } + }, + { "name": "token", "required": true, "in": "path", "schema": { "type": "string" } } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/OrganizationProjectClaimResponse" } + } + } + }, + "403": { "description": "" } + }, + "tags": ["Organizations"], + "security": [{ "bearer": [] }] + }, + "post": { + "operationId": "v1-claim-project-for-organization", + "x-internal": true, + "summary": "Claims project for the specified organization", + "parameters": [ + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { "pattern": "^[\\w-]+$", "type": "string" } + }, + { "name": "token", "required": true, "in": "path", "schema": { "type": "string" } } + ], + "responses": { "204": { "description": "" }, "403": { "description": "" } }, + "tags": ["Organizations"], + "security": [{ "bearer": [] }] + } } }, "info": { @@ -2878,7 +4063,10 @@ "contact": {} }, "tags": [ + { "name": "Advisors", "description": "Advisors related endpoints" }, + { "name": "Analytics", "description": "Analytics related endpoints" }, { "name": "Auth", "description": "Auth related endpoints" }, + { "name": "Billing", "description": "Billing related endpoints" }, { "name": "Database", "description": "Database related endpoints" }, { "name": "Domains", "description": "Domains related endpoints" }, { "name": "Edge Functions", "description": "Edge related endpoints" }, @@ -2922,7 +4110,7 @@ ] }, "db_host": { "type": "string" }, - "db_port": { "type": "number" }, + "db_port": { "type": "integer", "minimum": 0, "exclusiveMinimum": true }, "db_user": { "type": "string" }, "db_pass": { "type": "string" }, "jwt_secret": { "type": "string" } @@ -2958,13 +4146,14 @@ "FUNCTIONS_DEPLOYED", "FUNCTIONS_FAILED" ] - } + }, + "request_review": { "type": "boolean" } } }, "BranchResponse": { "type": "object", "properties": { - "id": { "type": "string" }, + "id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "project_ref": { "type": "string" }, "parent_project_ref": { "type": "string" }, @@ -2988,8 +4177,9 @@ "FUNCTIONS_FAILED" ] }, - "created_at": { "type": "string" }, - "updated_at": { "type": "string" } + "created_at": { "type": "string", "format": "date-time" }, + "updated_at": { "type": "string", "format": "date-time" }, + "review_requested_at": { "type": "string", "format": "date-time" } }, "required": [ "id", @@ -3008,6 +4198,10 @@ "properties": { "message": { "type": "string", "enum": ["ok"] } }, "required": ["message"] }, + "BranchActionBody": { + "type": "object", + "properties": { "migration_version": { "type": "string" } } + }, "BranchUpdateResponse": { "type": "object", "properties": { @@ -3016,16 +4210,6 @@ }, "required": ["workflow_run_id", "message"] }, - "V1DatabaseResponse": { - "type": "object", - "properties": { - "host": { "type": "string", "description": "Database host" }, - "version": { "type": "string", "description": "Database version" }, - "postgres_engine": { "type": "string", "description": "Database engine" }, - "release_channel": { "type": "string", "description": "Release channel" } - }, - "required": ["host", "version", "postgres_engine", "release_channel"] - }, "V1ProjectWithDatabaseResponse": { "type": "object", "properties": { @@ -3062,15 +4246,24 @@ "RESIZING" ] }, - "database": { "$ref": "#/components/schemas/V1DatabaseResponse" } + "database": { + "type": "object", + "properties": { + "host": { "type": "string", "description": "Database host" }, + "version": { "type": "string", "description": "Database version" }, + "postgres_engine": { "type": "string", "description": "Database engine" }, + "release_channel": { "type": "string", "description": "Release channel" } + }, + "required": ["host", "version", "postgres_engine", "release_channel"] + } }, "required": ["id", "organization_id", "name", "region", "created_at", "status", "database"] }, - "V1CreateProjectBodyDto": { + "V1CreateProjectBody": { "type": "object", "properties": { "db_pass": { "type": "string", "description": "Database password" }, - "name": { "type": "string", "description": "Name of your project" }, + "name": { "type": "string", "maxLength": 256, "description": "Name of your project" }, "organization_id": { "type": "string", "description": "Slug of your organization" }, "plan": { "type": "string", @@ -3110,6 +4303,8 @@ "desired_instance_size": { "type": "string", "enum": [ + "pico", + "nano", "micro", "small", "medium", @@ -3119,7 +4314,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "template_url": { @@ -3177,7 +4380,7 @@ "properties": { "id": { "type": "string" }, "name": { "type": "string" } }, "required": ["id", "name"] }, - "CreateOrganizationV1Dto": { + "CreateOrganizationV1": { "type": "object", "properties": { "name": { "type": "string" } }, "required": ["name"], @@ -3207,7 +4410,7 @@ "required": ["access_token", "refresh_token", "expires_in", "token_type"], "additionalProperties": false }, - "OAuthRevokeTokenBodyDto": { + "OAuthRevokeTokenBody": { "type": "object", "properties": { "client_id": { "type": "string", "format": "uuid" }, @@ -3217,23 +4420,56 @@ "required": ["client_id", "client_secret", "refresh_token"], "additionalProperties": false }, - "SnippetProject": { + "SnippetList": { "type": "object", "properties": { - "id": { "type": "integer", "format": "int64" }, - "name": { "type": "string" } + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "inserted_at": { "type": "string" }, + "updated_at": { "type": "string" }, + "type": { "type": "string", "enum": ["sql"] }, + "visibility": { "type": "string", "enum": ["user", "project", "org", "public"] }, + "name": { "type": "string" }, + "description": { "type": "string", "nullable": true }, + "project": { + "type": "object", + "properties": { "id": { "type": "number" }, "name": { "type": "string" } }, + "required": ["id", "name"] + }, + "owner": { + "type": "object", + "properties": { "id": { "type": "number" }, "username": { "type": "string" } }, + "required": ["id", "username"] + }, + "updated_by": { + "type": "object", + "properties": { "id": { "type": "number" }, "username": { "type": "string" } }, + "required": ["id", "username"] + } + }, + "required": [ + "id", + "inserted_at", + "updated_at", + "type", + "visibility", + "name", + "description", + "project", + "owner", + "updated_by" + ] + } + }, + "cursor": { "type": "string" } }, - "required": ["id", "name"] + "required": ["data"] }, - "SnippetUser": { - "type": "object", - "properties": { - "id": { "type": "integer", "format": "int64" }, - "username": { "type": "string" } - }, - "required": ["id", "username"] - }, - "SnippetMeta": { + "SnippetResponse": { "type": "object", "properties": { "id": { "type": "string" }, @@ -3243,54 +4479,30 @@ "visibility": { "type": "string", "enum": ["user", "project", "org", "public"] }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, - "project": { "$ref": "#/components/schemas/SnippetProject" }, - "owner": { "$ref": "#/components/schemas/SnippetUser" }, - "updated_by": { "$ref": "#/components/schemas/SnippetUser" } - }, - "required": [ - "id", - "inserted_at", - "updated_at", - "type", - "visibility", - "name", - "description", - "project", - "owner", - "updated_by" - ] - }, - "SnippetList": { - "type": "object", - "properties": { - "data": { "type": "array", "items": { "$ref": "#/components/schemas/SnippetMeta" } }, - "cursor": { "type": "string" } - }, - "required": ["data"] - }, - "SnippetContent": { - "type": "object", - "properties": { - "favorite": { "type": "boolean" }, - "schema_version": { "type": "string" }, - "sql": { "type": "string" } - }, - "required": ["favorite", "schema_version", "sql"] - }, - "SnippetResponse": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "inserted_at": { "type": "string" }, - "updated_at": { "type": "string" }, - "type": { "type": "string", "enum": ["sql"] }, - "visibility": { "enum": ["user", "project", "org", "public"], "type": "string" }, - "name": { "type": "string" }, - "description": { "type": "string", "nullable": true }, - "project": { "$ref": "#/components/schemas/SnippetProject" }, - "owner": { "$ref": "#/components/schemas/SnippetUser" }, - "updated_by": { "$ref": "#/components/schemas/SnippetUser" }, - "content": { "$ref": "#/components/schemas/SnippetContent" } + "project": { + "type": "object", + "properties": { "id": { "type": "number" }, "name": { "type": "string" } }, + "required": ["id", "name"] + }, + "owner": { + "type": "object", + "properties": { "id": { "type": "number" }, "username": { "type": "string" } }, + "required": ["id", "username"] + }, + "updated_by": { + "type": "object", + "properties": { "id": { "type": "number" }, "username": { "type": "string" } }, + "required": ["id", "username"] + }, + "content": { + "type": "object", + "properties": { + "favorite": { "type": "boolean" }, + "schema_version": { "type": "string" }, + "sql": { "type": "string" } + }, + "required": ["favorite", "schema_version", "sql"] + } }, "required": [ "id", @@ -3309,15 +4521,15 @@ "ApiKeyResponse": { "type": "object", "properties": { - "name": { "type": "string" }, - "api_key": { "type": "string" }, + "api_key": { "type": "string", "nullable": true }, "id": { "type": "string", "nullable": true }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { "type": "string" }, "description": { "type": "string", "nullable": true }, "hash": { "type": "string", "nullable": true }, "secret_jwt_template": { @@ -3329,12 +4541,23 @@ "inserted_at": { "type": "string", "format": "date-time", "nullable": true }, "updated_at": { "type": "string", "format": "date-time", "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] + }, + "LegacyApiKeysResponse": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] }, "CreateApiKeyBody": { "type": "object", "properties": { "type": { "type": "string", "enum": ["publishable", "secret"] }, + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true }, "secret_jwt_template": { "type": "object", @@ -3343,11 +4566,17 @@ "nullable": true } }, - "required": ["type"] + "required": ["type", "name"] }, "UpdateApiKeyBody": { "type": "object", "properties": { + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true }, "secret_jwt_template": { "type": "object", @@ -3362,6 +4591,7 @@ "properties": { "branch_name": { "type": "string", "minLength": 1 }, "git_branch": { "type": "string" }, + "is_default": { "type": "boolean" }, "persistent": { "type": "boolean" }, "region": { "type": "string" }, "desired_instance_size": { @@ -3378,7 +4608,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "release_channel": { @@ -3388,92 +4626,96 @@ }, "postgres_engine": { "type": "string", - "enum": ["15", "17-oriole"], + "enum": ["15", "17", "17-oriole"], "description": "Postgres engine version. If not provided, the latest version will be used." }, - "secrets": { "type": "object", "additionalProperties": { "type": "string" } } + "secrets": { "type": "object", "additionalProperties": { "type": "string" } }, + "with_data": { "type": "boolean" } }, "required": ["branch_name"] }, - "ValidationRecord": { - "type": "object", - "properties": { "txt_name": { "type": "string" }, "txt_value": { "type": "string" } }, - "required": ["txt_name", "txt_value"] - }, - "ValidationError": { - "type": "object", - "properties": { "message": { "type": "string" } }, - "required": ["message"] - }, - "SslValidation": { - "type": "object", - "properties": { - "status": { "type": "string" }, - "validation_records": { - "type": "array", - "items": { "$ref": "#/components/schemas/ValidationRecord" } - }, - "validation_errors": { - "type": "array", - "items": { "$ref": "#/components/schemas/ValidationError" } - } - }, - "required": ["status", "validation_records"] - }, - "OwnershipVerification": { - "type": "object", - "properties": { - "type": { "type": "string" }, - "name": { "type": "string" }, - "value": { "type": "string" } - }, - "required": ["type", "name", "value"] - }, - "CustomHostnameDetails": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "hostname": { "type": "string" }, - "ssl": { "$ref": "#/components/schemas/SslValidation" }, - "ownership_verification": { "$ref": "#/components/schemas/OwnershipVerification" }, - "custom_origin_server": { "type": "string" }, - "verification_errors": { "type": "array", "items": { "type": "string" } }, - "status": { "type": "string" } - }, - "required": [ - "id", - "hostname", - "ssl", - "ownership_verification", - "custom_origin_server", - "status" - ] - }, - "CfResponse": { - "type": "object", - "properties": { - "success": { "type": "boolean" }, - "errors": { "type": "array", "items": { "type": "object" } }, - "messages": { "type": "array", "items": { "type": "object" } }, - "result": { "$ref": "#/components/schemas/CustomHostnameDetails" } - }, - "required": ["success", "errors", "messages", "result"] - }, "UpdateCustomHostnameResponse": { "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" }, - "data": { "$ref": "#/components/schemas/CfResponse" } + "data": { + "type": "object", + "properties": { + "success": { "type": "boolean" }, + "errors": { + "type": "array", + "items": { "description": "Any JSON-serializable value" } + }, + "messages": { + "type": "array", + "items": { "description": "Any JSON-serializable value" } + }, + "result": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "hostname": { "type": "string" }, + "ssl": { + "type": "object", + "properties": { + "status": { "type": "string" }, + "validation_records": { + "type": "array", + "items": { + "type": "object", + "properties": { + "txt_name": { "type": "string" }, + "txt_value": { "type": "string" } + }, + "required": ["txt_name", "txt_value"] + } + }, + "validation_errors": { + "type": "array", + "items": { + "type": "object", + "properties": { "message": { "type": "string" } }, + "required": ["message"] + } + } + }, + "required": ["status", "validation_records"] + }, + "ownership_verification": { + "type": "object", + "properties": { + "type": { "type": "string" }, + "name": { "type": "string" }, + "value": { "type": "string" } + }, + "required": ["type", "name", "value"] + }, + "custom_origin_server": { "type": "string" }, + "verification_errors": { "type": "array", "items": { "type": "string" } }, + "status": { "type": "string" } + }, + "required": [ + "id", + "hostname", + "ssl", + "ownership_verification", + "custom_origin_server", + "status" + ] + } + }, + "required": ["success", "errors", "messages", "result"] + } }, "required": ["status", "custom_hostname", "data"] }, @@ -3489,9 +4731,30 @@ }, "required": ["banned_ipv4_addresses"] }, + "NetworkBanResponseEnriched": { + "type": "object", + "properties": { + "banned_ipv4_addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "banned_address": { "type": "string" }, + "identifier": { "type": "string" }, + "type": { "type": "string" } + }, + "required": ["banned_address", "identifier", "type"] + } + } + }, + "required": ["banned_ipv4_addresses"] + }, "RemoveNetworkBanRequest": { "type": "object", - "properties": { "ipv4_addresses": { "type": "array", "items": { "type": "string" } } }, + "properties": { + "ipv4_addresses": { "type": "array", "items": { "type": "string" } }, + "identifier": { "type": "string" } + }, "required": ["ipv4_addresses"] }, "NetworkRestrictionsResponse": { @@ -3576,7 +4839,7 @@ "V1ProjectRefResponse": { "type": "object", "properties": { - "id": { "type": "integer", "format": "int64" }, + "id": { "type": "integer" }, "ref": { "type": "string" }, "name": { "type": "string" } }, @@ -3592,18 +4855,21 @@ "required": ["name", "value"] }, "CreateSecretBody": { - "type": "object", - "properties": { - "name": { - "type": "string", - "maxLength": 256, - "pattern": "^(?!SUPABASE_).*", - "description": "Secret name must not start with the SUPABASE_ prefix.", - "example": "string" + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 256, + "pattern": "^(?!SUPABASE_).*", + "description": "Secret name must not start with the SUPABASE_ prefix.", + "example": "string" + }, + "value": { "type": "string", "maxLength": 24576 } }, - "value": { "type": "string", "maxLength": 24576 } - }, - "required": ["name", "value"] + "required": ["name", "value"] + } }, "SslEnforcementResponse": { "type": "object", @@ -3687,7 +4953,7 @@ "items": { "type": "object", "properties": { - "postgres_version": { "type": "string", "enum": ["15", "17-oriole"] }, + "postgres_version": { "type": "string", "enum": ["15", "17", "17-oriole"] }, "release_channel": { "type": "string", "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] @@ -3697,10 +4963,14 @@ "required": ["postgres_version", "release_channel", "app_version"] } }, - "potential_breaking_changes": { "type": "array", "items": { "type": "string" } }, "duration_estimate_hours": { "type": "number" }, "legacy_auth_custom_roles": { "type": "array", "items": { "type": "string" } }, - "extension_dependent_objects": { "type": "array", "items": { "type": "string" } } + "objects_to_be_dropped": { "type": "array", "items": { "type": "string" } }, + "unsupported_extensions": { "type": "array", "items": { "type": "string" } }, + "user_defined_objects_in_internal_schemas": { + "type": "array", + "items": { "type": "string" } + } }, "required": [ "eligible", @@ -3708,10 +4978,11 @@ "current_app_version_release_channel", "latest_app_version", "target_upgrade_versions", - "potential_breaking_changes", "duration_estimate_hours", "legacy_auth_custom_roles", - "extension_dependent_objects" + "objects_to_be_dropped", + "unsupported_extensions", + "user_defined_objects_in_internal_schemas" ] }, "DatabaseUpgradeStatusResponse": { @@ -3806,40 +5077,115 @@ "properties": { "database_identifier": { "type": "string" } }, "required": ["database_identifier"] }, - "AuthHealthResponse": { - "type": "object", - "properties": { "name": { "type": "string", "enum": ["GoTrue"] } }, - "required": ["name"] - }, - "RealtimeHealthResponse": { - "type": "object", - "properties": { "connected_cluster": { "type": "integer" } }, - "required": ["connected_cluster"] - }, "V1ServiceHealthResponse": { "type": "object", "properties": { - "info": { - "oneOf": [ - { "$ref": "#/components/schemas/AuthHealthResponse" }, - { "$ref": "#/components/schemas/RealtimeHealthResponse" } - ] - }, "name": { - "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"], - "type": "string" + "type": "string", + "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"] }, "healthy": { "type": "boolean" }, - "status": { "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"], "type": "string" }, + "status": { "type": "string", "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"] }, + "info": { + "oneOf": [ + { + "type": "object", + "properties": { + "name": { "type": "string", "enum": ["GoTrue"] }, + "version": { "type": "string" }, + "description": { "type": "string" } + }, + "required": ["name", "version", "description"] + }, + { + "type": "object", + "properties": { + "healthy": { "type": "boolean" }, + "db_connected": { "type": "boolean" }, + "connected_cluster": { "type": "integer" } + }, + "required": ["healthy", "db_connected", "connected_cluster"] + } + ] + }, "error": { "type": "string" } }, "required": ["name", "healthy", "status"] }, + "SigningKeyResponse": { + "type": "object", + "properties": { + "id": { "type": "string", "format": "uuid" }, + "algorithm": { "type": "string", "enum": ["EdDSA", "ES256", "RS256", "HS256"] }, + "status": { + "type": "string", + "enum": ["in_use", "previously_used", "revoked", "standby"] + }, + "public_jwk": { "nullable": true }, + "created_at": { "type": "string", "format": "date-time" }, + "updated_at": { "type": "string", "format": "date-time" } + }, + "required": ["id", "algorithm", "status", "created_at", "updated_at"], + "additionalProperties": false + }, "CreateSigningKeyBody": { "type": "object", "properties": { "algorithm": { "type": "string", "enum": ["EdDSA", "ES256", "RS256", "HS256"] }, - "status": { "type": "string", "enum": ["in_use", "standby"] } + "status": { "type": "string", "enum": ["in_use", "standby"] }, + "private_jwk": { + "discriminator": { "propertyName": "kty" }, + "oneOf": [ + { + "type": "object", + "properties": { + "kty": { "type": "string", "enum": ["RSA"] }, + "n": { "type": "string" }, + "e": { "type": "string", "enum": ["AQAB"] }, + "d": { "type": "string" }, + "p": { "type": "string" }, + "q": { "type": "string" }, + "dp": { "type": "string" }, + "dq": { "type": "string" }, + "qi": { "type": "string" } + }, + "required": ["kty", "n", "e", "d", "p", "q", "dp", "dq", "qi"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { "type": "string", "enum": ["EC"] }, + "crv": { "type": "string", "enum": ["P-256"] }, + "x": { "type": "string" }, + "y": { "type": "string" }, + "d": { "type": "string" } + }, + "required": ["kty", "crv", "x", "y", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { "type": "string", "enum": ["OKP"] }, + "crv": { "type": "string", "enum": ["Ed25519"] }, + "x": { "type": "string" }, + "d": { "type": "string" } + }, + "required": ["kty", "crv", "x", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { "type": "string", "enum": ["oct"] }, + "k": { "type": "string", "minLength": 16 } + }, + "required": ["kty", "k"], + "additionalProperties": false + } + ] + } }, "required": ["algorithm"], "additionalProperties": false @@ -3870,22 +5216,6 @@ "required": ["keys"], "additionalProperties": false }, - "SigningKeyResponse": { - "type": "object", - "properties": { - "id": { "type": "string", "format": "uuid" }, - "algorithm": { "type": "string", "enum": ["EdDSA", "ES256", "RS256", "HS256"] }, - "status": { - "type": "string", - "enum": ["in_use", "previously_used", "revoked", "standby"] - }, - "public_jwk": { "nullable": true }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" } - }, - "required": ["id", "algorithm", "status", "created_at", "updated_at"], - "additionalProperties": false - }, "UpdateSigningKeyBody": { "type": "object", "properties": { @@ -3897,31 +5227,31 @@ "required": ["status"], "additionalProperties": false }, - "StorageFeatureImageTransformation": { - "type": "object", - "properties": { "enabled": { "type": "boolean" } }, - "required": ["enabled"] - }, - "StorageFeatureS3Protocol": { - "type": "object", - "properties": { "enabled": { "type": "boolean" } }, - "required": ["enabled"] - }, - "StorageFeatures": { - "type": "object", - "properties": { - "imageTransformation": { - "$ref": "#/components/schemas/StorageFeatureImageTransformation" - }, - "s3Protocol": { "$ref": "#/components/schemas/StorageFeatureS3Protocol" } - }, - "required": ["imageTransformation", "s3Protocol"] - }, "StorageConfigResponse": { "type": "object", "properties": { "fileSizeLimit": { "type": "integer", "format": "int64" }, - "features": { "$ref": "#/components/schemas/StorageFeatures" } + "features": { + "type": "object", + "properties": { + "imageTransformation": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + }, + "s3Protocol": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + } + }, + "required": ["imageTransformation", "s3Protocol"] + } }, "required": ["fileSizeLimit", "features"] }, @@ -3931,10 +5261,30 @@ "fileSizeLimit": { "type": "integer", "minimum": 0, - "maximum": 53687091200, + "maximum": 536870912000, "format": "int64" }, - "features": { "$ref": "#/components/schemas/StorageFeatures" } + "features": { + "type": "object", + "properties": { + "imageTransformation": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + }, + "s3Protocol": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { "enabled": { "type": "boolean" } }, + "required": ["enabled"] + } + }, + "required": ["imageTransformation", "s3Protocol"] + } } }, "PostgresConfigResponse": { @@ -3956,13 +5306,13 @@ "max_wal_size": { "type": "string" }, "max_wal_senders": { "type": "integer" }, "max_worker_processes": { "type": "integer", "minimum": 0, "maximum": 262143 }, + "session_replication_role": { "type": "string", "enum": ["origin", "replica", "local"] }, "shared_buffers": { "type": "string" }, "statement_timeout": { "type": "string" }, "track_commit_timestamp": { "type": "boolean" }, "wal_keep_size": { "type": "string" }, "wal_sender_timeout": { "type": "string" }, - "work_mem": { "type": "string" }, - "session_replication_role": { "enum": ["origin", "replica", "local"], "type": "string" } + "work_mem": { "type": "string" } } }, "UpdatePostgresConfigBody": { @@ -3984,59 +5334,59 @@ "max_wal_size": { "type": "string" }, "max_wal_senders": { "type": "integer" }, "max_worker_processes": { "type": "integer", "minimum": 0, "maximum": 262143 }, + "session_replication_role": { "type": "string", "enum": ["origin", "replica", "local"] }, "shared_buffers": { "type": "string" }, "statement_timeout": { "type": "string" }, "track_commit_timestamp": { "type": "boolean" }, "wal_keep_size": { "type": "string" }, "wal_sender_timeout": { "type": "string" }, "work_mem": { "type": "string" }, - "restart_database": { "type": "boolean" }, - "session_replication_role": { "enum": ["origin", "replica", "local"], "type": "string" } + "restart_database": { "type": "boolean" } } }, "V1PgbouncerConfigResponse": { "type": "object", "properties": { - "pool_mode": { "type": "string", "enum": ["transaction", "session", "statement"] }, - "default_pool_size": { "type": "number" }, + "default_pool_size": { "type": "integer" }, "ignore_startup_parameters": { "type": "string" }, - "max_client_conn": { "type": "number" }, - "connection_string": { "type": "string" } + "max_client_conn": { "type": "integer" }, + "pool_mode": { "type": "string", "enum": ["transaction", "session", "statement"] }, + "connection_string": { "type": "string" }, + "server_idle_timeout": { "type": "integer" }, + "server_lifetime": { "type": "integer" }, + "query_wait_timeout": { "type": "integer" }, + "reserve_pool_size": { "type": "integer" } } }, "SupavisorConfigResponse": { "type": "object", "properties": { - "database_type": { "type": "string", "enum": ["PRIMARY", "READ_REPLICA"] }, - "db_port": { "type": "integer" }, - "connectionString": { - "type": "string", - "deprecated": true, - "description": "Use connection_string instead" - }, - "default_pool_size": { "type": "integer", "nullable": true }, - "max_client_conn": { "type": "integer", "nullable": true }, - "pool_mode": { "enum": ["transaction", "session"], "type": "string" }, "identifier": { "type": "string" }, + "database_type": { "type": "string", "enum": ["PRIMARY", "READ_REPLICA"] }, "is_using_scram_auth": { "type": "boolean" }, "db_user": { "type": "string" }, "db_host": { "type": "string" }, + "db_port": { "type": "integer" }, "db_name": { "type": "string" }, - "connection_string": { "type": "string" } + "connection_string": { "type": "string" }, + "connectionString": { "type": "string", "description": "Use connection_string instead" }, + "default_pool_size": { "type": "integer", "nullable": true }, + "max_client_conn": { "type": "integer", "nullable": true }, + "pool_mode": { "type": "string", "enum": ["transaction", "session"] } }, "required": [ - "database_type", - "db_port", - "connectionString", - "default_pool_size", - "max_client_conn", - "pool_mode", "identifier", + "database_type", "is_using_scram_auth", "db_user", "db_host", + "db_port", "db_name", - "connection_string" + "connection_string", + "connectionString", + "default_pool_size", + "max_client_conn", + "pool_mode" ] }, "UpdateSupavisorConfigBody": { @@ -4044,15 +5394,14 @@ "properties": { "default_pool_size": { "type": "integer", - "nullable": true, "minimum": 0, - "maximum": 1000 + "maximum": 3000, + "nullable": true }, "pool_mode": { - "enum": ["transaction", "session"], "type": "string", - "description": "Dedicated pooler mode for the project", - "deprecated": true + "enum": ["transaction", "session"], + "description": "Dedicated pooler mode for the project" } } }, @@ -4069,26 +5418,6 @@ "properties": { "api_max_request_duration": { "type": "integer", "nullable": true }, "db_max_pool_size": { "type": "integer", "nullable": true }, - "jwt_exp": { "type": "integer", "nullable": true }, - "mailer_otp_exp": { "type": "integer" }, - "mailer_otp_length": { "type": "integer", "nullable": true }, - "mfa_max_enrolled_factors": { "type": "integer", "nullable": true }, - "mfa_phone_otp_length": { "type": "integer" }, - "mfa_phone_max_frequency": { "type": "integer", "nullable": true }, - "password_min_length": { "type": "integer", "nullable": true }, - "rate_limit_anonymous_users": { "type": "integer", "nullable": true }, - "rate_limit_email_sent": { "type": "integer", "nullable": true }, - "rate_limit_sms_sent": { "type": "integer", "nullable": true }, - "rate_limit_token_refresh": { "type": "integer", "nullable": true }, - "rate_limit_verify": { "type": "integer", "nullable": true }, - "rate_limit_otp": { "type": "integer", "nullable": true }, - "security_refresh_token_reuse_interval": { "type": "integer", "nullable": true }, - "sessions_inactivity_timeout": { "type": "integer", "nullable": true }, - "sessions_timebox": { "type": "integer", "nullable": true }, - "sms_max_frequency": { "type": "integer", "nullable": true }, - "sms_otp_exp": { "type": "integer", "nullable": true }, - "sms_otp_length": { "type": "integer" }, - "smtp_max_frequency": { "type": "integer", "nullable": true }, "disable_signup": { "type": "boolean", "nullable": true }, "external_anonymous_users_enabled": { "type": "boolean", "nullable": true }, "external_apple_additional_client_ids": { "type": "string", "nullable": true }, @@ -4157,6 +5486,7 @@ "external_workos_enabled": { "type": "boolean", "nullable": true }, "external_workos_secret": { "type": "string", "nullable": true }, "external_workos_url": { "type": "string", "nullable": true }, + "external_web3_solana_enabled": { "type": "boolean", "nullable": true }, "external_zoom_client_id": { "type": "string", "nullable": true }, "external_zoom_enabled": { "type": "boolean", "nullable": true }, "external_zoom_secret": { "type": "string", "nullable": true }, @@ -4175,8 +5505,14 @@ "hook_send_email_enabled": { "type": "boolean", "nullable": true }, "hook_send_email_uri": { "type": "string", "nullable": true }, "hook_send_email_secrets": { "type": "string", "nullable": true }, + "hook_before_user_created_enabled": { "type": "boolean", "nullable": true }, + "hook_before_user_created_uri": { "type": "string", "nullable": true }, + "hook_before_user_created_secrets": { "type": "string", "nullable": true }, + "jwt_exp": { "type": "integer", "nullable": true }, "mailer_allow_unverified_email_sign_ins": { "type": "boolean", "nullable": true }, "mailer_autoconfirm": { "type": "boolean", "nullable": true }, + "mailer_otp_exp": { "type": "integer" }, + "mailer_otp_length": { "type": "integer", "nullable": true }, "mailer_secure_email_change_enabled": { "type": "boolean", "nullable": true }, "mailer_subjects_confirmation": { "type": "string", "nullable": true }, "mailer_subjects_email_change": { "type": "string", "nullable": true }, @@ -4190,37 +5526,71 @@ "mailer_templates_magic_link_content": { "type": "string", "nullable": true }, "mailer_templates_reauthentication_content": { "type": "string", "nullable": true }, "mailer_templates_recovery_content": { "type": "string", "nullable": true }, + "mfa_max_enrolled_factors": { "type": "integer", "nullable": true }, "mfa_totp_enroll_enabled": { "type": "boolean", "nullable": true }, "mfa_totp_verify_enabled": { "type": "boolean", "nullable": true }, "mfa_phone_enroll_enabled": { "type": "boolean", "nullable": true }, "mfa_phone_verify_enabled": { "type": "boolean", "nullable": true }, "mfa_web_authn_enroll_enabled": { "type": "boolean", "nullable": true }, "mfa_web_authn_verify_enabled": { "type": "boolean", "nullable": true }, + "mfa_phone_otp_length": { "type": "integer" }, "mfa_phone_template": { "type": "string", "nullable": true }, + "mfa_phone_max_frequency": { "type": "integer", "nullable": true }, "password_hibp_enabled": { "type": "boolean", "nullable": true }, - "password_required_characters": { "type": "string", "nullable": true }, + "password_min_length": { "type": "integer", "nullable": true }, + "password_required_characters": { + "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "rate_limit_anonymous_users": { "type": "integer", "nullable": true }, + "rate_limit_email_sent": { "type": "integer", "nullable": true }, + "rate_limit_sms_sent": { "type": "integer", "nullable": true }, + "rate_limit_token_refresh": { "type": "integer", "nullable": true }, + "rate_limit_verify": { "type": "integer", "nullable": true }, + "rate_limit_otp": { "type": "integer", "nullable": true }, + "rate_limit_web3": { "type": "integer", "nullable": true }, "refresh_token_rotation_enabled": { "type": "boolean", "nullable": true }, "saml_enabled": { "type": "boolean", "nullable": true }, "saml_external_url": { "type": "string", "nullable": true }, "saml_allow_encrypted_assertions": { "type": "boolean", "nullable": true }, "security_captcha_enabled": { "type": "boolean", "nullable": true }, - "security_captcha_provider": { "type": "string", "nullable": true }, + "security_captcha_provider": { + "type": "string", + "enum": ["turnstile", "hcaptcha"], + "nullable": true + }, "security_captcha_secret": { "type": "string", "nullable": true }, "security_manual_linking_enabled": { "type": "boolean", "nullable": true }, + "security_refresh_token_reuse_interval": { "type": "integer", "nullable": true }, "security_update_password_require_reauthentication": { "type": "boolean", "nullable": true }, + "sessions_inactivity_timeout": { "type": "integer", "nullable": true }, "sessions_single_per_user": { "type": "boolean", "nullable": true }, "sessions_tags": { "type": "string", "nullable": true }, + "sessions_timebox": { "type": "integer", "nullable": true }, "site_url": { "type": "string", "nullable": true }, "sms_autoconfirm": { "type": "boolean", "nullable": true }, + "sms_max_frequency": { "type": "integer", "nullable": true }, "sms_messagebird_access_key": { "type": "string", "nullable": true }, "sms_messagebird_originator": { "type": "string", "nullable": true }, - "sms_provider": { "type": "string", "nullable": true }, + "sms_otp_exp": { "type": "integer", "nullable": true }, + "sms_otp_length": { "type": "integer" }, + "sms_provider": { + "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], + "nullable": true + }, "sms_template": { "type": "string", "nullable": true }, "sms_test_otp": { "type": "string", "nullable": true }, - "sms_test_otp_valid_until": { "type": "string", "nullable": true }, + "sms_test_otp_valid_until": { "type": "string", "format": "date-time", "nullable": true }, "sms_textlocal_api_key": { "type": "string", "nullable": true }, "sms_textlocal_sender": { "type": "string", "nullable": true }, "sms_twilio_account_sid": { "type": "string", "nullable": true }, @@ -4233,8 +5603,9 @@ "sms_vonage_api_key": { "type": "string", "nullable": true }, "sms_vonage_api_secret": { "type": "string", "nullable": true }, "sms_vonage_from": { "type": "string", "nullable": true }, - "smtp_admin_email": { "type": "string", "nullable": true }, + "smtp_admin_email": { "type": "string", "format": "email", "nullable": true }, "smtp_host": { "type": "string", "nullable": true }, + "smtp_max_frequency": { "type": "integer", "nullable": true }, "smtp_pass": { "type": "string", "nullable": true }, "smtp_port": { "type": "string", "nullable": true }, "smtp_sender_name": { "type": "string", "nullable": true }, @@ -4244,26 +5615,6 @@ "required": [ "api_max_request_duration", "db_max_pool_size", - "jwt_exp", - "mailer_otp_exp", - "mailer_otp_length", - "mfa_max_enrolled_factors", - "mfa_phone_otp_length", - "mfa_phone_max_frequency", - "password_min_length", - "rate_limit_anonymous_users", - "rate_limit_email_sent", - "rate_limit_sms_sent", - "rate_limit_token_refresh", - "rate_limit_verify", - "rate_limit_otp", - "security_refresh_token_reuse_interval", - "sessions_inactivity_timeout", - "sessions_timebox", - "sms_max_frequency", - "sms_otp_exp", - "sms_otp_length", - "smtp_max_frequency", "disable_signup", "external_anonymous_users_enabled", "external_apple_additional_client_ids", @@ -4332,6 +5683,7 @@ "external_workos_enabled", "external_workos_secret", "external_workos_url", + "external_web3_solana_enabled", "external_zoom_client_id", "external_zoom_enabled", "external_zoom_secret", @@ -4350,8 +5702,14 @@ "hook_send_email_enabled", "hook_send_email_uri", "hook_send_email_secrets", + "hook_before_user_created_enabled", + "hook_before_user_created_uri", + "hook_before_user_created_secrets", + "jwt_exp", "mailer_allow_unverified_email_sign_ins", "mailer_autoconfirm", + "mailer_otp_exp", + "mailer_otp_length", "mailer_secure_email_change_enabled", "mailer_subjects_confirmation", "mailer_subjects_email_change", @@ -4365,15 +5723,26 @@ "mailer_templates_magic_link_content", "mailer_templates_reauthentication_content", "mailer_templates_recovery_content", + "mfa_max_enrolled_factors", "mfa_totp_enroll_enabled", "mfa_totp_verify_enabled", "mfa_phone_enroll_enabled", "mfa_phone_verify_enabled", "mfa_web_authn_enroll_enabled", "mfa_web_authn_verify_enabled", + "mfa_phone_otp_length", "mfa_phone_template", + "mfa_phone_max_frequency", "password_hibp_enabled", + "password_min_length", "password_required_characters", + "rate_limit_anonymous_users", + "rate_limit_email_sent", + "rate_limit_sms_sent", + "rate_limit_token_refresh", + "rate_limit_verify", + "rate_limit_otp", + "rate_limit_web3", "refresh_token_rotation_enabled", "saml_enabled", "saml_external_url", @@ -4382,13 +5751,19 @@ "security_captcha_provider", "security_captcha_secret", "security_manual_linking_enabled", + "security_refresh_token_reuse_interval", "security_update_password_require_reauthentication", + "sessions_inactivity_timeout", "sessions_single_per_user", "sessions_tags", + "sessions_timebox", "site_url", "sms_autoconfirm", + "sms_max_frequency", "sms_messagebird_access_key", "sms_messagebird_originator", + "sms_otp_exp", + "sms_otp_length", "sms_provider", "sms_template", "sms_test_otp", @@ -4407,6 +5782,7 @@ "sms_vonage_from", "smtp_admin_email", "smtp_host", + "smtp_max_frequency", "smtp_pass", "smtp_port", "smtp_sender_name", @@ -4417,71 +5793,113 @@ "UpdateAuthConfigBody": { "type": "object", "properties": { - "jwt_exp": { "type": "integer", "minimum": 0, "maximum": 604800 }, - "smtp_max_frequency": { "type": "integer", "minimum": 0, "maximum": 32767 }, - "mfa_max_enrolled_factors": { "type": "integer", "minimum": 0, "maximum": 2147483647 }, - "sessions_timebox": { "type": "integer", "minimum": 0 }, - "sessions_inactivity_timeout": { "type": "integer", "minimum": 0 }, - "rate_limit_anonymous_users": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "rate_limit_email_sent": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "rate_limit_sms_sent": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "rate_limit_verify": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "rate_limit_token_refresh": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "rate_limit_otp": { "type": "integer", "minimum": 1, "maximum": 2147483647 }, - "password_min_length": { "type": "integer", "minimum": 6, "maximum": 32767 }, - "security_refresh_token_reuse_interval": { + "site_url": { "type": "string", "pattern": "^[^,]+$", "nullable": true }, + "disable_signup": { "type": "boolean", "nullable": true }, + "jwt_exp": { "type": "integer", "minimum": 0, "maximum": 604800, "nullable": true }, + "smtp_admin_email": { "type": "string", "format": "email", "nullable": true }, + "smtp_host": { "type": "string", "nullable": true }, + "smtp_port": { "type": "string", "nullable": true }, + "smtp_user": { "type": "string", "nullable": true }, + "smtp_pass": { "type": "string", "nullable": true }, + "smtp_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 32767, + "nullable": true }, - "mailer_otp_exp": { "type": "integer", "minimum": 0, "maximum": 2147483647 }, - "mailer_otp_length": { "type": "integer", "minimum": 6, "maximum": 10 }, - "sms_max_frequency": { "type": "integer", "minimum": 0, "maximum": 32767 }, - "sms_otp_exp": { "type": "integer", "minimum": 0, "maximum": 2147483647 }, - "sms_otp_length": { "type": "integer", "minimum": 0, "maximum": 32767 }, - "db_max_pool_size": { "type": "integer" }, - "api_max_request_duration": { "type": "integer" }, - "mfa_phone_max_frequency": { "type": "integer", "minimum": 0, "maximum": 32767 }, - "mfa_phone_otp_length": { "type": "integer", "minimum": 0, "maximum": 32767 }, - "site_url": { "type": "string", "pattern": "/^[^,]+$/" }, - "disable_signup": { "type": "boolean" }, - "smtp_admin_email": { "type": "string" }, - "smtp_host": { "type": "string" }, - "smtp_port": { "type": "string" }, - "smtp_user": { "type": "string" }, - "smtp_pass": { "type": "string" }, - "smtp_sender_name": { "type": "string" }, - "mailer_allow_unverified_email_sign_ins": { "type": "boolean" }, - "mailer_autoconfirm": { "type": "boolean" }, - "mailer_subjects_invite": { "type": "string" }, - "mailer_subjects_confirmation": { "type": "string" }, - "mailer_subjects_recovery": { "type": "string" }, - "mailer_subjects_email_change": { "type": "string" }, - "mailer_subjects_magic_link": { "type": "string" }, - "mailer_subjects_reauthentication": { "type": "string" }, - "mailer_templates_invite_content": { "type": "string" }, - "mailer_templates_confirmation_content": { "type": "string" }, - "mailer_templates_recovery_content": { "type": "string" }, - "mailer_templates_email_change_content": { "type": "string" }, - "mailer_templates_magic_link_content": { "type": "string" }, - "mailer_templates_reauthentication_content": { "type": "string" }, - "uri_allow_list": { "type": "string" }, - "external_anonymous_users_enabled": { "type": "boolean" }, - "external_email_enabled": { "type": "boolean" }, - "external_phone_enabled": { "type": "boolean" }, - "saml_enabled": { "type": "boolean" }, - "saml_external_url": { "type": "string", "pattern": "/^[^,]+$/" }, - "security_captcha_enabled": { "type": "boolean" }, - "security_captcha_provider": { "type": "string" }, - "security_captcha_secret": { "type": "string" }, - "sessions_single_per_user": { "type": "boolean" }, + "smtp_sender_name": { "type": "string", "nullable": true }, + "mailer_allow_unverified_email_sign_ins": { "type": "boolean", "nullable": true }, + "mailer_autoconfirm": { "type": "boolean", "nullable": true }, + "mailer_subjects_invite": { "type": "string", "nullable": true }, + "mailer_subjects_confirmation": { "type": "string", "nullable": true }, + "mailer_subjects_recovery": { "type": "string", "nullable": true }, + "mailer_subjects_email_change": { "type": "string", "nullable": true }, + "mailer_subjects_magic_link": { "type": "string", "nullable": true }, + "mailer_subjects_reauthentication": { "type": "string", "nullable": true }, + "mailer_templates_invite_content": { "type": "string", "nullable": true }, + "mailer_templates_confirmation_content": { "type": "string", "nullable": true }, + "mailer_templates_recovery_content": { "type": "string", "nullable": true }, + "mailer_templates_email_change_content": { "type": "string", "nullable": true }, + "mailer_templates_magic_link_content": { "type": "string", "nullable": true }, + "mailer_templates_reauthentication_content": { "type": "string", "nullable": true }, + "mfa_max_enrolled_factors": { + "type": "integer", + "minimum": 0, + "maximum": 2147483647, + "nullable": true + }, + "uri_allow_list": { "type": "string", "nullable": true }, + "external_anonymous_users_enabled": { "type": "boolean", "nullable": true }, + "external_email_enabled": { "type": "boolean", "nullable": true }, + "external_phone_enabled": { "type": "boolean", "nullable": true }, + "saml_enabled": { "type": "boolean", "nullable": true }, + "saml_external_url": { "type": "string", "pattern": "^[^,]+$", "nullable": true }, + "security_captcha_enabled": { "type": "boolean", "nullable": true }, + "security_captcha_provider": { + "type": "string", + "enum": ["turnstile", "hcaptcha"], + "nullable": true + }, + "security_captcha_secret": { "type": "string", "nullable": true }, + "sessions_timebox": { "type": "integer", "minimum": 0, "nullable": true }, + "sessions_inactivity_timeout": { "type": "integer", "minimum": 0, "nullable": true }, + "sessions_single_per_user": { "type": "boolean", "nullable": true }, "sessions_tags": { "type": "string", - "pattern": "/^\\s*([a-z0-9_-]+(\\s*,+\\s*)?)*\\s*$/i" + "pattern": "^\\s*([a-zA-Z0-9_-]+(\\s*,+\\s*)?)*\\s*$", + "nullable": true + }, + "rate_limit_anonymous_users": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_email_sent": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_sms_sent": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_verify": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_token_refresh": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_otp": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "mailer_secure_email_change_enabled": { "type": "boolean", "nullable": true }, + "refresh_token_rotation_enabled": { "type": "boolean", "nullable": true }, + "password_hibp_enabled": { "type": "boolean", "nullable": true }, + "password_min_length": { + "type": "integer", + "minimum": 6, + "maximum": 32767, + "nullable": true }, - "mailer_secure_email_change_enabled": { "type": "boolean" }, - "refresh_token_rotation_enabled": { "type": "boolean" }, - "password_hibp_enabled": { "type": "boolean" }, "password_required_characters": { "type": "string", "enum": [ @@ -4489,118 +5907,169 @@ "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", "" - ] + ], + "nullable": true }, - "security_manual_linking_enabled": { "type": "boolean" }, - "security_update_password_require_reauthentication": { "type": "boolean" }, - "sms_autoconfirm": { "type": "boolean" }, - "sms_provider": { "type": "string" }, - "sms_messagebird_access_key": { "type": "string" }, - "sms_messagebird_originator": { "type": "string" }, - "sms_test_otp": { "type": "string", "pattern": "/^([0-9]{1,15}=[0-9]+,?)*$/" }, - "sms_test_otp_valid_until": { "type": "string" }, - "sms_textlocal_api_key": { "type": "string" }, - "sms_textlocal_sender": { "type": "string" }, - "sms_twilio_account_sid": { "type": "string" }, - "sms_twilio_auth_token": { "type": "string" }, - "sms_twilio_content_sid": { "type": "string" }, - "sms_twilio_message_service_sid": { "type": "string" }, - "sms_twilio_verify_account_sid": { "type": "string" }, - "sms_twilio_verify_auth_token": { "type": "string" }, - "sms_twilio_verify_message_service_sid": { "type": "string" }, - "sms_vonage_api_key": { "type": "string" }, - "sms_vonage_api_secret": { "type": "string" }, - "sms_vonage_from": { "type": "string" }, - "sms_template": { "type": "string" }, - "hook_mfa_verification_attempt_enabled": { "type": "boolean" }, - "hook_mfa_verification_attempt_uri": { "type": "string" }, - "hook_mfa_verification_attempt_secrets": { "type": "string" }, - "hook_password_verification_attempt_enabled": { "type": "boolean" }, - "hook_password_verification_attempt_uri": { "type": "string" }, - "hook_password_verification_attempt_secrets": { "type": "string" }, - "hook_custom_access_token_enabled": { "type": "boolean" }, - "hook_custom_access_token_uri": { "type": "string" }, - "hook_custom_access_token_secrets": { "type": "string" }, - "hook_send_sms_enabled": { "type": "boolean" }, - "hook_send_sms_uri": { "type": "string" }, - "hook_send_sms_secrets": { "type": "string" }, - "hook_send_email_enabled": { "type": "boolean" }, - "hook_send_email_uri": { "type": "string" }, - "hook_send_email_secrets": { "type": "string" }, - "external_apple_enabled": { "type": "boolean" }, - "external_apple_client_id": { "type": "string" }, - "external_apple_secret": { "type": "string" }, - "external_apple_additional_client_ids": { "type": "string" }, - "external_azure_enabled": { "type": "boolean" }, - "external_azure_client_id": { "type": "string" }, - "external_azure_secret": { "type": "string" }, - "external_azure_url": { "type": "string" }, - "external_bitbucket_enabled": { "type": "boolean" }, - "external_bitbucket_client_id": { "type": "string" }, - "external_bitbucket_secret": { "type": "string" }, - "external_discord_enabled": { "type": "boolean" }, - "external_discord_client_id": { "type": "string" }, - "external_discord_secret": { "type": "string" }, - "external_facebook_enabled": { "type": "boolean" }, - "external_facebook_client_id": { "type": "string" }, - "external_facebook_secret": { "type": "string" }, - "external_figma_enabled": { "type": "boolean" }, - "external_figma_client_id": { "type": "string" }, - "external_figma_secret": { "type": "string" }, - "external_github_enabled": { "type": "boolean" }, - "external_github_client_id": { "type": "string" }, - "external_github_secret": { "type": "string" }, - "external_gitlab_enabled": { "type": "boolean" }, - "external_gitlab_client_id": { "type": "string" }, - "external_gitlab_secret": { "type": "string" }, - "external_gitlab_url": { "type": "string" }, - "external_google_enabled": { "type": "boolean" }, - "external_google_client_id": { "type": "string" }, - "external_google_secret": { "type": "string" }, - "external_google_additional_client_ids": { "type": "string" }, - "external_google_skip_nonce_check": { "type": "boolean" }, - "external_kakao_enabled": { "type": "boolean" }, - "external_kakao_client_id": { "type": "string" }, - "external_kakao_secret": { "type": "string" }, - "external_keycloak_enabled": { "type": "boolean" }, - "external_keycloak_client_id": { "type": "string" }, - "external_keycloak_secret": { "type": "string" }, - "external_keycloak_url": { "type": "string" }, - "external_linkedin_oidc_enabled": { "type": "boolean" }, - "external_linkedin_oidc_client_id": { "type": "string" }, - "external_linkedin_oidc_secret": { "type": "string" }, - "external_slack_oidc_enabled": { "type": "boolean" }, - "external_slack_oidc_client_id": { "type": "string" }, - "external_slack_oidc_secret": { "type": "string" }, - "external_notion_enabled": { "type": "boolean" }, - "external_notion_client_id": { "type": "string" }, - "external_notion_secret": { "type": "string" }, - "external_slack_enabled": { "type": "boolean" }, - "external_slack_client_id": { "type": "string" }, - "external_slack_secret": { "type": "string" }, - "external_spotify_enabled": { "type": "boolean" }, - "external_spotify_client_id": { "type": "string" }, - "external_spotify_secret": { "type": "string" }, - "external_twitch_enabled": { "type": "boolean" }, - "external_twitch_client_id": { "type": "string" }, - "external_twitch_secret": { "type": "string" }, - "external_twitter_enabled": { "type": "boolean" }, - "external_twitter_client_id": { "type": "string" }, - "external_twitter_secret": { "type": "string" }, - "external_workos_enabled": { "type": "boolean" }, - "external_workos_client_id": { "type": "string" }, - "external_workos_secret": { "type": "string" }, - "external_workos_url": { "type": "string" }, - "external_zoom_enabled": { "type": "boolean" }, - "external_zoom_client_id": { "type": "string" }, - "external_zoom_secret": { "type": "string" }, - "mfa_totp_enroll_enabled": { "type": "boolean" }, - "mfa_totp_verify_enabled": { "type": "boolean" }, - "mfa_web_authn_enroll_enabled": { "type": "boolean" }, - "mfa_web_authn_verify_enabled": { "type": "boolean" }, - "mfa_phone_enroll_enabled": { "type": "boolean" }, - "mfa_phone_verify_enabled": { "type": "boolean" }, - "mfa_phone_template": { "type": "string" } + "security_manual_linking_enabled": { "type": "boolean", "nullable": true }, + "security_update_password_require_reauthentication": { + "type": "boolean", + "nullable": true + }, + "security_refresh_token_reuse_interval": { + "type": "integer", + "minimum": 0, + "maximum": 2147483647, + "nullable": true + }, + "mailer_otp_exp": { "type": "integer", "minimum": 0, "maximum": 2147483647 }, + "mailer_otp_length": { "type": "integer", "minimum": 6, "maximum": 10, "nullable": true }, + "sms_autoconfirm": { "type": "boolean", "nullable": true }, + "sms_max_frequency": { + "type": "integer", + "minimum": 0, + "maximum": 32767, + "nullable": true + }, + "sms_otp_exp": { + "type": "integer", + "minimum": 0, + "maximum": 2147483647, + "nullable": true + }, + "sms_otp_length": { "type": "integer", "minimum": 0, "maximum": 32767 }, + "sms_provider": { + "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], + "nullable": true + }, + "sms_messagebird_access_key": { "type": "string", "nullable": true }, + "sms_messagebird_originator": { "type": "string", "nullable": true }, + "sms_test_otp": { + "type": "string", + "pattern": "^([0-9]{1,15}=[0-9]+,?)*$", + "nullable": true + }, + "sms_test_otp_valid_until": { "type": "string", "format": "date-time", "nullable": true }, + "sms_textlocal_api_key": { "type": "string", "nullable": true }, + "sms_textlocal_sender": { "type": "string", "nullable": true }, + "sms_twilio_account_sid": { "type": "string", "nullable": true }, + "sms_twilio_auth_token": { "type": "string", "nullable": true }, + "sms_twilio_content_sid": { "type": "string", "nullable": true }, + "sms_twilio_message_service_sid": { "type": "string", "nullable": true }, + "sms_twilio_verify_account_sid": { "type": "string", "nullable": true }, + "sms_twilio_verify_auth_token": { "type": "string", "nullable": true }, + "sms_twilio_verify_message_service_sid": { "type": "string", "nullable": true }, + "sms_vonage_api_key": { "type": "string", "nullable": true }, + "sms_vonage_api_secret": { "type": "string", "nullable": true }, + "sms_vonage_from": { "type": "string", "nullable": true }, + "sms_template": { "type": "string", "nullable": true }, + "hook_mfa_verification_attempt_enabled": { "type": "boolean", "nullable": true }, + "hook_mfa_verification_attempt_uri": { "type": "string", "nullable": true }, + "hook_mfa_verification_attempt_secrets": { "type": "string", "nullable": true }, + "hook_password_verification_attempt_enabled": { "type": "boolean", "nullable": true }, + "hook_password_verification_attempt_uri": { "type": "string", "nullable": true }, + "hook_password_verification_attempt_secrets": { "type": "string", "nullable": true }, + "hook_custom_access_token_enabled": { "type": "boolean", "nullable": true }, + "hook_custom_access_token_uri": { "type": "string", "nullable": true }, + "hook_custom_access_token_secrets": { "type": "string", "nullable": true }, + "hook_send_sms_enabled": { "type": "boolean", "nullable": true }, + "hook_send_sms_uri": { "type": "string", "nullable": true }, + "hook_send_sms_secrets": { "type": "string", "nullable": true }, + "hook_send_email_enabled": { "type": "boolean", "nullable": true }, + "hook_send_email_uri": { "type": "string", "nullable": true }, + "hook_send_email_secrets": { "type": "string", "nullable": true }, + "hook_before_user_created_enabled": { "type": "boolean", "nullable": true }, + "hook_before_user_created_uri": { "type": "string", "nullable": true }, + "hook_before_user_created_secrets": { "type": "string", "nullable": true }, + "external_apple_enabled": { "type": "boolean", "nullable": true }, + "external_apple_client_id": { "type": "string", "nullable": true }, + "external_apple_secret": { "type": "string", "nullable": true }, + "external_apple_additional_client_ids": { "type": "string", "nullable": true }, + "external_azure_enabled": { "type": "boolean", "nullable": true }, + "external_azure_client_id": { "type": "string", "nullable": true }, + "external_azure_secret": { "type": "string", "nullable": true }, + "external_azure_url": { "type": "string", "nullable": true }, + "external_bitbucket_enabled": { "type": "boolean", "nullable": true }, + "external_bitbucket_client_id": { "type": "string", "nullable": true }, + "external_bitbucket_secret": { "type": "string", "nullable": true }, + "external_discord_enabled": { "type": "boolean", "nullable": true }, + "external_discord_client_id": { "type": "string", "nullable": true }, + "external_discord_secret": { "type": "string", "nullable": true }, + "external_facebook_enabled": { "type": "boolean", "nullable": true }, + "external_facebook_client_id": { "type": "string", "nullable": true }, + "external_facebook_secret": { "type": "string", "nullable": true }, + "external_figma_enabled": { "type": "boolean", "nullable": true }, + "external_figma_client_id": { "type": "string", "nullable": true }, + "external_figma_secret": { "type": "string", "nullable": true }, + "external_github_enabled": { "type": "boolean", "nullable": true }, + "external_github_client_id": { "type": "string", "nullable": true }, + "external_github_secret": { "type": "string", "nullable": true }, + "external_gitlab_enabled": { "type": "boolean", "nullable": true }, + "external_gitlab_client_id": { "type": "string", "nullable": true }, + "external_gitlab_secret": { "type": "string", "nullable": true }, + "external_gitlab_url": { "type": "string", "nullable": true }, + "external_google_enabled": { "type": "boolean", "nullable": true }, + "external_google_client_id": { "type": "string", "nullable": true }, + "external_google_secret": { "type": "string", "nullable": true }, + "external_google_additional_client_ids": { "type": "string", "nullable": true }, + "external_google_skip_nonce_check": { "type": "boolean", "nullable": true }, + "external_kakao_enabled": { "type": "boolean", "nullable": true }, + "external_kakao_client_id": { "type": "string", "nullable": true }, + "external_kakao_secret": { "type": "string", "nullable": true }, + "external_keycloak_enabled": { "type": "boolean", "nullable": true }, + "external_keycloak_client_id": { "type": "string", "nullable": true }, + "external_keycloak_secret": { "type": "string", "nullable": true }, + "external_keycloak_url": { "type": "string", "nullable": true }, + "external_linkedin_oidc_enabled": { "type": "boolean", "nullable": true }, + "external_linkedin_oidc_client_id": { "type": "string", "nullable": true }, + "external_linkedin_oidc_secret": { "type": "string", "nullable": true }, + "external_slack_oidc_enabled": { "type": "boolean", "nullable": true }, + "external_slack_oidc_client_id": { "type": "string", "nullable": true }, + "external_slack_oidc_secret": { "type": "string", "nullable": true }, + "external_notion_enabled": { "type": "boolean", "nullable": true }, + "external_notion_client_id": { "type": "string", "nullable": true }, + "external_notion_secret": { "type": "string", "nullable": true }, + "external_slack_enabled": { "type": "boolean", "nullable": true }, + "external_slack_client_id": { "type": "string", "nullable": true }, + "external_slack_secret": { "type": "string", "nullable": true }, + "external_spotify_enabled": { "type": "boolean", "nullable": true }, + "external_spotify_client_id": { "type": "string", "nullable": true }, + "external_spotify_secret": { "type": "string", "nullable": true }, + "external_twitch_enabled": { "type": "boolean", "nullable": true }, + "external_twitch_client_id": { "type": "string", "nullable": true }, + "external_twitch_secret": { "type": "string", "nullable": true }, + "external_twitter_enabled": { "type": "boolean", "nullable": true }, + "external_twitter_client_id": { "type": "string", "nullable": true }, + "external_twitter_secret": { "type": "string", "nullable": true }, + "external_workos_enabled": { "type": "boolean", "nullable": true }, + "external_workos_client_id": { "type": "string", "nullable": true }, + "external_workos_secret": { "type": "string", "nullable": true }, + "external_workos_url": { "type": "string", "nullable": true }, + "external_web3_solana_enabled": { "type": "boolean", "nullable": true }, + "external_zoom_enabled": { "type": "boolean", "nullable": true }, + "external_zoom_client_id": { "type": "string", "nullable": true }, + "external_zoom_secret": { "type": "string", "nullable": true }, + "db_max_pool_size": { "type": "integer", "nullable": true }, + "api_max_request_duration": { "type": "integer", "nullable": true }, + "mfa_totp_enroll_enabled": { "type": "boolean", "nullable": true }, + "mfa_totp_verify_enabled": { "type": "boolean", "nullable": true }, + "mfa_web_authn_enroll_enabled": { "type": "boolean", "nullable": true }, + "mfa_web_authn_verify_enabled": { "type": "boolean", "nullable": true }, + "mfa_phone_enroll_enabled": { "type": "boolean", "nullable": true }, + "mfa_phone_verify_enabled": { "type": "boolean", "nullable": true }, + "mfa_phone_max_frequency": { + "type": "integer", + "minimum": 0, + "maximum": 32767, + "nullable": true + }, + "mfa_phone_otp_length": { + "type": "integer", + "minimum": 0, + "maximum": 32767, + "nullable": true + }, + "mfa_phone_template": { "type": "string", "nullable": true } } }, "CreateThirdPartyAuthBody": { @@ -4608,52 +6077,49 @@ "properties": { "oidc_issuer_url": { "type": "string" }, "jwks_url": { "type": "string" }, - "custom_jwks": { "type": "object" } + "custom_jwks": {} } }, "ThirdPartyAuth": { "type": "object", "properties": { - "id": { "type": "string" }, + "id": { "type": "string", "format": "uuid" }, "type": { "type": "string" }, "oidc_issuer_url": { "type": "string", "nullable": true }, "jwks_url": { "type": "string", "nullable": true }, - "custom_jwks": { "type": "object", "nullable": true }, - "resolved_jwks": { "type": "object", "nullable": true }, + "custom_jwks": { "nullable": true }, + "resolved_jwks": { "nullable": true }, "inserted_at": { "type": "string" }, "updated_at": { "type": "string" }, "resolved_at": { "type": "string", "nullable": true } }, "required": ["id", "type", "inserted_at", "updated_at"] }, - "ProjectAvailableRestoreVersion": { - "type": "object", - "properties": { - "version": { "type": "string" }, - "release_channel": { - "type": "string", - "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] - }, - "postgres_engine": { "type": "string", "enum": ["13", "14", "15", "17", "17-oriole"] } - }, - "required": ["version", "release_channel", "postgres_engine"] - }, "GetProjectAvailableRestoreVersionsResponse": { "type": "object", "properties": { "available_versions": { "type": "array", - "items": { "$ref": "#/components/schemas/ProjectAvailableRestoreVersion" } + "items": { + "type": "object", + "properties": { + "version": { "type": "string" }, + "release_channel": { + "type": "string", + "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] + }, + "postgres_engine": { + "type": "string", + "enum": ["13", "14", "15", "17", "17-oriole"] + } + }, + "required": ["version", "release_channel", "postgres_engine"] + } } }, "required": ["available_versions"] }, - "RestoreProjectBodyDto": { - "type": "object", - "properties": {}, - "hideDefinitions": ["release_channel", "postgres_engine"] - }, - "ListProjectAddonsResponseDto": { + "ListProjectAddonsResponse": { "type": "object", "properties": { "selected_addons": { @@ -4690,7 +6156,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { "type": "string", "enum": ["cd_default"] }, @@ -4712,17 +6186,7 @@ }, "required": ["description", "type", "interval", "amount"] }, - "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { "type": "number" }, - { "type": "boolean" }, - { "type": "string" }, - { "type": "array", "items": { "type": "string" } } - ] - } - } + "meta": { "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] } @@ -4767,7 +6231,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { "type": "string", "enum": ["cd_default"] }, @@ -4789,17 +6261,7 @@ }, "required": ["description", "type", "interval", "amount"] }, - "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { "type": "number" }, - { "type": "boolean" }, - { "type": "string" }, - { "type": "array", "items": { "type": "string" } } - ] - } - } + "meta": { "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] } @@ -4811,7 +6273,7 @@ }, "required": ["selected_addons", "available_addons"] }, - "ApplyProjectAddonBodyDto": { + "ApplyProjectAddonBody": { "type": "object", "properties": { "addon_variant": { @@ -4828,7 +6290,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { "type": "string", "enum": ["cd_default"] }, @@ -4851,34 +6321,142 @@ }, "required": ["addon_variant", "addon_type"] }, - "V1AnalyticsResponse": { + "ProjectClaimTokenResponse": { "type": "object", "properties": { + "token_alias": { "type": "string" }, + "expires_at": { "type": "string" }, + "created_at": { "type": "string" }, + "created_by": { "type": "string", "format": "uuid" } + }, + "required": ["token_alias", "expires_at", "created_at", "created_by"] + }, + "CreateProjectClaimTokenResponse": { + "type": "object", + "properties": { + "token": { "type": "string" }, + "token_alias": { "type": "string" }, + "expires_at": { "type": "string" }, + "created_at": { "type": "string" }, + "created_by": { "type": "string", "format": "uuid" } + }, + "required": ["token", "token_alias", "expires_at", "created_at", "created_by"] + }, + "V1ProjectAdvisorsResponse": { + "type": "object", + "properties": { + "lints": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "enum": [ + "unindexed_foreign_keys", + "auth_users_exposed", + "auth_rls_initplan", + "no_primary_key", + "unused_index", + "multiple_permissive_policies", + "policy_exists_rls_disabled", + "rls_enabled_no_policy", + "duplicate_index", + "security_definer_view", + "function_search_path_mutable", + "rls_disabled_in_public", + "extension_in_public", + "rls_references_user_metadata", + "materialized_view_in_api", + "foreign_table_in_api", + "unsupported_reg_types", + "auth_otp_long_expiry", + "auth_otp_short_length", + "ssl_not_enforced", + "network_restrictions_not_set", + "password_requirements_min_length", + "pitr_not_enabled", + "auth_leaked_password_protection", + "auth_insufficient_mfa_options", + "auth_password_policy_missing", + "leaked_service_key", + "no_backup_admin" + ] + }, + "title": { "type": "string" }, + "level": { "type": "string", "enum": ["ERROR", "WARN", "INFO"] }, + "facing": { "type": "string", "enum": ["EXTERNAL"] }, + "categories": { + "type": "array", + "items": { "type": "string", "enum": ["PERFORMANCE", "SECURITY"] } + }, + "description": { "type": "string" }, + "detail": { "type": "string" }, + "remediation": { "type": "string" }, + "metadata": { + "type": "object", + "properties": { + "schema": { "type": "string" }, + "name": { "type": "string" }, + "entity": { "type": "string" }, + "type": { + "type": "string", + "enum": ["table", "view", "auth", "function", "extension", "compliance"] + }, + "fkey_name": { "type": "string" }, + "fkey_columns": { "type": "array", "items": { "type": "number" } } + } + }, + "cache_key": { "type": "string" } + }, + "required": [ + "name", + "title", + "level", + "facing", + "categories", + "description", + "detail", + "remediation", + "cache_key" + ] + } + } + }, + "required": ["lints"] + }, + "AnalyticsResponse": { + "type": "object", + "properties": { + "result": { "type": "array", "items": {} }, "error": { "oneOf": [ + { "type": "string" }, { + "type": "object", "properties": { "code": { "type": "number" }, "errors": { "type": "array", "items": { + "type": "object", "properties": { "domain": { "type": "string" }, "location": { "type": "string" }, "locationType": { "type": "string" }, "message": { "type": "string" }, "reason": { "type": "string" } - } + }, + "required": ["domain", "location", "locationType", "message", "reason"] } }, "message": { "type": "string" }, "status": { "type": "string" } - } - }, - { "type": "string" } + }, + "required": ["code", "errors", "message", "status"] + } ] - }, - "result": { "type": "array", "items": { "type": "object" } } + } } }, "V1ListMigrationsResponse": { @@ -4892,12 +6470,31 @@ "required": ["version"] } }, - "V1RunQueryBody": { + "V1CreateMigrationBody": { "type": "object", - "properties": { "query": { "type": "string", "minLength": 1 } }, + "properties": { + "query": { "type": "string", "minLength": 1 }, + "name": { "type": "string" } + }, "required": ["query"] }, - "GetProjectDbMetadataResponseDto": { + "V1UpsertMigrationBody": { + "type": "object", + "properties": { + "query": { "type": "string", "minLength": 1 }, + "name": { "type": "string" } + }, + "required": ["query"] + }, + "V1RunQueryBody": { + "type": "object", + "properties": { + "query": { "type": "string", "minLength": 1 }, + "read_only": { "type": "boolean" } + }, + "required": ["query"] + }, + "GetProjectDbMetadataResponse": { "type": "object", "properties": { "databases": { @@ -4931,12 +6528,13 @@ "name": { "type": "string" }, "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, "version": { "type": "integer" }, - "created_at": { "type": "integer" }, - "updated_at": { "type": "integer" }, + "created_at": { "type": "integer", "format": "int64" }, + "updated_at": { "type": "integer", "format": "int64" }, "verify_jwt": { "type": "boolean" }, "import_map": { "type": "boolean" }, "entrypoint_path": { "type": "string" }, - "import_map_path": { "type": "string" } + "import_map_path": { "type": "string" }, + "ezbr_sha256": { "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] }, @@ -4951,20 +6549,24 @@ "required": ["slug", "name", "body"] }, "BulkUpdateFunctionBody": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "slug": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" }, - "name": { "type": "string" }, - "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, - "version": { "type": "integer" }, - "created_at": { "type": "integer" }, - "verify_jwt": { "type": "boolean" }, - "import_map": { "type": "boolean" }, - "entrypoint_path": { "type": "string" }, - "import_map_path": { "type": "string" } - }, - "required": ["id", "slug", "name", "status", "version"] + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "slug": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" }, + "name": { "type": "string" }, + "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, + "version": { "type": "integer" }, + "created_at": { "type": "integer", "format": "int64" }, + "verify_jwt": { "type": "boolean" }, + "import_map": { "type": "boolean" }, + "entrypoint_path": { "type": "string" }, + "import_map_path": { "type": "string" }, + "ezbr_sha256": { "type": "string" } + }, + "required": ["id", "slug", "name", "status", "version"] + } }, "BulkUpdateFunctionResponse": { "type": "object", @@ -4979,12 +6581,13 @@ "name": { "type": "string" }, "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, "version": { "type": "integer" }, - "created_at": { "type": "integer" }, - "updated_at": { "type": "integer" }, + "created_at": { "type": "integer", "format": "int64" }, + "updated_at": { "type": "integer", "format": "int64" }, "verify_jwt": { "type": "boolean" }, "import_map": { "type": "boolean" }, "entrypoint_path": { "type": "string" }, - "import_map_path": { "type": "string" } + "import_map_path": { "type": "string" }, + "ezbr_sha256": { "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] } @@ -5018,12 +6621,13 @@ "name": { "type": "string" }, "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, "version": { "type": "integer" }, - "created_at": { "type": "integer" }, - "updated_at": { "type": "integer" }, + "created_at": { "type": "integer", "format": "int64" }, + "updated_at": { "type": "integer", "format": "int64" }, "verify_jwt": { "type": "boolean" }, "import_map": { "type": "boolean" }, "entrypoint_path": { "type": "string" }, - "import_map_path": { "type": "string" } + "import_map_path": { "type": "string" }, + "ezbr_sha256": { "type": "string" } }, "required": ["id", "slug", "name", "status", "version"] }, @@ -5035,15 +6639,17 @@ "name": { "type": "string" }, "status": { "type": "string", "enum": ["ACTIVE", "REMOVED", "THROTTLED"] }, "version": { "type": "integer" }, - "created_at": { "type": "integer" }, - "updated_at": { "type": "integer" }, + "created_at": { "type": "integer", "format": "int64" }, + "updated_at": { "type": "integer", "format": "int64" }, "verify_jwt": { "type": "boolean" }, "import_map": { "type": "boolean" }, "entrypoint_path": { "type": "string" }, - "import_map_path": { "type": "string" } + "import_map_path": { "type": "string" }, + "ezbr_sha256": { "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] }, + "StreamableFile": { "type": "object", "properties": {} }, "V1UpdateFunctionBody": { "type": "object", "properties": { @@ -5064,32 +6670,6 @@ }, "required": ["id", "name", "owner", "created_at", "updated_at", "public"] }, - "AttributeValue": { - "type": "object", - "properties": { - "default": { - "oneOf": [ - { "type": "object" }, - { "type": "number" }, - { "type": "string" }, - { "type": "boolean" } - ] - }, - "name": { "type": "string" }, - "names": { "type": "array", "items": { "type": "string" } }, - "array": { "type": "boolean" } - } - }, - "AttributeMapping": { - "type": "object", - "properties": { - "keys": { - "type": "object", - "additionalProperties": { "$ref": "#/components/schemas/AttributeValue" } - } - }, - "required": ["keys"] - }, "CreateProviderBody": { "type": "object", "properties": { @@ -5101,48 +6681,86 @@ "metadata_xml": { "type": "string" }, "metadata_url": { "type": "string" }, "domains": { "type": "array", "items": { "type": "string" } }, - "attribute_mapping": { "$ref": "#/components/schemas/AttributeMapping" } + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } }, "required": ["type"] }, - "SamlDescriptor": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "entity_id": { "type": "string" }, - "metadata_url": { "type": "string" }, - "metadata_xml": { "type": "string" }, - "attribute_mapping": { "$ref": "#/components/schemas/AttributeMapping" } - }, - "required": ["id", "entity_id"] - }, - "Domain": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "domain": { "type": "string" }, - "created_at": { "type": "string" }, - "updated_at": { "type": "string" } - }, - "required": ["id"] - }, "CreateProviderResponse": { "type": "object", "properties": { "id": { "type": "string" }, - "saml": { "$ref": "#/components/schemas/SamlDescriptor" }, - "domains": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } }, - "created_at": { "type": "string" }, - "updated_at": { "type": "string" } - }, - "required": ["id"] - }, - "Provider": { - "type": "object", - "properties": { - "id": { "type": "string" }, - "saml": { "$ref": "#/components/schemas/SamlDescriptor" }, - "domains": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } }, + "saml": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "entity_id": { "type": "string" }, + "metadata_url": { "type": "string" }, + "metadata_xml": { "type": "string" }, + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } + }, + "required": ["id", "entity_id"] + }, + "domains": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "domain": { "type": "string" }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, @@ -5151,7 +6769,66 @@ "ListProvidersResponse": { "type": "object", "properties": { - "items": { "type": "array", "items": { "$ref": "#/components/schemas/Provider" } } + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "saml": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "entity_id": { "type": "string" }, + "metadata_url": { "type": "string" }, + "metadata_xml": { "type": "string" }, + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } + }, + "required": ["id", "entity_id"] + }, + "domains": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "domain": { "type": "string" }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + } }, "required": ["items"] }, @@ -5159,8 +6836,54 @@ "type": "object", "properties": { "id": { "type": "string" }, - "saml": { "$ref": "#/components/schemas/SamlDescriptor" }, - "domains": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } }, + "saml": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "entity_id": { "type": "string" }, + "metadata_url": { "type": "string" }, + "metadata_xml": { "type": "string" }, + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } + }, + "required": ["id", "entity_id"] + }, + "domains": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "domain": { "type": "string" }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, @@ -5172,15 +6895,85 @@ "metadata_xml": { "type": "string" }, "metadata_url": { "type": "string" }, "domains": { "type": "array", "items": { "type": "string" } }, - "attribute_mapping": { "$ref": "#/components/schemas/AttributeMapping" } + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } } }, "UpdateProviderResponse": { "type": "object", "properties": { "id": { "type": "string" }, - "saml": { "$ref": "#/components/schemas/SamlDescriptor" }, - "domains": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } }, + "saml": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "entity_id": { "type": "string" }, + "metadata_url": { "type": "string" }, + "metadata_xml": { "type": "string" }, + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } + }, + "required": ["id", "entity_id"] + }, + "domains": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "domain": { "type": "string" }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, @@ -5190,40 +6983,87 @@ "type": "object", "properties": { "id": { "type": "string" }, - "saml": { "$ref": "#/components/schemas/SamlDescriptor" }, - "domains": { "type": "array", "items": { "$ref": "#/components/schemas/Domain" } }, + "saml": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "entity_id": { "type": "string" }, + "metadata_url": { "type": "string" }, + "metadata_xml": { "type": "string" }, + "attribute_mapping": { + "type": "object", + "properties": { + "keys": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "names": { "type": "array", "items": { "type": "string" } }, + "default": { + "oneOf": [ + { "type": "object", "properties": {} }, + { "type": "number" }, + { "type": "string" }, + { "type": "boolean" } + ] + }, + "array": { "type": "boolean" } + } + } + } + }, + "required": ["keys"] + } + }, + "required": ["id", "entity_id"] + }, + "domains": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "domain": { "type": "string" }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" } + }, + "required": ["id"] + } + }, "created_at": { "type": "string" }, "updated_at": { "type": "string" } }, "required": ["id"] }, - "V1Backup": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": ["COMPLETED", "FAILED", "PENDING", "REMOVED", "ARCHIVED", "CANCELLED"] - }, - "is_physical_backup": { "type": "boolean" }, - "inserted_at": { "type": "string" } - }, - "required": ["status", "is_physical_backup", "inserted_at"] - }, - "V1PhysicalBackup": { - "type": "object", - "properties": { - "earliest_physical_backup_date_unix": { "type": "integer", "format": "int64" }, - "latest_physical_backup_date_unix": { "type": "integer", "format": "int64" } - } - }, "V1BackupsResponse": { "type": "object", "properties": { "region": { "type": "string" }, "walg_enabled": { "type": "boolean" }, "pitr_enabled": { "type": "boolean" }, - "backups": { "type": "array", "items": { "$ref": "#/components/schemas/V1Backup" } }, - "physical_backup_data": { "$ref": "#/components/schemas/V1PhysicalBackup" } + "backups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "is_physical_backup": { "type": "boolean" }, + "status": { + "type": "string", + "enum": ["COMPLETED", "FAILED", "PENDING", "REMOVED", "ARCHIVED", "CANCELLED"] + }, + "inserted_at": { "type": "string" } + }, + "required": ["is_physical_backup", "status", "inserted_at"] + } + }, + "physical_backup_data": { + "type": "object", + "properties": { + "earliest_physical_backup_date_unix": { "type": "integer" }, + "latest_physical_backup_date_unix": { "type": "integer" } + } + } }, "required": ["region", "walg_enabled", "pitr_enabled", "backups", "physical_backup_data"] }, @@ -5234,6 +7074,24 @@ }, "required": ["recovery_time_target_unix"] }, + "V1RestorePointPostBody": { + "type": "object", + "properties": { "name": { "type": "string", "maxLength": 20 } }, + "required": ["name"] + }, + "V1RestorePointResponse": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "status": { "type": "string", "enum": ["AVAILABLE", "PENDING", "REMOVED"] } + }, + "required": ["name", "status"] + }, + "V1UndoBody": { + "type": "object", + "properties": { "name": { "type": "string", "maxLength": 20 } }, + "required": ["name"] + }, "V1OrganizationMemberResponse": { "type": "object", "properties": { @@ -5245,27 +7103,106 @@ }, "required": ["user_id", "user_name", "role_name", "mfa_enabled"] }, - "BillingPlanId": { "type": "string", "enum": ["free", "pro", "team", "enterprise"] }, - "ReleaseChannel": { - "type": "string", - "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] - }, "V1OrganizationSlugResponse": { "type": "object", "properties": { - "plan": { "$ref": "#/components/schemas/BillingPlanId" }, + "id": { "type": "string" }, + "name": { "type": "string" }, + "plan": { "type": "string", "enum": ["free", "pro", "team", "enterprise"] }, "opt_in_tags": { "type": "array", - "items": { "type": "string", "enum": ["AI_SQL_GENERATOR_OPT_IN"] } + "items": { + "type": "string", + "enum": [ + "AI_SQL_GENERATOR_OPT_IN", + "AI_DATA_GENERATOR_OPT_IN", + "AI_LOG_GENERATOR_OPT_IN" + ] + } }, "allowed_release_channels": { "type": "array", - "items": { "$ref": "#/components/schemas/ReleaseChannel" } - }, - "id": { "type": "string" }, - "name": { "type": "string" } + "items": { + "type": "string", + "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] + } + } }, - "required": ["opt_in_tags", "allowed_release_channels", "id", "name"] + "required": ["id", "name", "opt_in_tags", "allowed_release_channels"] + }, + "OrganizationProjectClaimResponse": { + "type": "object", + "properties": { + "project": { + "type": "object", + "properties": { "ref": { "type": "string" }, "name": { "type": "string" } }, + "required": ["ref", "name"] + }, + "preview": { + "type": "object", + "properties": { + "valid": { "type": "boolean" }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { "key": { "type": "string" }, "message": { "type": "string" } }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { "key": { "type": "string" }, "message": { "type": "string" } }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { "key": { "type": "string" }, "message": { "type": "string" } }, + "required": ["key", "message"] + } + }, + "members_exceeding_free_project_limit": { + "type": "array", + "items": { + "type": "object", + "properties": { "name": { "type": "string" }, "limit": { "type": "number" } }, + "required": ["name", "limit"] + } + }, + "target_organization_eligible": { "type": "boolean", "nullable": true }, + "target_organization_has_free_project_slots": { "type": "boolean", "nullable": true }, + "source_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"] + }, + "target_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"], + "nullable": true + } + }, + "required": [ + "valid", + "warnings", + "errors", + "info", + "members_exceeding_free_project_limit", + "target_organization_eligible", + "target_organization_has_free_project_slots", + "source_subscription_plan", + "target_subscription_plan" + ] + }, + "expires_at": { "type": "string" }, + "created_at": { "type": "string" }, + "created_by": { "type": "string", "format": "uuid" } + }, + "required": ["project", "preview", "expires_at", "created_at", "created_by"] } } } diff --git a/apps/docs/spec/common-api-sections.json b/apps/docs/spec/common-api-sections.json index c2549bc3b09..733b6ffb814 100644 --- a/apps/docs/spec/common-api-sections.json +++ b/apps/docs/spec/common-api-sections.json @@ -6,6 +6,48 @@ "type": "markdown", "items": [] }, + { + "type": "category", + "title": "Advisors", + "items": [ + { + "id": "v1-get-performance-advisors", + "title": "Get performance advisors", + "slug": "v1-get-performance-advisors", + "type": "operation" + }, + { + "id": "v1-get-security-advisors", + "title": "Get security advisors", + "slug": "v1-get-security-advisors", + "type": "operation" + } + ] + }, + { + "type": "category", + "title": "Analytics", + "items": [ + { + "id": "v1-get-project-logs", + "title": "Get project logs", + "slug": "v1-get-project-logs", + "type": "operation" + }, + { + "id": "v1-get-project-usage-api-count", + "title": "Get project usage api count", + "slug": "v1-get-project-usage-api-count", + "type": "operation" + }, + { + "id": "v1-get-project-usage-request-count", + "title": "Get project usage request count", + "slug": "v1-get-project-usage-request-count", + "type": "operation" + } + ] + }, { "type": "category", "title": "Auth", @@ -16,12 +58,36 @@ "slug": "v1-create-a-sso-provider", "type": "operation" }, + { + "id": "v1-create-legacy-signing-key", + "title": "Create legacy signing key", + "slug": "v1-create-legacy-signing-key", + "type": "operation" + }, + { + "id": "v1-create-project-signing-key", + "title": "Create project signing key", + "slug": "v1-create-project-signing-key", + "type": "operation" + }, + { + "id": "v1-create-project-tpa-integration", + "title": "Create project tpa integration", + "slug": "v1-create-project-tpa-integration", + "type": "operation" + }, { "id": "v1-delete-a-sso-provider", "title": "Delete a sso provider", "slug": "v1-delete-a-sso-provider", "type": "operation" }, + { + "id": "v1-delete-project-tpa-integration", + "title": "Delete project tpa integration", + "slug": "v1-delete-project-tpa-integration", + "type": "operation" + }, { "id": "v1-get-a-sso-provider", "title": "Get a sso provider", @@ -34,12 +100,48 @@ "slug": "v1-get-auth-service-config", "type": "operation" }, + { + "id": "v1-get-legacy-signing-key", + "title": "Get legacy signing key", + "slug": "v1-get-legacy-signing-key", + "type": "operation" + }, + { + "id": "v1-get-project-signing-key", + "title": "Get project signing key", + "slug": "v1-get-project-signing-key", + "type": "operation" + }, + { + "id": "v1-get-project-signing-keys", + "title": "Get project signing keys", + "slug": "v1-get-project-signing-keys", + "type": "operation" + }, + { + "id": "v1-get-project-tpa-integration", + "title": "Get project tpa integration", + "slug": "v1-get-project-tpa-integration", + "type": "operation" + }, { "id": "v1-list-all-sso-provider", "title": "List all sso provider", "slug": "v1-list-all-sso-provider", "type": "operation" }, + { + "id": "v1-list-project-tpa-integrations", + "title": "List project tpa integrations", + "slug": "v1-list-project-tpa-integrations", + "type": "operation" + }, + { + "id": "v1-remove-project-signing-key", + "title": "Remove project signing key", + "slug": "v1-remove-project-signing-key", + "type": "operation" + }, { "id": "v1-update-a-sso-provider", "title": "Update a sso provider", @@ -51,6 +153,36 @@ "title": "Update auth service config", "slug": "v1-update-auth-service-config", "type": "operation" + }, + { + "id": "v1-update-project-signing-key", + "title": "Update project signing key", + "slug": "v1-update-project-signing-key", + "type": "operation" + } + ] + }, + { + "type": "category", + "title": "Billing", + "items": [ + { + "id": "v1-apply-project-addon", + "title": "Apply project addon", + "slug": "v1-apply-project-addon", + "type": "operation" + }, + { + "id": "v1-list-project-addons", + "title": "List project addons", + "slug": "v1-list-project-addons", + "type": "operation" + }, + { + "id": "v1-remove-project-addon", + "title": "Remove project addon", + "slug": "v1-remove-project-addon", + "type": "operation" } ] }, @@ -64,6 +196,12 @@ "slug": "v1-apply-a-migration", "type": "operation" }, + { + "id": "v1-create-restore-point", + "title": "Create restore point", + "slug": "v1-create-restore-point", + "type": "operation" + }, { "id": "v1-disable-readonly-mode-temporarily", "title": "Disable readonly mode temporarily", @@ -88,6 +226,18 @@ "slug": "v1-get-a-snippet", "type": "operation" }, + { + "id": "v1-get-database-metadata", + "title": "Get database metadata", + "slug": "v1-get-database-metadata", + "type": "operation" + }, + { + "id": "v1-get-pooler-config", + "title": "Get pooler config", + "slug": "v1-get-pooler-config", + "type": "operation" + }, { "id": "v1-get-postgres-config", "title": "Get postgres config", @@ -106,6 +256,12 @@ "slug": "v1-get-readonly-mode-status", "type": "operation" }, + { + "id": "v1-get-restore-point", + "title": "Get restore point", + "slug": "v1-get-restore-point", + "type": "operation" + }, { "id": "v1-get-ssl-enforcement-config", "title": "Get ssl enforcement config", @@ -125,9 +281,9 @@ "type": "operation" }, { - "id": "v1-list-migrations", - "title": "List migrations", - "slug": "v1-list-migrations", + "id": "v1-list-migration-history", + "title": "List migration history", + "slug": "v1-list-migration-history", "type": "operation" }, { @@ -154,6 +310,18 @@ "slug": "v1-setup-a-read-replica", "type": "operation" }, + { + "id": "v1-undo", + "title": "Undo", + "slug": "v1-undo", + "type": "operation" + }, + { + "id": "v1-update-pooler-config", + "title": "Update pooler config", + "slug": "v1-update-pooler-config", + "type": "operation" + }, { "id": "v1-update-postgres-config", "title": "Update postgres config", @@ -165,6 +333,12 @@ "title": "Update ssl enforcement config", "slug": "v1-update-ssl-enforcement-config", "type": "operation" + }, + { + "id": "v1-upsert-a-migration", + "title": "Upsert a migration", + "slug": "v1-upsert-a-migration", + "type": "operation" } ] }, @@ -292,12 +466,24 @@ "slug": "v1-delete-a-branch", "type": "operation" }, + { + "id": "v1-diff-a-branch", + "title": "Diff a branch", + "slug": "v1-diff-a-branch", + "type": "operation" + }, { "id": "v1-disable-preview-branching", "title": "Disable preview branching", "slug": "v1-disable-preview-branching", "type": "operation" }, + { + "id": "v1-get-a-branch", + "title": "Get a branch", + "slug": "v1-get-a-branch", + "type": "operation" + }, { "id": "v1-get-a-branch-config", "title": "Get a branch config", @@ -352,6 +538,12 @@ "slug": "v1-exchange-oauth-token", "type": "operation" }, + { + "id": "v1-oauth-authorize-project-claim", + "title": "Oauth authorize project claim", + "slug": "v1-oauth-authorize-project-claim", + "type": "operation" + }, { "id": "v1-revoke-token", "title": "Revoke token", @@ -364,6 +556,12 @@ "type": "category", "title": "Organizations", "items": [ + { + "id": "v1-claim-project-for-organization", + "title": "Claim project for organization", + "slug": "v1-claim-project-for-organization", + "type": "operation" + }, { "id": "v1-create-an-organization", "title": "Create an organization", @@ -376,6 +574,12 @@ "slug": "v1-get-an-organization", "type": "operation" }, + { + "id": "v1-get-organization-project-claim", + "title": "Get organization project claim", + "slug": "v1-get-organization-project-claim", + "type": "operation" + }, { "id": "v1-list-all-organizations", "title": "List all organizations", @@ -406,6 +610,12 @@ "slug": "v1-create-a-project", "type": "operation" }, + { + "id": "v1-create-project-claim-token", + "title": "Create project claim token", + "slug": "v1-create-project-claim-token", + "type": "operation" + }, { "id": "v1-delete-a-project", "title": "Delete a project", @@ -418,6 +628,12 @@ "slug": "v1-delete-network-bans", "type": "operation" }, + { + "id": "v1-delete-project-claim-token", + "title": "Delete project claim token", + "slug": "v1-delete-project-claim-token", + "type": "operation" + }, { "id": "v1-get-network-restrictions", "title": "Get network restrictions", @@ -442,6 +658,12 @@ "slug": "v1-get-project", "type": "operation" }, + { + "id": "v1-get-project-claim-token", + "title": "Get project claim token", + "slug": "v1-get-project-claim-token", + "type": "operation" + }, { "id": "v1-get-services-health", "title": "Get services health", @@ -454,6 +676,12 @@ "slug": "v1-list-all-network-bans", "type": "operation" }, + { + "id": "v1-list-all-network-bans-enriched", + "title": "List all network bans enriched", + "slug": "v1-list-all-network-bans-enriched", + "type": "operation" + }, { "id": "v1-list-all-projects", "title": "List all projects", @@ -526,18 +754,42 @@ "slug": "v1-bulk-delete-secrets", "type": "operation" }, + { + "id": "v1-create-project-api-key", + "title": "Create project api key", + "slug": "v1-create-project-api-key", + "type": "operation" + }, + { + "id": "v1-delete-project-api-key", + "title": "Delete project api key", + "slug": "v1-delete-project-api-key", + "type": "operation" + }, { "id": "v1-get-pgsodium-config", "title": "Get pgsodium config", "slug": "v1-get-pgsodium-config", "type": "operation" }, + { + "id": "v1-get-project-api-key", + "title": "Get project api key", + "slug": "v1-get-project-api-key", + "type": "operation" + }, { "id": "v1-get-project-api-keys", "title": "Get project api keys", "slug": "v1-get-project-api-keys", "type": "operation" }, + { + "id": "v1-get-project-legacy-api-keys", + "title": "Get project legacy api keys", + "slug": "v1-get-project-legacy-api-keys", + "type": "operation" + }, { "id": "v1-list-all-secrets", "title": "List all secrets", @@ -549,6 +801,18 @@ "title": "Update pgsodium config", "slug": "v1-update-pgsodium-config", "type": "operation" + }, + { + "id": "v1-update-project-api-key", + "title": "Update project api key", + "slug": "v1-update-project-api-key", + "type": "operation" + }, + { + "id": "v1-update-project-legacy-api-keys", + "title": "Update project legacy api keys", + "slug": "v1-update-project-legacy-api-keys", + "type": "operation" } ] }, diff --git a/apps/docs/spec/transforms/api_v1_openapi_deparsed.json b/apps/docs/spec/transforms/api_v1_openapi_deparsed.json index 9815cec79d5..3231de60004 100644 --- a/apps/docs/spec/transforms/api_v1_openapi_deparsed.json +++ b/apps/docs/spec/transforms/api_v1_openapi_deparsed.json @@ -8,10 +8,22 @@ }, "servers": [], "tags": [ + { + "name": "Advisors", + "description": "Advisors related endpoints" + }, + { + "name": "Analytics", + "description": "Analytics related endpoints" + }, { "name": "Auth", "description": "Auth related endpoints" }, + { + "name": "Billing", + "description": "Billing related endpoints" + }, { "name": "Database", "description": "Database related endpoints" @@ -64,7 +76,9 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } @@ -113,7 +127,9 @@ "type": "string" }, "db_port": { - "type": "number" + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true }, "db_user": { "type": "string" @@ -158,7 +174,9 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } @@ -194,6 +212,9 @@ "FUNCTIONS_DEPLOYED", "FUNCTIONS_FAILED" ] + }, + "request_review": { + "type": "boolean" } } } @@ -209,7 +230,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "name": { "type": "string" @@ -250,10 +272,16 @@ ] }, "created_at": { - "type": "string" + "type": "string", + "format": "date-time" }, "updated_at": { - "type": "string" + "type": "string", + "format": "date-time" + }, + "review_requested_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -291,7 +319,9 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } @@ -336,11 +366,28 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "migration_version": { + "type": "string" + } + } + } + } + } + }, "responses": { "201": { "description": "", @@ -384,11 +431,28 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "migration_version": { + "type": "string" + } + } + } + } + } + }, "responses": { "201": { "description": "", @@ -432,11 +496,28 @@ "name": "branch_id", "required": true, "in": "path", + "description": "Branch ID", "schema": { + "format": "uuid", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "migration_version": { + "type": "string" + } + } + } + } + } + }, "responses": { "201": { "description": "", @@ -470,6 +551,54 @@ ] } }, + "/v1/branches/{branch_id}/diff": { + "get": { + "operationId": "v1-diff-a-branch", + "summary": "[Beta] Diffs a database branch", + "description": "Diffs the specified database branch", + "parameters": [ + { + "name": "branch_id", + "required": true, + "in": "path", + "description": "Branch ID", + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "name": "included_schemas", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "" + }, + "500": { + "description": "Failed to diff database branch" + } + }, + "tags": ["Environments"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/projects": { "get": { "operationId": "v1-list-all-projects", @@ -590,6 +719,7 @@ }, "name": { "type": "string", + "maxLength": 256, "description": "Name of your project" }, "organization_id": { @@ -634,6 +764,8 @@ "desired_instance_size": { "type": "string", "enum": [ + "pico", + "nano", "micro", "small", "medium", @@ -643,7 +775,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "template_url": { @@ -824,16 +964,33 @@ "summary": "[Beta] Authorize user through oauth", "parameters": [ { - "name": "code_challenge_method", - "required": false, + "name": "client_id", + "required": true, "in": "query", "schema": { - "enum": ["plain", "sha256", "S256"], + "format": "uuid", "type": "string" } }, { - "name": "code_challenge", + "name": "response_type", + "required": true, + "in": "query", + "schema": { + "enum": ["code", "token", "id_token token"], + "type": "string" + } + }, + { + "name": "redirect_uri", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "scope", "required": false, "in": "query", "schema": { @@ -849,32 +1006,43 @@ } }, { - "name": "response_type", - "required": true, + "name": "response_mode", + "required": false, "in": "query", "schema": { "type": "string" } }, { - "name": "redirect_uri", - "required": true, + "name": "code_challenge", + "required": false, "in": "query", "schema": { "type": "string" } }, { - "name": "client_id", - "required": true, + "name": "code_challenge_method", + "required": false, "in": "query", "schema": { + "enum": ["plain", "sha256", "S256"], + "type": "string" + } + }, + { + "name": "organization_slug", + "required": false, + "in": "query", + "description": "Organization slug", + "schema": { + "pattern": "^[\\w-]+$", "type": "string" } } ], "responses": { - "303": { + "204": { "description": "" } }, @@ -1006,11 +1174,115 @@ ] } }, + "/v1/oauth/authorize/project-claim": { + "get": { + "operationId": "v1-oauth-authorize-project-claim", + "x-internal": true, + "summary": "Authorize user through oauth and claim a project", + "description": "Initiates the OAuth authorization flow for the specified provider. After successful authentication, the user can claim ownership of the specified project.", + "parameters": [ + { + "name": "project_ref", + "required": true, + "in": "query", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "client_id", + "required": true, + "in": "query", + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "name": "response_type", + "required": true, + "in": "query", + "schema": { + "enum": ["code", "token", "id_token token"], + "type": "string" + } + }, + { + "name": "redirect_uri", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "state", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "response_mode", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "code_challenge", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "code_challenge_method", + "required": false, + "in": "query", + "schema": { + "enum": ["plain", "sha256", "S256"], + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "" + } + }, + "tags": ["OAuth"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/snippets": { "get": { "operationId": "v1-list-all-snippets", "summary": "Lists SQL snippets for the logged in user", "parameters": [ + { + "name": "project_ref", + "required": false, + "in": "query", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, { "name": "cursor", "required": false, @@ -1046,14 +1318,6 @@ "enum": ["asc", "desc"], "type": "string" } - }, - { - "name": "project_ref", - "required": false, - "in": "query", - "schema": { - "type": "string" - } } ], "responses": { @@ -1097,8 +1361,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "name": { "type": "string" @@ -1110,8 +1373,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -1123,8 +1385,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -1205,8 +1466,8 @@ "enum": ["sql"] }, "visibility": { - "enum": ["user", "project", "org", "public"], - "type": "string" + "type": "string", + "enum": ["user", "project", "org", "public"] }, "name": { "type": "string" @@ -1219,8 +1480,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "name": { "type": "string" @@ -1232,8 +1492,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -1245,8 +1504,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -1304,21 +1562,26 @@ "operationId": "v1-get-project-api-keys", "summary": "Get project api keys", "parameters": [ - { - "name": "reveal", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, { "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -1331,11 +1594,9 @@ "items": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -1343,13 +1604,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -1380,7 +1644,7 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] } } } @@ -1398,24 +1662,29 @@ ] }, "post": { - "operationId": "createApiKey", - "summary": "[Alpha] Creates a new API key for the project", + "operationId": "v1-create-project-api-key", + "summary": "Creates a new API key for the project", "parameters": [ - { - "name": "reveal", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, { "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } + }, + { + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } } ], "requestBody": { @@ -1429,6 +1698,12 @@ "type": "string", "enum": ["publishable", "secret"] }, + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true @@ -1445,7 +1720,7 @@ "nullable": true } }, - "required": ["type"] + "required": ["type", "name"] } } } @@ -1458,11 +1733,9 @@ "schema": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -1470,13 +1743,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -1507,7 +1783,108 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Secrets"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/api-keys/legacy": { + "get": { + "operationId": "v1-get-project-legacy-api-keys", + "summary": "Check whether JWT based legacy (anon, service_role) API keys are enabled. This API endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Secrets"], + "security": [ + { + "bearer": [] + } + ] + }, + "put": { + "operationId": "v1-update-project-legacy-api-keys", + "summary": "Disable or re-enable JWT based legacy (anon, service_role) API keys. This API endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "enabled", + "required": true, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] } } } @@ -1526,15 +1903,19 @@ }, "/v1/projects/{ref}/api-keys/{id}": { "patch": { - "operationId": "updateApiKey", - "summary": "[Alpha] Updates an API key for the project", + "operationId": "v1-update-project-api-key", + "summary": "Updates an API key for the project", "parameters": [ { - "name": "reveal", - "required": false, - "in": "query", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", "schema": { - "type": "boolean" + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" } }, { @@ -1542,15 +1923,17 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, { - "name": "ref", - "required": true, - "in": "path", + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", "schema": { - "type": "string" + "type": "boolean" } } ], @@ -1561,6 +1944,12 @@ "schema": { "type": "object", "properties": { + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true @@ -1589,11 +1978,9 @@ "schema": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -1601,13 +1988,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -1638,7 +2028,7 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] } } } @@ -1655,15 +2045,19 @@ ] }, "get": { - "operationId": "getApiKey", - "summary": "[Alpha] Get API key", + "operationId": "v1-get-project-api-key", + "summary": "Get API key", "parameters": [ { - "name": "reveal", - "required": false, - "in": "query", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", "schema": { - "type": "boolean" + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" } }, { @@ -1671,15 +2065,17 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, { - "name": "ref", - "required": true, - "in": "path", + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", "schema": { - "type": "string" + "type": "boolean" } } ], @@ -1691,11 +2087,9 @@ "schema": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -1703,13 +2097,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -1740,7 +2137,7 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] } } } @@ -1757,15 +2154,19 @@ ] }, "delete": { - "operationId": "deleteApiKey", - "summary": "[Alpha] Deletes an API key for the project", + "operationId": "v1-delete-project-api-key", + "summary": "Deletes an API key for the project", "parameters": [ { - "name": "reveal", - "required": false, - "in": "query", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", "schema": { - "type": "boolean" + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" } }, { @@ -1773,13 +2174,32 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, { - "name": "ref", - "required": true, - "in": "path", + "name": "reveal", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "was_compromised", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "reason", + "required": false, + "in": "query", "schema": { "type": "string" } @@ -1793,11 +2213,9 @@ "schema": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -1805,13 +2223,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -1842,7 +2263,7 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] } } } @@ -1869,7 +2290,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -1885,7 +2310,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "name": { "type": "string" @@ -1926,10 +2352,16 @@ ] }, "created_at": { - "type": "string" + "type": "string", + "format": "date-time" }, "updated_at": { - "type": "string" + "type": "string", + "format": "date-time" + }, + "review_requested_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -1971,7 +2403,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -1990,6 +2426,9 @@ "git_branch": { "type": "string" }, + "is_default": { + "type": "boolean" + }, "persistent": { "type": "boolean" }, @@ -2010,7 +2449,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "release_channel": { @@ -2020,7 +2467,7 @@ }, "postgres_engine": { "type": "string", - "enum": ["15", "17-oriole"], + "enum": ["15", "17", "17-oriole"], "description": "Postgres engine version. If not provided, the latest version will be used." }, "secrets": { @@ -2028,6 +2475,9 @@ "additionalProperties": { "type": "string" } + }, + "with_data": { + "type": "boolean" } }, "required": ["branch_name"] @@ -2044,7 +2494,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "name": { "type": "string" @@ -2085,10 +2536,16 @@ ] }, "created_at": { - "type": "string" + "type": "string", + "format": "date-time" }, "updated_at": { - "type": "string" + "type": "string", + "format": "date-time" + }, + "review_requested_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -2129,7 +2586,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2153,6 +2614,126 @@ ] } }, + "/v1/projects/{ref}/branches/{name}": { + "get": { + "operationId": "v1-get-a-branch", + "summary": "Get a database branch", + "description": "Fetches the specified database branch by its name.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "name", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "project_ref": { + "type": "string" + }, + "parent_project_ref": { + "type": "string" + }, + "is_default": { + "type": "boolean" + }, + "git_branch": { + "type": "string" + }, + "pr_number": { + "type": "integer", + "format": "int32" + }, + "latest_check_run_id": { + "type": "number", + "description": "This field is deprecated and will not be populated.", + "deprecated": true + }, + "persistent": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": [ + "CREATING_PROJECT", + "RUNNING_MIGRATIONS", + "MIGRATIONS_PASSED", + "MIGRATIONS_FAILED", + "FUNCTIONS_DEPLOYED", + "FUNCTIONS_FAILED" + ] + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "review_requested_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "id", + "name", + "project_ref", + "parent_project_ref", + "is_default", + "persistent", + "status", + "created_at", + "updated_at" + ] + } + } + } + }, + "403": { + "description": "" + }, + "500": { + "description": "Failed to fetch database branch" + } + }, + "tags": ["Environments"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/projects/{ref}/custom-hostname": { "get": { "operationId": "v1-get-hostname-config", @@ -2166,6 +2747,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2179,14 +2761,14 @@ "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" @@ -2200,13 +2782,13 @@ "errors": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "messages": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "result": { @@ -2326,6 +2908,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2362,6 +2945,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2391,14 +2975,14 @@ "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" @@ -2412,13 +2996,13 @@ "errors": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "messages": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "result": { @@ -2540,6 +3124,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2553,14 +3138,14 @@ "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" @@ -2574,13 +3159,13 @@ "errors": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "messages": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "result": { @@ -2702,6 +3287,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2715,14 +3301,14 @@ "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" @@ -2736,13 +3322,13 @@ "errors": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "messages": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "result": { @@ -2860,7 +3446,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2900,6 +3490,71 @@ ] } }, + "/v1/projects/{ref}/network-bans/retrieve/enriched": { + "post": { + "operationId": "v1-list-all-network-bans-enriched", + "summary": "[Beta] Gets project's network bans with additional information about which databases they affect", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "banned_ipv4_addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "banned_address": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["banned_address", "identifier", "type"] + } + } + }, + "required": ["banned_ipv4_addresses"] + } + } + } + }, + "403": { + "description": "" + }, + "500": { + "description": "Failed to retrieve project's enriched network bans" + } + }, + "tags": ["Projects"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/projects/{ref}/network-bans": { "delete": { "operationId": "v1-delete-network-bans", @@ -2909,7 +3564,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -2926,6 +3585,9 @@ "items": { "type": "string" } + }, + "identifier": { + "type": "string" } }, "required": ["ipv4_addresses"] @@ -2961,7 +3623,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3048,7 +3714,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3159,7 +3829,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3203,7 +3877,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3267,6 +3945,9 @@ "in": "path", "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3326,6 +4007,9 @@ "in": "path", "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3414,6 +4098,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3530,6 +4215,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3543,8 +4229,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "integer" }, "ref": { "type": "string" @@ -3580,7 +4265,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3634,7 +4323,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3693,7 +4386,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3713,14 +4410,7 @@ }, "responses": { "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } + "description": "" }, "403": { "description": "" @@ -3746,7 +4436,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3799,7 +4493,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3886,7 +4584,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3932,7 +4634,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -3980,7 +4686,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4013,7 +4723,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4075,7 +4789,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4137,7 +4855,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4203,7 +4925,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4236,7 +4962,7 @@ "properties": { "postgres_version": { "type": "string", - "enum": ["15", "17-oriole"] + "enum": ["15", "17", "17-oriole"] }, "release_channel": { "type": "string", @@ -4249,12 +4975,6 @@ "required": ["postgres_version", "release_channel", "app_version"] } }, - "potential_breaking_changes": { - "type": "array", - "items": { - "type": "string" - } - }, "duration_estimate_hours": { "type": "number" }, @@ -4264,7 +4984,19 @@ "type": "string" } }, - "extension_dependent_objects": { + "objects_to_be_dropped": { + "type": "array", + "items": { + "type": "string" + } + }, + "unsupported_extensions": { + "type": "array", + "items": { + "type": "string" + } + }, + "user_defined_objects_in_internal_schemas": { "type": "array", "items": { "type": "string" @@ -4277,10 +5009,11 @@ "current_app_version_release_channel", "latest_app_version", "target_upgrade_versions", - "potential_breaking_changes", "duration_estimate_hours", "legacy_auth_custom_roles", - "extension_dependent_objects" + "objects_to_be_dropped", + "unsupported_extensions", + "user_defined_objects_in_internal_schemas" ] } } @@ -4307,17 +5040,21 @@ "summary": "[Beta] Gets the latest status of the project's upgrade", "parameters": [ { - "name": "tracking_id", - "required": false, - "in": "query", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, { - "name": "ref", - "required": true, - "in": "path", + "name": "tracking_id", + "required": false, + "in": "query", "schema": { "type": "string" } @@ -4414,6 +5151,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4469,6 +5207,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4501,7 +5240,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4572,7 +5315,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4625,19 +5372,10 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, - { - "name": "timeout_ms", - "required": false, - "in": "query", - "schema": { - "minimum": 0, - "maximum": 10000, - "type": "integer" - } - }, { "name": "services", "required": true, @@ -4649,6 +5387,16 @@ "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"] } } + }, + { + "name": "timeout_ms", + "required": false, + "in": "query", + "schema": { + "minimum": 0, + "maximum": 10000, + "type": "integer" + } } ], "responses": { @@ -4661,6 +5409,17 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"] + }, + "healthy": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"] + }, "info": { "oneOf": [ { @@ -4669,32 +5428,33 @@ "name": { "type": "string", "enum": ["GoTrue"] + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" } }, - "required": ["name"] + "required": ["name", "version", "description"] }, { "type": "object", "properties": { + "healthy": { + "type": "boolean" + }, + "db_connected": { + "type": "boolean" + }, "connected_cluster": { "type": "integer" } }, - "required": ["connected_cluster"] + "required": ["healthy", "db_connected", "connected_cluster"] } ] }, - "name": { - "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"], - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "status": { - "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"], - "type": "string" - }, "error": { "type": "string" } @@ -4720,16 +5480,154 @@ ] } }, - "/v1/projects/{ref}/config/auth/signing-keys": { + "/v1/projects/{ref}/config/auth/signing-keys/legacy": { "post": { - "operationId": "createSigningKeyForProject", - "summary": "[Alpha] Create a new signing key for the project in standby status", + "operationId": "v1-create-legacy-signing-key", + "summary": "Set up the project's existing JWT secret as an in_use JWT signing key. This endpoint will be removed in the future always check for HTTP 404 Not Found.", "parameters": [ { "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "algorithm": { + "type": "string", + "enum": ["EdDSA", "ES256", "RS256", "HS256"] + }, + "status": { + "type": "string", + "enum": ["in_use", "previously_used", "revoked", "standby"] + }, + "public_jwk": { + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "required": ["id", "algorithm", "status", "created_at", "updated_at"], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Auth"], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "v1-get-legacy-signing-key", + "summary": "Get the signing key information for the JWT secret imported as signing key for this project. This endpoint will be removed in the future, check for HTTP 404 Not Found.", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "algorithm": { + "type": "string", + "enum": ["EdDSA", "ES256", "RS256", "HS256"] + }, + "status": { + "type": "string", + "enum": ["in_use", "previously_used", "revoked", "standby"] + }, + "public_jwk": { + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "required": ["id", "algorithm", "status", "created_at", "updated_at"], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Auth"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/config/auth/signing-keys": { + "post": { + "operationId": "v1-create-project-signing-key", + "summary": "Create a new signing key for the project in standby status", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4748,6 +5646,109 @@ "status": { "type": "string", "enum": ["in_use", "standby"] + }, + "private_jwk": { + "discriminator": { + "propertyName": "kty" + }, + "oneOf": [ + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["RSA"] + }, + "n": { + "type": "string" + }, + "e": { + "type": "string", + "enum": ["AQAB"] + }, + "d": { + "type": "string" + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "qi": { + "type": "string" + } + }, + "required": ["kty", "n", "e", "d", "p", "q", "dp", "dq", "qi"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["EC"] + }, + "crv": { + "type": "string", + "enum": ["P-256"] + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "d": { + "type": "string" + } + }, + "required": ["kty", "crv", "x", "y", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["OKP"] + }, + "crv": { + "type": "string", + "enum": ["Ed25519"] + }, + "x": { + "type": "string" + }, + "d": { + "type": "string" + } + }, + "required": ["kty", "crv", "x", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["oct"] + }, + "k": { + "type": "string", + "minLength": 16 + } + }, + "required": ["kty", "k"], + "additionalProperties": false + } + ] } }, "required": ["algorithm"], @@ -4758,22 +5759,37 @@ }, "responses": { "201": { - "description": "[Alpha] Create a new signing key for the project in standby status", + "description": "", "content": { "application/json": { "schema": { "type": "object", "properties": { + "id": { + "type": "string", + "format": "uuid" + }, "algorithm": { "type": "string", "enum": ["EdDSA", "ES256", "RS256", "HS256"] }, "status": { "type": "string", - "enum": ["in_use", "standby"] + "enum": ["in_use", "previously_used", "revoked", "standby"] + }, + "public_jwk": { + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" } }, - "required": ["algorithm"], + "required": ["id", "algorithm", "status", "created_at", "updated_at"], "additionalProperties": false } } @@ -4791,14 +5807,18 @@ ] }, "get": { - "operationId": "listSigningKeysForProject", - "summary": "[Alpha] List all signing keys for the project", + "operationId": "v1-get-project-signing-keys", + "summary": "List all signing keys for the project", "parameters": [ { "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4865,14 +5885,15 @@ }, "/v1/projects/{ref}/config/auth/signing-keys/{id}": { "get": { - "operationId": "getSigningKeyForProject", - "summary": "[Alpha] Get information about a signing key", + "operationId": "v1-get-project-signing-key", + "summary": "Get information about a signing key", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, @@ -4880,7 +5901,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -4935,14 +5960,15 @@ ] }, "delete": { - "operationId": "deleteSigningKey", - "summary": "[Alpha] Remove a signing key from a project, where the status is previously_used", + "operationId": "v1-remove-project-signing-key", + "summary": "Remove a signing key from a project. Only possible if the key has been in revoked status for a while.", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, @@ -4950,7 +5976,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5005,14 +6035,15 @@ ] }, "patch": { - "operationId": "patchSigningKey", - "summary": "[Alpha] Update a signing key, mainly its status", + "operationId": "v1-update-project-signing-key", + "summary": "Update a signing key, mainly its status", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } }, @@ -5020,7 +6051,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5106,6 +6141,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5142,6 +6178,15 @@ } }, "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] } }, "required": ["imageTransformation", "s3Protocol"] @@ -5178,6 +6223,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5192,7 +6238,7 @@ "fileSizeLimit": { "type": "integer", "minimum": 0, - "maximum": 53687091200, + "maximum": 536870912000, "format": "int64" }, "features": { @@ -5215,6 +6261,15 @@ } }, "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] } }, "required": ["imageTransformation", "s3Protocol"] @@ -5256,6 +6311,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5328,6 +6384,10 @@ "minimum": 0, "maximum": 262143 }, + "session_replication_role": { + "type": "string", + "enum": ["origin", "replica", "local"] + }, "shared_buffers": { "type": "string" }, @@ -5345,10 +6405,6 @@ }, "work_mem": { "type": "string" - }, - "session_replication_role": { - "enum": ["origin", "replica", "local"], - "type": "string" } } } @@ -5381,6 +6437,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5452,6 +6509,10 @@ "minimum": 0, "maximum": 262143 }, + "session_replication_role": { + "type": "string", + "enum": ["origin", "replica", "local"] + }, "shared_buffers": { "type": "string" }, @@ -5472,10 +6533,6 @@ }, "restart_database": { "type": "boolean" - }, - "session_replication_role": { - "enum": ["origin", "replica", "local"], - "type": "string" } } } @@ -5550,6 +6607,10 @@ "minimum": 0, "maximum": 262143 }, + "session_replication_role": { + "type": "string", + "enum": ["origin", "replica", "local"] + }, "shared_buffers": { "type": "string" }, @@ -5567,10 +6628,6 @@ }, "work_mem": { "type": "string" - }, - "session_replication_role": { - "enum": ["origin", "replica", "local"], - "type": "string" } } } @@ -5605,6 +6662,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5617,21 +6675,33 @@ "schema": { "type": "object", "properties": { - "pool_mode": { - "type": "string", - "enum": ["transaction", "session", "statement"] - }, "default_pool_size": { - "type": "number" + "type": "integer" }, "ignore_startup_parameters": { "type": "string" }, "max_client_conn": { - "type": "number" + "type": "integer" + }, + "pool_mode": { + "type": "string", + "enum": ["transaction", "session", "statement"] }, "connection_string": { "type": "string" + }, + "server_idle_timeout": { + "type": "integer" + }, + "server_lifetime": { + "type": "integer" + }, + "query_wait_timeout": { + "type": "integer" + }, + "reserve_pool_size": { + "type": "integer" } } } @@ -5650,7 +6720,7 @@ }, "/v1/projects/{ref}/config/database/pooler": { "get": { - "operationId": "getSupavisorConfig", + "operationId": "v1-get-pooler-config", "summary": "Gets project's supavisor config", "parameters": [ { @@ -5661,6 +6731,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5675,16 +6746,33 @@ "items": { "type": "object", "properties": { + "identifier": { + "type": "string" + }, "database_type": { "type": "string", "enum": ["PRIMARY", "READ_REPLICA"] }, + "is_using_scram_auth": { + "type": "boolean" + }, + "db_user": { + "type": "string" + }, + "db_host": { + "type": "string" + }, "db_port": { "type": "integer" }, + "db_name": { + "type": "string" + }, + "connection_string": { + "type": "string" + }, "connectionString": { "type": "string", - "deprecated": true, "description": "Use connection_string instead" }, "default_pool_size": { @@ -5696,41 +6784,23 @@ "nullable": true }, "pool_mode": { - "enum": ["transaction", "session"], - "type": "string" - }, - "identifier": { - "type": "string" - }, - "is_using_scram_auth": { - "type": "boolean" - }, - "db_user": { - "type": "string" - }, - "db_host": { - "type": "string" - }, - "db_name": { - "type": "string" - }, - "connection_string": { - "type": "string" + "type": "string", + "enum": ["transaction", "session"] } }, "required": [ - "database_type", - "db_port", - "connectionString", - "default_pool_size", - "max_client_conn", - "pool_mode", "identifier", + "database_type", "is_using_scram_auth", "db_user", "db_host", + "db_port", "db_name", - "connection_string" + "connection_string", + "connectionString", + "default_pool_size", + "max_client_conn", + "pool_mode" ] } } @@ -5749,7 +6819,7 @@ ] }, "patch": { - "operationId": "updateSupavisorConfig", + "operationId": "v1-update-pooler-config", "summary": "Updates project's supavisor config", "parameters": [ { @@ -5760,6 +6830,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5773,15 +6844,14 @@ "properties": { "default_pool_size": { "type": "integer", - "nullable": true, "minimum": 0, - "maximum": 1000 + "maximum": 3000, + "nullable": true }, "pool_mode": { - "enum": ["transaction", "session"], "type": "string", - "description": "Dedicated pooler mode for the project", - "deprecated": true + "enum": ["transaction", "session"], + "description": "Dedicated pooler mode for the project" } } } @@ -5837,6 +6907,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -5857,83 +6928,6 @@ "type": "integer", "nullable": true }, - "jwt_exp": { - "type": "integer", - "nullable": true - }, - "mailer_otp_exp": { - "type": "integer" - }, - "mailer_otp_length": { - "type": "integer", - "nullable": true - }, - "mfa_max_enrolled_factors": { - "type": "integer", - "nullable": true - }, - "mfa_phone_otp_length": { - "type": "integer" - }, - "mfa_phone_max_frequency": { - "type": "integer", - "nullable": true - }, - "password_min_length": { - "type": "integer", - "nullable": true - }, - "rate_limit_anonymous_users": { - "type": "integer", - "nullable": true - }, - "rate_limit_email_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_sms_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_token_refresh": { - "type": "integer", - "nullable": true - }, - "rate_limit_verify": { - "type": "integer", - "nullable": true - }, - "rate_limit_otp": { - "type": "integer", - "nullable": true - }, - "security_refresh_token_reuse_interval": { - "type": "integer", - "nullable": true - }, - "sessions_inactivity_timeout": { - "type": "integer", - "nullable": true - }, - "sessions_timebox": { - "type": "integer", - "nullable": true - }, - "sms_max_frequency": { - "type": "integer", - "nullable": true - }, - "sms_otp_exp": { - "type": "integer", - "nullable": true - }, - "sms_otp_length": { - "type": "integer" - }, - "smtp_max_frequency": { - "type": "integer", - "nullable": true - }, "disable_signup": { "type": "boolean", "nullable": true @@ -6206,6 +7200,10 @@ "type": "string", "nullable": true }, + "external_web3_solana_enabled": { + "type": "boolean", + "nullable": true + }, "external_zoom_client_id": { "type": "string", "nullable": true @@ -6278,6 +7276,22 @@ "type": "string", "nullable": true }, + "hook_before_user_created_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_before_user_created_uri": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_secrets": { + "type": "string", + "nullable": true + }, + "jwt_exp": { + "type": "integer", + "nullable": true + }, "mailer_allow_unverified_email_sign_ins": { "type": "boolean", "nullable": true @@ -6286,6 +7300,13 @@ "type": "boolean", "nullable": true }, + "mailer_otp_exp": { + "type": "integer" + }, + "mailer_otp_length": { + "type": "integer", + "nullable": true + }, "mailer_secure_email_change_enabled": { "type": "boolean", "nullable": true @@ -6338,6 +7359,10 @@ "type": "string", "nullable": true }, + "mfa_max_enrolled_factors": { + "type": "integer", + "nullable": true + }, "mfa_totp_enroll_enabled": { "type": "boolean", "nullable": true @@ -6362,16 +7387,61 @@ "type": "boolean", "nullable": true }, + "mfa_phone_otp_length": { + "type": "integer" + }, "mfa_phone_template": { "type": "string", "nullable": true }, + "mfa_phone_max_frequency": { + "type": "integer", + "nullable": true + }, "password_hibp_enabled": { "type": "boolean", "nullable": true }, + "password_min_length": { + "type": "integer", + "nullable": true + }, "password_required_characters": { "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "rate_limit_anonymous_users": { + "type": "integer", + "nullable": true + }, + "rate_limit_email_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_sms_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_token_refresh": { + "type": "integer", + "nullable": true + }, + "rate_limit_verify": { + "type": "integer", + "nullable": true + }, + "rate_limit_otp": { + "type": "integer", + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", "nullable": true }, "refresh_token_rotation_enabled": { @@ -6396,6 +7466,7 @@ }, "security_captcha_provider": { "type": "string", + "enum": ["turnstile", "hcaptcha"], "nullable": true }, "security_captcha_secret": { @@ -6406,10 +7477,18 @@ "type": "boolean", "nullable": true }, + "security_refresh_token_reuse_interval": { + "type": "integer", + "nullable": true + }, "security_update_password_require_reauthentication": { "type": "boolean", "nullable": true }, + "sessions_inactivity_timeout": { + "type": "integer", + "nullable": true + }, "sessions_single_per_user": { "type": "boolean", "nullable": true @@ -6418,6 +7497,10 @@ "type": "string", "nullable": true }, + "sessions_timebox": { + "type": "integer", + "nullable": true + }, "site_url": { "type": "string", "nullable": true @@ -6426,6 +7509,10 @@ "type": "boolean", "nullable": true }, + "sms_max_frequency": { + "type": "integer", + "nullable": true + }, "sms_messagebird_access_key": { "type": "string", "nullable": true @@ -6434,8 +7521,16 @@ "type": "string", "nullable": true }, + "sms_otp_exp": { + "type": "integer", + "nullable": true + }, + "sms_otp_length": { + "type": "integer" + }, "sms_provider": { "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], "nullable": true }, "sms_template": { @@ -6448,6 +7543,7 @@ }, "sms_test_otp_valid_until": { "type": "string", + "format": "date-time", "nullable": true }, "sms_textlocal_api_key": { @@ -6500,12 +7596,17 @@ }, "smtp_admin_email": { "type": "string", + "format": "email", "nullable": true }, "smtp_host": { "type": "string", "nullable": true }, + "smtp_max_frequency": { + "type": "integer", + "nullable": true + }, "smtp_pass": { "type": "string", "nullable": true @@ -6530,26 +7631,6 @@ "required": [ "api_max_request_duration", "db_max_pool_size", - "jwt_exp", - "mailer_otp_exp", - "mailer_otp_length", - "mfa_max_enrolled_factors", - "mfa_phone_otp_length", - "mfa_phone_max_frequency", - "password_min_length", - "rate_limit_anonymous_users", - "rate_limit_email_sent", - "rate_limit_sms_sent", - "rate_limit_token_refresh", - "rate_limit_verify", - "rate_limit_otp", - "security_refresh_token_reuse_interval", - "sessions_inactivity_timeout", - "sessions_timebox", - "sms_max_frequency", - "sms_otp_exp", - "sms_otp_length", - "smtp_max_frequency", "disable_signup", "external_anonymous_users_enabled", "external_apple_additional_client_ids", @@ -6618,6 +7699,7 @@ "external_workos_enabled", "external_workos_secret", "external_workos_url", + "external_web3_solana_enabled", "external_zoom_client_id", "external_zoom_enabled", "external_zoom_secret", @@ -6636,8 +7718,14 @@ "hook_send_email_enabled", "hook_send_email_uri", "hook_send_email_secrets", + "hook_before_user_created_enabled", + "hook_before_user_created_uri", + "hook_before_user_created_secrets", + "jwt_exp", "mailer_allow_unverified_email_sign_ins", "mailer_autoconfirm", + "mailer_otp_exp", + "mailer_otp_length", "mailer_secure_email_change_enabled", "mailer_subjects_confirmation", "mailer_subjects_email_change", @@ -6651,15 +7739,26 @@ "mailer_templates_magic_link_content", "mailer_templates_reauthentication_content", "mailer_templates_recovery_content", + "mfa_max_enrolled_factors", "mfa_totp_enroll_enabled", "mfa_totp_verify_enabled", "mfa_phone_enroll_enabled", "mfa_phone_verify_enabled", "mfa_web_authn_enroll_enabled", "mfa_web_authn_verify_enabled", + "mfa_phone_otp_length", "mfa_phone_template", + "mfa_phone_max_frequency", "password_hibp_enabled", + "password_min_length", "password_required_characters", + "rate_limit_anonymous_users", + "rate_limit_email_sent", + "rate_limit_sms_sent", + "rate_limit_token_refresh", + "rate_limit_verify", + "rate_limit_otp", + "rate_limit_web3", "refresh_token_rotation_enabled", "saml_enabled", "saml_external_url", @@ -6668,13 +7767,19 @@ "security_captcha_provider", "security_captcha_secret", "security_manual_linking_enabled", + "security_refresh_token_reuse_interval", "security_update_password_require_reauthentication", + "sessions_inactivity_timeout", "sessions_single_per_user", "sessions_tags", + "sessions_timebox", "site_url", "sms_autoconfirm", + "sms_max_frequency", "sms_messagebird_access_key", "sms_messagebird_originator", + "sms_otp_exp", + "sms_otp_length", "sms_provider", "sms_template", "sms_test_otp", @@ -6693,6 +7798,7 @@ "sms_vonage_from", "smtp_admin_email", "smtp_host", + "smtp_max_frequency", "smtp_pass", "smtp_port", "smtp_sender_name", @@ -6729,6 +7835,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -6740,68 +7847,254 @@ "schema": { "type": "object", "properties": { + "site_url": { + "type": "string", + "pattern": "^[^,]+$", + "nullable": true + }, + "disable_signup": { + "type": "boolean", + "nullable": true + }, "jwt_exp": { "type": "integer", "minimum": 0, - "maximum": 604800 + "maximum": 604800, + "nullable": true + }, + "smtp_admin_email": { + "type": "string", + "format": "email", + "nullable": true + }, + "smtp_host": { + "type": "string", + "nullable": true + }, + "smtp_port": { + "type": "string", + "nullable": true + }, + "smtp_user": { + "type": "string", + "nullable": true + }, + "smtp_pass": { + "type": "string", + "nullable": true }, "smtp_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true + }, + "smtp_sender_name": { + "type": "string", + "nullable": true + }, + "mailer_allow_unverified_email_sign_ins": { + "type": "boolean", + "nullable": true + }, + "mailer_autoconfirm": { + "type": "boolean", + "nullable": true + }, + "mailer_subjects_invite": { + "type": "string", + "nullable": true + }, + "mailer_subjects_confirmation": { + "type": "string", + "nullable": true + }, + "mailer_subjects_recovery": { + "type": "string", + "nullable": true + }, + "mailer_subjects_email_change": { + "type": "string", + "nullable": true + }, + "mailer_subjects_magic_link": { + "type": "string", + "nullable": true + }, + "mailer_subjects_reauthentication": { + "type": "string", + "nullable": true + }, + "mailer_templates_invite_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_confirmation_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_recovery_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_email_change_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_magic_link_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_reauthentication_content": { + "type": "string", + "nullable": true }, "mfa_max_enrolled_factors": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true + }, + "uri_allow_list": { + "type": "string", + "nullable": true + }, + "external_anonymous_users_enabled": { + "type": "boolean", + "nullable": true + }, + "external_email_enabled": { + "type": "boolean", + "nullable": true + }, + "external_phone_enabled": { + "type": "boolean", + "nullable": true + }, + "saml_enabled": { + "type": "boolean", + "nullable": true + }, + "saml_external_url": { + "type": "string", + "pattern": "^[^,]+$", + "nullable": true + }, + "security_captcha_enabled": { + "type": "boolean", + "nullable": true + }, + "security_captcha_provider": { + "type": "string", + "enum": ["turnstile", "hcaptcha"], + "nullable": true + }, + "security_captcha_secret": { + "type": "string", + "nullable": true }, "sessions_timebox": { "type": "integer", - "minimum": 0 + "minimum": 0, + "nullable": true }, "sessions_inactivity_timeout": { "type": "integer", - "minimum": 0 + "minimum": 0, + "nullable": true + }, + "sessions_single_per_user": { + "type": "boolean", + "nullable": true + }, + "sessions_tags": { + "type": "string", + "pattern": "^\\s*([a-zA-Z0-9_-]+(\\s*,+\\s*)?)*\\s*$", + "nullable": true }, "rate_limit_anonymous_users": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_email_sent": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_sms_sent": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_verify": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_token_refresh": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_otp": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "mailer_secure_email_change_enabled": { + "type": "boolean", + "nullable": true + }, + "refresh_token_rotation_enabled": { + "type": "boolean", + "nullable": true + }, + "password_hibp_enabled": { + "type": "boolean", + "nullable": true }, "password_min_length": { "type": "integer", "minimum": 6, - "maximum": 32767 + "maximum": 32767, + "nullable": true + }, + "password_required_characters": { + "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "security_manual_linking_enabled": { + "type": "boolean", + "nullable": true + }, + "security_update_password_require_reauthentication": { + "type": "boolean", + "nullable": true }, "security_refresh_token_reuse_interval": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "mailer_otp_exp": { "type": "integer", @@ -6811,489 +8104,496 @@ "mailer_otp_length": { "type": "integer", "minimum": 6, - "maximum": 10 + "maximum": 10, + "nullable": true + }, + "sms_autoconfirm": { + "type": "boolean", + "nullable": true }, "sms_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true }, "sms_otp_exp": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "sms_otp_length": { "type": "integer", "minimum": 0, "maximum": 32767 }, + "sms_provider": { + "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], + "nullable": true + }, + "sms_messagebird_access_key": { + "type": "string", + "nullable": true + }, + "sms_messagebird_originator": { + "type": "string", + "nullable": true + }, + "sms_test_otp": { + "type": "string", + "pattern": "^([0-9]{1,15}=[0-9]+,?)*$", + "nullable": true + }, + "sms_test_otp_valid_until": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "sms_textlocal_api_key": { + "type": "string", + "nullable": true + }, + "sms_textlocal_sender": { + "type": "string", + "nullable": true + }, + "sms_twilio_account_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_auth_token": { + "type": "string", + "nullable": true + }, + "sms_twilio_content_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_message_service_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_account_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_auth_token": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_message_service_sid": { + "type": "string", + "nullable": true + }, + "sms_vonage_api_key": { + "type": "string", + "nullable": true + }, + "sms_vonage_api_secret": { + "type": "string", + "nullable": true + }, + "sms_vonage_from": { + "type": "string", + "nullable": true + }, + "sms_template": { + "type": "string", + "nullable": true + }, + "hook_mfa_verification_attempt_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_mfa_verification_attempt_uri": { + "type": "string", + "nullable": true + }, + "hook_mfa_verification_attempt_secrets": { + "type": "string", + "nullable": true + }, + "hook_password_verification_attempt_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_password_verification_attempt_uri": { + "type": "string", + "nullable": true + }, + "hook_password_verification_attempt_secrets": { + "type": "string", + "nullable": true + }, + "hook_custom_access_token_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_custom_access_token_uri": { + "type": "string", + "nullable": true + }, + "hook_custom_access_token_secrets": { + "type": "string", + "nullable": true + }, + "hook_send_sms_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_send_sms_uri": { + "type": "string", + "nullable": true + }, + "hook_send_sms_secrets": { + "type": "string", + "nullable": true + }, + "hook_send_email_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_send_email_uri": { + "type": "string", + "nullable": true + }, + "hook_send_email_secrets": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_before_user_created_uri": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_secrets": { + "type": "string", + "nullable": true + }, + "external_apple_enabled": { + "type": "boolean", + "nullable": true + }, + "external_apple_client_id": { + "type": "string", + "nullable": true + }, + "external_apple_secret": { + "type": "string", + "nullable": true + }, + "external_apple_additional_client_ids": { + "type": "string", + "nullable": true + }, + "external_azure_enabled": { + "type": "boolean", + "nullable": true + }, + "external_azure_client_id": { + "type": "string", + "nullable": true + }, + "external_azure_secret": { + "type": "string", + "nullable": true + }, + "external_azure_url": { + "type": "string", + "nullable": true + }, + "external_bitbucket_enabled": { + "type": "boolean", + "nullable": true + }, + "external_bitbucket_client_id": { + "type": "string", + "nullable": true + }, + "external_bitbucket_secret": { + "type": "string", + "nullable": true + }, + "external_discord_enabled": { + "type": "boolean", + "nullable": true + }, + "external_discord_client_id": { + "type": "string", + "nullable": true + }, + "external_discord_secret": { + "type": "string", + "nullable": true + }, + "external_facebook_enabled": { + "type": "boolean", + "nullable": true + }, + "external_facebook_client_id": { + "type": "string", + "nullable": true + }, + "external_facebook_secret": { + "type": "string", + "nullable": true + }, + "external_figma_enabled": { + "type": "boolean", + "nullable": true + }, + "external_figma_client_id": { + "type": "string", + "nullable": true + }, + "external_figma_secret": { + "type": "string", + "nullable": true + }, + "external_github_enabled": { + "type": "boolean", + "nullable": true + }, + "external_github_client_id": { + "type": "string", + "nullable": true + }, + "external_github_secret": { + "type": "string", + "nullable": true + }, + "external_gitlab_enabled": { + "type": "boolean", + "nullable": true + }, + "external_gitlab_client_id": { + "type": "string", + "nullable": true + }, + "external_gitlab_secret": { + "type": "string", + "nullable": true + }, + "external_gitlab_url": { + "type": "string", + "nullable": true + }, + "external_google_enabled": { + "type": "boolean", + "nullable": true + }, + "external_google_client_id": { + "type": "string", + "nullable": true + }, + "external_google_secret": { + "type": "string", + "nullable": true + }, + "external_google_additional_client_ids": { + "type": "string", + "nullable": true + }, + "external_google_skip_nonce_check": { + "type": "boolean", + "nullable": true + }, + "external_kakao_enabled": { + "type": "boolean", + "nullable": true + }, + "external_kakao_client_id": { + "type": "string", + "nullable": true + }, + "external_kakao_secret": { + "type": "string", + "nullable": true + }, + "external_keycloak_enabled": { + "type": "boolean", + "nullable": true + }, + "external_keycloak_client_id": { + "type": "string", + "nullable": true + }, + "external_keycloak_secret": { + "type": "string", + "nullable": true + }, + "external_keycloak_url": { + "type": "string", + "nullable": true + }, + "external_linkedin_oidc_enabled": { + "type": "boolean", + "nullable": true + }, + "external_linkedin_oidc_client_id": { + "type": "string", + "nullable": true + }, + "external_linkedin_oidc_secret": { + "type": "string", + "nullable": true + }, + "external_slack_oidc_enabled": { + "type": "boolean", + "nullable": true + }, + "external_slack_oidc_client_id": { + "type": "string", + "nullable": true + }, + "external_slack_oidc_secret": { + "type": "string", + "nullable": true + }, + "external_notion_enabled": { + "type": "boolean", + "nullable": true + }, + "external_notion_client_id": { + "type": "string", + "nullable": true + }, + "external_notion_secret": { + "type": "string", + "nullable": true + }, + "external_slack_enabled": { + "type": "boolean", + "nullable": true + }, + "external_slack_client_id": { + "type": "string", + "nullable": true + }, + "external_slack_secret": { + "type": "string", + "nullable": true + }, + "external_spotify_enabled": { + "type": "boolean", + "nullable": true + }, + "external_spotify_client_id": { + "type": "string", + "nullable": true + }, + "external_spotify_secret": { + "type": "string", + "nullable": true + }, + "external_twitch_enabled": { + "type": "boolean", + "nullable": true + }, + "external_twitch_client_id": { + "type": "string", + "nullable": true + }, + "external_twitch_secret": { + "type": "string", + "nullable": true + }, + "external_twitter_enabled": { + "type": "boolean", + "nullable": true + }, + "external_twitter_client_id": { + "type": "string", + "nullable": true + }, + "external_twitter_secret": { + "type": "string", + "nullable": true + }, + "external_workos_enabled": { + "type": "boolean", + "nullable": true + }, + "external_workos_client_id": { + "type": "string", + "nullable": true + }, + "external_workos_secret": { + "type": "string", + "nullable": true + }, + "external_workos_url": { + "type": "string", + "nullable": true + }, + "external_web3_solana_enabled": { + "type": "boolean", + "nullable": true + }, + "external_zoom_enabled": { + "type": "boolean", + "nullable": true + }, + "external_zoom_client_id": { + "type": "string", + "nullable": true + }, + "external_zoom_secret": { + "type": "string", + "nullable": true + }, "db_max_pool_size": { - "type": "integer" + "type": "integer", + "nullable": true }, "api_max_request_duration": { - "type": "integer" + "type": "integer", + "nullable": true + }, + "mfa_totp_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_totp_verify_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_web_authn_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_web_authn_verify_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_phone_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_phone_verify_enabled": { + "type": "boolean", + "nullable": true }, "mfa_phone_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true }, "mfa_phone_otp_length": { "type": "integer", "minimum": 0, - "maximum": 32767 - }, - "site_url": { - "type": "string", - "pattern": "/^[^,]+$/" - }, - "disable_signup": { - "type": "boolean" - }, - "smtp_admin_email": { - "type": "string" - }, - "smtp_host": { - "type": "string" - }, - "smtp_port": { - "type": "string" - }, - "smtp_user": { - "type": "string" - }, - "smtp_pass": { - "type": "string" - }, - "smtp_sender_name": { - "type": "string" - }, - "mailer_allow_unverified_email_sign_ins": { - "type": "boolean" - }, - "mailer_autoconfirm": { - "type": "boolean" - }, - "mailer_subjects_invite": { - "type": "string" - }, - "mailer_subjects_confirmation": { - "type": "string" - }, - "mailer_subjects_recovery": { - "type": "string" - }, - "mailer_subjects_email_change": { - "type": "string" - }, - "mailer_subjects_magic_link": { - "type": "string" - }, - "mailer_subjects_reauthentication": { - "type": "string" - }, - "mailer_templates_invite_content": { - "type": "string" - }, - "mailer_templates_confirmation_content": { - "type": "string" - }, - "mailer_templates_recovery_content": { - "type": "string" - }, - "mailer_templates_email_change_content": { - "type": "string" - }, - "mailer_templates_magic_link_content": { - "type": "string" - }, - "mailer_templates_reauthentication_content": { - "type": "string" - }, - "uri_allow_list": { - "type": "string" - }, - "external_anonymous_users_enabled": { - "type": "boolean" - }, - "external_email_enabled": { - "type": "boolean" - }, - "external_phone_enabled": { - "type": "boolean" - }, - "saml_enabled": { - "type": "boolean" - }, - "saml_external_url": { - "type": "string", - "pattern": "/^[^,]+$/" - }, - "security_captcha_enabled": { - "type": "boolean" - }, - "security_captcha_provider": { - "type": "string" - }, - "security_captcha_secret": { - "type": "string" - }, - "sessions_single_per_user": { - "type": "boolean" - }, - "sessions_tags": { - "type": "string", - "pattern": "/^\\s*([a-z0-9_-]+(\\s*,+\\s*)?)*\\s*$/i" - }, - "mailer_secure_email_change_enabled": { - "type": "boolean" - }, - "refresh_token_rotation_enabled": { - "type": "boolean" - }, - "password_hibp_enabled": { - "type": "boolean" - }, - "password_required_characters": { - "type": "string", - "enum": [ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", - "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", - "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", - "" - ] - }, - "security_manual_linking_enabled": { - "type": "boolean" - }, - "security_update_password_require_reauthentication": { - "type": "boolean" - }, - "sms_autoconfirm": { - "type": "boolean" - }, - "sms_provider": { - "type": "string" - }, - "sms_messagebird_access_key": { - "type": "string" - }, - "sms_messagebird_originator": { - "type": "string" - }, - "sms_test_otp": { - "type": "string", - "pattern": "/^([0-9]{1,15}=[0-9]+,?)*$/" - }, - "sms_test_otp_valid_until": { - "type": "string" - }, - "sms_textlocal_api_key": { - "type": "string" - }, - "sms_textlocal_sender": { - "type": "string" - }, - "sms_twilio_account_sid": { - "type": "string" - }, - "sms_twilio_auth_token": { - "type": "string" - }, - "sms_twilio_content_sid": { - "type": "string" - }, - "sms_twilio_message_service_sid": { - "type": "string" - }, - "sms_twilio_verify_account_sid": { - "type": "string" - }, - "sms_twilio_verify_auth_token": { - "type": "string" - }, - "sms_twilio_verify_message_service_sid": { - "type": "string" - }, - "sms_vonage_api_key": { - "type": "string" - }, - "sms_vonage_api_secret": { - "type": "string" - }, - "sms_vonage_from": { - "type": "string" - }, - "sms_template": { - "type": "string" - }, - "hook_mfa_verification_attempt_enabled": { - "type": "boolean" - }, - "hook_mfa_verification_attempt_uri": { - "type": "string" - }, - "hook_mfa_verification_attempt_secrets": { - "type": "string" - }, - "hook_password_verification_attempt_enabled": { - "type": "boolean" - }, - "hook_password_verification_attempt_uri": { - "type": "string" - }, - "hook_password_verification_attempt_secrets": { - "type": "string" - }, - "hook_custom_access_token_enabled": { - "type": "boolean" - }, - "hook_custom_access_token_uri": { - "type": "string" - }, - "hook_custom_access_token_secrets": { - "type": "string" - }, - "hook_send_sms_enabled": { - "type": "boolean" - }, - "hook_send_sms_uri": { - "type": "string" - }, - "hook_send_sms_secrets": { - "type": "string" - }, - "hook_send_email_enabled": { - "type": "boolean" - }, - "hook_send_email_uri": { - "type": "string" - }, - "hook_send_email_secrets": { - "type": "string" - }, - "external_apple_enabled": { - "type": "boolean" - }, - "external_apple_client_id": { - "type": "string" - }, - "external_apple_secret": { - "type": "string" - }, - "external_apple_additional_client_ids": { - "type": "string" - }, - "external_azure_enabled": { - "type": "boolean" - }, - "external_azure_client_id": { - "type": "string" - }, - "external_azure_secret": { - "type": "string" - }, - "external_azure_url": { - "type": "string" - }, - "external_bitbucket_enabled": { - "type": "boolean" - }, - "external_bitbucket_client_id": { - "type": "string" - }, - "external_bitbucket_secret": { - "type": "string" - }, - "external_discord_enabled": { - "type": "boolean" - }, - "external_discord_client_id": { - "type": "string" - }, - "external_discord_secret": { - "type": "string" - }, - "external_facebook_enabled": { - "type": "boolean" - }, - "external_facebook_client_id": { - "type": "string" - }, - "external_facebook_secret": { - "type": "string" - }, - "external_figma_enabled": { - "type": "boolean" - }, - "external_figma_client_id": { - "type": "string" - }, - "external_figma_secret": { - "type": "string" - }, - "external_github_enabled": { - "type": "boolean" - }, - "external_github_client_id": { - "type": "string" - }, - "external_github_secret": { - "type": "string" - }, - "external_gitlab_enabled": { - "type": "boolean" - }, - "external_gitlab_client_id": { - "type": "string" - }, - "external_gitlab_secret": { - "type": "string" - }, - "external_gitlab_url": { - "type": "string" - }, - "external_google_enabled": { - "type": "boolean" - }, - "external_google_client_id": { - "type": "string" - }, - "external_google_secret": { - "type": "string" - }, - "external_google_additional_client_ids": { - "type": "string" - }, - "external_google_skip_nonce_check": { - "type": "boolean" - }, - "external_kakao_enabled": { - "type": "boolean" - }, - "external_kakao_client_id": { - "type": "string" - }, - "external_kakao_secret": { - "type": "string" - }, - "external_keycloak_enabled": { - "type": "boolean" - }, - "external_keycloak_client_id": { - "type": "string" - }, - "external_keycloak_secret": { - "type": "string" - }, - "external_keycloak_url": { - "type": "string" - }, - "external_linkedin_oidc_enabled": { - "type": "boolean" - }, - "external_linkedin_oidc_client_id": { - "type": "string" - }, - "external_linkedin_oidc_secret": { - "type": "string" - }, - "external_slack_oidc_enabled": { - "type": "boolean" - }, - "external_slack_oidc_client_id": { - "type": "string" - }, - "external_slack_oidc_secret": { - "type": "string" - }, - "external_notion_enabled": { - "type": "boolean" - }, - "external_notion_client_id": { - "type": "string" - }, - "external_notion_secret": { - "type": "string" - }, - "external_slack_enabled": { - "type": "boolean" - }, - "external_slack_client_id": { - "type": "string" - }, - "external_slack_secret": { - "type": "string" - }, - "external_spotify_enabled": { - "type": "boolean" - }, - "external_spotify_client_id": { - "type": "string" - }, - "external_spotify_secret": { - "type": "string" - }, - "external_twitch_enabled": { - "type": "boolean" - }, - "external_twitch_client_id": { - "type": "string" - }, - "external_twitch_secret": { - "type": "string" - }, - "external_twitter_enabled": { - "type": "boolean" - }, - "external_twitter_client_id": { - "type": "string" - }, - "external_twitter_secret": { - "type": "string" - }, - "external_workos_enabled": { - "type": "boolean" - }, - "external_workos_client_id": { - "type": "string" - }, - "external_workos_secret": { - "type": "string" - }, - "external_workos_url": { - "type": "string" - }, - "external_zoom_enabled": { - "type": "boolean" - }, - "external_zoom_client_id": { - "type": "string" - }, - "external_zoom_secret": { - "type": "string" - }, - "mfa_totp_enroll_enabled": { - "type": "boolean" - }, - "mfa_totp_verify_enabled": { - "type": "boolean" - }, - "mfa_web_authn_enroll_enabled": { - "type": "boolean" - }, - "mfa_web_authn_verify_enabled": { - "type": "boolean" - }, - "mfa_phone_enroll_enabled": { - "type": "boolean" - }, - "mfa_phone_verify_enabled": { - "type": "boolean" + "maximum": 32767, + "nullable": true }, "mfa_phone_template": { - "type": "string" + "type": "string", + "nullable": true } } } @@ -7316,83 +8616,6 @@ "type": "integer", "nullable": true }, - "jwt_exp": { - "type": "integer", - "nullable": true - }, - "mailer_otp_exp": { - "type": "integer" - }, - "mailer_otp_length": { - "type": "integer", - "nullable": true - }, - "mfa_max_enrolled_factors": { - "type": "integer", - "nullable": true - }, - "mfa_phone_otp_length": { - "type": "integer" - }, - "mfa_phone_max_frequency": { - "type": "integer", - "nullable": true - }, - "password_min_length": { - "type": "integer", - "nullable": true - }, - "rate_limit_anonymous_users": { - "type": "integer", - "nullable": true - }, - "rate_limit_email_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_sms_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_token_refresh": { - "type": "integer", - "nullable": true - }, - "rate_limit_verify": { - "type": "integer", - "nullable": true - }, - "rate_limit_otp": { - "type": "integer", - "nullable": true - }, - "security_refresh_token_reuse_interval": { - "type": "integer", - "nullable": true - }, - "sessions_inactivity_timeout": { - "type": "integer", - "nullable": true - }, - "sessions_timebox": { - "type": "integer", - "nullable": true - }, - "sms_max_frequency": { - "type": "integer", - "nullable": true - }, - "sms_otp_exp": { - "type": "integer", - "nullable": true - }, - "sms_otp_length": { - "type": "integer" - }, - "smtp_max_frequency": { - "type": "integer", - "nullable": true - }, "disable_signup": { "type": "boolean", "nullable": true @@ -7665,6 +8888,10 @@ "type": "string", "nullable": true }, + "external_web3_solana_enabled": { + "type": "boolean", + "nullable": true + }, "external_zoom_client_id": { "type": "string", "nullable": true @@ -7737,6 +8964,22 @@ "type": "string", "nullable": true }, + "hook_before_user_created_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_before_user_created_uri": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_secrets": { + "type": "string", + "nullable": true + }, + "jwt_exp": { + "type": "integer", + "nullable": true + }, "mailer_allow_unverified_email_sign_ins": { "type": "boolean", "nullable": true @@ -7745,6 +8988,13 @@ "type": "boolean", "nullable": true }, + "mailer_otp_exp": { + "type": "integer" + }, + "mailer_otp_length": { + "type": "integer", + "nullable": true + }, "mailer_secure_email_change_enabled": { "type": "boolean", "nullable": true @@ -7797,6 +9047,10 @@ "type": "string", "nullable": true }, + "mfa_max_enrolled_factors": { + "type": "integer", + "nullable": true + }, "mfa_totp_enroll_enabled": { "type": "boolean", "nullable": true @@ -7821,16 +9075,61 @@ "type": "boolean", "nullable": true }, + "mfa_phone_otp_length": { + "type": "integer" + }, "mfa_phone_template": { "type": "string", "nullable": true }, + "mfa_phone_max_frequency": { + "type": "integer", + "nullable": true + }, "password_hibp_enabled": { "type": "boolean", "nullable": true }, + "password_min_length": { + "type": "integer", + "nullable": true + }, "password_required_characters": { "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "rate_limit_anonymous_users": { + "type": "integer", + "nullable": true + }, + "rate_limit_email_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_sms_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_token_refresh": { + "type": "integer", + "nullable": true + }, + "rate_limit_verify": { + "type": "integer", + "nullable": true + }, + "rate_limit_otp": { + "type": "integer", + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", "nullable": true }, "refresh_token_rotation_enabled": { @@ -7855,6 +9154,7 @@ }, "security_captcha_provider": { "type": "string", + "enum": ["turnstile", "hcaptcha"], "nullable": true }, "security_captcha_secret": { @@ -7865,10 +9165,18 @@ "type": "boolean", "nullable": true }, + "security_refresh_token_reuse_interval": { + "type": "integer", + "nullable": true + }, "security_update_password_require_reauthentication": { "type": "boolean", "nullable": true }, + "sessions_inactivity_timeout": { + "type": "integer", + "nullable": true + }, "sessions_single_per_user": { "type": "boolean", "nullable": true @@ -7877,6 +9185,10 @@ "type": "string", "nullable": true }, + "sessions_timebox": { + "type": "integer", + "nullable": true + }, "site_url": { "type": "string", "nullable": true @@ -7885,6 +9197,10 @@ "type": "boolean", "nullable": true }, + "sms_max_frequency": { + "type": "integer", + "nullable": true + }, "sms_messagebird_access_key": { "type": "string", "nullable": true @@ -7893,8 +9209,16 @@ "type": "string", "nullable": true }, + "sms_otp_exp": { + "type": "integer", + "nullable": true + }, + "sms_otp_length": { + "type": "integer" + }, "sms_provider": { "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], "nullable": true }, "sms_template": { @@ -7907,6 +9231,7 @@ }, "sms_test_otp_valid_until": { "type": "string", + "format": "date-time", "nullable": true }, "sms_textlocal_api_key": { @@ -7959,12 +9284,17 @@ }, "smtp_admin_email": { "type": "string", + "format": "email", "nullable": true }, "smtp_host": { "type": "string", "nullable": true }, + "smtp_max_frequency": { + "type": "integer", + "nullable": true + }, "smtp_pass": { "type": "string", "nullable": true @@ -7989,26 +9319,6 @@ "required": [ "api_max_request_duration", "db_max_pool_size", - "jwt_exp", - "mailer_otp_exp", - "mailer_otp_length", - "mfa_max_enrolled_factors", - "mfa_phone_otp_length", - "mfa_phone_max_frequency", - "password_min_length", - "rate_limit_anonymous_users", - "rate_limit_email_sent", - "rate_limit_sms_sent", - "rate_limit_token_refresh", - "rate_limit_verify", - "rate_limit_otp", - "security_refresh_token_reuse_interval", - "sessions_inactivity_timeout", - "sessions_timebox", - "sms_max_frequency", - "sms_otp_exp", - "sms_otp_length", - "smtp_max_frequency", "disable_signup", "external_anonymous_users_enabled", "external_apple_additional_client_ids", @@ -8077,6 +9387,7 @@ "external_workos_enabled", "external_workos_secret", "external_workos_url", + "external_web3_solana_enabled", "external_zoom_client_id", "external_zoom_enabled", "external_zoom_secret", @@ -8095,8 +9406,14 @@ "hook_send_email_enabled", "hook_send_email_uri", "hook_send_email_secrets", + "hook_before_user_created_enabled", + "hook_before_user_created_uri", + "hook_before_user_created_secrets", + "jwt_exp", "mailer_allow_unverified_email_sign_ins", "mailer_autoconfirm", + "mailer_otp_exp", + "mailer_otp_length", "mailer_secure_email_change_enabled", "mailer_subjects_confirmation", "mailer_subjects_email_change", @@ -8110,15 +9427,26 @@ "mailer_templates_magic_link_content", "mailer_templates_reauthentication_content", "mailer_templates_recovery_content", + "mfa_max_enrolled_factors", "mfa_totp_enroll_enabled", "mfa_totp_verify_enabled", "mfa_phone_enroll_enabled", "mfa_phone_verify_enabled", "mfa_web_authn_enroll_enabled", "mfa_web_authn_verify_enabled", + "mfa_phone_otp_length", "mfa_phone_template", + "mfa_phone_max_frequency", "password_hibp_enabled", + "password_min_length", "password_required_characters", + "rate_limit_anonymous_users", + "rate_limit_email_sent", + "rate_limit_sms_sent", + "rate_limit_token_refresh", + "rate_limit_verify", + "rate_limit_otp", + "rate_limit_web3", "refresh_token_rotation_enabled", "saml_enabled", "saml_external_url", @@ -8127,13 +9455,19 @@ "security_captcha_provider", "security_captcha_secret", "security_manual_linking_enabled", + "security_refresh_token_reuse_interval", "security_update_password_require_reauthentication", + "sessions_inactivity_timeout", "sessions_single_per_user", "sessions_tags", + "sessions_timebox", "site_url", "sms_autoconfirm", + "sms_max_frequency", "sms_messagebird_access_key", "sms_messagebird_originator", + "sms_otp_exp", + "sms_otp_length", "sms_provider", "sms_template", "sms_test_otp", @@ -8152,6 +9486,7 @@ "sms_vonage_from", "smtp_admin_email", "smtp_host", + "smtp_max_frequency", "smtp_pass", "smtp_port", "smtp_sender_name", @@ -8179,7 +9514,7 @@ }, "/v1/projects/{ref}/config/auth/third-party-auth": { "post": { - "operationId": "createTPAForProject", + "operationId": "v1-create-project-tpa-integration", "summary": "Creates a new third-party auth integration", "parameters": [ { @@ -8190,6 +9525,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8207,9 +9543,7 @@ "jwks_url": { "type": "string" }, - "custom_jwks": { - "type": "object" - } + "custom_jwks": {} } } } @@ -8224,7 +9558,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "type": { "type": "string" @@ -8238,11 +9573,9 @@ "nullable": true }, "custom_jwks": { - "type": "object", "nullable": true }, "resolved_jwks": { - "type": "object", "nullable": true }, "inserted_at": { @@ -8273,7 +9606,7 @@ ] }, "get": { - "operationId": "listTPAForProject", + "operationId": "v1-list-project-tpa-integrations", "summary": "Lists all third-party auth integrations", "parameters": [ { @@ -8284,6 +9617,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8299,7 +9633,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "type": { "type": "string" @@ -8313,11 +9648,9 @@ "nullable": true }, "custom_jwks": { - "type": "object", "nullable": true }, "resolved_jwks": { - "type": "object", "nullable": true }, "inserted_at": { @@ -8351,7 +9684,7 @@ }, "/v1/projects/{ref}/config/auth/third-party-auth/{tpa_id}": { "delete": { - "operationId": "deleteTPAForProject", + "operationId": "v1-delete-project-tpa-integration", "summary": "Removes a third-party auth integration", "parameters": [ { @@ -8362,6 +9695,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, @@ -8370,6 +9704,7 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -8383,7 +9718,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "type": { "type": "string" @@ -8397,11 +9733,9 @@ "nullable": true }, "custom_jwks": { - "type": "object", "nullable": true }, "resolved_jwks": { - "type": "object", "nullable": true }, "inserted_at": { @@ -8432,7 +9766,7 @@ ] }, "get": { - "operationId": "getTPAForProject", + "operationId": "v1-get-project-tpa-integration", "summary": "Get a third-party integration", "parameters": [ { @@ -8443,6 +9777,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, @@ -8451,6 +9786,7 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -8464,7 +9800,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "type": { "type": "string" @@ -8478,11 +9815,9 @@ "nullable": true }, "custom_jwks": { - "type": "object", "nullable": true }, "resolved_jwks": { - "type": "object", "nullable": true }, "inserted_at": { @@ -8526,6 +9861,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8555,7 +9891,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8613,23 +9953,15 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": {}, - "hideDefinitions": ["release_channel", "postgres_engine"] - } - } - } - }, "responses": { "200": { "description": "" @@ -8655,7 +9987,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8685,7 +10021,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8732,7 +10072,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -8785,26 +10133,7 @@ "required": ["description", "type", "interval", "amount"] }, "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } + "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] @@ -8852,7 +10181,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -8905,26 +10242,7 @@ "required": ["description", "type", "interval", "amount"] }, "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } + "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] @@ -8947,6 +10265,7 @@ "description": "Failed to list project addons" } }, + "tags": ["Billing"], "security": [ { "bearer": [] @@ -8961,7 +10280,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -8987,7 +10310,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -9033,6 +10364,7 @@ "description": "Failed to apply project addon" } }, + "tags": ["Billing"], "security": [ { "bearer": [] @@ -9046,37 +10378,59 @@ "summary": "Removes project addon", "parameters": [ { - "name": "addon_variant", + "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { - "enum": [ - "ci_micro", - "ci_small", - "ci_medium", - "ci_large", - "ci_xlarge", - "ci_2xlarge", - "ci_4xlarge", - "ci_8xlarge", - "ci_12xlarge", - "ci_16xlarge", - "cd_default", - "pitr_7", - "pitr_14", - "pitr_28", - "ipv4_default" - ], + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, { - "name": "ref", + "name": "addon_variant", "required": true, "in": "path", - "schema": { - "type": "string" - } + "oneOf": [ + { + "type": "string", + "enum": [ + "ci_micro", + "ci_small", + "ci_medium", + "ci_large", + "ci_xlarge", + "ci_2xlarge", + "ci_4xlarge", + "ci_8xlarge", + "ci_12xlarge", + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" + ] + }, + { + "type": "string", + "enum": ["cd_default"] + }, + { + "type": "string", + "enum": ["pitr_7", "pitr_14", "pitr_28"] + }, + { + "type": "string", + "enum": ["ipv4_default"] + } + ], + "schema": {} } ], "responses": { @@ -9090,6 +10444,7 @@ "description": "Failed to remove project addon" } }, + "tags": ["Billing"], "security": [ { "bearer": [] @@ -9097,40 +10452,21 @@ ] } }, - "/v1/projects/{ref}/analytics/endpoints/logs.all": { + "/v1/projects/{ref}/claim-token": { "get": { - "operationId": "getLogs", - "summary": "Gets project's logs", + "operationId": "v1-get-project-claim-token", + "x-internal": true, + "summary": "Gets project claim token", "parameters": [ - { - "name": "iso_timestamp_end", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "iso_timestamp_start", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "sql", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, { "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9143,9 +10479,526 @@ "schema": { "type": "object", "properties": { + "token_alias": { + "type": "string" + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "type": "string", + "format": "uuid" + } + }, + "required": ["token_alias", "expires_at", "created_at", "created_by"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Projects"], + "security": [ + { + "bearer": [] + } + ] + }, + "post": { + "operationId": "v1-create-project-claim-token", + "x-internal": true, + "summary": "Creates project claim token", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "token_alias": { + "type": "string" + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "type": "string", + "format": "uuid" + } + }, + "required": ["token", "token_alias", "expires_at", "created_at", "created_by"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Projects"], + "security": [ + { + "bearer": [] + } + ] + }, + "delete": { + "operationId": "v1-delete-project-claim-token", + "x-internal": true, + "summary": "Revokes project claim token", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "" + }, + "403": { + "description": "" + } + }, + "tags": ["Projects"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/advisors/performance": { + "get": { + "operationId": "v1-get-performance-advisors", + "summary": "Gets project performance advisors.", + "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", + "deprecated": true, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lints": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "enum": [ + "unindexed_foreign_keys", + "auth_users_exposed", + "auth_rls_initplan", + "no_primary_key", + "unused_index", + "multiple_permissive_policies", + "policy_exists_rls_disabled", + "rls_enabled_no_policy", + "duplicate_index", + "security_definer_view", + "function_search_path_mutable", + "rls_disabled_in_public", + "extension_in_public", + "rls_references_user_metadata", + "materialized_view_in_api", + "foreign_table_in_api", + "unsupported_reg_types", + "auth_otp_long_expiry", + "auth_otp_short_length", + "ssl_not_enforced", + "network_restrictions_not_set", + "password_requirements_min_length", + "pitr_not_enabled", + "auth_leaked_password_protection", + "auth_insufficient_mfa_options", + "auth_password_policy_missing", + "leaked_service_key", + "no_backup_admin" + ] + }, + "title": { + "type": "string" + }, + "level": { + "type": "string", + "enum": ["ERROR", "WARN", "INFO"] + }, + "facing": { + "type": "string", + "enum": ["EXTERNAL"] + }, + "categories": { + "type": "array", + "items": { + "type": "string", + "enum": ["PERFORMANCE", "SECURITY"] + } + }, + "description": { + "type": "string" + }, + "detail": { + "type": "string" + }, + "remediation": { + "type": "string" + }, + "metadata": { + "type": "object", + "properties": { + "schema": { + "type": "string" + }, + "name": { + "type": "string" + }, + "entity": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "table", + "view", + "auth", + "function", + "extension", + "compliance" + ] + }, + "fkey_name": { + "type": "string" + }, + "fkey_columns": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, + "cache_key": { + "type": "string" + } + }, + "required": [ + "name", + "title", + "level", + "facing", + "categories", + "description", + "detail", + "remediation", + "cache_key" + ] + } + } + }, + "required": ["lints"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Advisors"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/advisors/security": { + "get": { + "operationId": "v1-get-security-advisors", + "summary": "Gets project security advisors.", + "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", + "deprecated": true, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "lint_type", + "required": false, + "in": "query", + "schema": { + "enum": ["sql"], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lints": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "enum": [ + "unindexed_foreign_keys", + "auth_users_exposed", + "auth_rls_initplan", + "no_primary_key", + "unused_index", + "multiple_permissive_policies", + "policy_exists_rls_disabled", + "rls_enabled_no_policy", + "duplicate_index", + "security_definer_view", + "function_search_path_mutable", + "rls_disabled_in_public", + "extension_in_public", + "rls_references_user_metadata", + "materialized_view_in_api", + "foreign_table_in_api", + "unsupported_reg_types", + "auth_otp_long_expiry", + "auth_otp_short_length", + "ssl_not_enforced", + "network_restrictions_not_set", + "password_requirements_min_length", + "pitr_not_enabled", + "auth_leaked_password_protection", + "auth_insufficient_mfa_options", + "auth_password_policy_missing", + "leaked_service_key", + "no_backup_admin" + ] + }, + "title": { + "type": "string" + }, + "level": { + "type": "string", + "enum": ["ERROR", "WARN", "INFO"] + }, + "facing": { + "type": "string", + "enum": ["EXTERNAL"] + }, + "categories": { + "type": "array", + "items": { + "type": "string", + "enum": ["PERFORMANCE", "SECURITY"] + } + }, + "description": { + "type": "string" + }, + "detail": { + "type": "string" + }, + "remediation": { + "type": "string" + }, + "metadata": { + "type": "object", + "properties": { + "schema": { + "type": "string" + }, + "name": { + "type": "string" + }, + "entity": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "table", + "view", + "auth", + "function", + "extension", + "compliance" + ] + }, + "fkey_name": { + "type": "string" + }, + "fkey_columns": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, + "cache_key": { + "type": "string" + } + }, + "required": [ + "name", + "title", + "level", + "facing", + "categories", + "description", + "detail", + "remediation", + "cache_key" + ] + } + } + }, + "required": ["lints"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Advisors"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/analytics/endpoints/logs.all": { + "get": { + "operationId": "v1-get-project-logs", + "summary": "Gets project's logs", + "description": "Executes a SQL query on the project's logs.\n\nEither the 'iso_timestamp_start' and 'iso_timestamp_end' parameters must be provided.\nIf both are not provided, only the last 1 minute of logs will be queried.\nThe timestamp range must be no more than 24 hours and is rounded to the nearest minute. If the range is more than 24 hours, a validation error will be thrown.\n", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "sql", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "iso_timestamp_start", + "required": false, + "in": "query", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "iso_timestamp_end", + "required": false, + "in": "query", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "array", + "items": {} + }, "error": { "oneOf": [ { + "type": "string" + }, + { + "type": "object", "properties": { "code": { "type": "number" @@ -9153,6 +11006,7 @@ "errors": { "type": "array", "items": { + "type": "object", "properties": { "domain": { "type": "string" @@ -9169,7 +11023,14 @@ "reason": { "type": "string" } - } + }, + "required": [ + "domain", + "location", + "locationType", + "message", + "reason" + ] } }, "message": { @@ -9178,18 +11039,10 @@ "status": { "type": "string" } - } - }, - { - "type": "string" + }, + "required": ["code", "errors", "message", "status"] } ] - }, - "result": { - "type": "array", - "items": { - "type": "object" - } } } } @@ -9208,9 +11061,219 @@ ] } }, + "/v1/projects/{ref}/analytics/endpoints/usage.api-counts": { + "get": { + "operationId": "v1-get-project-usage-api-count", + "summary": "Gets project's usage api counts", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "interval", + "required": false, + "in": "query", + "schema": { + "enum": ["15min", "30min", "1hr", "3hr", "1day", "3day", "7day"], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "array", + "items": {} + }, + "error": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "code": { + "type": "number" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "location": { + "type": "string" + }, + "locationType": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "domain", + "location", + "locationType", + "message", + "reason" + ] + } + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": ["code", "errors", "message", "status"] + } + ] + } + } + } + } + } + }, + "403": { + "description": "" + }, + "500": { + "description": "Failed to get project's usage api counts" + } + }, + "tags": ["Analytics"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/analytics/endpoints/usage.api-requests-count": { + "get": { + "operationId": "v1-get-project-usage-request-count", + "summary": "Gets project's usage api requests count", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "array", + "items": {} + }, + "error": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "code": { + "type": "number" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "location": { + "type": "string" + }, + "locationType": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "domain", + "location", + "locationType", + "message", + "reason" + ] + } + }, + "message": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": ["code", "errors", "message", "status"] + } + ] + } + } + } + } + } + }, + "500": { + "description": "Failed to get project's usage api requests count" + } + }, + "tags": ["Analytics"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/projects/{ref}/database/migrations": { "get": { - "operationId": "v1-list-migrations", + "operationId": "v1-list-migration-history", "summary": "[Beta] List applied migration versions", "description": "Only available to selected partner OAuth apps", "parameters": [ @@ -9218,7 +11281,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9270,21 +11337,47 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "Idempotency-Key", + "required": false, + "in": "header", + "description": "A unique key to ensure the same migration is tracked only once.", "schema": { "type": "string" } } ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "minLength": 1 + }, + "name": { + "type": "string" + } + }, + "required": ["query"] } } + } + }, + "responses": { + "200": { + "description": "" }, "403": { "description": "" @@ -9299,6 +11392,71 @@ "bearer": [] } ] + }, + "put": { + "operationId": "v1-upsert-a-migration", + "summary": "[Beta] Upsert a database migration without applying", + "description": "Only available to selected partner OAuth apps", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "Idempotency-Key", + "required": false, + "in": "header", + "description": "A unique key to ensure the same migration is tracked only once.", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "query": { + "type": "string", + "minLength": 1 + }, + "name": { + "type": "string" + } + }, + "required": ["query"] + } + } + } + }, + "responses": { + "200": { + "description": "" + }, + "403": { + "description": "" + }, + "500": { + "description": "Failed to upsert database migration" + } + }, + "tags": ["Database"], + "security": [ + { + "bearer": [] + } + ] } }, "/v1/projects/{ref}/database/query": { @@ -9310,7 +11468,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9325,6 +11487,9 @@ "query": { "type": "string", "minLength": 1 + }, + "read_only": { + "type": "boolean" } }, "required": ["query"] @@ -9334,14 +11499,7 @@ }, "responses": { "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } + "description": "" }, "403": { "description": "" @@ -9371,6 +11529,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9396,7 +11555,7 @@ }, "/v1/projects/{ref}/database/context": { "get": { - "operationId": "getDatabaseMetadata", + "operationId": "v1-get-database-metadata", "summary": "Gets database metadata for the given project.", "description": "This is an **experimental** endpoint. It is subject to change or removal in future versions. Use it with caution, as it may not remain supported or stable.", "deprecated": true, @@ -9405,7 +11564,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9472,7 +11635,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9504,10 +11671,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -9520,6 +11689,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": [ @@ -9555,89 +11727,16 @@ "summary": "Create a function", "description": "This endpoint is deprecated - use the deploy endpoint. Creates a function and adds it to the specified project.", "deprecated": true, - "parameters": [ - { - "name": "import_map_path", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "entrypoint_path", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "import_map", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "verify_jwt", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "name", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "slug", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "ref", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], "requestBody": { "required": true, "content": { - "application/json": { + "application/vnd.denoland.eszip": { "schema": { - "type": "object", - "properties": { - "slug": { - "type": "string", - "pattern": "^[A-Za-z0-9_-]+$" - }, - "name": { - "type": "string" - }, - "body": { - "type": "string" - }, - "verify_jwt": { - "type": "boolean" - } - }, - "required": ["slug", "name", "body"] + "type": "string", + "format": "binary" } }, - "application/vnd.denoland.eszip": { + "application/json": { "schema": { "type": "object", "properties": { @@ -9660,6 +11759,79 @@ } } }, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "slug", + "required": false, + "in": "query", + "schema": { + "pattern": "^[A-Za-z0-9_-]+$", + "type": "string" + } + }, + { + "name": "name", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "verify_jwt", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "import_map", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "entrypoint_path", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "import_map_path", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "ezbr_sha256", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -9685,10 +11857,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -9701,6 +11875,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": [ @@ -9739,7 +11916,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -9771,7 +11952,8 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -9784,6 +11966,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version"] @@ -9822,10 +12007,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -9838,6 +12025,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": [ @@ -9879,11 +12069,15 @@ "description": "A new endpoint to deploy functions. It will create if function does not exist.", "parameters": [ { - "name": "bundleOnly", - "required": false, - "in": "query", + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", "schema": { - "type": "boolean" + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" } }, { @@ -9891,15 +12085,17 @@ "required": false, "in": "query", "schema": { + "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } }, { - "name": "ref", - "required": true, - "in": "path", + "name": "bundleOnly", + "required": false, + "in": "query", + "description": "Boolean string, true or false", "schema": { - "type": "string" + "type": "boolean" } } ], @@ -9972,10 +12168,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -9988,6 +12186,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version"] @@ -10017,19 +12218,24 @@ "description": "Retrieves a function with the specified slug and project.", "parameters": [ { - "name": "function_slug", + "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { - "pattern": "^[A-Za-z0-9_-]+$", + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, { - "name": "ref", + "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { + "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } } @@ -10059,10 +12265,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -10075,6 +12283,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": [ @@ -10108,85 +12319,16 @@ "operationId": "v1-update-a-function", "summary": "Update a function", "description": "Updates a function with the specified slug and project.", - "parameters": [ - { - "name": "import_map_path", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "entrypoint_path", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "import_map", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "verify_jwt", - "required": false, - "in": "query", - "schema": { - "type": "boolean" - } - }, - { - "name": "name", - "required": false, - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "function_slug", - "required": true, - "in": "path", - "schema": { - "pattern": "^[A-Za-z0-9_-]+$", - "type": "string" - } - }, - { - "name": "ref", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], "requestBody": { "required": true, "content": { - "application/json": { + "application/vnd.denoland.eszip": { "schema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "body": { - "type": "string" - }, - "verify_jwt": { - "type": "boolean" - } - } + "type": "string", + "format": "binary" } }, - "application/vnd.denoland.eszip": { + "application/json": { "schema": { "type": "object", "properties": { @@ -10204,6 +12346,89 @@ } } }, + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "function_slug", + "required": true, + "in": "path", + "description": "Function slug", + "schema": { + "pattern": "^[A-Za-z0-9_-]+$", + "type": "string" + } + }, + { + "name": "slug", + "required": false, + "in": "query", + "schema": { + "pattern": "^[A-Za-z0-9_-]+$", + "type": "string" + } + }, + { + "name": "name", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "verify_jwt", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "import_map", + "required": false, + "in": "query", + "description": "Boolean string, true or false", + "schema": { + "type": "boolean" + } + }, + { + "name": "entrypoint_path", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "import_map_path", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "ezbr_sha256", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -10229,10 +12454,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -10245,6 +12472,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": [ @@ -10280,19 +12510,24 @@ "description": "Deletes a function with the specified slug from the specified project.", "parameters": [ { - "name": "function_slug", + "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { - "pattern": "^[A-Za-z0-9_-]+$", + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, { - "name": "ref", + "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { + "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } } @@ -10323,26 +12558,39 @@ "description": "Retrieves a function body for the specified slug and project.", "parameters": [ { - "name": "function_slug", + "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { - "pattern": "^[A-Za-z0-9_-]+$", + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, { - "name": "ref", + "name": "function_slug", "required": true, "in": "path", + "description": "Function slug", "schema": { + "pattern": "^[A-Za-z0-9_-]+$", "type": "string" } } ], "responses": { "200": { - "description": "" + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + } }, "403": { "description": "" @@ -10372,6 +12620,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -10439,6 +12688,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -10475,10 +12725,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -10491,15 +12751,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -10549,10 +12800,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -10565,15 +12826,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -10645,6 +12897,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -10688,10 +12941,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -10704,15 +12967,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -10790,6 +13044,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, @@ -10798,6 +13053,7 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -10836,10 +13092,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -10852,15 +13118,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -10932,6 +13189,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, @@ -10940,6 +13198,7 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -10971,10 +13230,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -10987,15 +13256,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -11044,10 +13304,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -11060,15 +13330,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -11140,6 +13401,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } }, @@ -11148,6 +13410,7 @@ "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -11186,10 +13449,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -11202,15 +13475,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -11284,6 +13548,7 @@ "schema": { "minLength": 20, "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -11310,6 +13575,9 @@ "items": { "type": "object", "properties": { + "is_physical_backup": { + "type": "boolean" + }, "status": { "type": "string", "enum": [ @@ -11321,26 +13589,21 @@ "CANCELLED" ] }, - "is_physical_backup": { - "type": "boolean" - }, "inserted_at": { "type": "string" } }, - "required": ["status", "is_physical_backup", "inserted_at"] + "required": ["is_physical_backup", "status", "inserted_at"] } }, "physical_backup_data": { "type": "object", "properties": { "earliest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" + "type": "integer" }, "latest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" + "type": "integer" } } } @@ -11380,7 +13643,11 @@ "name": "ref", "required": true, "in": "path", + "description": "Project ref", "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", "type": "string" } } @@ -11419,6 +13686,186 @@ ] } }, + "/v1/projects/{ref}/database/backups/restore-point": { + "post": { + "operationId": "v1-create-restore-point", + "x-internal": true, + "summary": "Initiates a creation of a restore point for a database", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 20 + } + }, + "required": ["name"] + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string", + "enum": ["AVAILABLE", "PENDING", "REMOVED"] + } + }, + "required": ["name", "status"] + } + } + } + } + }, + "tags": ["Database"], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "v1-get-restore-point", + "x-internal": true, + "summary": "Get restore points for project", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + }, + { + "name": "name", + "required": false, + "in": "query", + "schema": { + "maxLength": 20, + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string", + "enum": ["AVAILABLE", "PENDING", "REMOVED"] + } + }, + "required": ["name", "status"] + } + } + } + }, + "403": { + "description": "" + }, + "500": { + "description": "Failed to get requested restore points" + } + }, + "tags": ["Database"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/projects/{ref}/database/backups/undo": { + "post": { + "operationId": "v1-undo", + "x-internal": true, + "summary": "Initiates an undo to a given restore point", + "parameters": [ + { + "name": "ref", + "required": true, + "in": "path", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 20 + } + }, + "required": ["name"] + } + } + } + }, + "responses": { + "201": { + "description": "" + }, + "403": { + "description": "" + } + }, + "tags": ["Database"], + "security": [ + { + "bearer": [] + } + ] + } + }, "/v1/organizations/{slug}/members": { "get": { "operationId": "v1-list-organization-members", @@ -11428,7 +13875,9 @@ "name": "slug", "required": true, "in": "path", + "description": "Organization slug", "schema": { + "pattern": "^[\\w-]+$", "type": "string" } } @@ -11486,6 +13935,87 @@ "name": "slug", "required": true, "in": "path", + "description": "Organization slug", + "schema": { + "pattern": "^[\\w-]+$", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"] + }, + "opt_in_tags": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "AI_SQL_GENERATOR_OPT_IN", + "AI_DATA_GENERATOR_OPT_IN", + "AI_LOG_GENERATOR_OPT_IN" + ] + } + }, + "allowed_release_channels": { + "type": "array", + "items": { + "type": "string", + "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] + } + } + }, + "required": ["id", "name", "opt_in_tags", "allowed_release_channels"] + } + } + } + }, + "403": { + "description": "" + } + }, + "tags": ["Organizations"], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v1/organizations/{slug}/project-claim/{token}": { + "get": { + "operationId": "v1-get-organization-project-claim", + "x-internal": true, + "summary": "Gets project details for the specified organization and claim token", + "parameters": [ + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { + "pattern": "^[\\w-]+$", + "type": "string" + } + }, + { + "name": "token", + "required": true, + "in": "path", "schema": { "type": "string" } @@ -11499,32 +14029,126 @@ "schema": { "type": "object", "properties": { - "plan": { + "project": { + "type": "object", + "properties": { + "ref": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["ref", "name"] + }, + "preview": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "members_exceeding_free_project_limit": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "limit": { + "type": "number" + } + }, + "required": ["name", "limit"] + } + }, + "target_organization_eligible": { + "type": "boolean", + "nullable": true + }, + "target_organization_has_free_project_slots": { + "type": "boolean", + "nullable": true + }, + "source_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"] + }, + "target_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"], + "nullable": true + } + }, + "required": [ + "valid", + "warnings", + "errors", + "info", + "members_exceeding_free_project_limit", + "target_organization_eligible", + "target_organization_has_free_project_slots", + "source_subscription_plan", + "target_subscription_plan" + ] + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { "type": "string", - "enum": ["free", "pro", "team", "enterprise"] - }, - "opt_in_tags": { - "type": "array", - "items": { - "type": "string", - "enum": ["AI_SQL_GENERATOR_OPT_IN"] - } - }, - "allowed_release_channels": { - "type": "array", - "items": { - "type": "string", - "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] - } - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" + "format": "uuid" } }, - "required": ["opt_in_tags", "allowed_release_channels", "id", "name"] + "required": ["project", "preview", "expires_at", "created_at", "created_by"] } } } @@ -11539,6 +14163,45 @@ "bearer": [] } ] + }, + "post": { + "operationId": "v1-claim-project-for-organization", + "x-internal": true, + "summary": "Claims project for the specified organization", + "parameters": [ + { + "name": "slug", + "required": true, + "in": "path", + "description": "Organization slug", + "schema": { + "pattern": "^[\\w-]+$", + "type": "string" + } + }, + { + "name": "token", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "" + }, + "403": { + "description": "" + } + }, + "tags": ["Organizations"], + "security": [ + { + "bearer": [] + } + ] } } }, @@ -11590,7 +14253,9 @@ "type": "string" }, "db_port": { - "type": "number" + "type": "integer", + "minimum": 0, + "exclusiveMinimum": true }, "db_user": { "type": "string" @@ -11639,6 +14304,9 @@ "FUNCTIONS_DEPLOYED", "FUNCTIONS_FAILED" ] + }, + "request_review": { + "type": "boolean" } } }, @@ -11646,7 +14314,8 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "name": { "type": "string" @@ -11687,10 +14356,16 @@ ] }, "created_at": { - "type": "string" + "type": "string", + "format": "date-time" }, "updated_at": { - "type": "string" + "type": "string", + "format": "date-time" + }, + "review_requested_at": { + "type": "string", + "format": "date-time" } }, "required": [ @@ -11715,6 +14390,14 @@ }, "required": ["message"] }, + "BranchActionBody": { + "type": "object", + "properties": { + "migration_version": { + "type": "string" + } + } + }, "BranchUpdateResponse": { "type": "object", "properties": { @@ -11728,28 +14411,6 @@ }, "required": ["workflow_run_id", "message"] }, - "V1DatabaseResponse": { - "type": "object", - "properties": { - "host": { - "type": "string", - "description": "Database host" - }, - "version": { - "type": "string", - "description": "Database version" - }, - "postgres_engine": { - "type": "string", - "description": "Database engine" - }, - "release_channel": { - "type": "string", - "description": "Release channel" - } - }, - "required": ["host", "version", "postgres_engine", "release_channel"] - }, "V1ProjectWithDatabaseResponse": { "type": "object", "properties": { @@ -11820,7 +14481,7 @@ }, "required": ["id", "organization_id", "name", "region", "created_at", "status", "database"] }, - "V1CreateProjectBodyDto": { + "V1CreateProjectBody": { "type": "object", "properties": { "db_pass": { @@ -11829,6 +14490,7 @@ }, "name": { "type": "string", + "maxLength": 256, "description": "Name of your project" }, "organization_id": { @@ -11873,6 +14535,8 @@ "desired_instance_size": { "type": "string", "enum": [ + "pico", + "nano", "micro", "small", "medium", @@ -11882,7 +14546,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "template_url": { @@ -11956,7 +14628,7 @@ }, "required": ["id", "name"] }, - "CreateOrganizationV1Dto": { + "CreateOrganizationV1": { "type": "object", "properties": { "name": { @@ -12015,7 +14687,7 @@ "required": ["access_token", "refresh_token", "expires_in", "token_type"], "additionalProperties": false }, - "OAuthRevokeTokenBodyDto": { + "OAuthRevokeTokenBody": { "type": "object", "properties": { "client_id": { @@ -12032,112 +14704,6 @@ "required": ["client_id", "client_secret", "refresh_token"], "additionalProperties": false }, - "SnippetProject": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "required": ["id", "name"] - }, - "SnippetUser": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - } - }, - "required": ["id", "username"] - }, - "SnippetMeta": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "inserted_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - }, - "type": { - "type": "string", - "enum": ["sql"] - }, - "visibility": { - "type": "string", - "enum": ["user", "project", "org", "public"] - }, - "name": { - "type": "string" - }, - "description": { - "type": "string", - "nullable": true - }, - "project": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "required": ["id", "name"] - }, - "owner": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - } - }, - "required": ["id", "username"] - }, - "updated_by": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - } - }, - "required": ["id", "username"] - } - }, - "required": [ - "id", - "inserted_at", - "updated_at", - "type", - "visibility", - "name", - "description", - "project", - "owner", - "updated_by" - ] - }, "SnippetList": { "type": "object", "properties": { @@ -12174,8 +14740,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "name": { "type": "string" @@ -12187,8 +14752,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -12200,8 +14764,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -12230,21 +14793,6 @@ }, "required": ["data"] }, - "SnippetContent": { - "type": "object", - "properties": { - "favorite": { - "type": "boolean" - }, - "schema_version": { - "type": "string" - }, - "sql": { - "type": "string" - } - }, - "required": ["favorite", "schema_version", "sql"] - }, "SnippetResponse": { "type": "object", "properties": { @@ -12262,8 +14810,8 @@ "enum": ["sql"] }, "visibility": { - "enum": ["user", "project", "org", "public"], - "type": "string" + "type": "string", + "enum": ["user", "project", "org", "public"] }, "name": { "type": "string" @@ -12276,8 +14824,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "name": { "type": "string" @@ -12289,8 +14836,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -12302,8 +14848,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "number" }, "username": { "type": "string" @@ -12344,11 +14889,9 @@ "ApiKeyResponse": { "type": "object", "properties": { - "name": { - "type": "string" - }, "api_key": { - "type": "string" + "type": "string", + "nullable": true }, "id": { "type": "string", @@ -12356,13 +14899,16 @@ }, "type": { "type": "string", - "enum": ["publishable", "secret", "legacy"], + "enum": ["legacy", "publishable", "secret"], "nullable": true }, "prefix": { "type": "string", "nullable": true }, + "name": { + "type": "string" + }, "description": { "type": "string", "nullable": true @@ -12393,7 +14939,16 @@ "nullable": true } }, - "required": ["name", "api_key"] + "required": ["name"] + }, + "LegacyApiKeysResponse": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] }, "CreateApiKeyBody": { "type": "object", @@ -12402,6 +14957,12 @@ "type": "string", "enum": ["publishable", "secret"] }, + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true @@ -12418,11 +14979,17 @@ "nullable": true } }, - "required": ["type"] + "required": ["type", "name"] }, "UpdateApiKeyBody": { "type": "object", "properties": { + "name": { + "type": "string", + "minLength": 4, + "maxLength": 64, + "pattern": "^[a-z_][a-z0-9_]+$" + }, "description": { "type": "string", "nullable": true @@ -12450,6 +15017,9 @@ "git_branch": { "type": "string" }, + "is_default": { + "type": "boolean" + }, "persistent": { "type": "boolean" }, @@ -12470,7 +15040,15 @@ "4xlarge", "8xlarge", "12xlarge", - "16xlarge" + "16xlarge", + "24xlarge", + "24xlarge_optimized_memory", + "24xlarge_optimized_cpu", + "24xlarge_high_memory", + "48xlarge", + "48xlarge_optimized_memory", + "48xlarge_optimized_cpu", + "48xlarge_high_memory" ] }, "release_channel": { @@ -12480,7 +15058,7 @@ }, "postgres_engine": { "type": "string", - "enum": ["15", "17-oriole"], + "enum": ["15", "17", "17-oriole"], "description": "Postgres engine version. If not provided, the latest version will be used." }, "secrets": { @@ -12488,279 +15066,25 @@ "additionalProperties": { "type": "string" } + }, + "with_data": { + "type": "boolean" } }, "required": ["branch_name"] }, - "ValidationRecord": { - "type": "object", - "properties": { - "txt_name": { - "type": "string" - }, - "txt_value": { - "type": "string" - } - }, - "required": ["txt_name", "txt_value"] - }, - "ValidationError": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": ["message"] - }, - "SslValidation": { - "type": "object", - "properties": { - "status": { - "type": "string" - }, - "validation_records": { - "type": "array", - "items": { - "type": "object", - "properties": { - "txt_name": { - "type": "string" - }, - "txt_value": { - "type": "string" - } - }, - "required": ["txt_name", "txt_value"] - } - }, - "validation_errors": { - "type": "array", - "items": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": ["message"] - } - } - }, - "required": ["status", "validation_records"] - }, - "OwnershipVerification": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": ["type", "name", "value"] - }, - "CustomHostnameDetails": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "hostname": { - "type": "string" - }, - "ssl": { - "type": "object", - "properties": { - "status": { - "type": "string" - }, - "validation_records": { - "type": "array", - "items": { - "type": "object", - "properties": { - "txt_name": { - "type": "string" - }, - "txt_value": { - "type": "string" - } - }, - "required": ["txt_name", "txt_value"] - } - }, - "validation_errors": { - "type": "array", - "items": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": ["message"] - } - } - }, - "required": ["status", "validation_records"] - }, - "ownership_verification": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": ["type", "name", "value"] - }, - "custom_origin_server": { - "type": "string" - }, - "verification_errors": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string" - } - }, - "required": [ - "id", - "hostname", - "ssl", - "ownership_verification", - "custom_origin_server", - "status" - ] - }, - "CfResponse": { - "type": "object", - "properties": { - "success": { - "type": "boolean" - }, - "errors": { - "type": "array", - "items": { - "type": "object" - } - }, - "messages": { - "type": "array", - "items": { - "type": "object" - } - }, - "result": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "hostname": { - "type": "string" - }, - "ssl": { - "type": "object", - "properties": { - "status": { - "type": "string" - }, - "validation_records": { - "type": "array", - "items": { - "type": "object", - "properties": { - "txt_name": { - "type": "string" - }, - "txt_value": { - "type": "string" - } - }, - "required": ["txt_name", "txt_value"] - } - }, - "validation_errors": { - "type": "array", - "items": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": ["message"] - } - } - }, - "required": ["status", "validation_records"] - }, - "ownership_verification": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - }, - "required": ["type", "name", "value"] - }, - "custom_origin_server": { - "type": "string" - }, - "verification_errors": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string" - } - }, - "required": [ - "id", - "hostname", - "ssl", - "ownership_verification", - "custom_origin_server", - "status" - ] - } - }, - "required": ["success", "errors", "messages", "result"] - }, "UpdateCustomHostnameResponse": { "type": "object", "properties": { "status": { + "type": "string", "enum": [ "1_not_started", "2_initiated", "3_challenge_verified", "4_origin_setup_completed", "5_services_reconfigured" - ], - "type": "string" + ] }, "custom_hostname": { "type": "string" @@ -12774,13 +15098,13 @@ "errors": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "messages": { "type": "array", "items": { - "type": "object" + "description": "Any JSON-serializable value" } }, "result": { @@ -12892,6 +15216,30 @@ }, "required": ["banned_ipv4_addresses"] }, + "NetworkBanResponseEnriched": { + "type": "object", + "properties": { + "banned_ipv4_addresses": { + "type": "array", + "items": { + "type": "object", + "properties": { + "banned_address": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["banned_address", "identifier", "type"] + } + } + }, + "required": ["banned_ipv4_addresses"] + }, "RemoveNetworkBanRequest": { "type": "object", "properties": { @@ -12900,6 +15248,9 @@ "items": { "type": "string" } + }, + "identifier": { + "type": "string" } }, "required": ["ipv4_addresses"] @@ -13057,8 +15408,7 @@ "type": "object", "properties": { "id": { - "type": "integer", - "format": "int64" + "type": "integer" }, "ref": { "type": "string" @@ -13085,21 +15435,24 @@ "required": ["name", "value"] }, "CreateSecretBody": { - "type": "object", - "properties": { - "name": { - "type": "string", - "maxLength": 256, - "pattern": "^(?!SUPABASE_).*", - "description": "Secret name must not start with the SUPABASE_ prefix.", - "example": "string" + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 256, + "pattern": "^(?!SUPABASE_).*", + "description": "Secret name must not start with the SUPABASE_ prefix.", + "example": "string" + }, + "value": { + "type": "string", + "maxLength": 24576 + } }, - "value": { - "type": "string", - "maxLength": 24576 - } - }, - "required": ["name", "value"] + "required": ["name", "value"] + } }, "SslEnforcementResponse": { "type": "object", @@ -13228,7 +15581,7 @@ "properties": { "postgres_version": { "type": "string", - "enum": ["15", "17-oriole"] + "enum": ["15", "17", "17-oriole"] }, "release_channel": { "type": "string", @@ -13241,12 +15594,6 @@ "required": ["postgres_version", "release_channel", "app_version"] } }, - "potential_breaking_changes": { - "type": "array", - "items": { - "type": "string" - } - }, "duration_estimate_hours": { "type": "number" }, @@ -13256,7 +15603,19 @@ "type": "string" } }, - "extension_dependent_objects": { + "objects_to_be_dropped": { + "type": "array", + "items": { + "type": "string" + } + }, + "unsupported_extensions": { + "type": "array", + "items": { + "type": "string" + } + }, + "user_defined_objects_in_internal_schemas": { "type": "array", "items": { "type": "string" @@ -13269,10 +15628,11 @@ "current_app_version_release_channel", "latest_app_version", "target_upgrade_versions", - "potential_breaking_changes", "duration_estimate_hours", "legacy_auth_custom_roles", - "extension_dependent_objects" + "objects_to_be_dropped", + "unsupported_extensions", + "user_defined_objects_in_internal_schemas" ] }, "DatabaseUpgradeStatusResponse": { @@ -13385,28 +15745,20 @@ }, "required": ["database_identifier"] }, - "AuthHealthResponse": { + "V1ServiceHealthResponse": { "type": "object", "properties": { "name": { "type": "string", - "enum": ["GoTrue"] - } - }, - "required": ["name"] - }, - "RealtimeHealthResponse": { - "type": "object", - "properties": { - "connected_cluster": { - "type": "integer" - } - }, - "required": ["connected_cluster"] - }, - "V1ServiceHealthResponse": { - "type": "object", - "properties": { + "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"] + }, + "healthy": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"] + }, "info": { "oneOf": [ { @@ -13415,38 +15767,69 @@ "name": { "type": "string", "enum": ["GoTrue"] + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" } }, - "required": ["name"] + "required": ["name", "version", "description"] }, { "type": "object", "properties": { + "healthy": { + "type": "boolean" + }, + "db_connected": { + "type": "boolean" + }, "connected_cluster": { "type": "integer" } }, - "required": ["connected_cluster"] + "required": ["healthy", "db_connected", "connected_cluster"] } ] }, - "name": { - "enum": ["auth", "db", "pooler", "realtime", "rest", "storage"], - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "status": { - "enum": ["COMING_UP", "ACTIVE_HEALTHY", "UNHEALTHY"], - "type": "string" - }, "error": { "type": "string" } }, "required": ["name", "healthy", "status"] }, + "SigningKeyResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "algorithm": { + "type": "string", + "enum": ["EdDSA", "ES256", "RS256", "HS256"] + }, + "status": { + "type": "string", + "enum": ["in_use", "previously_used", "revoked", "standby"] + }, + "public_jwk": { + "nullable": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + }, + "required": ["id", "algorithm", "status", "created_at", "updated_at"], + "additionalProperties": false + }, "CreateSigningKeyBody": { "type": "object", "properties": { @@ -13457,6 +15840,109 @@ "status": { "type": "string", "enum": ["in_use", "standby"] + }, + "private_jwk": { + "discriminator": { + "propertyName": "kty" + }, + "oneOf": [ + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["RSA"] + }, + "n": { + "type": "string" + }, + "e": { + "type": "string", + "enum": ["AQAB"] + }, + "d": { + "type": "string" + }, + "p": { + "type": "string" + }, + "q": { + "type": "string" + }, + "dp": { + "type": "string" + }, + "dq": { + "type": "string" + }, + "qi": { + "type": "string" + } + }, + "required": ["kty", "n", "e", "d", "p", "q", "dp", "dq", "qi"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["EC"] + }, + "crv": { + "type": "string", + "enum": ["P-256"] + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "d": { + "type": "string" + } + }, + "required": ["kty", "crv", "x", "y", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["OKP"] + }, + "crv": { + "type": "string", + "enum": ["Ed25519"] + }, + "x": { + "type": "string" + }, + "d": { + "type": "string" + } + }, + "required": ["kty", "crv", "x", "d"], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "kty": { + "type": "string", + "enum": ["oct"] + }, + "k": { + "type": "string", + "minLength": 16 + } + }, + "required": ["kty", "k"], + "additionalProperties": false + } + ] } }, "required": ["algorithm"], @@ -13502,36 +15988,6 @@ "required": ["keys"], "additionalProperties": false }, - "SigningKeyResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid" - }, - "algorithm": { - "type": "string", - "enum": ["EdDSA", "ES256", "RS256", "HS256"] - }, - "status": { - "type": "string", - "enum": ["in_use", "previously_used", "revoked", "standby"] - }, - "public_jwk": { - "nullable": true - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - }, - "required": ["id", "algorithm", "status", "created_at", "updated_at"], - "additionalProperties": false - }, "UpdateSigningKeyBody": { "type": "object", "properties": { @@ -13543,48 +15999,6 @@ "required": ["status"], "additionalProperties": false }, - "StorageFeatureImageTransformation": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": ["enabled"] - }, - "StorageFeatureS3Protocol": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": ["enabled"] - }, - "StorageFeatures": { - "type": "object", - "properties": { - "imageTransformation": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": ["enabled"] - }, - "s3Protocol": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": ["enabled"] - } - }, - "required": ["imageTransformation", "s3Protocol"] - }, "StorageConfigResponse": { "type": "object", "properties": { @@ -13612,6 +16026,15 @@ } }, "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] } }, "required": ["imageTransformation", "s3Protocol"] @@ -13625,7 +16048,7 @@ "fileSizeLimit": { "type": "integer", "minimum": 0, - "maximum": 53687091200, + "maximum": 536870912000, "format": "int64" }, "features": { @@ -13648,6 +16071,15 @@ } }, "required": ["enabled"] + }, + "icebergCatalog": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": ["enabled"] } }, "required": ["imageTransformation", "s3Protocol"] @@ -13717,6 +16149,10 @@ "minimum": 0, "maximum": 262143 }, + "session_replication_role": { + "type": "string", + "enum": ["origin", "replica", "local"] + }, "shared_buffers": { "type": "string" }, @@ -13734,10 +16170,6 @@ }, "work_mem": { "type": "string" - }, - "session_replication_role": { - "enum": ["origin", "replica", "local"], - "type": "string" } } }, @@ -13804,6 +16236,10 @@ "minimum": 0, "maximum": 262143 }, + "session_replication_role": { + "type": "string", + "enum": ["origin", "replica", "local"] + }, "shared_buffers": { "type": "string" }, @@ -13824,47 +16260,72 @@ }, "restart_database": { "type": "boolean" - }, - "session_replication_role": { - "enum": ["origin", "replica", "local"], - "type": "string" } } }, "V1PgbouncerConfigResponse": { "type": "object", "properties": { - "pool_mode": { - "type": "string", - "enum": ["transaction", "session", "statement"] - }, "default_pool_size": { - "type": "number" + "type": "integer" }, "ignore_startup_parameters": { "type": "string" }, "max_client_conn": { - "type": "number" + "type": "integer" + }, + "pool_mode": { + "type": "string", + "enum": ["transaction", "session", "statement"] }, "connection_string": { "type": "string" + }, + "server_idle_timeout": { + "type": "integer" + }, + "server_lifetime": { + "type": "integer" + }, + "query_wait_timeout": { + "type": "integer" + }, + "reserve_pool_size": { + "type": "integer" } } }, "SupavisorConfigResponse": { "type": "object", "properties": { + "identifier": { + "type": "string" + }, "database_type": { "type": "string", "enum": ["PRIMARY", "READ_REPLICA"] }, + "is_using_scram_auth": { + "type": "boolean" + }, + "db_user": { + "type": "string" + }, + "db_host": { + "type": "string" + }, "db_port": { "type": "integer" }, + "db_name": { + "type": "string" + }, + "connection_string": { + "type": "string" + }, "connectionString": { "type": "string", - "deprecated": true, "description": "Use connection_string instead" }, "default_pool_size": { @@ -13876,41 +16337,23 @@ "nullable": true }, "pool_mode": { - "enum": ["transaction", "session"], - "type": "string" - }, - "identifier": { - "type": "string" - }, - "is_using_scram_auth": { - "type": "boolean" - }, - "db_user": { - "type": "string" - }, - "db_host": { - "type": "string" - }, - "db_name": { - "type": "string" - }, - "connection_string": { - "type": "string" + "type": "string", + "enum": ["transaction", "session"] } }, "required": [ - "database_type", - "db_port", - "connectionString", - "default_pool_size", - "max_client_conn", - "pool_mode", "identifier", + "database_type", "is_using_scram_auth", "db_user", "db_host", + "db_port", "db_name", - "connection_string" + "connection_string", + "connectionString", + "default_pool_size", + "max_client_conn", + "pool_mode" ] }, "UpdateSupavisorConfigBody": { @@ -13918,15 +16361,14 @@ "properties": { "default_pool_size": { "type": "integer", - "nullable": true, "minimum": 0, - "maximum": 1000 + "maximum": 3000, + "nullable": true }, "pool_mode": { - "enum": ["transaction", "session"], "type": "string", - "description": "Dedicated pooler mode for the project", - "deprecated": true + "enum": ["transaction", "session"], + "description": "Dedicated pooler mode for the project" } } }, @@ -13954,83 +16396,6 @@ "type": "integer", "nullable": true }, - "jwt_exp": { - "type": "integer", - "nullable": true - }, - "mailer_otp_exp": { - "type": "integer" - }, - "mailer_otp_length": { - "type": "integer", - "nullable": true - }, - "mfa_max_enrolled_factors": { - "type": "integer", - "nullable": true - }, - "mfa_phone_otp_length": { - "type": "integer" - }, - "mfa_phone_max_frequency": { - "type": "integer", - "nullable": true - }, - "password_min_length": { - "type": "integer", - "nullable": true - }, - "rate_limit_anonymous_users": { - "type": "integer", - "nullable": true - }, - "rate_limit_email_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_sms_sent": { - "type": "integer", - "nullable": true - }, - "rate_limit_token_refresh": { - "type": "integer", - "nullable": true - }, - "rate_limit_verify": { - "type": "integer", - "nullable": true - }, - "rate_limit_otp": { - "type": "integer", - "nullable": true - }, - "security_refresh_token_reuse_interval": { - "type": "integer", - "nullable": true - }, - "sessions_inactivity_timeout": { - "type": "integer", - "nullable": true - }, - "sessions_timebox": { - "type": "integer", - "nullable": true - }, - "sms_max_frequency": { - "type": "integer", - "nullable": true - }, - "sms_otp_exp": { - "type": "integer", - "nullable": true - }, - "sms_otp_length": { - "type": "integer" - }, - "smtp_max_frequency": { - "type": "integer", - "nullable": true - }, "disable_signup": { "type": "boolean", "nullable": true @@ -14303,6 +16668,10 @@ "type": "string", "nullable": true }, + "external_web3_solana_enabled": { + "type": "boolean", + "nullable": true + }, "external_zoom_client_id": { "type": "string", "nullable": true @@ -14375,6 +16744,22 @@ "type": "string", "nullable": true }, + "hook_before_user_created_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_before_user_created_uri": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_secrets": { + "type": "string", + "nullable": true + }, + "jwt_exp": { + "type": "integer", + "nullable": true + }, "mailer_allow_unverified_email_sign_ins": { "type": "boolean", "nullable": true @@ -14383,6 +16768,13 @@ "type": "boolean", "nullable": true }, + "mailer_otp_exp": { + "type": "integer" + }, + "mailer_otp_length": { + "type": "integer", + "nullable": true + }, "mailer_secure_email_change_enabled": { "type": "boolean", "nullable": true @@ -14435,6 +16827,10 @@ "type": "string", "nullable": true }, + "mfa_max_enrolled_factors": { + "type": "integer", + "nullable": true + }, "mfa_totp_enroll_enabled": { "type": "boolean", "nullable": true @@ -14459,16 +16855,61 @@ "type": "boolean", "nullable": true }, + "mfa_phone_otp_length": { + "type": "integer" + }, "mfa_phone_template": { "type": "string", "nullable": true }, + "mfa_phone_max_frequency": { + "type": "integer", + "nullable": true + }, "password_hibp_enabled": { "type": "boolean", "nullable": true }, + "password_min_length": { + "type": "integer", + "nullable": true + }, "password_required_characters": { "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "rate_limit_anonymous_users": { + "type": "integer", + "nullable": true + }, + "rate_limit_email_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_sms_sent": { + "type": "integer", + "nullable": true + }, + "rate_limit_token_refresh": { + "type": "integer", + "nullable": true + }, + "rate_limit_verify": { + "type": "integer", + "nullable": true + }, + "rate_limit_otp": { + "type": "integer", + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", "nullable": true }, "refresh_token_rotation_enabled": { @@ -14493,6 +16934,7 @@ }, "security_captcha_provider": { "type": "string", + "enum": ["turnstile", "hcaptcha"], "nullable": true }, "security_captcha_secret": { @@ -14503,10 +16945,18 @@ "type": "boolean", "nullable": true }, + "security_refresh_token_reuse_interval": { + "type": "integer", + "nullable": true + }, "security_update_password_require_reauthentication": { "type": "boolean", "nullable": true }, + "sessions_inactivity_timeout": { + "type": "integer", + "nullable": true + }, "sessions_single_per_user": { "type": "boolean", "nullable": true @@ -14515,6 +16965,10 @@ "type": "string", "nullable": true }, + "sessions_timebox": { + "type": "integer", + "nullable": true + }, "site_url": { "type": "string", "nullable": true @@ -14523,6 +16977,10 @@ "type": "boolean", "nullable": true }, + "sms_max_frequency": { + "type": "integer", + "nullable": true + }, "sms_messagebird_access_key": { "type": "string", "nullable": true @@ -14531,8 +16989,16 @@ "type": "string", "nullable": true }, + "sms_otp_exp": { + "type": "integer", + "nullable": true + }, + "sms_otp_length": { + "type": "integer" + }, "sms_provider": { "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], "nullable": true }, "sms_template": { @@ -14545,6 +17011,7 @@ }, "sms_test_otp_valid_until": { "type": "string", + "format": "date-time", "nullable": true }, "sms_textlocal_api_key": { @@ -14597,12 +17064,17 @@ }, "smtp_admin_email": { "type": "string", + "format": "email", "nullable": true }, "smtp_host": { "type": "string", "nullable": true }, + "smtp_max_frequency": { + "type": "integer", + "nullable": true + }, "smtp_pass": { "type": "string", "nullable": true @@ -14627,26 +17099,6 @@ "required": [ "api_max_request_duration", "db_max_pool_size", - "jwt_exp", - "mailer_otp_exp", - "mailer_otp_length", - "mfa_max_enrolled_factors", - "mfa_phone_otp_length", - "mfa_phone_max_frequency", - "password_min_length", - "rate_limit_anonymous_users", - "rate_limit_email_sent", - "rate_limit_sms_sent", - "rate_limit_token_refresh", - "rate_limit_verify", - "rate_limit_otp", - "security_refresh_token_reuse_interval", - "sessions_inactivity_timeout", - "sessions_timebox", - "sms_max_frequency", - "sms_otp_exp", - "sms_otp_length", - "smtp_max_frequency", "disable_signup", "external_anonymous_users_enabled", "external_apple_additional_client_ids", @@ -14715,6 +17167,7 @@ "external_workos_enabled", "external_workos_secret", "external_workos_url", + "external_web3_solana_enabled", "external_zoom_client_id", "external_zoom_enabled", "external_zoom_secret", @@ -14733,8 +17186,14 @@ "hook_send_email_enabled", "hook_send_email_uri", "hook_send_email_secrets", + "hook_before_user_created_enabled", + "hook_before_user_created_uri", + "hook_before_user_created_secrets", + "jwt_exp", "mailer_allow_unverified_email_sign_ins", "mailer_autoconfirm", + "mailer_otp_exp", + "mailer_otp_length", "mailer_secure_email_change_enabled", "mailer_subjects_confirmation", "mailer_subjects_email_change", @@ -14748,15 +17207,26 @@ "mailer_templates_magic_link_content", "mailer_templates_reauthentication_content", "mailer_templates_recovery_content", + "mfa_max_enrolled_factors", "mfa_totp_enroll_enabled", "mfa_totp_verify_enabled", "mfa_phone_enroll_enabled", "mfa_phone_verify_enabled", "mfa_web_authn_enroll_enabled", "mfa_web_authn_verify_enabled", + "mfa_phone_otp_length", "mfa_phone_template", + "mfa_phone_max_frequency", "password_hibp_enabled", + "password_min_length", "password_required_characters", + "rate_limit_anonymous_users", + "rate_limit_email_sent", + "rate_limit_sms_sent", + "rate_limit_token_refresh", + "rate_limit_verify", + "rate_limit_otp", + "rate_limit_web3", "refresh_token_rotation_enabled", "saml_enabled", "saml_external_url", @@ -14765,13 +17235,19 @@ "security_captcha_provider", "security_captcha_secret", "security_manual_linking_enabled", + "security_refresh_token_reuse_interval", "security_update_password_require_reauthentication", + "sessions_inactivity_timeout", "sessions_single_per_user", "sessions_tags", + "sessions_timebox", "site_url", "sms_autoconfirm", + "sms_max_frequency", "sms_messagebird_access_key", "sms_messagebird_originator", + "sms_otp_exp", + "sms_otp_length", "sms_provider", "sms_template", "sms_test_otp", @@ -14790,6 +17266,7 @@ "sms_vonage_from", "smtp_admin_email", "smtp_host", + "smtp_max_frequency", "smtp_pass", "smtp_port", "smtp_sender_name", @@ -14800,68 +17277,254 @@ "UpdateAuthConfigBody": { "type": "object", "properties": { + "site_url": { + "type": "string", + "pattern": "^[^,]+$", + "nullable": true + }, + "disable_signup": { + "type": "boolean", + "nullable": true + }, "jwt_exp": { "type": "integer", "minimum": 0, - "maximum": 604800 + "maximum": 604800, + "nullable": true + }, + "smtp_admin_email": { + "type": "string", + "format": "email", + "nullable": true + }, + "smtp_host": { + "type": "string", + "nullable": true + }, + "smtp_port": { + "type": "string", + "nullable": true + }, + "smtp_user": { + "type": "string", + "nullable": true + }, + "smtp_pass": { + "type": "string", + "nullable": true }, "smtp_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true + }, + "smtp_sender_name": { + "type": "string", + "nullable": true + }, + "mailer_allow_unverified_email_sign_ins": { + "type": "boolean", + "nullable": true + }, + "mailer_autoconfirm": { + "type": "boolean", + "nullable": true + }, + "mailer_subjects_invite": { + "type": "string", + "nullable": true + }, + "mailer_subjects_confirmation": { + "type": "string", + "nullable": true + }, + "mailer_subjects_recovery": { + "type": "string", + "nullable": true + }, + "mailer_subjects_email_change": { + "type": "string", + "nullable": true + }, + "mailer_subjects_magic_link": { + "type": "string", + "nullable": true + }, + "mailer_subjects_reauthentication": { + "type": "string", + "nullable": true + }, + "mailer_templates_invite_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_confirmation_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_recovery_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_email_change_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_magic_link_content": { + "type": "string", + "nullable": true + }, + "mailer_templates_reauthentication_content": { + "type": "string", + "nullable": true }, "mfa_max_enrolled_factors": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true + }, + "uri_allow_list": { + "type": "string", + "nullable": true + }, + "external_anonymous_users_enabled": { + "type": "boolean", + "nullable": true + }, + "external_email_enabled": { + "type": "boolean", + "nullable": true + }, + "external_phone_enabled": { + "type": "boolean", + "nullable": true + }, + "saml_enabled": { + "type": "boolean", + "nullable": true + }, + "saml_external_url": { + "type": "string", + "pattern": "^[^,]+$", + "nullable": true + }, + "security_captcha_enabled": { + "type": "boolean", + "nullable": true + }, + "security_captcha_provider": { + "type": "string", + "enum": ["turnstile", "hcaptcha"], + "nullable": true + }, + "security_captcha_secret": { + "type": "string", + "nullable": true }, "sessions_timebox": { "type": "integer", - "minimum": 0 + "minimum": 0, + "nullable": true }, "sessions_inactivity_timeout": { "type": "integer", - "minimum": 0 + "minimum": 0, + "nullable": true + }, + "sessions_single_per_user": { + "type": "boolean", + "nullable": true + }, + "sessions_tags": { + "type": "string", + "pattern": "^\\s*([a-zA-Z0-9_-]+(\\s*,+\\s*)?)*\\s*$", + "nullable": true }, "rate_limit_anonymous_users": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_email_sent": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_sms_sent": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_verify": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_token_refresh": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "rate_limit_otp": { "type": "integer", "minimum": 1, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true + }, + "rate_limit_web3": { + "type": "integer", + "minimum": 1, + "maximum": 2147483647, + "nullable": true + }, + "mailer_secure_email_change_enabled": { + "type": "boolean", + "nullable": true + }, + "refresh_token_rotation_enabled": { + "type": "boolean", + "nullable": true + }, + "password_hibp_enabled": { + "type": "boolean", + "nullable": true }, "password_min_length": { "type": "integer", "minimum": 6, - "maximum": 32767 + "maximum": 32767, + "nullable": true + }, + "password_required_characters": { + "type": "string", + "enum": [ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", + "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", + "" + ], + "nullable": true + }, + "security_manual_linking_enabled": { + "type": "boolean", + "nullable": true + }, + "security_update_password_require_reauthentication": { + "type": "boolean", + "nullable": true }, "security_refresh_token_reuse_interval": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "mailer_otp_exp": { "type": "integer", @@ -14871,489 +17534,496 @@ "mailer_otp_length": { "type": "integer", "minimum": 6, - "maximum": 10 + "maximum": 10, + "nullable": true + }, + "sms_autoconfirm": { + "type": "boolean", + "nullable": true }, "sms_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true }, "sms_otp_exp": { "type": "integer", "minimum": 0, - "maximum": 2147483647 + "maximum": 2147483647, + "nullable": true }, "sms_otp_length": { "type": "integer", "minimum": 0, "maximum": 32767 }, + "sms_provider": { + "type": "string", + "enum": ["messagebird", "textlocal", "twilio", "twilio_verify", "vonage"], + "nullable": true + }, + "sms_messagebird_access_key": { + "type": "string", + "nullable": true + }, + "sms_messagebird_originator": { + "type": "string", + "nullable": true + }, + "sms_test_otp": { + "type": "string", + "pattern": "^([0-9]{1,15}=[0-9]+,?)*$", + "nullable": true + }, + "sms_test_otp_valid_until": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "sms_textlocal_api_key": { + "type": "string", + "nullable": true + }, + "sms_textlocal_sender": { + "type": "string", + "nullable": true + }, + "sms_twilio_account_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_auth_token": { + "type": "string", + "nullable": true + }, + "sms_twilio_content_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_message_service_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_account_sid": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_auth_token": { + "type": "string", + "nullable": true + }, + "sms_twilio_verify_message_service_sid": { + "type": "string", + "nullable": true + }, + "sms_vonage_api_key": { + "type": "string", + "nullable": true + }, + "sms_vonage_api_secret": { + "type": "string", + "nullable": true + }, + "sms_vonage_from": { + "type": "string", + "nullable": true + }, + "sms_template": { + "type": "string", + "nullable": true + }, + "hook_mfa_verification_attempt_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_mfa_verification_attempt_uri": { + "type": "string", + "nullable": true + }, + "hook_mfa_verification_attempt_secrets": { + "type": "string", + "nullable": true + }, + "hook_password_verification_attempt_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_password_verification_attempt_uri": { + "type": "string", + "nullable": true + }, + "hook_password_verification_attempt_secrets": { + "type": "string", + "nullable": true + }, + "hook_custom_access_token_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_custom_access_token_uri": { + "type": "string", + "nullable": true + }, + "hook_custom_access_token_secrets": { + "type": "string", + "nullable": true + }, + "hook_send_sms_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_send_sms_uri": { + "type": "string", + "nullable": true + }, + "hook_send_sms_secrets": { + "type": "string", + "nullable": true + }, + "hook_send_email_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_send_email_uri": { + "type": "string", + "nullable": true + }, + "hook_send_email_secrets": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_enabled": { + "type": "boolean", + "nullable": true + }, + "hook_before_user_created_uri": { + "type": "string", + "nullable": true + }, + "hook_before_user_created_secrets": { + "type": "string", + "nullable": true + }, + "external_apple_enabled": { + "type": "boolean", + "nullable": true + }, + "external_apple_client_id": { + "type": "string", + "nullable": true + }, + "external_apple_secret": { + "type": "string", + "nullable": true + }, + "external_apple_additional_client_ids": { + "type": "string", + "nullable": true + }, + "external_azure_enabled": { + "type": "boolean", + "nullable": true + }, + "external_azure_client_id": { + "type": "string", + "nullable": true + }, + "external_azure_secret": { + "type": "string", + "nullable": true + }, + "external_azure_url": { + "type": "string", + "nullable": true + }, + "external_bitbucket_enabled": { + "type": "boolean", + "nullable": true + }, + "external_bitbucket_client_id": { + "type": "string", + "nullable": true + }, + "external_bitbucket_secret": { + "type": "string", + "nullable": true + }, + "external_discord_enabled": { + "type": "boolean", + "nullable": true + }, + "external_discord_client_id": { + "type": "string", + "nullable": true + }, + "external_discord_secret": { + "type": "string", + "nullable": true + }, + "external_facebook_enabled": { + "type": "boolean", + "nullable": true + }, + "external_facebook_client_id": { + "type": "string", + "nullable": true + }, + "external_facebook_secret": { + "type": "string", + "nullable": true + }, + "external_figma_enabled": { + "type": "boolean", + "nullable": true + }, + "external_figma_client_id": { + "type": "string", + "nullable": true + }, + "external_figma_secret": { + "type": "string", + "nullable": true + }, + "external_github_enabled": { + "type": "boolean", + "nullable": true + }, + "external_github_client_id": { + "type": "string", + "nullable": true + }, + "external_github_secret": { + "type": "string", + "nullable": true + }, + "external_gitlab_enabled": { + "type": "boolean", + "nullable": true + }, + "external_gitlab_client_id": { + "type": "string", + "nullable": true + }, + "external_gitlab_secret": { + "type": "string", + "nullable": true + }, + "external_gitlab_url": { + "type": "string", + "nullable": true + }, + "external_google_enabled": { + "type": "boolean", + "nullable": true + }, + "external_google_client_id": { + "type": "string", + "nullable": true + }, + "external_google_secret": { + "type": "string", + "nullable": true + }, + "external_google_additional_client_ids": { + "type": "string", + "nullable": true + }, + "external_google_skip_nonce_check": { + "type": "boolean", + "nullable": true + }, + "external_kakao_enabled": { + "type": "boolean", + "nullable": true + }, + "external_kakao_client_id": { + "type": "string", + "nullable": true + }, + "external_kakao_secret": { + "type": "string", + "nullable": true + }, + "external_keycloak_enabled": { + "type": "boolean", + "nullable": true + }, + "external_keycloak_client_id": { + "type": "string", + "nullable": true + }, + "external_keycloak_secret": { + "type": "string", + "nullable": true + }, + "external_keycloak_url": { + "type": "string", + "nullable": true + }, + "external_linkedin_oidc_enabled": { + "type": "boolean", + "nullable": true + }, + "external_linkedin_oidc_client_id": { + "type": "string", + "nullable": true + }, + "external_linkedin_oidc_secret": { + "type": "string", + "nullable": true + }, + "external_slack_oidc_enabled": { + "type": "boolean", + "nullable": true + }, + "external_slack_oidc_client_id": { + "type": "string", + "nullable": true + }, + "external_slack_oidc_secret": { + "type": "string", + "nullable": true + }, + "external_notion_enabled": { + "type": "boolean", + "nullable": true + }, + "external_notion_client_id": { + "type": "string", + "nullable": true + }, + "external_notion_secret": { + "type": "string", + "nullable": true + }, + "external_slack_enabled": { + "type": "boolean", + "nullable": true + }, + "external_slack_client_id": { + "type": "string", + "nullable": true + }, + "external_slack_secret": { + "type": "string", + "nullable": true + }, + "external_spotify_enabled": { + "type": "boolean", + "nullable": true + }, + "external_spotify_client_id": { + "type": "string", + "nullable": true + }, + "external_spotify_secret": { + "type": "string", + "nullable": true + }, + "external_twitch_enabled": { + "type": "boolean", + "nullable": true + }, + "external_twitch_client_id": { + "type": "string", + "nullable": true + }, + "external_twitch_secret": { + "type": "string", + "nullable": true + }, + "external_twitter_enabled": { + "type": "boolean", + "nullable": true + }, + "external_twitter_client_id": { + "type": "string", + "nullable": true + }, + "external_twitter_secret": { + "type": "string", + "nullable": true + }, + "external_workos_enabled": { + "type": "boolean", + "nullable": true + }, + "external_workos_client_id": { + "type": "string", + "nullable": true + }, + "external_workos_secret": { + "type": "string", + "nullable": true + }, + "external_workos_url": { + "type": "string", + "nullable": true + }, + "external_web3_solana_enabled": { + "type": "boolean", + "nullable": true + }, + "external_zoom_enabled": { + "type": "boolean", + "nullable": true + }, + "external_zoom_client_id": { + "type": "string", + "nullable": true + }, + "external_zoom_secret": { + "type": "string", + "nullable": true + }, "db_max_pool_size": { - "type": "integer" + "type": "integer", + "nullable": true }, "api_max_request_duration": { - "type": "integer" + "type": "integer", + "nullable": true + }, + "mfa_totp_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_totp_verify_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_web_authn_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_web_authn_verify_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_phone_enroll_enabled": { + "type": "boolean", + "nullable": true + }, + "mfa_phone_verify_enabled": { + "type": "boolean", + "nullable": true }, "mfa_phone_max_frequency": { "type": "integer", "minimum": 0, - "maximum": 32767 + "maximum": 32767, + "nullable": true }, "mfa_phone_otp_length": { "type": "integer", "minimum": 0, - "maximum": 32767 - }, - "site_url": { - "type": "string", - "pattern": "/^[^,]+$/" - }, - "disable_signup": { - "type": "boolean" - }, - "smtp_admin_email": { - "type": "string" - }, - "smtp_host": { - "type": "string" - }, - "smtp_port": { - "type": "string" - }, - "smtp_user": { - "type": "string" - }, - "smtp_pass": { - "type": "string" - }, - "smtp_sender_name": { - "type": "string" - }, - "mailer_allow_unverified_email_sign_ins": { - "type": "boolean" - }, - "mailer_autoconfirm": { - "type": "boolean" - }, - "mailer_subjects_invite": { - "type": "string" - }, - "mailer_subjects_confirmation": { - "type": "string" - }, - "mailer_subjects_recovery": { - "type": "string" - }, - "mailer_subjects_email_change": { - "type": "string" - }, - "mailer_subjects_magic_link": { - "type": "string" - }, - "mailer_subjects_reauthentication": { - "type": "string" - }, - "mailer_templates_invite_content": { - "type": "string" - }, - "mailer_templates_confirmation_content": { - "type": "string" - }, - "mailer_templates_recovery_content": { - "type": "string" - }, - "mailer_templates_email_change_content": { - "type": "string" - }, - "mailer_templates_magic_link_content": { - "type": "string" - }, - "mailer_templates_reauthentication_content": { - "type": "string" - }, - "uri_allow_list": { - "type": "string" - }, - "external_anonymous_users_enabled": { - "type": "boolean" - }, - "external_email_enabled": { - "type": "boolean" - }, - "external_phone_enabled": { - "type": "boolean" - }, - "saml_enabled": { - "type": "boolean" - }, - "saml_external_url": { - "type": "string", - "pattern": "/^[^,]+$/" - }, - "security_captcha_enabled": { - "type": "boolean" - }, - "security_captcha_provider": { - "type": "string" - }, - "security_captcha_secret": { - "type": "string" - }, - "sessions_single_per_user": { - "type": "boolean" - }, - "sessions_tags": { - "type": "string", - "pattern": "/^\\s*([a-z0-9_-]+(\\s*,+\\s*)?)*\\s*$/i" - }, - "mailer_secure_email_change_enabled": { - "type": "boolean" - }, - "refresh_token_rotation_enabled": { - "type": "boolean" - }, - "password_hibp_enabled": { - "type": "boolean" - }, - "password_required_characters": { - "type": "string", - "enum": [ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", - "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789", - "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~", - "" - ] - }, - "security_manual_linking_enabled": { - "type": "boolean" - }, - "security_update_password_require_reauthentication": { - "type": "boolean" - }, - "sms_autoconfirm": { - "type": "boolean" - }, - "sms_provider": { - "type": "string" - }, - "sms_messagebird_access_key": { - "type": "string" - }, - "sms_messagebird_originator": { - "type": "string" - }, - "sms_test_otp": { - "type": "string", - "pattern": "/^([0-9]{1,15}=[0-9]+,?)*$/" - }, - "sms_test_otp_valid_until": { - "type": "string" - }, - "sms_textlocal_api_key": { - "type": "string" - }, - "sms_textlocal_sender": { - "type": "string" - }, - "sms_twilio_account_sid": { - "type": "string" - }, - "sms_twilio_auth_token": { - "type": "string" - }, - "sms_twilio_content_sid": { - "type": "string" - }, - "sms_twilio_message_service_sid": { - "type": "string" - }, - "sms_twilio_verify_account_sid": { - "type": "string" - }, - "sms_twilio_verify_auth_token": { - "type": "string" - }, - "sms_twilio_verify_message_service_sid": { - "type": "string" - }, - "sms_vonage_api_key": { - "type": "string" - }, - "sms_vonage_api_secret": { - "type": "string" - }, - "sms_vonage_from": { - "type": "string" - }, - "sms_template": { - "type": "string" - }, - "hook_mfa_verification_attempt_enabled": { - "type": "boolean" - }, - "hook_mfa_verification_attempt_uri": { - "type": "string" - }, - "hook_mfa_verification_attempt_secrets": { - "type": "string" - }, - "hook_password_verification_attempt_enabled": { - "type": "boolean" - }, - "hook_password_verification_attempt_uri": { - "type": "string" - }, - "hook_password_verification_attempt_secrets": { - "type": "string" - }, - "hook_custom_access_token_enabled": { - "type": "boolean" - }, - "hook_custom_access_token_uri": { - "type": "string" - }, - "hook_custom_access_token_secrets": { - "type": "string" - }, - "hook_send_sms_enabled": { - "type": "boolean" - }, - "hook_send_sms_uri": { - "type": "string" - }, - "hook_send_sms_secrets": { - "type": "string" - }, - "hook_send_email_enabled": { - "type": "boolean" - }, - "hook_send_email_uri": { - "type": "string" - }, - "hook_send_email_secrets": { - "type": "string" - }, - "external_apple_enabled": { - "type": "boolean" - }, - "external_apple_client_id": { - "type": "string" - }, - "external_apple_secret": { - "type": "string" - }, - "external_apple_additional_client_ids": { - "type": "string" - }, - "external_azure_enabled": { - "type": "boolean" - }, - "external_azure_client_id": { - "type": "string" - }, - "external_azure_secret": { - "type": "string" - }, - "external_azure_url": { - "type": "string" - }, - "external_bitbucket_enabled": { - "type": "boolean" - }, - "external_bitbucket_client_id": { - "type": "string" - }, - "external_bitbucket_secret": { - "type": "string" - }, - "external_discord_enabled": { - "type": "boolean" - }, - "external_discord_client_id": { - "type": "string" - }, - "external_discord_secret": { - "type": "string" - }, - "external_facebook_enabled": { - "type": "boolean" - }, - "external_facebook_client_id": { - "type": "string" - }, - "external_facebook_secret": { - "type": "string" - }, - "external_figma_enabled": { - "type": "boolean" - }, - "external_figma_client_id": { - "type": "string" - }, - "external_figma_secret": { - "type": "string" - }, - "external_github_enabled": { - "type": "boolean" - }, - "external_github_client_id": { - "type": "string" - }, - "external_github_secret": { - "type": "string" - }, - "external_gitlab_enabled": { - "type": "boolean" - }, - "external_gitlab_client_id": { - "type": "string" - }, - "external_gitlab_secret": { - "type": "string" - }, - "external_gitlab_url": { - "type": "string" - }, - "external_google_enabled": { - "type": "boolean" - }, - "external_google_client_id": { - "type": "string" - }, - "external_google_secret": { - "type": "string" - }, - "external_google_additional_client_ids": { - "type": "string" - }, - "external_google_skip_nonce_check": { - "type": "boolean" - }, - "external_kakao_enabled": { - "type": "boolean" - }, - "external_kakao_client_id": { - "type": "string" - }, - "external_kakao_secret": { - "type": "string" - }, - "external_keycloak_enabled": { - "type": "boolean" - }, - "external_keycloak_client_id": { - "type": "string" - }, - "external_keycloak_secret": { - "type": "string" - }, - "external_keycloak_url": { - "type": "string" - }, - "external_linkedin_oidc_enabled": { - "type": "boolean" - }, - "external_linkedin_oidc_client_id": { - "type": "string" - }, - "external_linkedin_oidc_secret": { - "type": "string" - }, - "external_slack_oidc_enabled": { - "type": "boolean" - }, - "external_slack_oidc_client_id": { - "type": "string" - }, - "external_slack_oidc_secret": { - "type": "string" - }, - "external_notion_enabled": { - "type": "boolean" - }, - "external_notion_client_id": { - "type": "string" - }, - "external_notion_secret": { - "type": "string" - }, - "external_slack_enabled": { - "type": "boolean" - }, - "external_slack_client_id": { - "type": "string" - }, - "external_slack_secret": { - "type": "string" - }, - "external_spotify_enabled": { - "type": "boolean" - }, - "external_spotify_client_id": { - "type": "string" - }, - "external_spotify_secret": { - "type": "string" - }, - "external_twitch_enabled": { - "type": "boolean" - }, - "external_twitch_client_id": { - "type": "string" - }, - "external_twitch_secret": { - "type": "string" - }, - "external_twitter_enabled": { - "type": "boolean" - }, - "external_twitter_client_id": { - "type": "string" - }, - "external_twitter_secret": { - "type": "string" - }, - "external_workos_enabled": { - "type": "boolean" - }, - "external_workos_client_id": { - "type": "string" - }, - "external_workos_secret": { - "type": "string" - }, - "external_workos_url": { - "type": "string" - }, - "external_zoom_enabled": { - "type": "boolean" - }, - "external_zoom_client_id": { - "type": "string" - }, - "external_zoom_secret": { - "type": "string" - }, - "mfa_totp_enroll_enabled": { - "type": "boolean" - }, - "mfa_totp_verify_enabled": { - "type": "boolean" - }, - "mfa_web_authn_enroll_enabled": { - "type": "boolean" - }, - "mfa_web_authn_verify_enabled": { - "type": "boolean" - }, - "mfa_phone_enroll_enabled": { - "type": "boolean" - }, - "mfa_phone_verify_enabled": { - "type": "boolean" + "maximum": 32767, + "nullable": true }, "mfa_phone_template": { - "type": "string" + "type": "string", + "nullable": true } } }, @@ -15366,16 +18036,15 @@ "jwks_url": { "type": "string" }, - "custom_jwks": { - "type": "object" - } + "custom_jwks": {} } }, "ThirdPartyAuth": { "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "type": { "type": "string" @@ -15389,11 +18058,9 @@ "nullable": true }, "custom_jwks": { - "type": "object", "nullable": true }, "resolved_jwks": { - "type": "object", "nullable": true }, "inserted_at": { @@ -15409,23 +18076,6 @@ }, "required": ["id", "type", "inserted_at", "updated_at"] }, - "ProjectAvailableRestoreVersion": { - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "release_channel": { - "type": "string", - "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] - }, - "postgres_engine": { - "type": "string", - "enum": ["13", "14", "15", "17", "17-oriole"] - } - }, - "required": ["version", "release_channel", "postgres_engine"] - }, "GetProjectAvailableRestoreVersionsResponse": { "type": "object", "properties": { @@ -15452,12 +18102,7 @@ }, "required": ["available_versions"] }, - "RestoreProjectBodyDto": { - "type": "object", - "properties": {}, - "hideDefinitions": ["release_channel", "postgres_engine"] - }, - "ListProjectAddonsResponseDto": { + "ListProjectAddonsResponse": { "type": "object", "properties": { "selected_addons": { @@ -15494,7 +18139,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -15547,26 +18200,7 @@ "required": ["description", "type", "interval", "amount"] }, "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } + "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] @@ -15614,7 +18248,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -15667,26 +18309,7 @@ "required": ["description", "type", "interval", "amount"] }, "meta": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } + "description": "Any JSON-serializable value" } }, "required": ["id", "name", "price"] @@ -15699,7 +18322,7 @@ }, "required": ["selected_addons", "available_addons"] }, - "ApplyProjectAddonBodyDto": { + "ApplyProjectAddonBody": { "type": "object", "properties": { "addon_variant": { @@ -15716,7 +18339,15 @@ "ci_4xlarge", "ci_8xlarge", "ci_12xlarge", - "ci_16xlarge" + "ci_16xlarge", + "ci_24xlarge", + "ci_24xlarge_optimized_cpu", + "ci_24xlarge_optimized_memory", + "ci_24xlarge_high_memory", + "ci_48xlarge", + "ci_48xlarge_optimized_cpu", + "ci_48xlarge_optimized_memory", + "ci_48xlarge_high_memory" ] }, { @@ -15748,12 +18379,176 @@ }, "required": ["addon_variant", "addon_type"] }, - "V1AnalyticsResponse": { + "ProjectClaimTokenResponse": { "type": "object", "properties": { + "token_alias": { + "type": "string" + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "type": "string", + "format": "uuid" + } + }, + "required": ["token_alias", "expires_at", "created_at", "created_by"] + }, + "CreateProjectClaimTokenResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "token_alias": { + "type": "string" + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "type": "string", + "format": "uuid" + } + }, + "required": ["token", "token_alias", "expires_at", "created_at", "created_by"] + }, + "V1ProjectAdvisorsResponse": { + "type": "object", + "properties": { + "lints": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "enum": [ + "unindexed_foreign_keys", + "auth_users_exposed", + "auth_rls_initplan", + "no_primary_key", + "unused_index", + "multiple_permissive_policies", + "policy_exists_rls_disabled", + "rls_enabled_no_policy", + "duplicate_index", + "security_definer_view", + "function_search_path_mutable", + "rls_disabled_in_public", + "extension_in_public", + "rls_references_user_metadata", + "materialized_view_in_api", + "foreign_table_in_api", + "unsupported_reg_types", + "auth_otp_long_expiry", + "auth_otp_short_length", + "ssl_not_enforced", + "network_restrictions_not_set", + "password_requirements_min_length", + "pitr_not_enabled", + "auth_leaked_password_protection", + "auth_insufficient_mfa_options", + "auth_password_policy_missing", + "leaked_service_key", + "no_backup_admin" + ] + }, + "title": { + "type": "string" + }, + "level": { + "type": "string", + "enum": ["ERROR", "WARN", "INFO"] + }, + "facing": { + "type": "string", + "enum": ["EXTERNAL"] + }, + "categories": { + "type": "array", + "items": { + "type": "string", + "enum": ["PERFORMANCE", "SECURITY"] + } + }, + "description": { + "type": "string" + }, + "detail": { + "type": "string" + }, + "remediation": { + "type": "string" + }, + "metadata": { + "type": "object", + "properties": { + "schema": { + "type": "string" + }, + "name": { + "type": "string" + }, + "entity": { + "type": "string" + }, + "type": { + "type": "string", + "enum": ["table", "view", "auth", "function", "extension", "compliance"] + }, + "fkey_name": { + "type": "string" + }, + "fkey_columns": { + "type": "array", + "items": { + "type": "number" + } + } + } + }, + "cache_key": { + "type": "string" + } + }, + "required": [ + "name", + "title", + "level", + "facing", + "categories", + "description", + "detail", + "remediation", + "cache_key" + ] + } + } + }, + "required": ["lints"] + }, + "AnalyticsResponse": { + "type": "object", + "properties": { + "result": { + "type": "array", + "items": {} + }, "error": { "oneOf": [ { + "type": "string" + }, + { + "type": "object", "properties": { "code": { "type": "number" @@ -15761,6 +18556,7 @@ "errors": { "type": "array", "items": { + "type": "object", "properties": { "domain": { "type": "string" @@ -15777,7 +18573,8 @@ "reason": { "type": "string" } - } + }, + "required": ["domain", "location", "locationType", "message", "reason"] } }, "message": { @@ -15786,18 +18583,10 @@ "status": { "type": "string" } - } - }, - { - "type": "string" + }, + "required": ["code", "errors", "message", "status"] } ] - }, - "result": { - "type": "array", - "items": { - "type": "object" - } } } }, @@ -15817,17 +18606,46 @@ "required": ["version"] } }, + "V1CreateMigrationBody": { + "type": "object", + "properties": { + "query": { + "type": "string", + "minLength": 1 + }, + "name": { + "type": "string" + } + }, + "required": ["query"] + }, + "V1UpsertMigrationBody": { + "type": "object", + "properties": { + "query": { + "type": "string", + "minLength": 1 + }, + "name": { + "type": "string" + } + }, + "required": ["query"] + }, "V1RunQueryBody": { "type": "object", "properties": { "query": { "type": "string", "minLength": 1 + }, + "read_only": { + "type": "boolean" } }, "required": ["query"] }, - "GetProjectDbMetadataResponseDto": { + "GetProjectDbMetadataResponse": { "type": "object", "properties": { "databases": { @@ -15879,10 +18697,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -15895,6 +18715,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] @@ -15919,42 +18742,49 @@ "required": ["slug", "name", "body"] }, "BulkUpdateFunctionBody": { - "type": "object", - "properties": { - "id": { - "type": "string" + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "slug": { + "type": "string", + "pattern": "^[A-Za-z0-9_-]+$" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string", + "enum": ["ACTIVE", "REMOVED", "THROTTLED"] + }, + "version": { + "type": "integer" + }, + "created_at": { + "type": "integer", + "format": "int64" + }, + "verify_jwt": { + "type": "boolean" + }, + "import_map": { + "type": "boolean" + }, + "entrypoint_path": { + "type": "string" + }, + "import_map_path": { + "type": "string" + }, + "ezbr_sha256": { + "type": "string" + } }, - "slug": { - "type": "string", - "pattern": "^[A-Za-z0-9_-]+$" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string", - "enum": ["ACTIVE", "REMOVED", "THROTTLED"] - }, - "version": { - "type": "integer" - }, - "created_at": { - "type": "integer" - }, - "verify_jwt": { - "type": "boolean" - }, - "import_map": { - "type": "boolean" - }, - "entrypoint_path": { - "type": "string" - }, - "import_map_path": { - "type": "string" - } - }, - "required": ["id", "slug", "name", "status", "version"] + "required": ["id", "slug", "name", "status", "version"] + } }, "BulkUpdateFunctionResponse": { "type": "object", @@ -15981,10 +18811,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -15997,6 +18829,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] @@ -16062,10 +18897,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -16078,6 +18915,9 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version"] @@ -16102,10 +18942,12 @@ "type": "integer" }, "created_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "updated_at": { - "type": "integer" + "type": "integer", + "format": "int64" }, "verify_jwt": { "type": "boolean" @@ -16118,10 +18960,17 @@ }, "import_map_path": { "type": "string" + }, + "ezbr_sha256": { + "type": "string" } }, "required": ["id", "slug", "name", "status", "version", "created_at", "updated_at"] }, + "StreamableFile": { + "type": "object", + "properties": {} + }, "V1UpdateFunctionBody": { "type": "object", "properties": { @@ -16160,81 +19009,6 @@ }, "required": ["id", "name", "owner", "created_at", "updated_at", "public"] }, - "AttributeValue": { - "type": "object", - "properties": { - "default": { - "oneOf": [ - { - "type": "object" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "boolean" - } - ] - }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "array": { - "type": "boolean" - } - } - }, - "AttributeMapping": { - "type": "object", - "properties": { - "keys": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "default": { - "oneOf": [ - { - "type": "object" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "boolean" - } - ] - }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "array": { - "type": "boolean" - } - } - } - } - }, - "required": ["keys"] - }, "CreateProviderBody": { "type": "object", "properties": { @@ -16263,10 +19037,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16279,15 +19063,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16300,84 +19075,6 @@ }, "required": ["type"] }, - "SamlDescriptor": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "entity_id": { - "type": "string" - }, - "metadata_url": { - "type": "string" - }, - "metadata_xml": { - "type": "string" - }, - "attribute_mapping": { - "type": "object", - "properties": { - "keys": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "default": { - "oneOf": [ - { - "type": "object" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "boolean" - } - ] - }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "array": { - "type": "boolean" - } - } - } - } - }, - "required": ["keys"] - } - }, - "required": ["id", "entity_id"] - }, - "Domain": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": ["id"] - }, "CreateProviderResponse": { "type": "object", "properties": { @@ -16407,10 +19104,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16423,111 +19130,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "array": { - "type": "boolean" - } - } - } - } - }, - "required": ["keys"] - } - }, - "required": ["id", "entity_id"] - }, - "domains": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": ["id"] - } - }, - "created_at": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - }, - "required": ["id"] - }, - "Provider": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "saml": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "entity_id": { - "type": "string" - }, - "metadata_url": { - "type": "string" - }, - "metadata_xml": { - "type": "string" - }, - "attribute_mapping": { - "type": "object", - "properties": { - "keys": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "default": { - "oneOf": [ - { - "type": "object" - }, - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "boolean" - } - ] - }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16604,10 +19206,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16620,15 +19232,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16704,10 +19307,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16720,15 +19333,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16794,10 +19398,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16810,15 +19424,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16859,10 +19464,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16875,15 +19490,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -16955,10 +19561,20 @@ "additionalProperties": { "type": "object", "properties": { + "name": { + "type": "string" + }, + "names": { + "type": "array", + "items": { + "type": "string" + } + }, "default": { "oneOf": [ { - "type": "object" + "type": "object", + "properties": {} }, { "type": "number" @@ -16971,15 +19587,6 @@ } ] }, - "name": { - "type": "string" - }, - "names": { - "type": "array", - "items": { - "type": "string" - } - }, "array": { "type": "boolean" } @@ -17022,35 +19629,6 @@ }, "required": ["id"] }, - "V1Backup": { - "type": "object", - "properties": { - "status": { - "type": "string", - "enum": ["COMPLETED", "FAILED", "PENDING", "REMOVED", "ARCHIVED", "CANCELLED"] - }, - "is_physical_backup": { - "type": "boolean" - }, - "inserted_at": { - "type": "string" - } - }, - "required": ["status", "is_physical_backup", "inserted_at"] - }, - "V1PhysicalBackup": { - "type": "object", - "properties": { - "earliest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" - }, - "latest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" - } - } - }, "V1BackupsResponse": { "type": "object", "properties": { @@ -17068,30 +19646,28 @@ "items": { "type": "object", "properties": { + "is_physical_backup": { + "type": "boolean" + }, "status": { "type": "string", "enum": ["COMPLETED", "FAILED", "PENDING", "REMOVED", "ARCHIVED", "CANCELLED"] }, - "is_physical_backup": { - "type": "boolean" - }, "inserted_at": { "type": "string" } }, - "required": ["status", "is_physical_backup", "inserted_at"] + "required": ["is_physical_backup", "status", "inserted_at"] } }, "physical_backup_data": { "type": "object", "properties": { "earliest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" + "type": "integer" }, "latest_physical_backup_date_unix": { - "type": "integer", - "format": "int64" + "type": "integer" } } } @@ -17109,6 +19685,39 @@ }, "required": ["recovery_time_target_unix"] }, + "V1RestorePointPostBody": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 20 + } + }, + "required": ["name"] + }, + "V1RestorePointResponse": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string", + "enum": ["AVAILABLE", "PENDING", "REMOVED"] + } + }, + "required": ["name", "status"] + }, + "V1UndoBody": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 20 + } + }, + "required": ["name"] + }, "V1OrganizationMemberResponse": { "type": "object", "properties": { @@ -17130,17 +19739,15 @@ }, "required": ["user_id", "user_name", "role_name", "mfa_enabled"] }, - "BillingPlanId": { - "type": "string", - "enum": ["free", "pro", "team", "enterprise"] - }, - "ReleaseChannel": { - "type": "string", - "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] - }, "V1OrganizationSlugResponse": { "type": "object", "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, "plan": { "type": "string", "enum": ["free", "pro", "team", "enterprise"] @@ -17149,7 +19756,11 @@ "type": "array", "items": { "type": "string", - "enum": ["AI_SQL_GENERATOR_OPT_IN"] + "enum": [ + "AI_SQL_GENERATOR_OPT_IN", + "AI_DATA_GENERATOR_OPT_IN", + "AI_LOG_GENERATOR_OPT_IN" + ] } }, "allowed_release_channels": { @@ -17158,15 +19769,133 @@ "type": "string", "enum": ["internal", "alpha", "beta", "ga", "withdrawn", "preview"] } - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" } }, - "required": ["opt_in_tags", "allowed_release_channels", "id", "name"] + "required": ["id", "name", "opt_in_tags", "allowed_release_channels"] + }, + "OrganizationProjectClaimResponse": { + "type": "object", + "properties": { + "project": { + "type": "object", + "properties": { + "ref": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["ref", "name"] + }, + "preview": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "warnings": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "info": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": ["key", "message"] + } + }, + "members_exceeding_free_project_limit": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "limit": { + "type": "number" + } + }, + "required": ["name", "limit"] + } + }, + "target_organization_eligible": { + "type": "boolean", + "nullable": true + }, + "target_organization_has_free_project_slots": { + "type": "boolean", + "nullable": true + }, + "source_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"] + }, + "target_subscription_plan": { + "type": "string", + "enum": ["free", "pro", "team", "enterprise"], + "nullable": true + } + }, + "required": [ + "valid", + "warnings", + "errors", + "info", + "members_exceeding_free_project_limit", + "target_organization_eligible", + "target_organization_has_free_project_slots", + "source_subscription_plan", + "target_subscription_plan" + ] + }, + "expires_at": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "type": "string", + "format": "uuid" + } + }, + "required": ["project", "preview", "expires_at", "created_at", "created_by"] } } } diff --git a/apps/studio/components/grid/components/header/ExportDialog.tsx b/apps/studio/components/grid/components/header/ExportDialog.tsx index 83d6f275d74..59ffe39bd9a 100644 --- a/apps/studio/components/grid/components/header/ExportDialog.tsx +++ b/apps/studio/components/grid/components/header/ExportDialog.tsx @@ -3,7 +3,6 @@ import { getConnectionStrings } from 'components/interfaces/Connect/DatabaseSett import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { pluckObjectFields } from 'lib/helpers' import { useState } from 'react' -import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Button, cn, @@ -23,13 +22,14 @@ import { import { Admonition } from 'ui-patterns' interface ExportDialogProps { + table?: { name: string; schema: string } open: boolean onOpenChange: (open: boolean) => void } -export const ExportDialog = ({ open, onOpenChange }: ExportDialogProps) => { +export const ExportDialog = ({ table, open, onOpenChange }: ExportDialogProps) => { const { ref: projectRef } = useParams() - const snap = useTableEditorTableStateSnapshot() + const [selectedTab, setSelectedTab] = useState('csv') const { data: databases } = useReadReplicasQuery({ projectRef }) @@ -47,14 +47,14 @@ export const ExportDialog = ({ open, onOpenChange }: ExportDialogProps) => { poolingInfo: { connectionString: '', db_host: '', db_name: '', db_port: 0, db_user: '' }, }) - const outputName = `${snap.table.name}_rows` + const outputName = `${table?.name}_rows` const csvExportCommand = ` -${connectionStrings.direct.psql} -c "COPY (SELECT * FROM "${snap.table.schema}"."${snap.table.name}") TO STDOUT WITH CSV HEADER DELIMITER ',';" > ${outputName}.csv +${connectionStrings.direct.psql} -c "COPY (SELECT * FROM "${table?.schema}"."${table?.name}") TO STDOUT WITH CSV HEADER DELIMITER ',';" > ${outputName}.csv `.trim() const sqlExportCommand = ` -pg_dump -h ${db_host} -p ${db_port} -d ${db_name} -U ${db_user} --table="${snap.table.schema}.${snap.table.name}" --data-only --column-inserts > ${outputName}.sql +pg_dump -h ${db_host} -p ${db_port} -d ${db_name} -U ${db_user} --table="${table?.schema}.${table?.name}" --data-only --column-inserts > ${outputName}.sql `.trim() return ( diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index 419f5f16b1e..67c129942a3 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -17,7 +17,7 @@ import { useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query' import { fetchAllTableRows, useTableRowsQuery } from 'data/table-rows/table-rows-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { RoleImpersonationState } from 'lib/role-impersonation' import { useRoleImpersonationStateSnapshot, @@ -88,10 +88,12 @@ export default Header const DefaultHeader = () => { const { ref: projectRef } = useParams() - const tableEditorSnap = useTableEditorStateSnapshot() + const { data: org } = useSelectedOrganizationQuery() + const snap = useTableEditorTableStateSnapshot() - const org = useSelectedOrganization() + const tableEditorSnap = useTableEditorStateSnapshot() const canCreateColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + const { mutate: sendEvent } = useSendEventMutation() const onAddRow = @@ -285,7 +287,7 @@ const RowHeader = () => { }) } - async function onRowsExportCSV() { + const onRowsExportCSV = async () => { setIsExporting(true) if (snap.allRowsSelected && totalRows > MAX_EXPORT_ROW_COUNT) { @@ -357,7 +359,7 @@ const RowHeader = () => { columns: snap.table!.columns.map((column) => column.name), }) const csvData = new Blob([csv], { type: 'text/csv;charset=utf-8;' }) - toast.success(`Downloaded ${rows.length} rows to CSV`, { + toast.success(`Downloaded ${rows.length} rows as CSV`, { id: toastId, closeButton: true, duration: 4000, @@ -366,7 +368,7 @@ const RowHeader = () => { setIsExporting(false) } - async function onRowsExportSQL() { + const onRowsExportSQL = async () => { setIsExporting(true) if (snap.allRowsSelected && totalRows > MAX_EXPORT_ROW_COUNT) { @@ -431,7 +433,7 @@ const RowHeader = () => { const sqlStatements = formatTableRowsToSQL(snap.table, rows) const sqlData = new Blob([sqlStatements], { type: 'text/sql;charset=utf-8;' }) - toast.success(`Downloading ${rows.length} rows to SQL`, { + toast.success(`Downloading ${rows.length} rows as SQL`, { id: toastId, closeButton: true, duration: 4000, @@ -440,6 +442,27 @@ const RowHeader = () => { setIsExporting(false) } + const onRowsExportJSON = async () => { + if (!project) { + return toast.error('Project is required') + } + + setIsExporting(true) + const toastId = toast.loading( + `Exporting ${snap.selectedRows.size} row${snap.selectedRows.size > 1 ? 's' : ''} from ${snap.table.name}` + ) + const rows = allRows.filter((x) => snap.selectedRows.has(x.idx)) + const sqlData = new Blob([JSON.stringify(rows)], { type: 'text/sql;charset=utf-8;' }) + toast.success(`Downloading ${rows.length} rows as JSON`, { + id: toastId, + closeButton: true, + duration: 4000, + }) + saveAs(sqlData, `${snap.table!.name}_rows.json`) + + setIsExporting(false) + } + function deselectRows() { snap.setSelectedRows(new Set()) } @@ -494,13 +517,15 @@ const RowHeader = () => { Export as SQL {/* [Joshen] Should make this available for all cases, but that'll involve updating the Dialog's SQL output to be dynamic based on any filters applied */} - {snap.allRowsSelected && ( + {snap.allRowsSelected ? ( setShowExportModal(true)}>

Export via CLI

Recommended for large tables

+ ) : ( + Export as JSON )} @@ -517,7 +542,11 @@ const RowHeader = () => { )}
- setShowExportModal(false)} /> + setShowExportModal(false)} + /> ) } diff --git a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx index a23bf75eb81..266b0a636c4 100644 --- a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx +++ b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx @@ -42,13 +42,16 @@ import { Form_Shadcn_, Input_Shadcn_, Label_Shadcn_ as Label, + Switch, cn, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { PermissionAction } from '@supabase/shared-types/out/constants' +import { useFlag } from 'hooks/ui/useFlag' export const CreateBranchModal = () => { + const allowDataBranching = useFlag('allowDataBranching') const { ref } = useParams() const router = useRouter() const queryClient = useQueryClient() @@ -141,6 +144,7 @@ export const CreateBranchModal = () => { (val) => gitlessBranching || !githubConnection || (val && val.length > 0), 'Git branch name is required when GitHub is connected' ), + withData: z.boolean().default(false).optional(), }) .superRefine(async (val, ctx) => { if (val.gitBranchName && val.gitBranchName.length > 0 && githubConnection?.repository.id) { @@ -164,7 +168,7 @@ export const CreateBranchModal = () => { mode: 'onSubmit', reValidateMode: 'onBlur', resolver: zodResolver(FormSchema), - defaultValues: { branchName: '', gitBranchName: '' }, + defaultValues: { branchName: '', gitBranchName: '', withData: false }, }) const canSubmit = !isCreating && !isChecking @@ -182,7 +186,9 @@ export const CreateBranchModal = () => { createBranch({ projectRef, branchName: data.branchName, + is_default: false, ...(data.gitBranchName ? { gitBranch: data.gitBranchName } : {}), + ...(allowDataBranching ? { withData: data.withData } : {}), }) } @@ -294,6 +300,7 @@ export const CreateBranchModal = () => { )} /> )} + {isLoadingConnections && } {isErrorConnections && ( { )}
-

+

Keep this preview branch in sync with a chosen GitHub branch

@@ -325,6 +332,23 @@ export const CreateBranchModal = () => { )} )} + {allowDataBranching && ( + ( + + + + + + )} + /> + )} diff --git a/apps/studio/components/interfaces/DataWarehouse/CollectionForm.tsx b/apps/studio/components/interfaces/DataWarehouse/CollectionForm.tsx deleted file mode 100644 index 5bb7e906d59..00000000000 --- a/apps/studio/components/interfaces/DataWarehouse/CollectionForm.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { zodResolver } from '@hookform/resolvers/zod' -import { useForm } from 'react-hook-form' -import { z } from 'zod' - -import { - Button, - FormControl_Shadcn_, - FormField_Shadcn_, - FormMessage_Shadcn_, - Form_Shadcn_, - Input_Shadcn_, - Modal, -} from 'ui' -import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' -import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' -import { Admonition } from 'ui-patterns' -import { useRouter } from 'next/router' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' - -export interface CollectionFormValues { - name: string - retention_days: number -} - -interface CollectionFormProps { - initialValues?: Partial - onSubmit: (values: CollectionFormValues) => void - isLoading?: boolean - onCancelClick: () => void -} - -export const CollectionForm = ({ - initialValues, - onSubmit, - isLoading, - onCancelClick, -}: CollectionFormProps) => { - const { plan, isLoading: planLoading } = useCurrentOrgPlan() - const router = useRouter() - const currentOrg = useSelectedOrganization() - - function getMaxRetentionDays() { - if (planLoading) return 1 - if (plan?.id === 'free') return 3 - else return 90 - } - const maxRetentionDays = getMaxRetentionDays() - - const FormSchema = z.object({ - name: z.string().min(1), - retention_days: z.coerce.number().min(1).max(maxRetentionDays).multipleOf(1).positive().int(), - }) - - const form = useForm({ - resolver: zodResolver(FormSchema), - defaultValues: { - name: initialValues?.name || '', - retention_days: initialValues?.retention_days || maxRetentionDays, - }, - }) - - const handleSubmit = form.handleSubmit(onSubmit) - - const formatDays = (days: number) => { - return days === 1 ? `1 day` : `${days} days` - } - - const retentionDescription = (days: number) => { - if (!Boolean(days) || days < 1) - return <>Your plan allows for a maximum of {formatDays(maxRetentionDays)}. - return ( - <> - Your logs will be removed after {formatDays(days)}.
- Your plan allows for a maximum of {formatDays(maxRetentionDays)}. - - ) - } - - return ( - -
- - ( - - - - - - )} - /> - ( - - -
- - - days - -
-
-
- )} - /> -
- - {plan?.id === 'free' && ( - <> - - - Upgrade to the pro plan to increase retention to 90 days. - -
- } - /> - - )} - - - - - - - - ) -} diff --git a/apps/studio/components/interfaces/DataWarehouse/CreateWarehouseCollection.tsx b/apps/studio/components/interfaces/DataWarehouse/CreateWarehouseCollection.tsx deleted file mode 100644 index 4b2126065e4..00000000000 --- a/apps/studio/components/interfaces/DataWarehouse/CreateWarehouseCollection.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useRouter } from 'next/router' -import { toast } from 'sonner' - -import { useParams } from 'common' -import { useCreateCollection } from 'data/analytics/warehouse-collections-create-mutation' -import { Modal } from 'ui' -import { CollectionForm } from './CollectionForm' - -export const CreateWarehouseCollectionModal = ({ - open, - onOpenChange, -}: { - open: boolean - onOpenChange: (open: boolean) => void -}) => { - const router = useRouter() - const { ref } = useParams() - - const { mutate: createCollection, isLoading } = useCreateCollection({ - onSuccess: (data) => { - onOpenChange(false) - toast.success('Collection created successfully') - router.push(`/project/${ref}/logs/collections/${data.token}`) - }, - onError: (error) => { - toast.error(error.message) - }, - }) - - return ( - onOpenChange(false)} - header="Create collection" - visible={open} - hideFooter - > - onOpenChange(false)} - isLoading={isLoading} - onSubmit={(vals) => { - if (!ref) { - return - } - createCollection({ - projectRef: ref, - name: vals.name, - retention_days: vals.retention_days, - }) - }} - /> - - ) -} diff --git a/apps/studio/components/interfaces/DataWarehouse/TestCollectionDialog.tsx b/apps/studio/components/interfaces/DataWarehouse/TestCollectionDialog.tsx deleted file mode 100644 index 489a9e29860..00000000000 --- a/apps/studio/components/interfaces/DataWarehouse/TestCollectionDialog.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import { Select, SelectContent, SelectItem, SelectTrigger } from '@ui/components/shadcn/ui/select' -import CopyButton from 'components/ui/CopyButton' -import type { WarehouseAccessTokensData } from 'data/analytics/warehouse-access-tokens-query' -import type { WarehouseCollectionsData } from 'data/analytics/warehouse-collections-query' -import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' -import { - Button, - Checkbox_Shadcn_, - CodeBlock, - Input_Shadcn_, - Label_Shadcn_, - Separator, - Sheet, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetSection, - SheetTitle, - SheetTrigger, - Tooltip, - TooltipContent, - TooltipTrigger, -} from 'ui' -import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' - -export function TestCollectionDialog({ - accessTokens, - collectionToken, - collections, - open, - onOpenChange, - onSubmit, -}: { - accessTokens: WarehouseAccessTokensData['data'] - collections: WarehouseCollectionsData - collectionToken: string - projectRef: string - open: boolean - onOpenChange: (open: boolean) => void - onSubmit: () => void -}) { - const router = useRouter() - const BASE_WAREHOUSE_URL = `https://api.warehouse.tech/api/events` - const [testAccessToken, setTestAccessToken] = useState('') - const [selectedCollection, setSelectedCollection] = useState(collectionToken || '') - const [showAccessToken, setShowAccessToken] = useState(false) - - useEffect(() => { - setSelectedCollection(collectionToken) - }, [collectionToken]) - - useEffect(() => { - if (accessTokens.length > 0) { - setTestAccessToken(accessTokens[0].token) - } - }, [accessTokens]) - - const selectedAccessToken = accessTokens.find((token) => token.token === testAccessToken) - const selectedCollectionName = collections?.find((col) => col.token === selectedCollection)?.name - - function getcURL(accessToken: string) { - return `curl -X "POST" "${BASE_WAREHOUSE_URL}?source=${selectedCollection}" \\ - -H 'Content-Type: application/json' \\ - -H 'Authorization: Bearer ${accessToken}' \\ - -d $'{ - "event_message": "Test event message", - "metadata": { - "ip_address": "100.100.100.100", - "request_method": "POST", - "custom_user_data": { - "foo": "bar" - }, - "datacenter": "aws", - "request_headers": { - "connection": "close", - "user_agent": "chrome" - } - } - }' -` - } - - return ( - - - - - - - - {accessTokens.length === 0 && ( - Create an access token to connect to your collection - )} - - - - - Send events to this collection - - Use the following cURL command to send events to this collection - - - - - - - - - - - - - - - - - - - - - - -
-
- setShowAccessToken(!showAccessToken)} - /> - Show access token -
- -
- -
- - {getcURL(showAccessToken ? testAccessToken : '********************')} - -
-
- - -

- Once you send an event, refresh the page to see it in the collection. -

-
- -
-
-
-
- ) -} diff --git a/apps/studio/components/interfaces/DataWarehouse/WarehouseCollectionDetail.tsx b/apps/studio/components/interfaces/DataWarehouse/WarehouseCollectionDetail.tsx deleted file mode 100644 index f0be4402a71..00000000000 --- a/apps/studio/components/interfaces/DataWarehouse/WarehouseCollectionDetail.tsx +++ /dev/null @@ -1,323 +0,0 @@ -import { useKeyboardShortcuts } from 'components/grid/components/common/Hooks' -import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' -import AlertError from 'components/ui/AlertError' -import LoadingOpacity from 'components/ui/LoadingOpacity' -import ShimmerLine from 'components/ui/ShimmerLine' -import { useWarehouseAccessTokensQuery } from 'data/analytics/warehouse-access-tokens-query' -import { useWarehouseLogDetailQuery } from 'data/analytics/warehouse-collection-log-detail-query' -import { useWarehouseCollectionsQuery } from 'data/analytics/warehouse-collections-query' -import { useWarehouseQueryQuery } from 'data/analytics/warehouse-query' -import dayjs from 'dayjs' -import { useSelectedLog } from 'hooks/analytics/useSelectedLog' -import { useFlag } from 'hooks/ui/useFlag' -import { RefreshCcw, Rewind, Terminal } from 'lucide-react' -import Link from 'next/link' -import { useRouter } from 'next/router' -import { useEffect, useState } from 'react' -import { Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui' -import { LogsDatePicker } from '../Settings/Logs/Logs.DatePickers' -import { DatetimeHelper } from '../Settings/Logs/Logs.types' -import LogTable from '../Settings/Logs/LogTable' -import { TestCollectionDialog } from './TestCollectionDialog' - -const INTERVALS: DatetimeHelper[] = [ - { - text: 'Last hour', - calcFrom: () => dayjs().subtract(1, 'hour').toISOString(), - calcTo: () => dayjs().toISOString(), - default: true, - }, - { - text: 'Last 12 hours', - calcFrom: () => dayjs().subtract(12, 'hour').toISOString(), - calcTo: () => dayjs().toISOString(), - }, - { - text: 'Last day', - calcFrom: () => dayjs().subtract(1, 'day').toISOString(), - calcTo: () => dayjs().toISOString(), - }, - { - text: 'Last 7 days', - calcFrom: () => dayjs().subtract(7, 'day').toISOString(), - calcTo: () => dayjs().toISOString(), - }, -] - -export const WarehouseCollectionDetail = () => { - const router = useRouter() - const collectionToken = router.query.collectionToken as string - const projectRef = router.query.ref as string - const accessTokens = useWarehouseAccessTokensQuery({ projectRef }) - const [testDialogOpen, setTestDialogOpen] = useState(false) - const hasWarehouse = useFlag('warehouse') - - const { data: collections, isLoading: collectionsLoading } = useWarehouseCollectionsQuery( - { projectRef }, - { enabled: hasWarehouse } - ) - const collection = collections?.find((c) => c.token === collectionToken) - const [search, setSearch] = useState('') - const [filters, setFilters] = useState({ - limit: 100, - offset: 0, - search: '', - interval: { - to: INTERVALS[0].calcTo, - from: INTERVALS[0].calcFrom, - }, - }) - const [sql, setSQL] = useState('') - - useEffect(() => { - if (collection) { - const from = filters.interval.from() - const to = filters.interval.to() - - const sql = `select id, timestamp from \`${collection.name}\` -where timestamp >= TIMESTAMP('${from}') -and timestamp <= TIMESTAMP('${to}') -order by timestamp desc limit ${filters.limit} offset ${filters.offset} - ` - - setSQL(sql) - } - }, [filters.interval, filters.limit, filters.offset, collection]) - - const { - isLoading: queryLoading, - data: queryData, - isError, - isRefetching, - } = useWarehouseQueryQuery( - { ref: projectRef, sql }, - { - enabled: !!sql && hasWarehouse, - } - ) - - const formatResults = (results: any) => { - if (!results || !results.length) { - return [] - } - - const r = results.map(({ timestamp, ...r }: any) => { - return { - timestamp: new Date(timestamp / 1000).toLocaleString(), - ...r, - } - }) - - return r - } - - const results = formatResults(queryData?.result) - - function loadMore() { - setFilters({ ...filters, offset: filters.offset + filters.limit }) - } - - const isLoading = queryLoading || collectionsLoading || isRefetching - - function refreshResults(e?: React.FormEvent) { - e?.preventDefault() - setFilters({ - ...filters, - search, - interval: { - to: () => dayjs().toISOString(), - from: () => filters.interval.from() || dayjs().subtract(1, 'hour').toISOString(), - }, - }) - } - - const queryUrl = `/project/${projectRef}/logs/explorer?q=${encodeURIComponent( - sql || '' - )}&source=warehouse` - - useKeyboardShortcuts( - { - r: () => { - document.getElementById('refresh-button')?.focus() - }, - s: () => { - document.getElementById('search-input')?.focus() - }, - }, - ['INPUT', 'BUTTON', 'TEXTAREA'] - ) - - function KeyboardShortcut({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ) - } - - // Selected Log Detail - const [selectedLogId, setSelectedLogId] = useSelectedLog() - const { - data: selectedLogDetail, - isLoading: selectedLogDetailLoading, - error: selectedLogDetailError, - } = useWarehouseLogDetailQuery({ - ref: projectRef, - collectionName: collection?.name, - logId: selectedLogId ?? undefined, - }) - - return ( -
- - -
-
-
-

- {collection?.name} -

- - - - - - Open query in Collections Explorer - -
- - { - refreshResults() - setTestDialogOpen(false) - }} - /> -
-
- - {isError && ( -
- -
- )} - - {!isError && ( - setSelectedLogId(log?.id ?? null)} - selectedLog={selectedLogDetail?.result[0] ?? undefined} - selectedLogError={selectedLogDetailError ?? undefined} - isSelectedLogLoading={!!selectedLogId && selectedLogDetailLoading} - data={results} - showHeader={false} - EmptyState={ - -
-

Try adjusting your filters, send a test event or refresh the results.

-
- - -
-
-
- } - /> - )} -
- - - {!isError && ( -
-
- {results.length > 0 && ( - - )} - {filters.offset !== 0 && ( - <> - - - )} -
-
- )} - - ) -} diff --git a/apps/studio/components/interfaces/DataWarehouse/WarehouseMenuItem.tsx b/apps/studio/components/interfaces/DataWarehouse/WarehouseMenuItem.tsx deleted file mode 100644 index 9b2c656e254..00000000000 --- a/apps/studio/components/interfaces/DataWarehouse/WarehouseMenuItem.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { PermissionAction } from '@supabase/shared-types/out/constants' -import { Database, EditIcon, TrashIcon } from 'lucide-react' -import { useRouter } from 'next/router' -import { useState } from 'react' -import { toast } from 'sonner' - -import { useParams } from 'common' -import { useDeleteCollectionMutation } from 'data/analytics/warehouse-collections-delete-mutation' -import { useUpdateCollection } from 'data/analytics/warehouse-collections-update-mutation' -import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { - DropdownMenuItem, - DropdownMenuSeparator, - Modal, - Tooltip, - TooltipContent, - TooltipTrigger, -} from 'ui' - -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { LogsSidebarItem } from '../Settings/Logs/SidebarV2/SidebarItem' -import { CollectionForm } from './CollectionForm' - -type Props = { - item: { - id: number - token: string - name: string - retention_days: number - } -} - -export const WarehouseMenuItem = ({ item }: Props) => { - const router = useRouter() - const { ref, collectionToken } = useParams() - const projectRef = ref || 'default' - - const [showUpdateDialog, setShowUpdateDialog] = useState(false) - const [showDeleteDialog, setDeleteDialog] = useState(false) - - const canUpdateCollection = useCheckPermissions(PermissionAction.ANALYTICS_WRITE, 'logflare') - - const updateCollection = useUpdateCollection({ - onSuccess: () => { - toast.success('Collection updated successfully') - setShowUpdateDialog(false) - }, - }) - const deleteCollection = useDeleteCollectionMutation({ - onSuccess: () => { - // If the current collection is deleted, redirect to default logs view - if (item.token === collectionToken) { - router.push(`/project/${projectRef}/logs/explorer`) - } - setDeleteDialog(false) - toast.success('Collection deleted successfully') - }, - }) - - const isLoading = updateCollection.isLoading || deleteCollection.isLoading - - return ( - <> - } - href={`/project/${projectRef}/logs/collections/${item.token}`} - dropdownItems={ - <> - - - { - e.preventDefault() - setShowUpdateDialog(true) - }} - > - -
Update collection
-
-
- {!canUpdateCollection && ( - - You need additional permissions to update collections - - )} -
- - - - { - e.preventDefault() - setDeleteDialog(true) - }} - > - -
Delete collection
-
-
- {!canUpdateCollection && ( - - You need additional permissions to delete collections - - )} -
- - } - >
- - setShowUpdateDialog(false)} - hideFooter - header={`Update collection "${item.name}"`} - > - setShowUpdateDialog(false)} - isLoading={isLoading} - initialValues={{ name: item.name, retention_days: item.retention_days }} - onSubmit={({ name, retention_days }) => { - updateCollection.mutate({ - projectRef, - collectionToken: item.token, - name, - retention_days, - }) - }} - /> - - setDeleteDialog(false)} - confirmLabel="Delete collection" - title={`Delete collection "${item.name}"`} - size="small" - onConfirm={() => { - deleteCollection.mutate({ projectRef, collectionToken: item.token }) - }} - > -

- All data in this collection will be deleted. -
-

This action cannot be undone.
-

-
- - ) -} diff --git a/apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx b/apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx index d51bdf2f5d4..d2830c5468e 100644 --- a/apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx +++ b/apps/studio/components/interfaces/Database/Replication/ComingSoon.tsx @@ -1,13 +1,15 @@ -import Table from 'components/to-be-cleaned/Table' import { motion } from 'framer-motion' -import { BASE_PATH } from 'lib/constants' import { ArrowUpRight, Circle, Database, MoreVertical, Plus, Search } from 'lucide-react' import { useTheme } from 'next-themes' import Link from 'next/link' import { useMemo } from 'react' import ReactFlow, { Background, Handle, Position, ReactFlowProvider } from 'reactflow' import 'reactflow/dist/style.css' -import { Button, Input } from 'ui' + +import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' +import Table from 'components/to-be-cleaned/Table' +import { BASE_PATH } from 'lib/constants' +import { Button, Input_Shadcn_ } from 'ui' import { NODE_WIDTH } from '../../Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants' const STATIC_NODES = [ @@ -62,6 +64,14 @@ const STATIC_EDGES = [ { id: 'e1-4', source: '1', target: '4', type: 'smoothstep', animated: true }, ] +export const ReplicationComingSoon = () => { + return ( + + + + ) +} + const ReplicationStaticMockup = () => { const nodes = useMemo(() => STATIC_NODES, []) const edges = useMemo(() => STATIC_EDGES, []) @@ -108,16 +118,6 @@ const ReplicationStaticMockup = () => { ) } -const ReplicationComingSoon = () => { - return ( - - - - ) -} - -export default ReplicationComingSoon - const PrimaryNode = ({ data, }: { @@ -251,58 +251,68 @@ const StaticDestinations = () => { return ( <> -
-
-
- } - placeholder="Search..." - /> - -
- Name, - Publication, - Lag, - Status, - , - ]} - className="mt-4" - body={mockRows.map((row, i) => ( - - {row.name} - - - All - {row.tables} tables - - - {row.lag} - - - - {row.status} - - - - - - - ))} - /> +
+
+ + + +
+
+
+ + +
+ +
+
Name, + Publication, + Lag, + Status, + , + ]} + className="mt-4" + body={mockRows.map((row, i) => ( + + {row.name} + + + All + {row.tables} tables + + + {row.lag} + + + + {row.status} + + + + + + + ))} + /> + + + ) diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx index edfab6d9239..5e693553554 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx @@ -1,26 +1,27 @@ +import Link from 'next/link' +import { useEffect, useState } from 'react' +import { toast } from 'sonner' + +import { useParams } from 'common' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' -import { ReplicationPipelinesData } from 'data/replication/pipelines-query' -import { ResponseError } from 'types' -import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' -import RowMenu from './RowMenu' -import PipelineStatus, { PipelineStatusRequestStatus, PipelineStatusName } from './PipelineStatus' -import { useParams } from 'common' -import { - ReplicationPipelineStatusData, - useReplicationPipelineStatusQuery, -} from 'data/replication/pipeline-status-query' -import { useState } from 'react' -import { toast } from 'sonner' -import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' -import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' import { useDeleteDestinationMutation } from 'data/replication/delete-destination-mutation' +import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query' +import { Pipeline } from 'data/replication/pipelines-query' +import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' +import { + PipelineStatusRequestStatus, + usePipelineRequestStatus, +} from 'state/replication-pipeline-request-status' +import { ResponseError } from 'types' +import { Button } from 'ui' +import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import DeleteDestination from './DeleteDestination' import DestinationPanel from './DestinationPanel' - -export type Pipeline = ReplicationPipelinesData['pipelines'][0] - -const refreshFrequencyMs: number = 5000 +import { getStatusName, PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' +import { PipelineStatus, PipelineStatusName } from './PipelineStatus' +import { STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants' +import { RowMenu } from './RowMenu' interface DestinationRowProps { sourceId: number | undefined @@ -34,7 +35,7 @@ interface DestinationRowProps { isSuccess: boolean } -const DestinationRow = ({ +export const DestinationRow = ({ sourceId, destinationId, destinationName, @@ -60,78 +61,25 @@ const DestinationRow = ({ projectRef, pipelineId: pipeline?.id, }, - { refetchInterval: refreshFrequencyMs } + { refetchInterval: STATUS_REFRESH_FREQUENCY_MS } ) - const [requestStatus, setRequestStatus] = useState( - PipelineStatusRequestStatus.None - ) - const { mutateAsync: startPipeline } = useStartPipelineMutation() + const { getRequestStatus, updatePipelineStatus } = usePipelineRequestStatus() + const requestStatus = pipeline?.id + ? getRequestStatus(pipeline.id) + : PipelineStatusRequestStatus.None + const { mutateAsync: stopPipeline } = useStopPipelineMutation() - const pipelineStatus = pipelineStatusData?.status - const getStatusName = ( - status: ReplicationPipelineStatusData['status'] | undefined - ): string | undefined => { - if (status && typeof status === 'object' && 'name' in status) { - return status.name - } - - return undefined - } - - const statusName = getStatusName(pipelineStatus) - if ( - (requestStatus === PipelineStatusRequestStatus.EnableRequested && - (statusName === PipelineStatusName.STARTED || statusName === PipelineStatusName.FAILED)) || - (requestStatus === PipelineStatusRequestStatus.DisableRequested && - (statusName === PipelineStatusName.STOPPED || statusName === PipelineStatusName.FAILED)) - ) { - setRequestStatus(PipelineStatusRequestStatus.None) - } - - const onEnableClick = async () => { - if (!projectRef) { - console.error('Project ref is required') - return - } - if (!pipeline) { - toast.error('No pipeline found') - return - } - - try { - await startPipeline({ projectRef, pipelineId: pipeline.id }) - } catch (error) { - toast.error('Failed to enable destination') - } - setRequestStatus(PipelineStatusRequestStatus.EnableRequested) - } - const onDisableClick = async () => { - if (!projectRef) { - console.error('Project ref is required') - return - } - if (!pipeline) { - toast.error('No pipeline found') - return - } - - try { - await stopPipeline({ projectRef, pipelineId: pipeline.id }) - } catch (error) { - toast.error('Failed to disable destination') - } - setRequestStatus(PipelineStatusRequestStatus.DisableRequested) - } const { mutateAsync: deleteDestination } = useDeleteDestinationMutation({}) + const pipelineStatus = pipelineStatusData?.status + const statusName = getStatusName(pipelineStatus) + const onDeleteClick = async () => { if (!projectRef) { - console.error('Project ref is required') - return + return console.error('Project ref is required') } if (!pipeline) { - toast.error('No pipeline found') - return + return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) } try { @@ -140,24 +88,28 @@ const DestinationRow = ({ // so we don't need to call deletePipeline explicitly await deleteDestination({ projectRef, destinationId: destinationId }) } catch (error) { - toast.error('Failed to delete destination') + toast.error(PIPELINE_ERROR_MESSAGES.DELETE_DESTINATION) } } + useEffect(() => { + if (pipeline?.id) { + updatePipelineStatus(pipeline.id, statusName) + } + }, [pipeline?.id, statusName, updatePipelineStatus]) + return ( <> {isPipelineError && ( - + )} {isPipelineSuccess && ( - - {isPipelineLoading ? : destinationName} - - {isPipelineLoading ? : type} + {isPipelineLoading ? : destinationName} + {isPipelineLoading ? : type} {isPipelineLoading || !pipeline ? ( - + ) : ( + /> )} {isPipelineLoading || !pipeline ? ( - + ) : ( pipeline.config.publication_name )} - setShowDeleteDestinationForm(true)} - onEditClick={() => setShowEditDestinationPanel(true)} - > +
+ + setShowDeleteDestinationForm(true)} + onEditClick={() => setShowEditDestinationPanel(true)} + /> +
)} @@ -211,5 +169,3 @@ const DestinationRow = ({ ) } - -export default DestinationRow diff --git a/apps/studio/components/interfaces/Database/Replication/Destinations.tsx b/apps/studio/components/interfaces/Database/Replication/Destinations.tsx index d1bbfc71b5d..2a408954c52 100644 --- a/apps/studio/components/interfaces/Database/Replication/Destinations.tsx +++ b/apps/studio/components/interfaces/Database/Replication/Destinations.tsx @@ -1,19 +1,21 @@ +import { Plus, Search } from 'lucide-react' +import { useState } from 'react' + import { useParams } from 'common' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { useReplicationDestinationsQuery } from 'data/replication/destinations-query' -import { Plus } from 'lucide-react' -import { Button, cn } from 'ui' -import { GenericSkeletonLoader } from 'ui-patterns' -import DestinationRow from './DestinationRow' import { useReplicationPipelinesQuery } from 'data/replication/pipelines-query' -import { useState } from 'react' -import NewDestinationPanel from './DestinationPanel' import { useReplicationSourcesQuery } from 'data/replication/sources-query' -import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' +import { Button, cn, Input_Shadcn_ } from 'ui' +import { GenericSkeletonLoader } from 'ui-patterns' +import NewDestinationPanel from './DestinationPanel' +import { DestinationRow } from './DestinationRow' +import { PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' -const Destinations = () => { +export const Destinations = () => { const [showNewDestinationPanel, setShowNewDestinationPanel] = useState(false) + const [filterString, setFilterString] = useState('') const { ref: projectRef } = useParams() const { @@ -21,12 +23,11 @@ const Destinations = () => { error: sourcesError, isLoading: isSourcesLoading, isError: isSourcesError, - isSuccess: isSourcesSuccess, } = useReplicationSourcesQuery({ projectRef, }) - let sourceId = sourcesData?.sources.find((s) => s.name === projectRef)?.id + const sourceId = sourcesData?.sources.find((s) => s.name === projectRef)?.id const { data: destinationsData, @@ -50,21 +51,44 @@ const Destinations = () => { const anyDestinations = isDestinationsSuccess && destinationsData.destinations.length > 0 + const filteredDestinations = + filterString.length === 0 + ? destinationsData?.destinations ?? [] + : (destinationsData?.destinations ?? []).filter((destination) => + destination.name.toLowerCase().includes(filterString.toLowerCase()) + ) + return ( <> - -
- Destinations +
+
+
+
+ + setFilterString(e.target.value)} + /> +
+
+
+ +
{(isSourcesLoading || isDestinationsLoading) && } {(isSourcesError || isDestinationsError) && ( )} @@ -77,7 +101,7 @@ const Destinations = () => { Publication, , ]} - body={destinationsData.destinations.map((destination) => { + body={filteredDestinations.map((destination) => { const pipeline = pipelinesData?.pipelines.find( (p) => p.destination_id === destination.id ) @@ -93,7 +117,7 @@ const Destinations = () => { isLoading={isPipelinesLoading} isError={isPipelinesError} isSuccess={isPipelinesSuccess} - > + /> ) })} >
@@ -124,15 +148,22 @@ const Destinations = () => {
) )} - + + + {!isSourcesLoading && + !isDestinationsLoading && + filteredDestinations.length === 0 && + anyDestinations && ( +
+

No destinations match "{filterString}"

+
+ )} setShowNewDestinationPanel(false)} - > + /> ) } - -export default Destinations diff --git a/apps/studio/components/interfaces/Database/Replication/Pipeline.utils.ts b/apps/studio/components/interfaces/Database/Replication/Pipeline.utils.ts new file mode 100644 index 00000000000..d15fe8040cc --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/Pipeline.utils.ts @@ -0,0 +1,96 @@ +import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' +import { PipelineStatusRequestStatus } from 'state/replication-pipeline-request-status' + +export const PIPELINE_ERROR_MESSAGES = { + RETRIEVE_PIPELINE: 'Failed to retrieve pipeline information', + RETRIEVE_PIPELINE_STATUS: 'Failed to retrieve pipeline status', + RETRIEVE_REPLICATION_STATUS: 'Failed to retrieve table replication status', + RETRIEVE_DESTINATIONS: 'Failed to retrieve destinations', + ENABLE_DESTINATION: 'Failed to enable destination', + DISABLE_DESTINATION: 'Failed to disable destination', + DELETE_DESTINATION: 'Failed to delete destination', + NO_PIPELINE_FOUND: 'No pipeline found', + COPY_TABLE_STATUS: 'Failed to copy table status', +} as const + +export const getStatusName = ( + status: ReplicationPipelineStatusData['status'] | undefined +): ReplicationPipelineStatusData['status']['name'] | undefined => { + if (status && typeof status === 'object' && 'name' in status) { + return status.name + } + return undefined +} + +export const PIPELINE_STATE_MESSAGES = { + enabling: { + title: 'Pipeline Enabling', + message: 'Starting the pipeline. Table replication will resume once enabled.', + badge: 'Enabling', + }, + disabling: { + title: 'Pipeline Disabling', + message: 'Stopping the pipeline. Table replication will be paused once disabled.', + badge: 'Disabling', + }, + failed: { + title: 'Pipeline Failed', + message: 'Replication has encountered an error. Check the logs for details.', + badge: 'Failed', + }, + stopped: { + title: 'Pipeline Stopped', + message: 'Replication is paused. Enable the pipeline to resume data synchronization.', + badge: 'Stopped', + }, + starting: { + title: 'Pipeline Starting', + message: 'Initializing replication. Table status will be available once running.', + badge: 'Starting', + }, + running: { + title: 'Pipeline Running', + message: 'Replication is active and processing data', + badge: 'Running', + }, + unknown: { + title: 'Pipeline Status Unknown', + message: 'Unable to determine replication status. Check the logs for more information.', + badge: 'Unknown', + }, + notRunning: { + title: 'Pipeline Not Running', + message: 'Replication is not active. Enable the pipeline to start data synchronization.', + badge: 'Disabled', + }, +} as const + +export const getPipelineStateMessages = ( + requestStatus: PipelineStatusRequestStatus | undefined, + statusName: string | undefined +) => { + // Always prioritize request status (enabling/disabling) over pipeline status + if (requestStatus === PipelineStatusRequestStatus.EnableRequested) { + return PIPELINE_STATE_MESSAGES.enabling + } + + if (requestStatus === PipelineStatusRequestStatus.DisableRequested) { + return PIPELINE_STATE_MESSAGES.disabling + } + + // Only check pipeline status if no request is in progress + switch (statusName) { + case 'failed': + return PIPELINE_STATE_MESSAGES.failed + case 'stopped': + return PIPELINE_STATE_MESSAGES.stopped + case 'starting': + return PIPELINE_STATE_MESSAGES.starting + case 'started': + return PIPELINE_STATE_MESSAGES.running + case 'unknown': + return PIPELINE_STATE_MESSAGES.unknown + default: + return PIPELINE_STATE_MESSAGES.notRunning + } +} diff --git a/apps/studio/components/interfaces/Database/Replication/PipelineStatus.tsx b/apps/studio/components/interfaces/Database/Replication/PipelineStatus.tsx index 6fb360e6d97..f81a8df536a 100644 --- a/apps/studio/components/interfaces/Database/Replication/PipelineStatus.tsx +++ b/apps/studio/components/interfaces/Database/Replication/PipelineStatus.tsx @@ -1,28 +1,11 @@ import AlertError from 'components/ui/AlertError' -import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' -import { cn } from 'ui' -import { ResponseError } from 'types' -import { Loader2, ChevronDown, ChevronRight, Copy, AlertTriangle } from 'lucide-react' -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, - Button, - Collapsible_Shadcn_ as Collapsible, - CollapsibleContent_Shadcn_ as CollapsibleContent, - CollapsibleTrigger_Shadcn_ as CollapsibleTrigger, -} from 'ui' -import { useState, useEffect, useRef } from 'react' -import { copyToClipboard } from 'ui' -import { toast } from 'sonner' import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' - -export enum PipelineStatusRequestStatus { - None = 'None', - EnableRequested = 'EnableRequested', - DisableRequested = 'DisableRequested', -} +import { AlertTriangle, Loader2 } from 'lucide-react' +import { PipelineStatusRequestStatus } from 'state/replication-pipeline-request-status' +import { ResponseError } from 'types' +import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' +import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' +import { getPipelineStateMessages, PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' export enum PipelineStatusName { FAILED = 'failed', @@ -41,10 +24,10 @@ interface PipelineStatusProps { isLoading: boolean isError: boolean isSuccess: boolean - requestStatus: PipelineStatusRequestStatus + requestStatus?: PipelineStatusRequestStatus } -const PipelineStatus = ({ +export const PipelineStatus = ({ pipelineStatus, error, isLoading, @@ -52,34 +35,6 @@ const PipelineStatus = ({ isSuccess, requestStatus, }: PipelineStatusProps) => { - const [isErrorDetailsOpen, setIsErrorDetailsOpen] = useState(false) - const errorDetailsRef = useRef(null) - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (errorDetailsRef.current && !errorDetailsRef.current.contains(event.target as Node)) { - setIsErrorDetailsOpen(false) - } - } - - if (isErrorDetailsOpen) { - document.addEventListener('mousedown', handleClickOutside) - } - - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, [isErrorDetailsOpen]) - - const handleCopyToClipboard = async (text: string) => { - try { - await copyToClipboard(text) - toast.success('Error details copied to clipboard') - } catch (error) { - toast.error('Failed to copy error details') - } - } - const isFailedStatus = ( status: ReplicationPipelineStatusData['status'] | undefined ): status is FailedStatus => { @@ -91,144 +46,37 @@ const PipelineStatus = ({ ) } - const isLogLoadingState = (failedStatus: FailedStatus): boolean => { - // Right now we hardcode the error message which is returned when k8s is not able to find logs, which seems - // to be a transient error. In case we find a way to properly handle this in the backend, this hack will not - // be needed anymore. + const renderFailedStatus = () => { return ( - failedStatus.message?.startsWith('unable to retrieve container logs for containerd://') === - true - ) - } - - const renderFailedStatus = (failedStatus: FailedStatus) => { - const hasDetails = - failedStatus.message || failedStatus.reason || failedStatus.exit_code !== undefined - const isLoadingLogs = isLogLoadingState(failedStatus) - - return ( -
- - - -
- {isLoadingLogs ? ( - - ) : ( - - )} - Failed -
-
- -

- {isLoadingLogs - ? 'Pipeline failed - logs are being retrieved from container' - : 'Pipeline has failed - expand for error details'} -

-
-
-
- {hasDetails && ( - - - - - -
- {isLoadingLogs ? ( -
- -
-
- Pipeline Failed - Loading logs... -
-
- Error logs are being retrieved from the container. This may take a few - moments. -
-
-
- ) : ( - <> -
- - Pipeline Error Details - - {(failedStatus.message || failedStatus.reason) && ( - - )} -
-
- {failedStatus.exit_code !== undefined && ( -
- - Exit Code: - -
- {failedStatus.exit_code} -
-
- )} - {failedStatus.reason && ( -
- Reason: -
-                            {failedStatus.reason}
-                          
-
- )} - {failedStatus.message && ( -
- - Message: - -
-                            {failedStatus.message}
-                          
-
- )} -
- - )} -
-
-
- )} -
+ + +
+ + Failed +
+
+ + {getPipelineStateMessages(requestStatus, 'failed').message} + +
) } // Map backend statuses to UX-friendly display const getStatusConfig = () => { + const statusName = + pipelineStatus && typeof pipelineStatus === 'object' && 'name' in pipelineStatus + ? pipelineStatus.name + : undefined + + // Get consistent tooltip message using the same logic as other components + const stateMessages = getPipelineStateMessages(requestStatus, statusName) + if (requestStatus === PipelineStatusRequestStatus.EnableRequested) { return { label: 'Enabling...', dot: , color: 'text-brand-600', - tooltip: 'Pipeline is being enabled and will start shortly', + tooltip: stateMessages.message, } } @@ -237,7 +85,7 @@ const PipelineStatus = ({ label: 'Disabling...', dot: , color: 'text-warning-600', - tooltip: 'Pipeline is being disabled and will stop shortly', + tooltip: stateMessages.message, } } @@ -255,35 +103,35 @@ const PipelineStatus = ({ label: 'Starting', dot: , color: 'text-warning-600', - tooltip: 'Pipeline is initializing and will be ready soon', + tooltip: stateMessages.message, } case PipelineStatusName.STARTED: return { label: 'Running', dot:
, color: 'text-brand-600', - tooltip: 'Pipeline is active and processing data', + tooltip: stateMessages.message, } case PipelineStatusName.STOPPED: return { label: 'Stopped', dot:
, color: 'text-foreground-light', - tooltip: 'Pipeline is not running - enable to start processing', + tooltip: stateMessages.message, } case PipelineStatusName.UNKNOWN: return { label: 'Unknown', dot:
, color: 'text-warning-600', - tooltip: 'Pipeline status could not be determined', + tooltip: stateMessages.message, } default: return { label: 'Unknown', dot:
, color: 'text-destructive-600', - tooltip: 'Pipeline status is unclear - check logs for details', + tooltip: stateMessages.message, } } } @@ -301,31 +149,27 @@ const PipelineStatus = ({ return ( <> - {isLoading && } - {isError && } + {isLoading && } + {isError && ( + + )} {isSuccess && ( <> {statusConfig.isFailedStatus ? ( -
{renderFailedStatus(pipelineStatus as FailedStatus)}
+
{renderFailedStatus()}
) : ( - - - -
- {statusConfig.dot} - {statusConfig.label} -
-
- -

{statusConfig.tooltip}

-
-
-
+ + +
+ {statusConfig.dot} + {statusConfig.label} +
+
+ {statusConfig.tooltip} +
)} )} ) } - -export default PipelineStatus diff --git a/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts b/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts new file mode 100644 index 00000000000..273adac9f5b --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts @@ -0,0 +1 @@ +export const STATUS_REFRESH_FREQUENCY_MS: number = 5000 diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx new file mode 100644 index 00000000000..29ccd56c333 --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx @@ -0,0 +1,371 @@ +import { Activity, AlertTriangle, ChevronLeft, Copy, ExternalLink, Search } from 'lucide-react' +import Link from 'next/link' +import { useEffect, useState } from 'react' +import { toast } from 'sonner' + +import { useParams } from 'common' +import Table from 'components/to-be-cleaned/Table' +import AlertError from 'components/ui/AlertError' +import { ButtonTooltip } from 'components/ui/ButtonTooltip' +import { useReplicationPipelineByIdQuery } from 'data/replication/pipeline-by-id-query' +import { useReplicationPipelineReplicationStatusQuery } from 'data/replication/pipeline-replication-status-query' +import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query' +import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' +import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' +import { + PipelineStatusRequestStatus, + usePipelineRequestStatus, +} from 'state/replication-pipeline-request-status' +import { Badge, Button, cn, copyToClipboard, Input_Shadcn_ } from 'ui' +import { GenericSkeletonLoader } from 'ui-patterns' +import { getStatusName, PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' +import { PipelineStatus } from './PipelineStatus' +import { STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants' +import { TableState } from './ReplicationPipelineStatus.types' +import { getDisabledStateConfig, getStatusConfig } from './ReplicationPipelineStatus.utils' + +export const ReplicationPipelineStatus = () => { + const { ref: projectRef, pipelineId: _pipelineId } = useParams() + const [filterString, setFilterString] = useState('') + + const pipelineId = Number(_pipelineId) + const { getRequestStatus, updatePipelineStatus, setRequestStatus } = usePipelineRequestStatus() + const requestStatus = getRequestStatus(pipelineId) + + const { + data: pipeline, + error: pipelineError, + isLoading: isPipelineLoading, + isError: isPipelineError, + } = useReplicationPipelineByIdQuery({ + projectRef, + pipelineId, + }) + + const { + data: pipelineStatusData, + error: pipelineStatusError, + isLoading: isPipelineStatusLoading, + isError: isPipelineStatusError, + isSuccess: isPipelineStatusSuccess, + } = useReplicationPipelineStatusQuery( + { projectRef, pipelineId }, + { + enabled: !!pipelineId, + refetchInterval: STATUS_REFRESH_FREQUENCY_MS, + } + ) + + const { + data: replicationStatusData, + error: statusError, + isLoading: isStatusLoading, + isError: isStatusError, + } = useReplicationPipelineReplicationStatusQuery( + { projectRef, pipelineId }, + { + enabled: !!pipelineId, + refetchInterval: STATUS_REFRESH_FREQUENCY_MS, + } + ) + + const { mutateAsync: startPipeline, isLoading: isStartingPipeline } = useStartPipelineMutation() + const { mutateAsync: stopPipeline, isLoading: isStoppingPipeline } = useStopPipelineMutation() + + const destinationName = pipeline?.destination_name + const statusName = getStatusName(pipelineStatusData?.status) + const config = getDisabledStateConfig({ requestStatus, statusName }) + + const tableStatuses = replicationStatusData?.table_statuses || [] + const filteredTableStatuses = + filterString.length === 0 + ? tableStatuses + : tableStatuses.filter((table: TableState) => + table.table_name.toLowerCase().includes(filterString.toLowerCase()) + ) + + const errorTables = tableStatuses.filter((table: TableState) => table.state.name === 'error') + const hasErrors = errorTables.length > 0 + const isPipelineRunning = statusName === 'started' + const hasTableData = tableStatuses.length > 0 + const isEnablingDisabling = + requestStatus === PipelineStatusRequestStatus.EnableRequested || + requestStatus === PipelineStatusRequestStatus.DisableRequested + const showDisabledState = !isPipelineRunning || isEnablingDisabling + + const handleCopyTableStatus = async (tableName: string, state: TableState['state']) => { + const statusText = `Table: ${tableName}\nStatus: ${state.name}${ + 'message' in state ? `\nError: ${state.message}` : '' + }${'lag' in state ? `\nLag: ${state.lag}ms` : ''}` + + try { + await copyToClipboard(statusText) + toast.success('Table status copied to clipboard') + } catch { + toast.error(PIPELINE_ERROR_MESSAGES.COPY_TABLE_STATUS) + } + } + + const onTogglePipeline = async () => { + if (!projectRef) { + return console.error('Project ref is required') + } + if (!pipeline) { + return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) + } + + try { + if (statusName === 'stopped') { + await startPipeline({ projectRef, pipelineId: pipeline.id }) + setRequestStatus(pipeline.id, PipelineStatusRequestStatus.EnableRequested) + } else if (statusName === 'started') { + await stopPipeline({ projectRef, pipelineId: pipeline.id }) + setRequestStatus(pipeline.id, PipelineStatusRequestStatus.DisableRequested) + } + } catch (error) { + toast.error(PIPELINE_ERROR_MESSAGES.ENABLE_DESTINATION) + } + } + + useEffect(() => { + updatePipelineStatus(pipelineId, statusName) + }, [pipelineId, statusName, updatePipelineStatus]) + + return ( +
+
+
+ +
+
+

{destinationName || 'Pipeline'}

+ +
+
+
+
+
+ + setFilterString(e.target.value)} + /> +
+ +
+
+ + {(isPipelineLoading || isStatusLoading) && } + + {isPipelineError && ( + + )} + + {isStatusError && ( + + )} + + {hasErrors && ( +
+
+ +
+

+ {errorTables.length} table{errorTables.length > 1 ? 's' : ''} failed +

+

+ Some tables encountered replication errors. Check the logs for detailed error + information. +

+ +
+
+
+ )} + + {hasTableData && ( +
+ {showDisabledState && ( +
+
+
+
{config.icon}
+
+
+

{config.title}

+

{config.message}

+
+
+
+ )} + +
+ Table, + Status, + Details, + + Actions + , + ]} + body={filteredTableStatuses.map((table: TableState, index: number) => { + const statusConfig = getStatusConfig(table.state) + return ( + + +
+

{table.table_name}

+ + } + tooltip={{ content: { side: 'bottom', text: 'Open in Table Editor' } }} + > + + +
+
+ + {showDisabledState ? ( + Not Available + ) : ( + statusConfig.badge + )} + + + {showDisabledState ? ( +

+ Status unavailable while pipeline is {config.badge.toLowerCase()} +

+ ) : ( +
+
{statusConfig.description}
+ {'lag' in table.state && ( +
+ Lag: {table.state.lag}ms +
+ )} +
+ )} +
+ + } + className="px-1.5" + disabled={showDisabledState} + onClick={() => handleCopyTableStatus(table.table_name, table.state)} + tooltip={{ + content: { + side: 'bottom', + text: showDisabledState + ? `Copy unavailable while pipeline is ${config.badge.toLowerCase()}` + : 'Copy status details', + }, + }} + /> + +
+ ) + })} + /> + + + )} + + {filteredTableStatuses.length === 0 && hasTableData && ( + + +
+

No results found

+

+ Your search for "{filterString}" did not return any results +

+
+
+
+ )} + + {!isStatusLoading && tableStatuses.length === 0 && ( +
+
+
+ +
+
+

+ {showDisabledState ? 'Pipeline Not Running' : 'No table status information'} +

+

+ {showDisabledState + ? `The replication pipeline is currently ${statusName || 'not active'}. Table status + information is not available while the pipeline is in this state.` + : `This pipeline doesn't have any table replication status data available yet. The status will appear here once replication begins.`} +

+
+

+ Data refreshes automatically every 2 seconds +

+
+
+ )} + + ) +} diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.types.ts b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.types.ts new file mode 100644 index 00000000000..c5ab523ec1e --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.types.ts @@ -0,0 +1,10 @@ +export type TableState = { + table_id: number + table_name: string + state: + | { name: 'queued' } + | { name: 'copying_table' } + | { name: 'copied_table' } + | { name: 'following_wal'; lag: number } + | { name: 'error'; message: string } +} diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.utils.tsx b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.utils.tsx new file mode 100644 index 00000000000..f9ff22a9e9a --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.utils.tsx @@ -0,0 +1,108 @@ +import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query' +import { Activity, Clock, HelpCircle, Loader2, XCircle } from 'lucide-react' +import { PipelineStatusRequestStatus } from 'state/replication-pipeline-request-status' +import { Badge } from 'ui' +import { getPipelineStateMessages } from './Pipeline.utils' +import { TableState } from './ReplicationPipelineStatus.types' + +export const getStatusConfig = (state: TableState['state']) => { + switch (state.name) { + case 'queued': + return { + badge: Queued, + description: 'Waiting to start replication', + color: 'text-warning-600', + } + case 'copying_table': + return { + badge: Copying, + description: 'Initial data copy in progress', + color: 'text-brand-600', + } + case 'copied_table': + return { + badge: Copied, + description: 'Initial copy completed', + color: 'text-success-600', + } + case 'following_wal': + return { + badge: Live, + description: `Replicating live changes`, + color: 'text-success-600', + } + case 'error': + return { + badge: Error, + description: state.message, + color: 'text-destructive-600', + } + default: + return { + badge: Unknown, + description: 'Unknown status', + color: 'text-warning-600', + } + } +} + +export const getDisabledStateConfig = ({ + requestStatus, + statusName, +}: { + requestStatus: PipelineStatusRequestStatus + statusName?: ReplicationPipelineStatusData['status']['name'] +}) => { + const { title, message, badge } = getPipelineStateMessages(requestStatus, statusName) + + // Get icon and colors based on current state + const isEnabling = requestStatus === PipelineStatusRequestStatus.EnableRequested + const isDisabling = requestStatus === PipelineStatusRequestStatus.DisableRequested + const isTransitioning = isEnabling || isDisabling + + const icon = isTransitioning ? ( + + ) : statusName === 'failed' ? ( + + ) : statusName === 'starting' ? ( + + ) : statusName === 'unknown' ? ( + + ) : ( + + ) + + const colors = isEnabling + ? { + bg: 'bg-brand-50', + text: 'text-brand-900', + subtext: 'text-brand-700', + iconBg: 'bg-brand-600', + icon: 'text-white dark:text-black', + } + : isDisabling || statusName === 'starting' || statusName === 'unknown' + ? { + bg: 'bg-warning-50', + text: 'text-warning-900', + subtext: 'text-warning-700', + iconBg: 'bg-warning-600', + icon: 'text-white dark:text-black', + } + : statusName === 'failed' + ? { + bg: 'bg-destructive-50', + text: 'text-destructive-900', + subtext: 'text-destructive-700', + iconBg: 'bg-destructive-600', + icon: 'text-white dark:text-black', + } + : { + bg: 'bg-surface-100', + text: 'text-foreground', + subtext: 'text-foreground-light', + iconBg: 'bg-foreground-lighter', + icon: 'text-white dark:text-black', + } + + return { title, message, badge, icon, colors } +} diff --git a/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx b/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx index f09cc703093..ae5734b2e9c 100644 --- a/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx +++ b/apps/studio/components/interfaces/Database/Replication/RowMenu.tsx @@ -1,5 +1,15 @@ -import AlertError from 'components/ui/AlertError' import { Edit, MoreVertical, Pause, Play, Trash } from 'lucide-react' +import { toast } from 'sonner' + +import { useParams } from 'common' +import AlertError from 'components/ui/AlertError' +import { Pipeline } from 'data/replication/pipelines-query' +import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation' +import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' +import { + PipelineStatusRequestStatus, + usePipelineRequestStatus, +} from 'state/replication-pipeline-request-status' import { ResponseError } from 'types' import { Button, @@ -10,29 +20,30 @@ import { DropdownMenuTrigger, } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' +import { PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' import { PipelineStatusName } from './PipelineStatus' interface RowMenuProps { + pipeline: Pipeline | undefined pipelineStatus: any error: ResponseError | null isLoading: boolean isError: boolean - onEnableClick: () => void - onDisableClick: () => void onEditClick: () => void onDeleteClick: () => void } -const RowMenu = ({ +export const RowMenu = ({ + pipeline, pipelineStatus, error, isLoading, isError, - onEnableClick, - onDisableClick, onEditClick, onDeleteClick, }: RowMenuProps) => { + const { ref: projectRef } = useParams() + const getStatusName = (status: any) => { if (status && typeof status === 'object' && 'name' in status) { return status.name @@ -43,10 +54,52 @@ const RowMenu = ({ const statusName = getStatusName(pipelineStatus) const pipelineEnabled = statusName !== PipelineStatusName.STOPPED + const { mutateAsync: startPipeline } = useStartPipelineMutation() + const { mutateAsync: stopPipeline } = useStopPipelineMutation() + const { setRequestStatus: setGlobalRequestStatus } = usePipelineRequestStatus() + + const onEnablePipeline = async () => { + if (!projectRef) { + return console.error('Project ref is required') + } + if (!pipeline) { + return toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) + } + + try { + await startPipeline({ projectRef, pipelineId: pipeline.id }) + toast(`Enabling pipeline ${pipeline.destination_name}`) + setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.EnableRequested) + } catch (error) { + toast.error(PIPELINE_ERROR_MESSAGES.ENABLE_DESTINATION) + } + } + + const onDisablePipeline = async () => { + if (!projectRef) { + console.error('Project ref is required') + return + } + if (!pipeline) { + toast.error(PIPELINE_ERROR_MESSAGES.NO_PIPELINE_FOUND) + return + } + + try { + await stopPipeline({ projectRef, pipelineId: pipeline.id }) + toast(`Disabling pipeline ${pipeline.destination_name}`) + setGlobalRequestStatus(pipeline.id, PipelineStatusRequestStatus.DisableRequested) + } catch (error) { + toast.error(PIPELINE_ERROR_MESSAGES.DISABLE_DESTINATION) + } + } + return (
- {isLoading && } - {isError && } + {isLoading && } + {isError && ( + + )} @@ -54,14 +107,14 @@ const RowMenu = ({ {pipelineEnabled ? ( - + -

Disable

+

Disable pipeline

) : ( - + -

Enable

+

Enable pipeline

)} @@ -78,5 +131,3 @@ const RowMenu = ({
) } - -export default RowMenu diff --git a/apps/studio/components/interfaces/Integrations/Integration/MarkdownContent.tsx b/apps/studio/components/interfaces/Integrations/Integration/MarkdownContent.tsx index cd5e5ec7af6..24b4bec4d40 100644 --- a/apps/studio/components/interfaces/Integrations/Integration/MarkdownContent.tsx +++ b/apps/studio/components/interfaces/Integrations/Integration/MarkdownContent.tsx @@ -42,7 +42,7 @@ export const MarkdownContent = ({ integrationId }: { integrationId: string }) => /> )} {supportExpanding && ( -
+
@@ -325,20 +359,11 @@ export const CreateIcebergWrapperSheet = ({ type="primary" form={FORM_ID} htmlType="submit" - disabled={isCreating} - loading={isCreating} + loading={isLoading} > Create wrapper - setCreateSchemaSheetOpen(false)} - onSuccess={(schema) => { - setFieldValue('target_schema', schema) - setCreateSchemaSheetOpen(false) - }} - /> ) }} diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx index d737aa6733b..73b2ce54d26 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx @@ -4,19 +4,18 @@ import { Edit, Trash } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' -import SchemaEditor from 'components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' -import SchemaSelector from 'components/ui/SchemaSelector' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' +import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' import { invalidateSchemasQuery, useSchemasQuery } from 'data/database/schemas-query' import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' +import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { Button, Form, Input, - Label_Shadcn_, RadioGroupStacked, RadioGroupStackedItem, Separator, @@ -30,7 +29,6 @@ import InputField from './InputField' import { WrapperMeta } from './Wrappers.types' import { makeValidateRequired } from './Wrappers.utils' import WrapperTableEditor from './WrapperTableEditor' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' export interface CreateWrapperSheetProps { isClosing: boolean @@ -48,6 +46,7 @@ export const CreateWrapperSheet = ({ onClose, }: CreateWrapperSheetProps) => { const queryClient = useQueryClient() + const { project } = useProjectContext() const org = useSelectedOrganization() const { mutate: sendEvent } = useSendEventMutation() @@ -73,7 +72,7 @@ export const CreateWrapperSheet = ({ const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) - const { mutate: createFDW, isLoading: isCreating } = useFDWCreateMutation({ + const { mutateAsync: createFDW, isLoading: isCreatingWrapper } = useFDWCreateMutation({ onSuccess: () => { toast.success(`Successfully created ${wrapperMeta?.label} foreign data wrapper`) setNewTables([]) @@ -85,8 +84,10 @@ export const CreateWrapperSheet = ({ }, }) - // prefetch schemas to make sure the schema selector is populated - useSchemasQuery({ projectRef: project?.ref, connectionString: project?.connectionString }) + const { data: schemas } = useSchemasQuery({ + projectRef: project?.ref!, + connectionString: project?.connectionString, + }) const initialValues = { wrapper_name: '', @@ -98,6 +99,8 @@ export const CreateWrapperSheet = ({ ), } + const { mutateAsync: createSchema, isLoading: isCreatingSchema } = useSchemaCreateMutation() + const onUpdateTable = (values: any) => { setNewTables((prev) => { // if the new values have tableIndex, we are editing an existing table @@ -121,37 +124,70 @@ export const CreateWrapperSheet = ({ if (values.wrapper_name.length === 0) { errors.wrapper_name = 'Please provide a name for your wrapper' } - if (selectedMode === 'tables' && newTables.length === 0) { - errors.tables = 'Please add at least one table' - } - if (selectedMode === 'schema' && values.source_schema.length === 0) { - errors.source_schema = 'Please provide a source schema' - } - if (!isEmpty(errors)) return setFormErrors(errors) - createFDW({ - projectRef: project?.ref, - connectionString: project?.connectionString, - wrapperMeta, - formState: { ...values, server_name: `${values.wrapper_name}_server` }, - mode: selectedMode, - tables: newTables, - sourceSchema: values.source_schema, - targetSchema: values.target_schema, - }) + if (selectedMode === 'tables') { + if (newTables.length === 0) { + errors.tables = 'Please provide at least one table' + } + } + if (selectedMode === 'schema') { + if (values.source_schema.length === 0) { + errors.source_schema = 'Please provide a source schema' + } + if (values.target_schema.length === 0) { + errors.target_schema = 'Please provide an unique target schema' + } + const foundSchema = schemas?.find((s) => s.name === values.target_schema) + if (foundSchema) { + errors.target_schema = 'This schema already exists. Please specify a unique schema name.' + } + } - sendEvent({ - action: 'foreign_data_wrapper_created', - properties: { - wrapperType: wrapperMeta.label, - }, - groups: { - project: project?.ref ?? 'Unknown', - organization: org?.slug ?? 'Unknown', - }, - }) + setFormErrors(errors) + if (!isEmpty(errors)) { + return + } + + try { + await createSchema({ + projectRef: project?.ref, + connectionString: project?.connectionString, + name: values.target_schema, + }) + + await createFDW({ + projectRef: project?.ref, + connectionString: project?.connectionString, + wrapperMeta, + formState: { + ...values, + server_name: `${values.wrapper_name}_server`, + supabase_target_schema: selectedMode === 'schema' ? values.target_schema : undefined, + }, + mode: selectedMode, + tables: newTables, + sourceSchema: values.source_schema, + targetSchema: values.target_schema, + }) + + sendEvent({ + action: 'foreign_data_wrapper_created', + properties: { + wrapperType: wrapperMeta.label, + }, + groups: { + project: project?.ref ?? 'Unknown', + organization: org?.slug ?? 'Unknown', + }, + }) + } catch (error) { + console.error(error) + // The error will be handled by the mutation onError callback (toast.error) + } } + const isLoading = isCreatingWrapper || isCreatingSchema + return ( <>
@@ -161,7 +197,7 @@ export const CreateWrapperSheet = ({ onSubmit={onSubmit} className="flex-grow flex flex-col h-full" > - {({ handleReset, values, initialValues, setFieldValue }: any) => { + {({ values, initialValues, setFieldValue }: any) => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) const onClosePanel = () => { @@ -236,7 +272,7 @@ export const CreateWrapperSheet = ({

- Define tables where the wrapper data will be shown. + Create foreign tables to query data from {wrapperMeta.label}.

@@ -261,7 +297,8 @@ export const CreateWrapperSheet = ({

- Specify schema in which the wrapper will create tables. + Create all foreign tables from {wrapperMeta.label} in a specified + schema.

@@ -366,38 +403,44 @@ export const CreateWrapperSheet = ({

Foreign Schema

- All wrapper tables will be created in the specified target schema. + You can query your data from the foreign tables in the specified schema + after the wrapper is created.

} > - {wrapperMeta.sourceSchemaOption && ( -
- -

- {wrapperMeta.sourceSchemaOption.description} -

-
- )} + {wrapperMeta.sourceSchemaOption && + !wrapperMeta.sourceSchemaOption?.readOnly && ( + // Hide the field if the source schema is read-only +
+ +

+ {wrapperMeta.sourceSchemaOption.description} +

+
+ )}
- - Target Schema - - setFieldValue('target_schema', schema)} - onSelectCreateSchema={() => setCreateSchemaSheetOpen(true)} +

- Be careful not to use an API exposed schema. + A new schema will be created. For security purposes, the wrapper tables + from the foreign schema cannot be created within an existing schema

@@ -411,7 +454,7 @@ export const CreateWrapperSheet = ({ type="default" htmlType="button" onClick={onClosePanel} - disabled={isCreating} + disabled={isLoading} > Cancel @@ -420,20 +463,11 @@ export const CreateWrapperSheet = ({ type="primary" form={FORM_ID} htmlType="submit" - disabled={isCreating} - loading={isCreating} + loading={isLoading} > Create wrapper - setCreateSchemaSheetOpen(false)} - onSuccess={(schema) => { - setFieldValue('target_schema', schema) - setCreateSchemaSheetOpen(false) - }} - /> ) }} diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperRow.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperRow.tsx index fb9763e6701..e7c9c155fbe 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperRow.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperRow.tsx @@ -107,37 +107,39 @@ const WrapperRow = ({ wrapper }: WrapperRowProps) => {
))} - - } - className="px-1.5" - onClick={() => setEditWrapperShown(true)} - tooltip={{ - content: { - side: 'bottom', - text: !canManageWrappers - ? 'You need additional permissions to edit wrappers' - : 'Edit wrapper', - }, - }} - /> - } - className="px-1.5" - onClick={() => setDeleteWrapperShown(true)} - tooltip={{ - content: { - side: 'bottom', - text: !canManageWrappers - ? 'You need additional permissions to delete wrappers' - : 'Delete wrapper', - }, - }} - /> + +
+ } + className="px-1.5" + onClick={() => setEditWrapperShown(true)} + tooltip={{ + content: { + side: 'bottom', + text: !canManageWrappers + ? 'You need additional permissions to edit wrappers' + : 'Edit wrapper', + }, + }} + /> + } + className="px-1.5" + onClick={() => setDeleteWrapperShown(true)} + tooltip={{ + content: { + side: 'bottom', + text: !canManageWrappers + ? 'You need additional permissions to delete wrappers' + : 'Delete wrapper', + }, + }} + /> +
setIsClosingEditWrapper(true)}> diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.constants.ts b/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.constants.ts index 4055a4423c3..dad85cda513 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.constants.ts +++ b/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.constants.ts @@ -1,6 +1,6 @@ import { BASE_PATH } from 'lib/constants' import { CreateIcebergWrapperSheet } from './CreateIcebergWrapperSheet' -import type { WrapperMeta } from './Wrappers.types' +import type { ServerOption, WrapperMeta } from './Wrappers.types' export const WRAPPER_HANDLERS = { STRIPE: 'stripe_fdw_handler', @@ -27,6 +27,16 @@ export const WRAPPER_HANDLERS = { ORB: 'wasm_fdw_handler', } +const SUPABASE_TARGET_SCHEMA_OPTION: ServerOption = { + name: 'supabase_target_schema', + label: 'Target Schema', + required: false, + encrypted: false, + secureEntry: false, + readOnly: true, + hidden: true, +} + export const WRAPPERS: WrapperMeta[] = [ { name: 'stripe_wrapper', @@ -55,6 +65,7 @@ export const WRAPPERS: WrapperMeta[] = [ encrypted: false, secureEntry: false, }, + SUPABASE_TARGET_SCHEMA_OPTION, ], }, tables: [ @@ -1775,6 +1786,7 @@ export const WRAPPERS: WrapperMeta[] = [ encrypted: false, secureEntry: false, }, + SUPABASE_TARGET_SCHEMA_OPTION, ], }, canTargetSchema: true, @@ -2224,12 +2236,13 @@ export const WRAPPERS: WrapperMeta[] = [ encrypted: false, secureEntry: false, }, + SUPABASE_TARGET_SCHEMA_OPTION, ], }, canTargetSchema: true, sourceSchemaOption: { name: 'source_schema', - label: 'Source Schema', + label: 'Namespace', description: 'It should match the namespace of the Iceberg catalog.', required: true, encrypted: false, diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.utils.ts b/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.utils.ts index 63786de027c..cddc265b165 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.utils.ts +++ b/apps/studio/components/interfaces/Integrations/Wrappers/Wrappers.utils.ts @@ -12,7 +12,7 @@ export const makeValidateRequired = (options: { name: string; required: boolean ) const requiredArrayOptions = Array.from(requiredArrayOptionsSet) - return (values: any) => { + return (values: Record) => { const errors = Object.fromEntries( Object.entries(values) .flatMap(([key, value]) => diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx index 9141ad9efc6..0638818ac92 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx @@ -48,8 +48,8 @@ const FORM_ID = 'credit-top-up' const FormSchema = z.object({ amount: z.coerce .number() - .gte(100, 'Amount must be between $100 - $999.') - .lte(999, 'Amount must be between $100 - $999.') + .gte(100, 'Amount must be between $100 - $2000.') + .lte(2000, 'Amount must be between $100 - $2000.') .int('Amount must be a whole number.'), paymentMethod: z.string(), }) diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails.tsx index 94ada25c2d2..248f01eed91 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails.tsx @@ -1,6 +1,8 @@ import { OAuthScope } from '@supabase/shared-types/out/constants' import { Check } from 'lucide-react' +import { PERMISSIONS_DESCRIPTIONS } from './OAuthApps.constants' + export interface AuthorizeRequesterDetailsProps { icon: string | null name: string @@ -48,7 +50,7 @@ export const ScopeSection = ({ return null } -const AuthorizeRequesterDetails = ({ +export const AuthorizeRequesterDetails = ({ icon, name, domain, @@ -79,57 +81,57 @@ const AuthorizeRequesterDetails = ({

@@ -138,5 +140,3 @@ const AuthorizeRequesterDetails = ({
) } - -export default AuthorizeRequesterDetails diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/OAuthApps.constants.ts b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthApps.constants.ts new file mode 100644 index 00000000000..6fdc47c2547 --- /dev/null +++ b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthApps.constants.ts @@ -0,0 +1,15 @@ +export const PERMISSIONS_DESCRIPTIONS = { + ANALYTICS: 'access to analytics logs.', + AUTH: 'access to auth configurations and SSO providers.', + DATABASE: + 'access to Postgres configurations, SQL snippets, SSL enforcement configurations and Typescript schema types.', + DOMAINS: 'access to custom domains and vanity subdomains.', + EDGE_FUNCTIONS: 'access to edge functions.', + ENVIRONMENT: 'access to environments/branches.', + ORGANIZATIONS: 'access to the organization and all its members.', + PROJECTS: + "access to creation and deletion of projects, each project's metadata, upgrade status, network restrictions and network bans.", + REST: 'access to PostgREST configurations.', + SECRETS: 'access to API keys, secrets and pgsodium configurations.', + STORAGE: 'access to storage buckets and files.', +} diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/OAuthSecrets/SecretRow.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthSecrets/SecretRow.tsx index f17a280cde7..20717de9729 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/OAuthSecrets/SecretRow.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthSecrets/SecretRow.tsx @@ -74,6 +74,14 @@ export const SecretRow = ({ secret, appId }: SecretRowProps) => {

Added {isNew ? 'now' : dayjs(secret.created_at).fromNow()} by {generatedByName}

+ {secret.last_used_at && ( +

+ Last used {dayjs(secret.last_used_at).fromNow()} +

+ )} + {!secret.last_used_at && !isNew && ( +

Never used

+ )}
diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/Scopes.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/Scopes.tsx index 1dc9e366a5d..7466baa694d 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/Scopes.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/Scopes.tsx @@ -11,6 +11,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from 'ui' +import { PERMISSIONS_DESCRIPTIONS } from '../OAuthApps.constants' const ScopeDropdownCheckboxItem = ({ children, @@ -66,12 +67,12 @@ const Scope = ({ return (
{title} - {description} + {description}
@@ -109,7 +110,7 @@ export const ScopesPanel = ({
diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx index 4eccdd17f71..068c517764d 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx @@ -88,7 +88,7 @@ export const MemberRow = ({ member }: MemberRowProps) => { />

{member.primary_email}

- {member.primary_email === profile?.primary_email && You} + {member.gotrue_id === profile?.gotrue_id && You}
{(member.metadata as any)?.origin && ( diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx index 2de693bc844..3ecc3b3de90 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/MembersView.tsx @@ -54,13 +54,13 @@ const MembersView = ({ searchString }: MembersViewProps) => { const [[user], otherMembers] = partition( filteredMembers, - (m) => m.primary_email === profile?.primary_email + (m) => m.gotrue_id === profile?.gotrue_id ) const sortedMembers = otherMembers.sort((a, b) => (a.primary_email ?? '').localeCompare(b.primary_email ?? '') ) - const userMember = members.find((m) => m.primary_email === profile?.primary_email) + const userMember = members.find((m) => m.gotrue_id === profile?.gotrue_id) const orgScopedRoleIds = (roles?.org_scoped_roles ?? []).map((r) => r.id) const isOrgScopedRole = orgScopedRoleIds.includes(userMember?.role_ids?.[0] ?? -1) diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx index 711deddee3e..7df15972893 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.tsx @@ -9,6 +9,7 @@ import { ScaffoldSectionContent, ScaffoldTitle, } from 'components/layouts/Scaffold' +import { DocsButton } from 'components/ui/DocsButton' import { Input } from 'ui-patterns/DataInputs/Input' import { InviteMemberButton } from './InviteMemberButton' import MembersView from './MembersView' @@ -32,6 +33,7 @@ export const TeamSettings = () => { placeholder="Filter members" /> + diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx index fc37dd4fe91..246dfd391d0 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx @@ -90,10 +90,11 @@ export const UpdateRolesConfirmationModal = ({ }) toast.success(`Successfully updated role for ${member.username}`) onClose(true) - return } catch (error: any) { + toast.error(`Failed to update role: ${error.message}`) + } finally { setSaving(false) - return toast.error(`Failed to update role: ${error.message}`) + return } } @@ -130,8 +131,10 @@ export const UpdateRolesConfirmationModal = ({ toast.success(`Successfully updated role for ${member.username}`) onClose(true) } catch (error: any) { + toast.error(`Failed to update role: ${error.message}`) + } finally { setSaving(false) - return toast.error(`Failed to update role: ${error.message}`) + return } } diff --git a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx index 5820c6e5ebe..4ec02427c22 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx @@ -195,8 +195,8 @@ const Usage = () => { title="Usage filtered by project" description={
- You are currently viewing usage for the " - {selectedProject?.name || selectedProjectRef}" project. Supabase uses{' '} + You are currently viewing usage for the + {selectedProject?.name || selectedProjectRef} project. Supabase uses{' '} ) : chartData.length > 0 && notAllValuesZero ? ( - +
Listen to event types
diff --git a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx index 87c29b77990..4553a4ee9a1 100644 --- a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx +++ b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx @@ -1,5 +1,6 @@ import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' +import Link from 'next/link' import { useEffect } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { toast } from 'sonner' @@ -11,6 +12,7 @@ import { ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { InlineLink } from 'components/ui/InlineLink' +import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useMaxConnectionsQuery } from 'data/database/max-connections-query' import { useRealtimeConfigurationUpdateMutation } from 'data/realtime/realtime-config-mutation' import { @@ -50,8 +52,21 @@ export const RealtimeSettings = () => { projectRef, }) + const { data: policies } = useDatabasePoliciesQuery({ + projectRef, + connectionString: project?.connectionString, + schema: 'realtime', + }) + const isUsageBillingEnabled = organization?.usage_billing_enabled + // Check if RLS policies exist for realtime.messages table + const realtimeMessagesPolicies = policies?.filter( + (policy) => policy.schema === 'realtime' && policy.table === 'messages' + ) + const hasRealtimeMessagesPolicies = + realtimeMessagesPolicies && realtimeMessagesPolicies.length > 0 + const { mutate: updateRealtimeConfig, isLoading: isUpdatingConfig } = useRealtimeConfigurationUpdateMutation({ onSuccess: () => { @@ -83,6 +98,9 @@ export const RealtimeSettings = () => { }, }) + const { allow_public } = form.watch() + const isSettingToPrivate = !data?.private_only && !allow_public + const onSubmit: SubmitHandler> = (data) => { if (!projectRef) return console.error('Project ref is required') updateRealtimeConfig({ @@ -132,6 +150,30 @@ export const RealtimeSettings = () => { /> + + {!hasRealtimeMessagesPolicies && !allow_public && ( + +

+ Private mode is {isSettingToPrivate ? 'being ' : ''} + enabled, but no RLS policies exists on the{' '} + realtime.messages table. No + messages will be received by users. +

+ + + + } + /> + )} )} diff --git a/apps/studio/components/interfaces/Reports/ReportChart.tsx b/apps/studio/components/interfaces/Reports/ReportChart.tsx index 6c2eb90253d..c24edbc1ef6 100644 --- a/apps/studio/components/interfaces/Reports/ReportChart.tsx +++ b/apps/studio/components/interfaces/Reports/ReportChart.tsx @@ -7,16 +7,19 @@ * This component acts as a bridge between the data-fetching logic and the * presentational chart component. */ -import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted' + +import Link from 'next/link' +import { useRef, useState } from 'react' + +import type { MultiAttribute } from 'components/ui/Charts/ComposedChart.utils' import LogChartHandler from 'components/ui/Charts/LogChartHandler' +import Panel from 'components/ui/Panel' +import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted' +import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' +import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { useChartData } from 'hooks/useChartData' import type { UpdateDateRange } from 'pages/project/[ref]/reports/database' -import type { MultiAttribute } from 'components/ui/Charts/ComposedChart.utils' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import Link from 'next/link' import { Button, cn } from 'ui' -import Panel from 'components/ui/Panel' -import { useRef, useState } from 'react' const ReportChart = ({ chart, @@ -25,9 +28,7 @@ const ReportChart = ({ interval, updateDateRange, functionIds, - orgPlanId, isLoading, - availableIn, className, }: { chart: any @@ -36,15 +37,17 @@ const ReportChart = ({ interval: string updateDateRange: UpdateDateRange functionIds?: string[] - orgPlanId?: string isLoading?: boolean - availableIn?: string[] className?: string }) => { const org = useSelectedOrganization() + const { plan: orgPlan } = useCurrentOrgPlan() + const orgPlanId = orgPlan?.id + const [isHoveringUpgrade, setIsHoveringUpgrade] = useState(false) const isAvailable = chart.availableIn === undefined || (orgPlanId && chart.availableIn.includes(orgPlanId)) + const canFetch = orgPlanId !== undefined const { data, @@ -114,7 +117,9 @@ const ReportChart = ({

{chart.label}

This chart is available from{' '} - {!!availableIn?.length ? availableIn[0] : 'Pro'}{' '} + + {!!chart.availableIn?.length ? chart.availableIn[0] : 'Pro'} + {' '} plan and above

diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx index 971d7ee7136..551e5ef2ac1 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx @@ -73,7 +73,7 @@ const RoleImpersonationPopover = ({ diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx index fa591e1e8a0..80a35929e36 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationSelector.tsx @@ -131,9 +131,7 @@ const RoleImpersonationSelector = ({ {selectedOption === 'authenticated' && ( <> -
- -
+ )} diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx index 970cefaeb09..edc0e0c753c 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx @@ -1,11 +1,12 @@ import { useDebounce } from '@uidotdev/usehooks' -import { ChevronDown, ExternalLink, User as IconUser, Loader2, Search, X } from 'lucide-react' +import { ChevronDown, User as IconUser, Loader2, Search, X } from 'lucide-react' import { useMemo, useState } from 'react' import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' +import { InlineLink } from 'components/ui/InlineLink' import { User, useUsersInfiniteQuery } from 'data/auth/users-infinite-query' import { useCustomAccessTokenHookDetails } from 'hooks/misc/useCustomAccessTokenHookDetails' import { useLocalStorage } from 'hooks/misc/useLocalStorage' @@ -13,13 +14,18 @@ import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-stat import { ResponseError } from 'types' import { Button, + cn, Collapsible_Shadcn_, CollapsibleContent_Shadcn_, CollapsibleTrigger_Shadcn_, + DropdownMenuSeparator, Input, - Switch, ScrollArea, - cn, + Switch, + Tabs_Shadcn_, + TabsContent_Shadcn_, + TabsList_Shadcn_, + TabsTrigger_Shadcn_, } from 'ui' import { InfoTooltip } from 'ui-patterns/info-tooltip' import { getAvatarUrl, getDisplayName } from '../Auth/Users/Users.utils' @@ -33,13 +39,13 @@ const UserImpersonationSelector = () => { const [additionalClaims, setAdditionalClaims] = useState('') const { id: tableId } = useParams() + const [selectedTab, setSelectedTab] = useState<'user' | 'external'>('user') const [previousSearches, setPreviousSearches] = useLocalStorage( LOCAL_STORAGE_KEYS.USER_IMPERSONATION_SELECTOR_PREVIOUS_SEARCHES(tableId!), [] ) - const [showExternalAuth, setShowExternalAuth] = useState(false) const state = useRoleImpersonationStateSnapshot() const debouncedSearchText = useDebounce(searchText, 300) @@ -146,7 +152,6 @@ const UserImpersonationSelector = () => { function stopImpersonating() { state.setRole(undefined) - setShowExternalAuth(false) // Reset external auth impersonation when stopping impersonation } function toggleAalState() { @@ -167,251 +172,246 @@ const UserImpersonationSelector = () => { setPreviousSearches([]) } - // Select a previous search - function selectPreviousSearch(prevUser: User) { - setSearchText(prevUser.email ?? prevUser.phone ?? prevUser.id ?? '') - } - return ( -
-

- {displayName ? `Impersonating ${displayName}` : 'Impersonate a User'} -

-

- {!impersonatingUser && !isExternalAuthImpersonating - ? "Select a user to respect your database's Row-Level Security policies for that particular user." - : "Results will respect your database's Row-Level Security policies for this user."} -

+ <> +
+

+ {displayName ? `Impersonating ${displayName}` : 'Impersonate a User'} +

+

+ {!impersonatingUser && !isExternalAuthImpersonating + ? "Select a user to respect your database's Row-Level Security policies for that particular user." + : "Results will respect your database's Row-Level Security policies for this user."} +

+ + {impersonatingUser && ( + + )} + {isExternalAuthImpersonating && ( + + )} + + {!impersonatingUser && !isExternalAuthImpersonating && ( + setSelectedTab(value)}> + + Project user + + External user + + Test RLS policies with external auth providers like Clerk or Auth0 by providing a + user ID and optional claims. + + + + + +
+ + ) : ( + + ) + } + placeholder="Search by id, email, phone, or name..." + onChange={(e) => setSearchText(e.target.value)} + value={searchText} + actions={ + searchText && ( + + ) + } + /> + {isLoading && ( +
+ + Loading users... +
+ )} + + {isError && } + + {isSuccess && + (users.length > 0 ? ( +
+
    + {users.map((user) => ( +
  • + +
  • + ))} +
+
+ ) : ( +
+

+ No users found +

+
+ ))} + + <> + {previousSearches.length > 0 && ( +
+ {previousSearches.length > 0 ? ( + <> + + +
+

+ Recents +

+ +
+
+ + + + 3 ? 'h-36' : 'h-auto')} + > +
    + {previousSearches.map((search) => ( +
  • + +
  • + ))} +
+
+
+
+ + ) : ( +
+ No recent searches +
+ )} +
+ )} + +
+
+ + +
+ setExternalUserId(e.target.value)} + /> + setAdditionalClaims(e.target.value)} + /> +
+ +
+
+
+
+ )} +
{/* Check for both regular user and external auth impersonation since they use different data structures but both need to be handled for displaying impersonation UI */} {!impersonatingUser && !isExternalAuthImpersonating ? ( -
- - ) : ( - - ) - } - placeholder="Search by id, email, phone, or name..." - onChange={(e) => setSearchText(e.target.value)} - value={searchText} - size="small" - actions={ - searchText && ( - - ) - } - /> - - - -
-

- Advanced options -

- -
-
- -
- -
-
-

External Auth Impersonation

- -

- Test RLS policies with external auth providers like Clerk or Auth0 by - providing a user ID and optional claims. -

-
-
- -
- -

- Enable external auth impersonation -

-
- - {showExternalAuth && ( -
- setExternalUserId(e.target.value)} - size="small" - /> - setAdditionalClaims(e.target.value)} - size="small" - /> -
-
- -
-
- )} -
- - - - {!showExternalAuth && ( - <> - {isLoading && ( -
- - Loading users... -
- )} - - {isError && } - - {isSuccess && - (users.length > 0 ? ( -
-
    - {users.map((user) => ( -
  • - -
  • - ))} -
-
- ) : ( -
-

- No users found -

-
- ))} - {previousSearches.length > 0 && ( -
- {previousSearches.length > 0 ? ( - <> - - -
-

- Recents -

- -
-
- - - - 3 ? 'h-36' : 'h-auto')} - > -
    - {previousSearches.map((search) => ( -
  • - -
  • - ))} -
-
-
-
- - ) : ( -
No recent searches
- )} -
- )} - - )} -
- ) : ( <> - {impersonatingUser && ( - - )} - {isExternalAuthImpersonating && ( - - )} + +
+ + +
+

+ Advanced options +

+ +
+
+ +
+
+

MFA assurance level

+ + AAL1 verifies users via standard login methods, while AAL2 adds a second + authentication factor. If you're not using MFA, you can leave this on AAL1. + Learn more about MFA{' '} + + here + + . + +
+ +
+

AAL1

+ +

AAL2

+
+
+
+
+
- )} -
+ ) : null} + ) } diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx index 520c479d647..7f7f3d8a2a2 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx @@ -416,7 +416,7 @@ const InfrastructureActivity = () => {
) : chartData.length ? ( void queryType?: QueryType projectRef: string - collectionName?: string isLoading: boolean error?: string | object } @@ -41,8 +40,6 @@ const LogSelection = ({ log, onClose, queryType, isLoading, error }: LogSelectio if (!log) return switch (queryType) { - // case 'warehouse': - // return case 'api': const status = log?.metadata?.[0]?.response?.[0]?.status_code const method = log?.metadata?.[0]?.request?.[0]?.method diff --git a/apps/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/WarehouseSelectionRenderer.tsx b/apps/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/WarehouseSelectionRenderer.tsx deleted file mode 100644 index 43047d1882e..00000000000 --- a/apps/studio/components/interfaces/Settings/Logs/LogSelectionRenderers/WarehouseSelectionRenderer.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { cn } from 'ui' -import { LOGS_TAILWIND_CLASSES } from '../Logs.constants' -import { jsonSyntaxHighlight, SelectionDetailedRow } from '../LogsFormatters' - -const DetailedJsonRow = ({ - label, - value, - code, -}: { - label: string - value: Object - code?: boolean -}) => { - return ( -
- {label} - -
-      
-    
- ) -} - -export const WarehouseSelectionRenderer = ({ log }: any) => { - return ( -
- {Object.entries(log).map(([key, value], index) => { - return ( -
- {value && typeof value === 'object' ? ( - - ) : ( - - )} -
- ) - })} -
- ) -} diff --git a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx index 7e043920a4b..bb5e4015af7 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -49,8 +49,6 @@ interface Props { onSave?: () => void hasEditorValue?: boolean className?: string - collectionName?: string // Used for warehouse queries - warehouseError?: string EmptyState?: ReactNode showHeader?: boolean showHistogramToggle?: boolean @@ -79,7 +77,6 @@ const LogTable = ({ onSave, hasEditorValue, className, - collectionName, EmptyState, showHeader = true, showHistogramToggle = true, @@ -154,9 +151,6 @@ const LogTable = ({ columns } else { switch (queryType) { - case 'warehouse': - columns = DEFAULT_COLUMNS - break case 'api': columns = DatabaseApiColumnRender break @@ -460,7 +454,6 @@ const LogTable = ({ log={selectedLog} error={selectedLogError} queryType={queryType} - collectionName={collectionName} /> )} diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.constants.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.constants.ts index c84fe325cc8..9044fd26bd9 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.constants.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.constants.ts @@ -369,7 +369,6 @@ export enum LogsTableName { POSTGREST = 'postgrest_logs', SUPAVISOR = 'supavisor_logs', PGBOUNCER = 'pgbouncer_logs', - WAREHOUSE = 'warehouse_logs', PG_UPGRADE = 'pg_upgrade_logs', PG_CRON = 'pg_cron_logs', } @@ -384,7 +383,6 @@ export const LOGS_TABLES = { storage: LogsTableName.STORAGE, postgrest: LogsTableName.POSTGREST, supavisor: LogsTableName.SUPAVISOR, - warehouse: LogsTableName.WAREHOUSE, pg_upgrade: LogsTableName.PG_UPGRADE, pg_cron: LogsTableName.POSTGRES, pgbouncer: LogsTableName.PGBOUNCER, @@ -401,7 +399,6 @@ export const LOGS_SOURCE_DESCRIPTION = { [LogsTableName.POSTGREST]: 'RESTful API web server logs', [LogsTableName.SUPAVISOR]: 'Shared connection pooler logs for PostgreSQL', [LogsTableName.PGBOUNCER]: 'Dedicated connection pooler for PostgreSQL', - [LogsTableName.WAREHOUSE]: 'Logs obtained from a data warehouse collection', [LogsTableName.PG_UPGRADE]: 'Logs generated by the Postgres version upgrade process', [LogsTableName.PG_CRON]: 'Postgres logs from pg_cron cron jobs', } diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts index d1f606a72ff..377f542ebb9 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts @@ -90,7 +90,6 @@ export type QueryType = | 'storage' | 'supavisor' | 'postgrest' - | 'warehouse' | 'pg_upgrade' | 'pg_cron' | 'pgbouncer' @@ -145,9 +144,3 @@ export interface DatetimeHelper { disabled?: boolean availableIn?: PlanId[] } - -export interface WarehouseCollection { - name: string - id: number - token: string -} diff --git a/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx b/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx index 5ea8b4292a3..f67aef39e04 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogsQueryPanel.tsx @@ -6,7 +6,6 @@ import { ReactNode, useState } from 'react' import { IS_PLATFORM } from 'common' import Table from 'components/to-be-cleaned/Table' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useFlag } from 'hooks/ui/useFlag' import { logConstants } from 'shared-data' import { Badge, @@ -28,23 +27,16 @@ import { LogsTableName, } from './Logs.constants' import { DatePickerValue, LogsDatePicker } from './Logs.DatePickers' -import { LogsWarning, LogTemplate, WarehouseCollection } from './Logs.types' -import { WarehouseQueryTemplate } from './Warehouse.utils' +import { LogsWarning, LogTemplate } from './Logs.types' -export type SourceType = 'logs' | 'warehouse' export interface LogsQueryPanelProps { templates?: LogTemplate[] - warehouseTemplates?: WarehouseQueryTemplate[] defaultFrom: string defaultTo: string warnings: LogsWarning[] - warehouseCollections: WarehouseCollection[] - dataSource: SourceType onSelectTemplate: (template: LogTemplate) => void - onSelectWarehouseTemplate: (template: WarehouseQueryTemplate) => void onSelectSource: (source: string) => void onDateChange: (value: DatePickerValue) => void - onDataSourceChange: (sourceType: SourceType) => void } function DropdownMenuItemContent({ name, desc }: { name: ReactNode; desc?: string }) { @@ -58,17 +50,12 @@ function DropdownMenuItemContent({ name, desc }: { name: ReactNode; desc?: strin const LogsQueryPanel = ({ templates = [], - warehouseTemplates = [], defaultFrom, defaultTo, warnings, - warehouseCollections, - dataSource, onSelectTemplate, - onSelectWarehouseTemplate, onSelectSource, onDateChange, - onDataSourceChange, }: LogsQueryPanelProps) => { const [showReference, setShowReference] = useState(false) @@ -78,15 +65,12 @@ const LogsQueryPanel = ({ projectEdgeFunctionAll: edgeFunctionsEnabled, } = useIsFeatureEnabled(['project_auth:all', 'project_storage:all', 'project_edge_function:all']) - const warehouseEnabled = useFlag('warehouse') - const logsTableNames = Object.entries(LogsTableName) .filter(([key]) => { if (key === 'AUTH') return authEnabled if (key === 'STORAGE') return storageEnabled if (key === 'FN_EDGE') return edgeFunctionsEnabled if (key === 'PG_CRON') return false - if (key === 'WAREHOUSE') return false return true }) .map(([, value]) => value) @@ -117,90 +101,31 @@ const LogsQueryPanel = ({
- {warehouseEnabled && ( - - - - - - onDataSourceChange('logs')}> - - - onDataSourceChange('warehouse')}> - - Collections NEW - - } - desc="Query your collections" - /> - - - - )} - - {dataSource === 'warehouse' && ( - - - - - - {warehouseTemplates.map((template) => ( - onSelectWarehouseTemplate(template)} - > - - - ))} - {warehouseCollections.length === 0 && ( - + + + + + + {logsTableNames + .sort((a, b) => a.localeCompare(b)) + .map((source) => ( + onSelectSource(source)}> - )} - - - )} + ))} + + - {dataSource === 'logs' && ( - - - - - - {dataSource === 'logs' && - logsTableNames - .sort((a, b) => a.localeCompare(b)) - .map((source) => ( - onSelectSource(source)}> - - - ))} - - - )} - - {dataSource === 'logs' && IS_PLATFORM && ( + {IS_PLATFORM && (
- {dataSource === 'logs' && ( - -

Field Reference

-
- } - visible={showReference} - cancelText="Close" - onCancel={() => setShowReference(false)} - hideFooter - triggerElement={ + + +

Field Reference

- } - > - -
-

- The following table shows all the available paths that can be queried from each - respective source. Do note that to access nested keys, you would need to perform - the necessary{' '} - - unnesting joins - - -

-
-
- - setShowReference(false)} + icon={} + /> +
+ } + visible={showReference} + cancelText="Close" + onCancel={() => setShowReference(false)} + hideFooter + triggerElement={ + + } + > + +
+

+ The following table shows all the available paths that can be queried from each + respective source. Do note that to access nested keys, you would need to perform + the necessary{' '} + -

- Path - , - - Type - , - ]} - body={schema.fields - .sort((a: any, b: any) => a.path - b.path) - .map((field) => ( - - ))} + unnesting joins + - - ))} - - - )} + +

+ + + + + {logConstants.schemas.map((schema) => ( + +
+ Path + , + + Type + , + ]} + body={schema.fields + .sort((a: any, b: any) => a.path - b.path) + .map((field) => ( + + ))} + /> + + ))} + + diff --git a/apps/studio/components/interfaces/Settings/Logs/Warehouse.utils.ts b/apps/studio/components/interfaces/Settings/Logs/Warehouse.utils.ts deleted file mode 100644 index fdb60183e09..00000000000 --- a/apps/studio/components/interfaces/Settings/Logs/Warehouse.utils.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type WarehouseQueryTemplate = { - query: string - name: string - description: string -} - -export function createWarehouseQueryTemplates( - collections: { name: string }[] -): WarehouseQueryTemplate[] { - return collections.flatMap((collection) => [ - { - query: `select count(*) as event_count from \`${collection.name}\` -where timestamp > timestamp_sub(current_timestamp(), interval 1 day)`, - name: `${collection.name} - Daily Event Count`, - description: `Count events in the last 24 hours from ${collection.name} collection`, - }, - { - query: `select id, timestamp, event_message from \`${collection.name}\` - where timestamp > timestamp_sub(current_timestamp(), interval 1 day) - and event_message like '%YOUR_TEXT_HERE%' - order by timestamp desc limit 10`, - name: `${collection.name} - Filter by text`, - description: `Select last 10 events from ${collection.name} collection`, - }, - ]) -} diff --git a/apps/studio/components/interfaces/Sidebar.tsx b/apps/studio/components/interfaces/Sidebar.tsx index e729bc0b732..44bfc0797c0 100644 --- a/apps/studio/components/interfaces/Sidebar.tsx +++ b/apps/studio/components/interfaces/Sidebar.tsx @@ -223,8 +223,6 @@ const ProjectLinks = () => { const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled() const { securityLints, errorLints } = useLints() - const showWarehouse = useFlag('warehouse') - const activeRoute = router.pathname.split('/')[3] const { @@ -310,14 +308,11 @@ const ProjectLinks = () => { ) } else if (route.key === 'logs') { - // TODO: Undo this when warehouse flag is removed - const label = showWarehouse ? 'Logs & Analytics' : route.label - const newRoute = { ...route, label } return ( ) } else { diff --git a/apps/studio/components/interfaces/SignIn/ForgotPasswordWizard.tsx b/apps/studio/components/interfaces/SignIn/ForgotPasswordWizard.tsx index 4aa80ad51d1..27e8df3b0a3 100644 --- a/apps/studio/components/interfaces/SignIn/ForgotPasswordWizard.tsx +++ b/apps/studio/components/interfaces/SignIn/ForgotPasswordWizard.tsx @@ -60,10 +60,13 @@ const ConfirmResetCodeForm = ({ email }: { email: string }) => { if (user?.factors?.length) { await router.push({ pathname: '/forgot-password-mfa', - query: { returnTo: '/reset-password' }, + query: router.query, }) } else { - await router.push('reset-password') + await router.push({ + pathname: '/reset-password', + query: router.query, + }) } } } diff --git a/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx b/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx index 868b5d96162..48e513fe0e8 100644 --- a/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx +++ b/apps/studio/components/interfaces/SignIn/ResetPasswordForm.tsx @@ -7,7 +7,7 @@ import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { z } from 'zod' -import { auth } from 'lib/gotrue' +import { auth, getReturnToPath } from 'lib/gotrue' import { Button, Form_Shadcn_, @@ -67,7 +67,7 @@ const ResetPasswordForm = () => { // logout all other sessions after changing password await auth.signOut({ scope: 'others' }) - await router.push('/organizations') + await router.push(getReturnToPath('/organizations')) } else { toast.error(`Failed to save password: ${error.message}`, { id: toastId }) if (!WHITELIST_ERRORS.some((e) => error.message.includes(e))) { diff --git a/apps/studio/components/interfaces/SignIn/SignInForm.tsx b/apps/studio/components/interfaces/SignIn/SignInForm.tsx index b25214fa34b..9460c7c2ebb 100644 --- a/apps/studio/components/interfaces/SignIn/SignInForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInForm.tsx @@ -4,7 +4,7 @@ import type { AuthError } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' import { useRouter } from 'next/router' -import { useRef, useState } from 'react' +import { useRef, useState, useEffect } from 'react' import { toast } from 'sonner' import { object, string } from 'yup' @@ -28,10 +28,22 @@ const SignInForm = () => { const [captchaToken, setCaptchaToken] = useState(null) const captchaRef = useRef(null) + const [returnTo, setReturnTo] = useState(null) + + useEffect(() => { + // Only call getReturnToPath after component mounts client-side + setReturnTo(getReturnToPath()) + }, []) const { mutate: sendEvent } = useSendEventMutation() const { mutate: addLoginEvent } = useAddLoginEvent() + let forgotPasswordUrl = `/forgot-password` + + if (returnTo && !returnTo.includes('/forgot-password')) { + forgotPasswordUrl = `${forgotPasswordUrl}?returnTo=${encodeURIComponent(returnTo)}` + } + const onSignIn = async ({ email, password }: { email: string; password: string }) => { const toastId = toast.loading('Signing in...') @@ -68,9 +80,12 @@ const SignInForm = () => { addLoginEvent({}) await queryClient.resetQueries() - const returnTo = getReturnToPath() // since we're already on the /sign-in page, prevent redirect loops - router.push(returnTo === '/sign-in' ? '/organizations' : returnTo) + let redirectPath = '/organizations' + if (returnTo && returnTo !== '/sign-in') { + redirectPath = returnTo + } + router.push(redirectPath) } catch (error: any) { toast.error(`Failed to sign in: ${(error as AuthError).message}`, { id: toastId }) Sentry.captureMessage('[CRITICAL] Failed to sign in via EP: ' + error.message) @@ -124,7 +139,7 @@ const SignInForm = () => { {/* positioned using absolute instead of labelOptional prop so tabbing between inputs works smoothly */} Forgot Password? diff --git a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx index 7543a1a4111..f0ec3eb1381 100644 --- a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx @@ -18,7 +18,11 @@ const signInSchema = object({ code: string().required('MFA Code is required'), }) -const SignInMfaForm = () => { +interface SignInMfaFormProps { + context?: 'forgot-password' | 'sign-in' +} + +const SignInMfaForm = ({ context = 'sign-in' }: SignInMfaFormProps) => { const router = useRouter() const signOut = useSignOut() const queryClient = useQueryClient() @@ -38,7 +42,15 @@ const SignInMfaForm = () => { } = useMfaChallengeAndVerifyMutation({ onSuccess: async () => { await queryClient.resetQueries() - router.push(getReturnToPath()) + + if (context === 'forgot-password') { + router.push({ + pathname: '/reset-password', + query: router.query, + }) + } else { + router.push(getReturnToPath()) + } }, }) diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx index e22c8a8e694..fff4f06387f 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx @@ -1,8 +1,10 @@ +import { ExternalLink, Eye, EyeOff, Loader } from 'lucide-react' +import { useState } from 'react' + +import { useParams } from 'common' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' -import { Eye, EyeOff, Loader } from 'lucide-react' -import { useState } from 'react' -import { Button, Input } from 'ui' +import { Button, Input, Tooltip, TooltipContent, TooltipTrigger } from 'ui' export const DecryptedReadOnlyInput = ({ value, @@ -15,10 +17,11 @@ export const DecryptedReadOnlyInput = ({ descriptionText: string label: string }) => { - const [showHidden, setShowHidden] = useState(false) + const { ref } = useParams() const { project } = useProjectContext() + const [showHidden, setShowHidden] = useState(false) - const { isLoading: isDecryptedValueLoading, data: decryptedValue } = + const { data: decryptedValue, isLoading: isDecryptedValueLoading } = useVaultSecretDecryptedValueQuery( { projectRef: project?.ref, @@ -29,22 +32,40 @@ export const DecryptedReadOnlyInput = ({ ) const isLoading = isDecryptedValueLoading && showHidden + const renderedValue = secureEntry + ? isLoading + ? 'Fetching value from Vault...' + : showHidden + ? decryptedValue + : value + : value return ( + {label} + + + + + + + View parameter in Vault + + } + value={renderedValue} type={secureEntry ? (isLoading ? 'text' : showHidden ? 'text' : 'password') : 'text'} descriptionText={descriptionText} layout="horizontal" diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx index 80d75a33da4..1c716007a56 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx @@ -1,6 +1,7 @@ import { RefreshCw, SquareArrowOutUpRight } from 'lucide-react' import { useMemo, useState } from 'react' +import type { WrapperMeta } from 'components/interfaces/Integrations/Wrappers/Wrappers.types' import { FormattedWrapperTable } from 'components/interfaces/Integrations/Wrappers/Wrappers.utils' import { ImportForeignSchemaDialog } from 'components/interfaces/Storage/ImportForeignSchemaDialog' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' @@ -9,34 +10,32 @@ import { useFDWImportForeignSchemaMutation } from 'data/fdw/fdw-import-foreign-s import { FDW } from 'data/fdw/fdws-query' import { useIcebergNamespaceTablesQuery } from 'data/storage/iceberg-namespace-tables-query' import { BASE_PATH } from 'lib/constants' -import { Badge, Button, TableCell, TableRow } from 'ui' +import { Button, cn, TableCell, TableRow } from 'ui' type NamespaceRowProps = { bucketName: string namespace: string schema: string - excludedSchemas: string[] tables: (FormattedWrapperTable & { id: number })[] token: string wrapperInstance: FDW wrapperValues: Record + wrapperMeta: WrapperMeta } export const NamespaceRow = ({ bucketName, namespace, schema, - excludedSchemas, tables, token, wrapperInstance, wrapperValues, + wrapperMeta, }: NamespaceRowProps) => { const { project } = useProjectContext() const [importForeignSchemaShown, setImportForeignSchemaShown] = useState(false) - const targetSchema = tables[0]?.schema_name ?? '' - const { data: tablesData, isLoading: isLoadingNamespaceTables } = useIcebergNamespaceTablesQuery( { catalogUri: wrapperValues.catalog_uri, @@ -56,7 +55,7 @@ export const NamespaceRow = ({ connectionString: project?.connectionString, serverName: wrapperInstance.server_name, sourceSchema: namespace, - targetSchema: targetSchema, + targetSchema: schema, }) } @@ -76,11 +75,11 @@ export const NamespaceRow = ({ return ( - - {namespace} + {namespace} + + {schema ?? 'No schema'} - {schema && {schema}} - + {tablesData ? `${tables.length}/${tablesData.length} connected tables` : ``} @@ -96,15 +95,15 @@ export const NamespaceRow = ({ Sync {schema ? ( - - - + ) : ( - Table Editor + Open in Table Editor )} @@ -122,8 +121,7 @@ export const NamespaceRow = ({ setImportForeignSchemaShown(false)} /> diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx index 49aead6e1f0..25945e40d77 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx @@ -127,7 +127,6 @@ export const AnalyticBucketDetails = ({ bucket }: { bucket: Bucket }) => { } }) }, [wrapperTables, namespacesData]) - const excludedSchemas = uniq(namespaces.map((n) => n.schema)) const wrappersExtension = extensionsData?.find((ext) => ext.name === 'wrappers') @@ -196,10 +195,10 @@ export const AnalyticBucketDetails = ({ bucket }: { bucket: Bucket }) => {
- Namespace - Schema - Tables - Actions + Namespace + Schema + Tables + @@ -209,11 +208,11 @@ export const AnalyticBucketDetails = ({ bucket }: { bucket: Bucket }) => { bucketName={bucket.name} namespace={namespace} schema={schema} - excludedSchemas={excludedSchemas} tables={tables as any} token={token!} wrapperInstance={wrapperInstance} wrapperValues={wrapperValues} + wrapperMeta={wrapperMeta} /> ))} diff --git a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx index 1523c488ee8..75911012462 100644 --- a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx @@ -11,10 +11,7 @@ import z from 'zod' import { useParams } from 'common' import { useIcebergWrapperExtension } from 'components/interfaces/Storage/AnalyticBucketDetails/useIcebergWrapper' import { StorageSizeUnits } from 'components/interfaces/Storage/StorageSettings/StorageSettings.constants' -import { - convertFromBytes, - convertToBytes, -} from 'components/interfaces/Storage/StorageSettings/StorageSettings.utils' +import { InlineLink } from 'components/ui/InlineLink' import { useProjectStorageConfigQuery } from 'data/config/project-storage-config-query' import { useBucketCreateMutation } from 'data/storage/bucket-create-mutation' import { useIcebergWrapperCreateMutation } from 'data/storage/iceberg-wrapper-create-mutation' @@ -42,6 +39,7 @@ import { } from 'ui' import { Admonition } from 'ui-patterns/admonition' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import { convertFromBytes, convertToBytes } from './StorageSettings/StorageSettings.utils' export interface CreateBucketModalProps { visible: boolean @@ -80,7 +78,10 @@ const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => { const { mutate: sendEvent } = useSendEventMutation() const router = useRouter() - const { mutateAsync: createBucket, isLoading: isCreating } = useBucketCreateMutation() + const { mutateAsync: createBucket, isLoading: isCreating } = useBucketCreateMutation({ + // [Joshen] Silencing the error here as it's being handled in onSubmit + onError: () => {}, + }) const { mutateAsync: createIcebergWrapper, isLoading: isCreatingIcebergWrapper } = useIcebergWrapperCreateMutation() @@ -150,9 +151,8 @@ const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => { toast.success(`Successfully created bucket ${values.name}`) router.push(`/project/${ref}/storage/buckets/${values.name}`) onClose() - } catch (error) { - console.error(error) - toast.error('Failed to create bucket') + } catch (error: any) { + toast.error(`Failed to create bucket: ${error.message}`) } } @@ -235,20 +235,16 @@ const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => {

- {icebergCatalogEnabled ? null : ( + {!icebergCatalogEnabled && (
- - This feature is currently in alpha and not yet enabled for your - project. Sign up{' '} - + + This is currently in alpha and not enabled for your project. Sign + up{' '} + here - + + .
)} diff --git a/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx index a173dbcfa52..c54d1e3bd45 100644 --- a/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx +++ b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx @@ -1,5 +1,5 @@ import { zodResolver } from '@hookform/resolvers/zod' -import { snakeCase } from 'lodash' +import { snakeCase, uniq } from 'lodash' import { useEffect, useState } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { toast } from 'sonner' @@ -7,41 +7,30 @@ import z from 'zod' import { useParams } from 'common' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import SchemaSelector from 'components/ui/SchemaSelector' +import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' +import { useSchemasQuery } from 'data/database/schemas-query' import { useFDWImportForeignSchemaMutation } from 'data/fdw/fdw-import-foreign-schema-mutation' -import { - Button, - Form_Shadcn_, - FormControl_Shadcn_, - FormField_Shadcn_, - Input_Shadcn_, - Modal, -} from 'ui' +import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' +import { getFDWs } from 'data/fdw/fdws-query' +import { Button, Form_Shadcn_, FormField_Shadcn_, Input_Shadcn_, Modal } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import type { WrapperMeta } from '../Integrations/Wrappers/Wrappers.types' +import { formatWrapperTables } from '../Integrations/Wrappers/Wrappers.utils' import SchemaEditor from '../TableGridEditor/SidePanelEditor/SchemaEditor' +import { getDecryptedParameters } from './ImportForeignSchemaDialog.utils' export interface ImportForeignSchemaDialogProps { bucketName: string namespace: string - excludedSchemas: string[] - wrapperValues: Record + wrapperMeta: WrapperMeta visible: boolean onClose: () => void } -const FormSchema = z.object({ - bucketName: z.string().trim(), - sourceNamespace: z.string().trim(), - targetSchema: z.string().trim(), -}) - -export type ImportForeignSchemaForm = z.infer - export const ImportForeignSchemaDialog = ({ bucketName, namespace, - excludedSchemas, - wrapperValues, + wrapperMeta, visible, onClose, }: ImportForeignSchemaDialogProps) => { @@ -50,14 +39,34 @@ export const ImportForeignSchemaDialog = ({ const [loading, setLoading] = useState(false) const [createSchemaSheetOpen, setCreateSchemaSheetOpen] = useState(false) - const { mutateAsync: importForeignSchema } = useFDWImportForeignSchemaMutation({ + const { mutateAsync: importForeignSchema } = useFDWImportForeignSchemaMutation({}) + const { mutateAsync: updateFDW } = useFDWUpdateMutation({ onSuccess: () => { toast.success(`Successfully connected ${bucketName} to the database.`) onClose() }, }) - const form = useForm({ + const { data: schemas } = useSchemasQuery({ projectRef: project?.ref! }) + + const FormSchema = z.object({ + bucketName: z.string().trim(), + sourceNamespace: z.string().trim(), + targetSchema: z + .string() + .trim() + .min(1, 'Schema name is required') + .refine( + (val) => { + return !schemas?.find((s) => s.name === val) + }, + { + message: 'This schema already exists. Please specify a unique schema name.', + } + ), + }) + + const form = useForm>({ resolver: zodResolver(FormSchema), defaultValues: { bucketName, @@ -66,18 +75,67 @@ export const ImportForeignSchemaDialog = ({ }, }) - const onSubmit: SubmitHandler = async (values) => { + const { mutateAsync: createSchema } = useSchemaCreateMutation() + + const onSubmit: SubmitHandler> = async (values) => { + const serverName = `${snakeCase(values.bucketName)}_fdw_server` + if (!ref) return console.error('Project ref is required') setLoading(true) try { + await createSchema({ + projectRef: ref, + connectionString: project?.connectionString, + name: values.targetSchema, + }) + await importForeignSchema({ projectRef: ref, connectionString: project?.connectionString, - serverName: `${snakeCase(values.bucketName)}_fdw_server`, + serverName: serverName, sourceSchema: values.sourceNamespace, targetSchema: values.targetSchema, }) + + const FDWs = await getFDWs({ projectRef: ref, connectionString: project?.connectionString }) + const wrapper = FDWs.find((fdw) => fdw.server_name === serverName) + if (!wrapper) { + throw new Error(`Foreign data wrapper with server name ${serverName} not found`) + } + + const serverOptions = await getDecryptedParameters({ + ref: project?.ref, + connectionString: project?.connectionString ?? undefined, + serverName, + }) + + const formValues: Record = { + wrapper_name: wrapper.name, + server_name: wrapper.server_name, + ...serverOptions, + } + + const targetSchemas = (formValues['supabase_target_schema'] || '') + .split(',') + .map((s) => s.trim()) + + const wrapperTables = formatWrapperTables(wrapper, wrapperMeta) + + await updateFDW({ + projectRef: project?.ref, + connectionString: project?.connectionString, + wrapper: wrapper, + wrapperMeta: wrapperMeta, + formState: { + ...formValues, + server_name: serverName, + supabase_target_schema: uniq([...targetSchemas, values.targetSchema]) + .filter(Boolean) + .join(','), + }, + tables: wrapperTables, + }) } catch (error: any) { // error will be handled by the mutation onError callback } finally { @@ -110,35 +168,16 @@ export const ImportForeignSchemaDialog = ({
- ( - - - - - - )} - /> - ( - field.onChange(schema)} - onSelectCreateSchema={() => setCreateSchemaSheetOpen(true)} - /> + )} /> diff --git a/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.utils.ts b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.utils.ts new file mode 100644 index 00000000000..923e41ae733 --- /dev/null +++ b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.utils.ts @@ -0,0 +1,51 @@ +import { getFDWs } from 'data/fdw/fdws-query' +import { getDecryptedValues } from 'data/vault/vault-secret-decrypted-value-query' +import { INTEGRATIONS } from '../Integrations/Landing/Integrations.constants' +import { WrapperMeta } from '../Integrations/Wrappers/Wrappers.types' +import { convertKVStringArrayToJson } from '../Integrations/Wrappers/Wrappers.utils' + +export const getDecryptedParameters = async ({ + ref, + connectionString, + serverName, +}: { + ref?: string + connectionString?: string + serverName: string +}) => { + const integration = INTEGRATIONS.find((i) => i.id === 'iceberg_wrapper' && i.type === 'wrapper') + const wrapperMeta = (integration?.type === 'wrapper' && integration.meta) as WrapperMeta + const wrapperServerOptions = wrapperMeta.server.options + + const FDWs = await getFDWs({ projectRef: ref, connectionString: connectionString }) + const wrapper = FDWs.find((fdw) => fdw.server_name === serverName) + const serverOptions = convertKVStringArrayToJson(wrapper?.server_options ?? []) + + const paramsToBeDecrypted = Object.fromEntries( + new Map( + Object.entries(serverOptions).filter(([key, value]) => { + return wrapperServerOptions.find((option) => option.name === key)?.encrypted + }) + ) + ) + + const decryptedValues = await getDecryptedValues({ + projectRef: ref, + connectionString: connectionString, + ids: Object.values(paramsToBeDecrypted), + }) + + const paramsWithDecryptedValues = Object.fromEntries( + new Map( + Object.entries(paramsToBeDecrypted).map(([name, id]) => { + const decryptedValue = decryptedValues[id] + return [name, decryptedValue] + }) + ) + ) + + return { + ...serverOptions, + ...paramsWithDecryptedValues, + } +} diff --git a/apps/studio/components/layouts/APIAuthorizationLayout.tsx b/apps/studio/components/layouts/APIAuthorizationLayout.tsx index 10a57ab76b7..bebbb882323 100644 --- a/apps/studio/components/layouts/APIAuthorizationLayout.tsx +++ b/apps/studio/components/layouts/APIAuthorizationLayout.tsx @@ -14,7 +14,7 @@ const APIAuthorizationLayout = ({ children }: PropsWithChildren Authorize API access | Supabase -
+
diff --git a/apps/studio/components/layouts/DefaultLayout.tsx b/apps/studio/components/layouts/DefaultLayout.tsx index 4280bacbcce..c9b8a705428 100644 --- a/apps/studio/components/layouts/DefaultLayout.tsx +++ b/apps/studio/components/layouts/DefaultLayout.tsx @@ -1,10 +1,11 @@ +import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' import { useParams } from 'common' import { AppBannerWrapper } from 'components/interfaces/App' import { AppBannerContextProvider } from 'components/interfaces/App/AppBannerWrapperContext' import { Sidebar } from 'components/interfaces/Sidebar' -import { useRouter } from 'next/router' +import { useCheckLatestDeploy } from 'hooks/use-check-latest-deploy' import { SidebarProvider } from 'ui' import { LayoutHeader } from './ProjectLayout/LayoutHeader' import MobileNavigationBar from './ProjectLayout/NavigationBar/MobileNavigationBar' @@ -29,6 +30,8 @@ const DefaultLayout = ({ children, headerTitle }: PropsWithChildren diff --git a/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx b/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx index 86f999ecd7f..785bb992b68 100644 --- a/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx +++ b/apps/studio/components/layouts/LogsLayout/LogsSidebarMenuV2.tsx @@ -9,13 +9,9 @@ import { useFeaturePreviewModal, useUnifiedLogsPreview, } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' -import { CreateWarehouseCollectionModal } from 'components/interfaces/DataWarehouse/CreateWarehouseCollection' -import { WarehouseMenuItem } from 'components/interfaces/DataWarehouse/WarehouseMenuItem' import SavedQueriesItem from 'components/interfaces/Settings/Logs/Logs.SavedQueriesItem' import { LogsSidebarItem } from 'components/interfaces/Settings/Logs/SidebarV2/SidebarItem' import { ButtonTooltip } from 'components/ui/ButtonTooltip' -import { useWarehouseCollectionsQuery } from 'data/analytics/warehouse-collections-query' -import { useWarehouseTenantQuery } from 'data/analytics/warehouse-tenant-query' import { useContentQuery } from 'data/content/content-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' @@ -27,14 +23,7 @@ import { Collapsible_Shadcn_, CollapsibleContent_Shadcn_, CollapsibleTrigger_Shadcn_, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, Separator, - Tooltip, - TooltipContent, - TooltipTrigger, } from 'ui' import { InnerSideBarEmptyPanel, @@ -90,16 +79,11 @@ export function LogsSidebarMenuV2() { const router = useRouter() const { ref } = useParams() as { ref: string } - const warehouseEnabled = useFlag('warehouse') const unifiedLogsFlagEnabled = useFlag('unifiedLogs') const { selectFeaturePreview } = useFeaturePreviewModal() const { enable: enableUnifiedLogs } = useUnifiedLogsPreview() const [searchText, setSearchText] = useState('') - const [createCollectionOpen, setCreateCollectionOpen] = useState(false) - const canCreateCollection = useCheckPermissions(PermissionAction.ANALYTICS_WRITE, 'logflare') - - const { data: tenantData } = useWarehouseTenantQuery({ projectRef: ref }) const { projectAuthAll: authEnabled, @@ -107,11 +91,6 @@ export function LogsSidebarMenuV2() { realtimeAll: realtimeEnabled, } = useIsFeatureEnabled(['project_storage:all', 'project_auth:all', 'realtime:all']) - const { data: whCollections, isLoading: whCollectionsLoading } = useWarehouseCollectionsQuery( - { projectRef: ref }, - { enabled: IS_PLATFORM && warehouseEnabled && !!tenantData } - ) - const { plan: orgPlan, isLoading: isOrgPlanLoading } = useCurrentOrgPlan() const isFreePlan = !isOrgPlanLoading && orgPlan?.id === 'free' @@ -223,9 +202,6 @@ export function LogsSidebarMenuV2() { const filteredOperationalLogs = OPERATIONAL_COLLECTIONS.filter((collection) => { return collection?.name.toLowerCase().includes(searchText.toLowerCase()) }) - const filteredWarehouse = whCollections?.filter((collection) => { - return collection.name.toLowerCase().includes(searchText.toLowerCase()) - }) return (
@@ -285,56 +261,11 @@ export function LogsSidebarMenuV2() { > - {warehouseEnabled ? ( - - - - - - {!canCreateCollection && ( - - You need additional permissions to create a collection - - )} - - - - ) : ( -
@@ -361,17 +292,6 @@ export function LogsSidebarMenuV2() { /> ) })} - {whCollectionsLoading && warehouseEnabled ? ( -
- -
- ) : filteredWarehouse?.length ? ( -
- {filteredWarehouse.map((collection) => ( - - ))} -
- ) : null} {OPERATIONAL_COLLECTIONS.length > 0 && ( <> diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index 62cea948bb6..f6c47c59ede 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -51,6 +51,7 @@ export interface EntityListItemProps { projectRef: string isLocked: boolean isActive?: boolean + onExportCLI: () => void } // [jordi] Used to determine the entity is a table and not a view or other unsupported entity type @@ -64,6 +65,7 @@ const EntityListItem: ItemRenderer = ({ item: entity, isLocked, isActive: _isActive, + onExportCLI, }) => { const { project } = useProjectContext() const snap = useTableEditorStateSnapshot() @@ -386,6 +388,16 @@ const EntityListItem: ItemRenderer = ({ > Export table as SQL + { + e.stopPropagation() + onExportCLI() + }} + > + Export table via CLI + diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index 84bd7f4f689..3262273143e 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -5,6 +5,7 @@ import { useEffect, useMemo, useState } from 'react' import { useParams } from 'common' import { useBreakpoint } from 'common/hooks/useBreakpoint' +import { ExportDialog } from 'components/grid/components/header/ExportDialog' import { ProtectedSchemaModal } from 'components/interfaces/Database/ProtectedSchemaWarning' import EditorMenuListSkeleton from 'components/layouts/TableEditorLayout/EditorMenuListSkeleton' import AlertError from 'components/ui/AlertError' @@ -52,6 +53,7 @@ const TableEditorMenu = () => { const [showModal, setShowModal] = useState(false) const [searchText, setSearchText] = useState('') + const [tableToExport, setTableToExport] = useState<{ name: string; schema: string }>() const [visibleTypes, setVisibleTypes] = useState(Object.values(ENTITY_TYPE)) const [sort, setSort] = useLocalStorage<'alphabetical' | 'grouped-alphabetical'>( 'table-editor-sort', @@ -281,6 +283,11 @@ const TableEditorMenu = () => { projectRef: project?.ref!, id: Number(id), isLocked, + onExportCLI: () => { + const entity = entityTypes?.find((x) => x.id === id) + if (!entity) return + setTableToExport({ name: entity.name, schema: entity.schema }) + }, }} getItemSize={() => 28} hasNextPage={hasNextPage} @@ -294,6 +301,13 @@ const TableEditorMenu = () => {
+ { + if (!open) setTableToExport(undefined) + }} + /> setShowModal(false)} /> ) diff --git a/apps/studio/components/ui/Charts/ComposedChart.tsx b/apps/studio/components/ui/Charts/ComposedChart.tsx index 78e1e45a09c..5f891992832 100644 --- a/apps/studio/components/ui/Charts/ComposedChart.tsx +++ b/apps/studio/components/ui/Charts/ComposedChart.tsx @@ -235,7 +235,10 @@ export default function ComposedChart({ }) : [] - const stackedAttributes = chartData.filter((att) => !att.name.includes('max')) + const stackedAttributes = chartData.filter((att) => { + const attribute = attributes.find((attr) => attr.attribute === att.name) + return !attribute?.isMaxValue + }) const isPercentage = format === '%' const isRamChart = !chartData?.some((att: any) => att.name.toLowerCase() === 'ram_usage') && diff --git a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterControlsDrawer.tsx b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterControlsDrawer.tsx index 835d77cc54e..0267de60693 100644 --- a/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterControlsDrawer.tsx +++ b/apps/studio/components/ui/DataTable/DataTableFilters/DataTableFilterControlsDrawer.tsx @@ -15,7 +15,6 @@ import { DrawerTrigger, Tooltip, TooltipContent, - TooltipProvider, TooltipTrigger, } from 'ui' import { useMediaQuery } from '../hooks/useMediaQuery' @@ -32,26 +31,24 @@ export function DataTableFilterControlsDrawer() { return ( - - - - - - - - -

- Toggle controls with{' '} - - ⌘ - B - -

-
-
-
+ + + + + + + +

+ Toggle controls with{' '} + + ⌘ + B + +

+
+
diff --git a/apps/studio/components/ui/DataTable/DataTableResetButton.tsx b/apps/studio/components/ui/DataTable/DataTableResetButton.tsx index 0e9c18c8911..3e373ff2ee5 100644 --- a/apps/studio/components/ui/DataTable/DataTableResetButton.tsx +++ b/apps/studio/components/ui/DataTable/DataTableResetButton.tsx @@ -1,7 +1,7 @@ import { X } from 'lucide-react' import { useHotKey } from 'hooks/ui/useHotKey' -import { Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from 'ui' +import { Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { Kbd } from './primitives/Kbd' import { useDataTable } from './providers/DataTableProvider' @@ -10,28 +10,21 @@ export function DataTableResetButton() { useHotKey(table.resetColumnFilters, 'Escape') return ( - - - - - - -

- Reset filters with{' '} - - ⌘ - Esc - -

-
-
-
+ + + + + +

+ Reset filters with{' '} + + ⌘ + Esc + +

+
+
) } diff --git a/apps/studio/components/ui/DataTable/DataTableSheetDetails.tsx b/apps/studio/components/ui/DataTable/DataTableSheetDetails.tsx index 4a5ed2200fe..29f7a7f0495 100644 --- a/apps/studio/components/ui/DataTable/DataTableSheetDetails.tsx +++ b/apps/studio/components/ui/DataTable/DataTableSheetDetails.tsx @@ -1,16 +1,7 @@ import { ChevronDown, ChevronUp, X } from 'lucide-react' import { ReactNode, useCallback, useEffect, useMemo } from 'react' -import { - Button, - cn, - Separator, - Skeleton, - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from 'ui' +import { Button, cn, Separator, Skeleton, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { Kbd } from './primitives/Kbd' import { useDataTable } from './providers/DataTableProvider' @@ -79,44 +70,41 @@ export function DataTableSheetDetails({ {isLoading && !selectedRowKey ? : title}
- - - - - - -

- Toggle controls with{' '} - - ⌘ - B - -

-
-
-
+ + + + + +

+ Toggle controls with{' '} + + ⌘ + B + +

+
+
diff --git a/apps/studio/data/analytics/keys.ts b/apps/studio/data/analytics/keys.ts index 5f1e97e656d..fa77be8e2c4 100644 --- a/apps/studio/data/analytics/keys.ts +++ b/apps/studio/data/analytics/keys.ts @@ -1,19 +1,4 @@ export const analyticsKeys = { - // warehouse - warehouseQuery: (projectRef: string, query: string) => - ['projects', projectRef, 'warehouse', 'query', query] as const, - warehouseTenant: (projectRef: string) => ['projects', projectRef, 'warehouse', 'tenant'] as const, - warehouseCollections: (projectRef: string) => - ['projects', projectRef, 'warehouse', 'collections'] as const, - warehouseCollectionsCreate: (projectRef: string) => - ['projects', projectRef, 'warehouse', 'collections', 'create'] as const, - warehouseEndpoints: (projectRef: string) => - ['projects', projectRef, 'warehouse', 'endpoints'] as const, - warehouseBackends: (projectRef: string) => - ['projects', projectRef, 'warehouse', 'backends'] as const, - warehouseAccessTokens: (projectRef: string) => - ['projects', projectRef, 'warehouse', 'access-tokens'] as const, - // logs/reports endpoints functionsInvStats: ( projectRef: string | undefined, diff --git a/apps/studio/data/analytics/warehouse-access-tokens-query.ts b/apps/studio/data/analytics/warehouse-access-tokens-query.ts deleted file mode 100644 index bfa30ccb304..00000000000 --- a/apps/studio/data/analytics/warehouse-access-tokens-query.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { analyticsKeys } from './keys' -import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' - -export type WarehouseAccessTokensVariables = { - projectRef: string -} - -export async function getWarehouseAccessTokens( - { projectRef }: WarehouseAccessTokensVariables, - signal?: AbortSignal -) { - if (!projectRef) { - throw new Error('projectRef is required') - } - - // TODO: Remove typecast when codegen types are fixed - const response = await get(`/platform/projects/{ref}/analytics/warehouse/access-tokens`, { - params: { path: { ref: projectRef } }, - signal, - }) - - if (response.error) { - handleError(response) - } - - return response -} - -export type WarehouseAccessTokensData = Awaited> -export type WarehouseAccessTokensError = ResponseError -/** - * This will be deprecated or rewritten in favor of the new project API keys - */ -export const useWarehouseAccessTokensQuery = ( - { projectRef }: WarehouseAccessTokensVariables, - { - enabled = true, - ...options - }: UseQueryOptions = {} -) => - useQuery( - analyticsKeys.warehouseAccessTokens(projectRef), - ({ signal }) => getWarehouseAccessTokens({ projectRef }, signal), - { - enabled: enabled && typeof projectRef !== 'undefined', - ...options, - } - ) diff --git a/apps/studio/data/analytics/warehouse-collection-log-detail-query.ts b/apps/studio/data/analytics/warehouse-collection-log-detail-query.ts deleted file mode 100644 index 4d8beefd712..00000000000 --- a/apps/studio/data/analytics/warehouse-collection-log-detail-query.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { useWarehouseQueryQuery } from './warehouse-query' - -export function useWarehouseLogDetailQuery({ - ref, - collectionName, - logId, - columns = ['id', 'timestamp'], -}: { - ref: string - collectionName?: string - logId?: string - columns?: string[] -}) { - const enabled = !!logId && !!collectionName - const sql = `select ${columns.join(',')} from \`${collectionName}\` - where id = '${logId}' and timestamp > '2024-01-01' limit 1` - - return useWarehouseQueryQuery({ ref, sql }, { enabled }) -} diff --git a/apps/studio/data/analytics/warehouse-collections-create-mutation.ts b/apps/studio/data/analytics/warehouse-collections-create-mutation.ts deleted file mode 100644 index f1ec421ae3d..00000000000 --- a/apps/studio/data/analytics/warehouse-collections-create-mutation.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { handleError, post } from 'data/fetchers' -import { toast } from 'sonner' -import type { ResponseError } from 'types' -import { analyticsKeys } from './keys' - -export type CreateCollectionArgs = { - projectRef: string - name: string - retention_days: number -} - -export async function createCollection({ projectRef, name, retention_days }: CreateCollectionArgs) { - const { data, error } = await post('/platform/projects/{ref}/analytics/warehouse/collections', { - params: { path: { ref: projectRef } }, - body: { name, retention_days }, - } as any) - - if (error) handleError(error) - return data -} - -type CreateCollectionData = Awaited> - -export const useCreateCollection = ({ - onSuccess, - onError, - ...options -}: Omit< - UseMutationOptions, - 'mutationFn' -> = {}) => { - const queryClient = useQueryClient() - - return useMutation( - (vars) => { - // temporal fix - // prevent users from creating collections with the same name - // this will be handled by the backend - // - jordi - - const existingCollectionNames = queryClient - .getQueryData(analyticsKeys.warehouseCollections(vars.projectRef)) - ?.map((c) => c.name) - - if (existingCollectionNames?.includes(vars.name)) { - throw new Error(`Collection with the name ${vars.name} already exists`) - } - - return createCollection(vars) - }, - { - async onSuccess(data, variables, context) { - const { projectRef } = variables - - await queryClient.invalidateQueries(analyticsKeys.warehouseCollections(projectRef)) - - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to create collection: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - } - ) -} diff --git a/apps/studio/data/analytics/warehouse-collections-delete-mutation.ts b/apps/studio/data/analytics/warehouse-collections-delete-mutation.ts deleted file mode 100644 index 376e5f378f3..00000000000 --- a/apps/studio/data/analytics/warehouse-collections-delete-mutation.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { toast } from 'sonner' - -import { del, handleError } from 'data/fetchers' -import type { ResponseError } from 'types' -import { analyticsKeys } from './keys' - -export type DeleteCollectionVariables = { - projectRef: string - collectionToken: string -} - -export async function deleteCollection({ projectRef, collectionToken }: DeleteCollectionVariables) { - const { data, error } = await del( - '/platform/projects/{ref}/analytics/warehouse/collections/{token}', - { - params: { path: { ref: projectRef, token: collectionToken } } as any, - } - ) - - if (error) handleError(error) - return data -} - -type DeleteCollectionData = Awaited> - -export const useDeleteCollectionMutation = ({ - onSuccess, - onError, - ...options -}: Omit< - UseMutationOptions, - 'mutationFn' -> = {}) => { - const queryClient = useQueryClient() - - return useMutation( - (vars) => deleteCollection(vars), - { - async onSuccess(data, variables, context) { - const { projectRef } = variables - - await queryClient.invalidateQueries(analyticsKeys.warehouseCollections(projectRef)) - - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to delete collection: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - } - ) -} diff --git a/apps/studio/data/analytics/warehouse-collections-query.ts b/apps/studio/data/analytics/warehouse-collections-query.ts deleted file mode 100644 index 4fde686a646..00000000000 --- a/apps/studio/data/analytics/warehouse-collections-query.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useQuery } from '@tanstack/react-query' -import { get, handleError } from 'data/fetchers' -import { IS_PLATFORM } from 'lib/constants' -import { analyticsKeys } from './keys' - -type WarehouseCollectionsVariables = { - projectRef: string -} - -export async function getWarehouseCollections( - { projectRef }: WarehouseCollectionsVariables, - signal?: AbortSignal -) { - if (!projectRef) { - throw new Error('projectRef is required') - } - - // TODO: Remove type cast when codegen types are fixed - const { data, error } = await get(`/platform/projects/{ref}/analytics/warehouse/collections`, { - params: { path: { ref: projectRef } }, - signal, - }) - - if (error) handleError(error) - - return data -} - -export type WarehouseCollectionsData = Awaited> - -export const useWarehouseCollectionsQuery = ( - { projectRef }: WarehouseCollectionsVariables, - { enabled }: { enabled: boolean } = { enabled: true } -) => - useQuery( - analyticsKeys.warehouseCollections(projectRef), - ({ signal }) => getWarehouseCollections({ projectRef }, signal), - { - enabled: enabled && !!projectRef && IS_PLATFORM, - } - ) diff --git a/apps/studio/data/analytics/warehouse-collections-update-mutation.ts b/apps/studio/data/analytics/warehouse-collections-update-mutation.ts deleted file mode 100644 index 6f96ef05575..00000000000 --- a/apps/studio/data/analytics/warehouse-collections-update-mutation.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { toast } from 'sonner' - -import { handleError, patch } from 'data/fetchers' -import type { ResponseError } from 'types' -import { analyticsKeys } from './keys' - -export type UpdateCollectionArgs = { - projectRef: string - collectionToken: string -} - -export type UpdateCollectionPayload = { - name?: string - // description?: string - retention_days?: number -} - -export async function updateCollection( - { projectRef, collectionToken }: UpdateCollectionArgs, - payload: UpdateCollectionPayload -) { - const { data, error } = await patch( - '/platform/projects/{ref}/analytics/warehouse/collections/{token}', - { - params: { path: { ref: projectRef, token: collectionToken } }, - body: payload, - } as any - ) - - if (error) handleError(error) - return data -} - -type UpdateCollectionData = Awaited> - -export const useUpdateCollection = ({ - onSuccess, - onError, - ...options -}: Omit< - UseMutationOptions, - 'mutationFn' -> = {}) => { - const queryClient = useQueryClient() - - return useMutation< - UpdateCollectionData, - ResponseError, - UpdateCollectionPayload & UpdateCollectionArgs - >( - (payload) => - updateCollection( - { projectRef: payload.projectRef, collectionToken: payload.collectionToken }, - { name: payload.name, retention_days: payload.retention_days } - ), - { - async onSuccess(data, variables, context) { - const { projectRef } = variables - - await queryClient.invalidateQueries(analyticsKeys.warehouseCollections(projectRef)) - - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to update collection: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - } - ) -} diff --git a/apps/studio/data/analytics/warehouse-query.ts b/apps/studio/data/analytics/warehouse-query.ts deleted file mode 100644 index 54c34a18414..00000000000 --- a/apps/studio/data/analytics/warehouse-query.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get, handleError } from 'data/fetchers' -import { analyticsKeys } from './keys' -import { ResponseError } from 'types' - -export type WarehouseQueryVariables = { - ref: string - sql: string -} - -export async function getWarehouseQuery( - { ref, sql }: WarehouseQueryVariables, - signal?: AbortSignal -) { - if (!sql) { - throw new Error('SQL must be provided') - } - - const { data, error } = await get(`/platform/projects/{ref}/analytics/warehouse/query`, { - params: { path: { ref: ref }, query: { bq_sql: sql } }, - signal, - } as any) - - if (error) { - handleError(error) - } - - // TODO!: Remove type assertion when we have a proper type for the response - return data as { result: any[] } -} - -export type WarehouseQueryData = Awaited> -export type WarehouseQueryError = ResponseError - -export const useWarehouseQueryQuery = ( - { ref, sql }: WarehouseQueryVariables, - { enabled, ...options }: UseQueryOptions = {} -) => - useQuery( - analyticsKeys.warehouseQuery(ref, sql), - ({ signal }) => getWarehouseQuery({ ref, sql }, signal), - { - enabled, - staleTime: Infinity, - cacheTime: 15 * 60 * 1000, // 15 mins cache time - refetchOnMount: false, - refetchInterval: false, - ...options, - } - ) diff --git a/apps/studio/data/analytics/warehouse-tenant-query.ts b/apps/studio/data/analytics/warehouse-tenant-query.ts deleted file mode 100644 index 624a6719641..00000000000 --- a/apps/studio/data/analytics/warehouse-tenant-query.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get, handleError } from 'data/fetchers' -import { IS_PLATFORM } from 'lib/constants' -import { ResponseError } from 'types' -import { analyticsKeys } from './keys' - -export type WarehouseTenantVariables = { - projectRef: string -} - -export type WarehouseTenantResponse = any - -export async function getWarehouseTenant( - { projectRef }: WarehouseTenantVariables, - signal?: AbortSignal -) { - if (!projectRef) { - throw new Error('projectRef is required') - } - const { data, error } = await get(`/platform/projects/{ref}/analytics/warehouse/tenant`, { - params: { path: { ref: projectRef } }, - signal, - }) - if (error) { - handleError(error) - } - - return data -} - -export type WarehouseTenantData = Awaited> -export type WarehouseTenantError = ResponseError - -export const useWarehouseTenantQuery = ( - { projectRef }: WarehouseTenantVariables, - { - enabled = true, - ...options - }: UseQueryOptions = {} -) => - useQuery( - analyticsKeys.warehouseTenant(projectRef), - ({ signal }) => getWarehouseTenant({ projectRef }, signal), - { - enabled: enabled && !!projectRef && IS_PLATFORM, - staleTime: Infinity, - // 2H mins cache time - cacheTime: 120 * 60 * 1000, - refetchOnMount: false, - refetchInterval: false, - ...options, - } - ) diff --git a/apps/studio/data/api-keys/api-key-create-mutation.ts b/apps/studio/data/api-keys/api-key-create-mutation.ts index 0cc6b36ec57..f84d56055ec 100644 --- a/apps/studio/data/api-keys/api-key-create-mutation.ts +++ b/apps/studio/data/api-keys/api-key-create-mutation.ts @@ -36,7 +36,7 @@ export async function createAPIKey(payload: APIKeyCreateVariables) { ? { // secret_jwt_template: payload?.secret_jwt_template || null, secret_jwt_template: { - role: 'service_role', // @mildtomato (Jonny) this should be default in API for type secret + role: 'service_role', }, } : name), diff --git a/apps/studio/data/api-keys/keys.ts b/apps/studio/data/api-keys/keys.ts index 222a51b0b1c..e0bfd893264 100644 --- a/apps/studio/data/api-keys/keys.ts +++ b/apps/studio/data/api-keys/keys.ts @@ -1,6 +1,6 @@ export const apiKeysKeys = { list: (projectRef?: string, reveal?: boolean) => - ['projects', projectRef, 'api-keys', reveal] as const, + ['projects', projectRef, 'api-keys', reveal].filter(Boolean), single: (projectRef?: string, id?: string) => ['projects', projectRef, 'api-keys', id] as const, status: (projectRef?: string) => ['projects', projectRef, 'api-keys', 'legacy'] as const, } diff --git a/apps/studio/data/branches/branch-create-mutation.ts b/apps/studio/data/branches/branch-create-mutation.ts index 7086cb8a2d4..34c25bfd014 100644 --- a/apps/studio/data/branches/branch-create-mutation.ts +++ b/apps/studio/data/branches/branch-create-mutation.ts @@ -11,6 +11,7 @@ export type BranchCreateVariables = { branchName: string gitBranch?: string region?: string + withData?: boolean } export async function createBranch({ @@ -19,6 +20,7 @@ export async function createBranch({ branchName, gitBranch, region, + withData, }: BranchCreateVariables) { const { data, error } = await post('/v1/projects/{ref}/branches', { params: { @@ -29,6 +31,7 @@ export async function createBranch({ branch_name: branchName, git_branch: gitBranch, region: region, + with_data: withData, }, }) diff --git a/apps/studio/data/projects/project-create-mutation.ts b/apps/studio/data/projects/project-create-mutation.ts index 1e6e4c3e313..ecfeb2c20fc 100644 --- a/apps/studio/data/projects/project-create-mutation.ts +++ b/apps/studio/data/projects/project-create-mutation.ts @@ -19,6 +19,9 @@ const WHITELIST_ERRORS = [ 'already exists in your organization.', ] +type CreateProjectBody = components['schemas']['CreateProjectBody'] +type CloudProvider = CreateProjectBody['cloud_provider'] + export type ProjectCreateVariables = { name: string organizationSlug: string @@ -51,8 +54,8 @@ export async function createProject({ postgresEngine, releaseChannel, }: ProjectCreateVariables) { - const body: components['schemas']['CreateProjectBody'] = { - cloud_provider: cloudProvider, + const body: CreateProjectBody = { + cloud_provider: cloudProvider as CloudProvider, organization_slug: organizationSlug, name, db_pass: dbPass, diff --git a/apps/studio/data/replication/keys.ts b/apps/studio/data/replication/keys.ts index ce20ee79d4a..30ae4cd85b7 100644 --- a/apps/studio/data/replication/keys.ts +++ b/apps/studio/data/replication/keys.ts @@ -13,4 +13,6 @@ export const replicationKeys = { ['projects', projectRef, 'pipelines', pipelineId] as const, pipelinesStatus: (projectRef: string | undefined, pipelineId: number | undefined) => ['projects', projectRef, 'pipelines', pipelineId, 'status'] as const, + pipelinesReplicationStatus: (projectRef: string | undefined, pipelineId: number | undefined) => + ['projects', projectRef, 'pipelines', pipelineId, 'replication-status'] as const, } diff --git a/apps/studio/data/replication/pipeline-replication-status-query.ts b/apps/studio/data/replication/pipeline-replication-status-query.ts new file mode 100644 index 00000000000..952fa97fa44 --- /dev/null +++ b/apps/studio/data/replication/pipeline-replication-status-query.ts @@ -0,0 +1,50 @@ +import { UseQueryOptions, useQuery } from '@tanstack/react-query' + +import { get, handleError } from 'data/fetchers' +import { ResponseError } from 'types' +import { replicationKeys } from './keys' + +type ReplicationPipelineReplicationStatusParams = { projectRef?: string; pipelineId?: number } + +async function fetchReplicationPipelineReplicationStatus( + { projectRef, pipelineId }: ReplicationPipelineReplicationStatusParams, + signal?: AbortSignal +) { + if (!projectRef) throw new Error('projectRef is required') + if (!pipelineId) throw new Error('pipelineId is required') + + const { data, error } = await get( + '/platform/replication/{ref}/pipelines/{pipeline_id}/replication-status', + { + params: { path: { ref: projectRef, pipeline_id: pipelineId } }, + signal, + } + ) + if (error) { + handleError(error) + } + + return data +} + +export type ReplicationPipelineReplicationStatusData = Awaited< + ReturnType +> + +export const useReplicationPipelineReplicationStatusQuery = < + TData = ReplicationPipelineReplicationStatusData, +>( + { projectRef, pipelineId }: ReplicationPipelineReplicationStatusParams, + { + enabled = true, + ...options + }: UseQueryOptions = {} +) => + useQuery( + replicationKeys.pipelinesReplicationStatus(projectRef, pipelineId), + ({ signal }) => fetchReplicationPipelineReplicationStatus({ projectRef, pipelineId }, signal), + { + enabled: enabled && typeof projectRef !== 'undefined' && typeof pipelineId !== 'undefined', + ...options, + } + ) diff --git a/apps/studio/data/replication/pipelines-query.ts b/apps/studio/data/replication/pipelines-query.ts index 6e09e1cc409..82d0117f080 100644 --- a/apps/studio/data/replication/pipelines-query.ts +++ b/apps/studio/data/replication/pipelines-query.ts @@ -24,6 +24,7 @@ async function fetchReplicationPipelines( } export type ReplicationPipelinesData = Awaited> +export type Pipeline = ReplicationPipelinesData['pipelines'][0] export const useReplicationPipelinesQuery = ( { projectRef }: ReplicationPipelinesParams, diff --git a/apps/studio/data/reports/auth-charts.ts b/apps/studio/data/reports/auth-charts.ts index 14676a0b23c..33f20b979ae 100644 --- a/apps/studio/data/reports/auth-charts.ts +++ b/apps/studio/data/reports/auth-charts.ts @@ -1,4 +1,4 @@ -export const getAuthReportAttributes = (isFreePlan: boolean) => [ +export const getAuthReportAttributes = () => [ { id: 'active-users', label: 'Active Users', diff --git a/apps/studio/data/reports/database-charts.ts b/apps/studio/data/reports/database-charts.ts index 1c7fcb47d33..1f38e714f72 100644 --- a/apps/studio/data/reports/database-charts.ts +++ b/apps/studio/data/reports/database-charts.ts @@ -1,8 +1,8 @@ import { numberFormatter } from 'components/ui/Charts/Charts.utils' +import { ReportAttributes } from 'components/ui/Charts/ComposedChart.utils' import { formatBytes } from 'lib/helpers' import { Organization } from 'types' import { Project } from '../projects/project-detail-query' -import { ReportAttributes } from 'components/ui/Charts/ComposedChart.utils' export const getReportAttributes = (org: Organization, project: Project): ReportAttributes[] => { const computeSize = project?.infra_compute_size || 'medium' @@ -34,7 +34,7 @@ export const getReportAttributes = (org: Organization, project: Project): Report }, { id: 'avg_cpu_usage', - label: 'CPU usage', + label: 'Average CPU usage', syncId: 'database-reports', format: '%', valuePrecision: 2, @@ -56,6 +56,30 @@ export const getReportAttributes = (org: Organization, project: Project): Report }, ], }, + { + id: 'max_cpu_usage', + label: 'Max CPU usage', + syncId: 'database-reports', + format: '%', + valuePrecision: 2, + availableIn: ['free', 'pro'], + hide: false, + showTooltip: false, + showLegend: false, + showMaxValue: false, + showGrid: false, + hideChartType: false, + defaultChartStyle: 'bar', + attributes: [ + { + attribute: 'max_cpu_usage', + provider: 'infra-monitoring', + label: 'Max CPU usage', + format: '%', + tooltip: 'Max CPU usage', + }, + ], + }, { id: 'disk-iops', label: 'Disk Input/Output operations per second (IOPS)', diff --git a/apps/studio/data/reports/edgefn-charts.ts b/apps/studio/data/reports/edgefn-charts.ts index aa2dd98de82..dbcd204e53d 100644 --- a/apps/studio/data/reports/edgefn-charts.ts +++ b/apps/studio/data/reports/edgefn-charts.ts @@ -12,7 +12,7 @@ export const getEdgeFunctionReportAttributes = (): ReportAttributes[] => [ hideChartType: false, defaultChartStyle: 'bar', titleTooltip: 'The total number of edge function executions by status code.', - availableIn: ['free', 'pro', 'team'], + availableIn: ['free', 'pro', 'team', 'enterprise'], attributes: [ { attribute: 'ExecutionStatusCodes', @@ -32,7 +32,7 @@ export const getEdgeFunctionReportAttributes = (): ReportAttributes[] => [ hideChartType: false, defaultChartStyle: 'line', titleTooltip: 'Average execution time for edge functions.', - availableIn: ['free', 'pro', 'team'], + availableIn: ['free', 'pro', 'team', 'enterprise'], format: 'ms', YAxisProps: { width: 50, @@ -58,7 +58,7 @@ export const getEdgeFunctionReportAttributes = (): ReportAttributes[] => [ hideChartType: false, defaultChartStyle: 'bar', titleTooltip: 'The total number of edge function invocations by region.', - availableIn: ['pro', 'team'], + availableIn: ['pro', 'team', 'enterprise'], attributes: [ { attribute: 'InvocationsByRegion', diff --git a/apps/studio/data/storage/iceberg-namespace-create-mutation.ts b/apps/studio/data/storage/iceberg-namespace-create-mutation.ts index 58f93dd4bd4..a2f68b752db 100644 --- a/apps/studio/data/storage/iceberg-namespace-create-mutation.ts +++ b/apps/studio/data/storage/iceberg-namespace-create-mutation.ts @@ -18,10 +18,20 @@ async function createIcebergNamespace({ token, namespace, }: CreateIcebergNamespaceVariables) { - const headers = await constructHeaders({ - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}`, - }) + let headers = new Headers() + // handle both secret key and service role key + if (token.startsWith('sb_secret_')) { + headers = await constructHeaders({ + 'Content-Type': 'application/json', + apikey: `${token}`, + }) + headers.delete('Authorization') + } else { + headers = await constructHeaders({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }) + } const url = `${catalogUri}/v1/${warehouse}/namespaces`.replaceAll(/(? { const { project } = useProjectContext() - const { data: apiKeys } = useAPIKeysQuery({ projectRef: project?.ref }) - const { serviceKey } = getKeys(apiKeys) + const { data: apiKeys } = useAPIKeysQuery({ projectRef: project?.ref, reveal: true }) + const { secretKey, serviceKey } = getKeys(apiKeys) const { data: settings } = useProjectSettingsV2Query({ projectRef: project?.ref }) const protocol = settings?.app_config?.protocol ?? 'https' const endpoint = settings?.app_config?.endpoint - const serviceApiKey = serviceKey?.api_key ?? 'SUPABASE_CLIENT_SERVICE_KEY' + const apiKey = secretKey?.api_key ?? serviceKey?.api_key ?? 'SUPABASE_CLIENT_API_KEY' const wrapperMeta = WRAPPERS.find((wrapper) => wrapper.name === 'iceberg_wrapper') - const isProjectActive = useIsProjectActive() - const canCreateCredentials = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') const { data: config } = useProjectStorageConfigQuery({ projectRef: project?.ref }) - const isS3ConnectionEnabled = config?.features.s3Protocol.enabled - const disableCreation = !isProjectActive || !canCreateCredentials || !isS3ConnectionEnabled const { mutateAsync: createS3AccessKey, isLoading: isCreatingS3AccessKey } = useS3AccessKeyCreateMutation() @@ -61,7 +54,7 @@ export const useIcebergWrapperCreateMutation = () => { server_name: `${wrapperName}_server`, vault_aws_access_key_id: createS3KeyData?.access_key, vault_aws_secret_access_key: createS3KeyData?.secret_key, - vault_token: serviceApiKey, + vault_token: apiKey, warehouse: bucketName, 's3.endpoint': getConnectionURL(project?.ref ?? '', protocol, endpoint), catalog_uri: getCatalogURI(project?.ref ?? '', protocol, endpoint), diff --git a/apps/studio/data/utils/deployment-commit-query.ts b/apps/studio/data/utils/deployment-commit-query.ts new file mode 100644 index 00000000000..67403cf23f5 --- /dev/null +++ b/apps/studio/data/utils/deployment-commit-query.ts @@ -0,0 +1,23 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' +import { fetchHandler } from 'data/fetchers' +import { BASE_PATH } from 'lib/constants' +import { ResponseError } from 'types' + +export async function getDeploymentCommit(signal?: AbortSignal) { + const response = await fetchHandler(`${BASE_PATH}/api/get-deployment-commit`) + return (await response.json()) as { commitSha: string; commitTime: string } +} + +export type DeploymentCommitData = Awaited> + +export const useDeploymentCommitQuery = ({ + enabled = true, + ...options +}: UseQueryOptions = {}) => + useQuery( + ['deployment-commit'], + ({ signal }) => getDeploymentCommit(signal), + { + ...options, + } + ) diff --git a/apps/studio/data/vault/vault-secret-decrypted-value-query.ts b/apps/studio/data/vault/vault-secret-decrypted-value-query.ts index 7b1235c206d..f64d00145cf 100644 --- a/apps/studio/data/vault/vault-secret-decrypted-value-query.ts +++ b/apps/studio/data/vault/vault-secret-decrypted-value-query.ts @@ -3,7 +3,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { executeSql } from '../sql/execute-sql-query' import { vaultSecretsKeys } from './keys' -export const vaultSecretDecryptedValueQuery = (id: string) => { +const vaultSecretDecryptedValueQuery = (id: string) => { const sql = new Query() .from('decrypted_secrets', 'vault') .select('decrypted_secret') @@ -13,6 +13,16 @@ export const vaultSecretDecryptedValueQuery = (id: string) => { return sql } +const vaultSecretDecryptedValuesQuery = (ids: string[]) => { + const sql = new Query() + .from('decrypted_secrets', 'vault') + .select('id,decrypted_secret') + .filter('id', 'in', ids) + .toSql() + + return sql +} + export type VaultSecretsDecryptedValueVariables = { projectRef?: string connectionString?: string | null @@ -58,3 +68,25 @@ export const useVaultSecretDecryptedValueQuery = ( ...options, } ) + +// [Joshen] Considering to consolidate fetching single and multiple decrypted values by just passing in a string array +// This is currently used in ImportForeignSchemaDialog, but reckon EditWrapperSheet can use this too to replace the useEffect on L153 +// which fetches all the decrypted secrets +export const getDecryptedValues = async ( + { + projectRef, + connectionString, + ids, + }: { + projectRef?: string + connectionString?: string | null + ids: string[] + }, + signal?: AbortSignal +) => { + const sql = vaultSecretDecryptedValuesQuery(ids) + const { result } = await executeSql({ projectRef, connectionString, sql }, signal) + return result.reduce((a: any, b: any) => { + return { ...a, [b.id]: b.decrypted_secret } + }, {}) +} diff --git a/apps/studio/hooks/analytics/useSelectedLog.ts b/apps/studio/hooks/analytics/useSelectedLog.ts index 5b52ce62d38..f156222e89b 100644 --- a/apps/studio/hooks/analytics/useSelectedLog.ts +++ b/apps/studio/hooks/analytics/useSelectedLog.ts @@ -1,6 +1,5 @@ import { useQueryState } from 'nuqs' -// Used in logs and warehouse. export function useSelectedLog() { return useQueryState('log') } diff --git a/apps/studio/hooks/analytics/useSingleLog.tsx b/apps/studio/hooks/analytics/useSingleLog.tsx index 6ca288c2122..b773b45e673 100644 --- a/apps/studio/hooks/analytics/useSingleLog.tsx +++ b/apps/studio/hooks/analytics/useSingleLog.tsx @@ -33,9 +33,7 @@ function useSingleLog({ const params: LogsEndpointParams = { ...paramsToMerge, sql } - const isWarehouseQuery = queryType === 'warehouse' - // Warehouse queries are handled differently - const enabled = Boolean(id && table && !isWarehouseQuery) + const enabled = Boolean(id && table) const { data, diff --git a/apps/studio/hooks/use-check-latest-deploy.tsx b/apps/studio/hooks/use-check-latest-deploy.tsx new file mode 100644 index 00000000000..cad2e77b005 --- /dev/null +++ b/apps/studio/hooks/use-check-latest-deploy.tsx @@ -0,0 +1,83 @@ +import dayjs from 'dayjs' +import { useRouter } from 'next/router' +import { useEffect, useState } from 'react' +import { toast } from 'sonner' + +import { IS_PLATFORM } from 'common' +import { useDeploymentCommitQuery } from 'data/utils/deployment-commit-query' +import { Button, StatusIcon } from 'ui' +import { useFlag } from './ui/useFlag' + +const DeployCheckToast = ({ id }: { id: string | number }) => { + const router = useRouter() + + return ( +
+
+ +
+

A new version of this page is available

+

Refresh to see the latest changes.

+
+
+ +
+ + +
+
+ ) +} + +// This hook checks if the user is using old Studio pages and shows a toast to refresh the page. It's only triggered if +// there's a new version of Studio is available, and the user has been on the old dashboard (based on commit) for more than 24 hours. +// [Joshen] K-Dog has a suggestion here to bring down the time period here by checking commits +export function useCheckLatestDeploy() { + const showRefreshToast = useFlag('showRefreshToast') + + const [currentCommitTime, setCurrentCommitTime] = useState('') + const [isToastShown, setIsToastShown] = useState(false) + + const { data: commit } = useDeploymentCommitQuery({ + enabled: IS_PLATFORM && showRefreshToast, + staleTime: 10000, // 10 seconds + }) + + useEffect(() => { + // if the fetched commit is undefined is undefined + if (!commit || commit.commitTime === 'unknown') { + return + } + + // set the current commit on first load + if (!currentCommitTime) { + setCurrentCommitTime(commit.commitTime) + return + } + + // if the current commit is the same as the fetched commit, do nothing + if (currentCommitTime === commit.commitTime) { + return + } + + // prevent showing the toast again if user has already seen and dismissed it + if (isToastShown) { + return + } + + // check if the time difference between commits is more than 24 hours + const hourDiff = dayjs(commit.commitTime).diff(dayjs(currentCommitTime), 'hour') + if (hourDiff < 24) { + return + } + + // show the toast + toast.custom((id) => , { + duration: Infinity, + position: 'bottom-right', + }) + setIsToastShown(true) + }, [commit, isToastShown, currentCommitTime]) +} diff --git a/apps/studio/lib/auth.tsx b/apps/studio/lib/auth.tsx index 18ef96866c1..92663680c91 100644 --- a/apps/studio/lib/auth.tsx +++ b/apps/studio/lib/auth.tsx @@ -8,6 +8,7 @@ import { import { PropsWithChildren, useCallback, useEffect } from 'react' import { toast } from 'sonner' +import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { GOTRUE_ERRORS, IS_PLATFORM } from './constants' const AuthErrorToaster = ({ children }: PropsWithChildren) => { @@ -42,12 +43,15 @@ export { useAuth, useIsLoggedIn, useSession, useUser } from 'common' export function useSignOut() { const queryClient = useQueryClient() + const { clearStorage: clearAssistantStorage } = useAiAssistantStateSnapshot() return useCallback(async () => { const result = await gotrueClient.signOut() clearLocalStorage() + // Clear Assistant IndexedDB + await clearAssistantStorage() await queryClient.clear() return result - }, [queryClient]) + }, [queryClient, clearAssistantStorage]) } diff --git a/apps/studio/lib/gotrue.ts b/apps/studio/lib/gotrue.ts index 0c96b31a04d..42c65673ae6 100644 --- a/apps/studio/lib/gotrue.ts +++ b/apps/studio/lib/gotrue.ts @@ -73,6 +73,11 @@ export const buildPathWithParams = (pathname: string) => { } export const getReturnToPath = (fallback = DEFAULT_FALLBACK_PATH) => { + // If we're in a server environment, return the fallback + if (typeof location === 'undefined') { + return fallback + } + const searchParams = new URLSearchParams(location.search) let returnTo = searchParams.get('returnTo') ?? fallback diff --git a/apps/studio/middleware.ts b/apps/studio/middleware.ts index 912c8ccb14a..17896820bdc 100644 --- a/apps/studio/middleware.ts +++ b/apps/studio/middleware.ts @@ -16,6 +16,7 @@ const HOSTED_SUPPORTED_API_URLS = [ '/ai/feedback/classify', '/get-ip-address', '/get-utc-time', + '/get-deployment-commit', '/check-cname', '/edge-functions/test', '/edge-functions/body', diff --git a/apps/studio/package.json b/apps/studio/package.json index c2545b712f2..8ee4acc6c77 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -65,7 +65,6 @@ "@tanstack/react-query-devtools": "4.35.7", "@tanstack/react-table": "^8.21.3", "@uidotdev/usehooks": "^2.4.1", - "@vercel/flags": "^2.6.0", "@vercel/functions": "^2.1.0", "@vitejs/plugin-react": "^4.3.4", "@zip.js/zip.js": "^2.7.29", diff --git a/apps/studio/pages/api/get-deployment-commit.ts b/apps/studio/pages/api/get-deployment-commit.ts new file mode 100644 index 00000000000..5b7cde2c504 --- /dev/null +++ b/apps/studio/pages/api/get-deployment-commit.ts @@ -0,0 +1,40 @@ +import { NextApiRequest, NextApiResponse } from 'next' + +async function getCommitTime(commitSha: string) { + try { + const response = await fetch(`https://github.com/supabase/supabase/commit/${commitSha}.json`, { + headers: { + Accept: 'application/json', + }, + }) + + if (!response.ok) { + throw new Error('Failed to fetch commit details') + } + + const data = await response.json() + return new Date(data.payload.commit.committedDate).toISOString() + } catch (error) { + console.error('Error fetching commit time:', error) + return 'unknown' + } +} + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse<{ commitSha: string; commitTime: string }> +) { + // Set cache control headers for 10 minutes so that we don't get banned by Github API + res.setHeader('Cache-Control', 's-maxage=600') + + // Get the build commit SHA from Vercel environment variable + const commitSha = process.env.VERCEL_GIT_COMMIT_SHA || 'development' + + // Only fetch commit time if we have a valid SHA + const commitTime = commitSha !== 'development' ? await getCommitTime(commitSha) : 'unknown' + + res.status(200).json({ + commitSha, + commitTime, + }) +} diff --git a/apps/studio/pages/authorize.tsx b/apps/studio/pages/authorize.tsx index 49e60d48ac9..8e56592aadb 100644 --- a/apps/studio/pages/authorize.tsx +++ b/apps/studio/pages/authorize.tsx @@ -6,7 +6,7 @@ import { useEffect, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import AuthorizeRequesterDetails from 'components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails' +import { AuthorizeRequesterDetails } from 'components/interfaces/Organization/OAuthApps/AuthorizeRequesterDetails' import APIAuthorizationLayout from 'components/layouts/APIAuthorizationLayout' import { FormPanel } from 'components/ui/Forms/FormPanel' import ShimmeringLoader from 'components/ui/ShimmeringLoader' @@ -30,7 +30,7 @@ import { const APIAuthorizationPage: NextPageWithLayout = () => { const router = useRouter() - const { auth_id } = useParams() + const { auth_id, organization_slug } = useParams() const [isApproving, setIsApproving] = useState(false) const [isDeclining, setIsDeclining] = useState(false) const [selectedOrgSlug, setSelectedOrgSlug] = useState() @@ -58,7 +58,11 @@ const APIAuthorizationPage: NextPageWithLayout = () => { useEffect(() => { if (isSuccessOrganizations && organizations.length > 0) { - setSelectedOrgSlug(organizations[0].slug) + if (organization_slug) { + setSelectedOrgSlug(organizations.find(({ slug }) => slug === organization_slug)?.slug) + } else { + setSelectedOrgSlug(organizations[0].slug) + } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isSuccessOrganizations]) @@ -168,7 +172,9 @@ const APIAuthorizationPage: NextPageWithLayout = () => {
diff --git a/apps/studio/state/ai-assistant-state.tsx b/apps/studio/state/ai-assistant-state.tsx index 8d8cc7e2713..b33feb97047 100644 --- a/apps/studio/state/ai-assistant-state.tsx +++ b/apps/studio/state/ai-assistant-state.tsx @@ -2,6 +2,7 @@ import type { Message as MessageType } from 'ai/react' import { DBSchema, IDBPDatabase, openDB } from 'idb' import { debounce } from 'lodash' import { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react' +import { v4 as uuidv4 } from 'uuid' import { proxy, snapshot, subscribe, useSnapshot } from 'valtio' import { LOCAL_STORAGE_KEYS } from 'common' @@ -94,6 +95,15 @@ async function saveAiState(state: StoredAiAssistantState): Promise { } } +async function clearStorage(): Promise { + try { + const db = await openAiDb() + await db.clear(STORE_NAME) + } catch (error) { + console.error('Failed to clear AI state from IndexedDB:', error) + } +} + // Helper function to load state from IndexedDB async function loadFromIndexedDB(projectRef: string): Promise { try { @@ -234,7 +244,7 @@ export const createAiAssistantState = (): AiAssistantState => { Pick > ) => { - const chatId = crypto.randomUUID() + const chatId = uuidv4() const newChat: ChatSession = { id: chatId, name: options?.name ?? 'Untitled', @@ -386,6 +396,10 @@ export const createAiAssistantState = (): AiAssistantState => { } } }, + + clearStorage: async () => { + await clearStorage() + }, }) return state @@ -412,6 +426,7 @@ export type AiAssistantState = AiAssistantData & { clearSqlSnippets: () => void getCachedSQLResults: (args: { messageId: string; snippetId?: string }) => any[] | undefined loadPersistedState: (persistedState: StoredAiAssistantState) => void + clearStorage: () => Promise } export const AiAssistantStateContext = createContext(createAiAssistantState()) diff --git a/apps/studio/state/replication-pipeline-request-status.tsx b/apps/studio/state/replication-pipeline-request-status.tsx new file mode 100644 index 00000000000..722c4de9120 --- /dev/null +++ b/apps/studio/state/replication-pipeline-request-status.tsx @@ -0,0 +1,76 @@ +import { createContext, useContext, useState, ReactNode, useCallback } from 'react' + +export enum PipelineStatusRequestStatus { + None = 'None', + EnableRequested = 'EnableRequested', + DisableRequested = 'DisableRequested', +} + +interface PipelineRequestStatusContextType { + requestStatus: Record + setRequestStatus: (pipelineId: number, status: PipelineStatusRequestStatus) => void + getRequestStatus: (pipelineId: number) => PipelineStatusRequestStatus + updatePipelineStatus: (pipelineId: number, backendStatus: string | undefined) => void +} + +interface PipelineRequestStatusProviderProps { + children: ReactNode +} + +const PipelineRequestStatusContext = createContext( + undefined +) + +export const PipelineRequestStatusProvider = ({ children }: PipelineRequestStatusProviderProps) => { + const [requestStatus, setRequestStatusState] = useState< + Record + >({}) + + const setRequestStatus = (pipelineId: number, status: PipelineStatusRequestStatus) => { + setRequestStatusState((prev) => ({ + ...prev, + [pipelineId]: status, + })) + } + + const getRequestStatus = (pipelineId: number): PipelineStatusRequestStatus => { + return requestStatus[pipelineId] || PipelineStatusRequestStatus.None + } + + const updatePipelineStatus = useCallback( + (pipelineId: number, backendStatus: string | undefined) => { + const currentRequestStatus = requestStatus[pipelineId] || PipelineStatusRequestStatus.None + + if ( + (currentRequestStatus === PipelineStatusRequestStatus.EnableRequested && + (backendStatus === 'started' || backendStatus === 'failed')) || + (currentRequestStatus === PipelineStatusRequestStatus.DisableRequested && + (backendStatus === 'stopped' || backendStatus === 'failed')) + ) { + setRequestStatus(pipelineId, PipelineStatusRequestStatus.None) + } + }, + [requestStatus, setRequestStatus] + ) + + return ( + + {children} + + ) +} + +export const usePipelineRequestStatus = () => { + const context = useContext(PipelineRequestStatusContext) + if (context === undefined) { + throw new Error('usePipelineRequestStatus must be used within a PipelineRequestStatusProvider') + } + return context +} diff --git a/apps/studio/state/tabs.tsx b/apps/studio/state/tabs.tsx index 59f9bdd8c44..2d6fda01035 100644 --- a/apps/studio/state/tabs.tsx +++ b/apps/studio/state/tabs.tsx @@ -1,9 +1,8 @@ -import { useConstant } from 'common' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { partition } from 'lodash' import { NextRouter } from 'next/router' -import { createContext, PropsWithChildren, ReactNode, useContext, useEffect } from 'react' +import { createContext, PropsWithChildren, ReactNode, useContext, useEffect, useState } from 'react' import { proxy, subscribe, useSnapshot } from 'valtio' export const editorEntityTypes = { @@ -78,6 +77,7 @@ const DEFAULT_TABS_STATE = { openTabs: [] as string[], tabsMap: {} as { [key: string]: Tab }, previewTabId: undefined as string | undefined, + recentItems: [], } const TABS_STORAGE_KEY = 'supabase_studio_tabs' const getTabsStorageKey = (ref: string) => `${TABS_STORAGE_KEY}_${ref}` @@ -399,8 +399,14 @@ export type TabsState = ReturnType export const TabsStateContext = createContext(createTabsState('')) export const TabsStateContextProvider = ({ children }: PropsWithChildren) => { - const project = useSelectedProject() - const state = useConstant(() => createTabsState(project?.ref ?? '')) + const { data: project } = useSelectedProjectQuery() + const [state, setState] = useState(createTabsState(project?.ref ?? '')) + + useEffect(() => { + if (typeof window !== 'undefined' && !!project?.ref) { + setState(createTabsState(project?.ref ?? '')) + } + }, [project?.ref]) useEffect(() => { if (typeof window !== 'undefined' && project?.ref) { @@ -422,8 +428,7 @@ export const TabsStateContextProvider = ({ children }: PropsWithChildren) => { ) }) } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [project?.ref, state]) return {children} } diff --git a/apps/studio/styles/ui.scss b/apps/studio/styles/ui.scss index 886f96393d4..f0f37298fec 100644 --- a/apps/studio/styles/ui.scss +++ b/apps/studio/styles/ui.scss @@ -119,7 +119,7 @@ } .table-container thead th:first-child { - @apply pl-6 rounded rounded-r-none rounded-b-none; + @apply rounded rounded-r-none rounded-b-none; @apply border-l; } diff --git a/apps/studio/tests/features/logs/LogsQueryPanel.test.tsx b/apps/studio/tests/features/logs/LogsQueryPanel.test.tsx index df741c9a2e6..7e860a924e9 100644 --- a/apps/studio/tests/features/logs/LogsQueryPanel.test.tsx +++ b/apps/studio/tests/features/logs/LogsQueryPanel.test.tsx @@ -13,12 +13,7 @@ test('run and clear', async () => { onSelectSource={() => {}} onSelectTemplate={() => {}} warnings={[]} - warehouseCollections={[]} - dataSource="logs" - onDataSourceChange={() => {}} templates={[]} - warehouseTemplates={[]} - onSelectWarehouseTemplate={() => {}} /> ) await expect(screen.findByPlaceholderText(/Search/)).rejects.toThrow() diff --git a/apps/studio/vitest.config.ts b/apps/studio/vitest.config.ts index 1f453470208..964b7ff991a 100644 --- a/apps/studio/vitest.config.ts +++ b/apps/studio/vitest.config.ts @@ -32,7 +32,11 @@ export default defineConfig({ reporters: [['default']], coverage: { reporter: ['lcov'], - exclude: ['**/*.test.ts', '**/*.test.tsx'], + exclude: [ + '**/*.test.ts', + '**/*.test.tsx', + '**/base64url.ts', // [Jordi] Tests for this file exist in https://github.com/supabase-community/base64url-js/blob/main/src/base64url.test.ts so we can ignore. + ], include: ['lib/**/*.ts'], }, }, diff --git a/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx b/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx index 73d81df5cbf..9bc362e67a4 100644 --- a/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx +++ b/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx @@ -1,8 +1,8 @@ +import { metadata as mainMetadata } from '@/app/layout' import { FrameworkSelector } from '@/components/framework-selector' import { Mdx } from '@/components/mdx-components' import { SourcePanel } from '@/components/source-panel' import { DashboardTableOfContents } from '@/components/toc' -import { siteConfig } from '@/config/site' import { getTableOfContents } from '@/lib/toc' import { absoluteUrl, cn } from '@/lib/utils' import '@/styles/code-block-variables.css' @@ -12,7 +12,7 @@ import { ChevronRight } from 'lucide-react' import type { Metadata } from 'next' import { notFound } from 'next/navigation' import Balancer from 'react-wrap-balancer' -import { ScrollArea, Separator } from 'ui' +import { ScrollArea } from 'ui' interface DocPageProps { params: Promise<{ @@ -39,31 +39,19 @@ export async function generateMetadata(props: DocPageProps): Promise { return {} } - return { + const metadata: Metadata = { + ...mainMetadata, title: doc.title, description: doc.description, openGraph: { + ...mainMetadata.openGraph, title: doc.title, description: doc.description, type: 'article', url: absoluteUrl(doc.slug), - images: [ - { - url: siteConfig.ogImage, - width: 1200, - height: 630, - alt: siteConfig.name, - }, - ], - }, - twitter: { - card: 'summary_large_image', - title: doc.title, - description: doc.description, - images: [siteConfig.ogImage], - creator: '@shadcn', }, } + return metadata } export async function generateStaticParams(): Promise<{ slug: string[] }[]> { diff --git a/apps/ui-library/components/site-footer.tsx b/apps/ui-library/components/site-footer.tsx index a51481a3e37..739de9f1abc 100644 --- a/apps/ui-library/components/site-footer.tsx +++ b/apps/ui-library/components/site-footer.tsx @@ -1,5 +1,3 @@ -import { siteConfig } from '@/config/site' - export function SiteFooter() { return (
-
diff --git a/examples/user-management/angular-user-management/src/app/auth/auth.component.spec.ts b/examples/user-management/angular-user-management/src/app/auth/auth.spec.ts similarity index 73% rename from examples/user-management/angular-user-management/src/app/auth/auth.component.spec.ts rename to examples/user-management/angular-user-management/src/app/auth/auth.spec.ts index ce785350ec7..113a852f27d 100644 --- a/examples/user-management/angular-user-management/src/app/auth/auth.component.spec.ts +++ b/examples/user-management/angular-user-management/src/app/auth/auth.spec.ts @@ -1,16 +1,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { AuthComponent } from './auth.component'; +import { AuthComponent } from './auth'; -describe('AuthComponent', () => { +describe('Auth', () => { let component: AuthComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ AuthComponent ] - }) - .compileComponents(); + declarations: [AuthComponent], + }).compileComponents(); fixture = TestBed.createComponent(AuthComponent); component = fixture.componentInstance; diff --git a/examples/user-management/angular-user-management/src/app/auth/auth.component.ts b/examples/user-management/angular-user-management/src/app/auth/auth.ts similarity index 67% rename from examples/user-management/angular-user-management/src/app/auth/auth.component.ts rename to examples/user-management/angular-user-management/src/app/auth/auth.ts index 6e80c347ac7..17feb934d9d 100644 --- a/examples/user-management/angular-user-management/src/app/auth/auth.component.ts +++ b/examples/user-management/angular-user-management/src/app/auth/auth.ts @@ -1,25 +1,26 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; +import { Component } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { SupabaseService } from '../supabase.service'; @Component({ selector: 'app-auth', - templateUrl: './auth.component.html', - styleUrls: ['./auth.component.css'], + templateUrl: './auth.html', + styleUrls: ['./auth.css'], + standalone: false, }) -export class AuthComponent implements OnInit { - loading = false; - - signInForm = this.formBuilder.group({ - email: '', - }); - +export class AuthComponent { + signInForm!: FormGroup; constructor( private readonly supabase: SupabaseService, private readonly formBuilder: FormBuilder ) {} - ngOnInit(): void {} + loading = false; + ngOnInit() { + this.signInForm = this.formBuilder.group({ + email: '', + }); + } async onSubmit(): Promise { try { diff --git a/examples/user-management/angular-user-management/src/app/avatar/avatar.component.css b/examples/user-management/angular-user-management/src/app/avatar/avatar.css similarity index 100% rename from examples/user-management/angular-user-management/src/app/avatar/avatar.component.css rename to examples/user-management/angular-user-management/src/app/avatar/avatar.css diff --git a/examples/user-management/angular-user-management/src/app/avatar/avatar.component.html b/examples/user-management/angular-user-management/src/app/avatar/avatar.html similarity index 82% rename from examples/user-management/angular-user-management/src/app/avatar/avatar.component.html rename to examples/user-management/angular-user-management/src/app/avatar/avatar.html index b86e45f254c..c3dc3b0a615 100644 --- a/examples/user-management/angular-user-management/src/app/avatar/avatar.component.html +++ b/examples/user-management/angular-user-management/src/app/avatar/avatar.html @@ -14,10 +14,10 @@ >
{ +describe('Avatar', () => { let component: AvatarComponent; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ AvatarComponent ] - }) - .compileComponents(); + declarations: [AvatarComponent], + }).compileComponents(); fixture = TestBed.createComponent(AvatarComponent); component = fixture.componentInstance; diff --git a/examples/user-management/angular-user-management/src/app/avatar/avatar.component.ts b/examples/user-management/angular-user-management/src/app/avatar/avatar.ts similarity index 86% rename from examples/user-management/angular-user-management/src/app/avatar/avatar.component.ts rename to examples/user-management/angular-user-management/src/app/avatar/avatar.ts index f89dfaa2054..584b9a83b21 100644 --- a/examples/user-management/angular-user-management/src/app/avatar/avatar.component.ts +++ b/examples/user-management/angular-user-management/src/app/avatar/avatar.ts @@ -1,13 +1,14 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'; import { SupabaseService } from '../supabase.service'; @Component({ selector: 'app-avatar', - templateUrl: './avatar.component.html', - styleUrls: ['./avatar.component.css'], + templateUrl: './avatar.html', + styleUrls: ['./avatar.css'], + standalone: false, }) -export class AvatarComponent implements OnInit { +export class AvatarComponent { _avatarUrl: SafeResourceUrl | undefined; uploading = false; @@ -25,8 +26,6 @@ export class AvatarComponent implements OnInit { private readonly dom: DomSanitizer ) {} - ngOnInit(): void {} - async downloadImage(path: string) { try { const { data } = await this.supabase.downLoadImage(path); diff --git a/examples/user-management/angular-user-management/src/app/supabase.service.spec.ts b/examples/user-management/angular-user-management/src/app/supabase.service.spec.ts deleted file mode 100644 index 6e1ce7dba08..00000000000 --- a/examples/user-management/angular-user-management/src/app/supabase.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { SupabaseService } from './supabase.service'; - -describe('SupabaseService', () => { - let service: SupabaseService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(SupabaseService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/examples/user-management/angular-user-management/src/app/supabase.service.ts b/examples/user-management/angular-user-management/src/app/supabase.service.ts index efb0dfde211..de672c3394a 100644 --- a/examples/user-management/angular-user-management/src/app/supabase.service.ts +++ b/examples/user-management/angular-user-management/src/app/supabase.service.ts @@ -7,8 +7,7 @@ import { SupabaseClient, User, } from '@supabase/supabase-js'; -import { environment } from 'src/environments/environment'; -import { Database } from 'src/schema'; +import { environment } from '../environments/environment'; export interface Profile { id?: string; @@ -21,11 +20,11 @@ export interface Profile { providedIn: 'root', }) export class SupabaseService { - private supabase: SupabaseClient; + private supabase: SupabaseClient; _session: AuthSession | null = null; constructor() { - this.supabase = createClient( + this.supabase = createClient( environment.supabaseUrl, environment.supabaseKey ); diff --git a/examples/user-management/angular-user-management/src/assets/.gitkeep b/examples/user-management/angular-user-management/src/assets/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/examples/user-management/angular-user-management/src/favicon.ico b/examples/user-management/angular-user-management/src/favicon.ico deleted file mode 100644 index 997406ad22c..00000000000 Binary files a/examples/user-management/angular-user-management/src/favicon.ico and /dev/null differ diff --git a/examples/user-management/angular-user-management/src/index.html b/examples/user-management/angular-user-management/src/index.html index 8e43ba66172..e46cb157e71 100644 --- a/examples/user-management/angular-user-management/src/index.html +++ b/examples/user-management/angular-user-management/src/index.html @@ -1,13 +1,13 @@ - + - - - AngularUserManagement - - - - - - - + + + SupabaseAngular + + + + + + + diff --git a/examples/user-management/angular-user-management/src/main.ts b/examples/user-management/angular-user-management/src/main.ts index c7b673cf44b..71eb23b9177 100644 --- a/examples/user-management/angular-user-management/src/main.ts +++ b/examples/user-management/angular-user-management/src/main.ts @@ -1,12 +1,8 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - +import { platformBrowser } from '@angular/platform-browser'; import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +platformBrowser() + .bootstrapModule(AppModule, { + ngZoneEventCoalescing: true, + }) + .catch((err) => console.error(err)); diff --git a/examples/user-management/angular-user-management/src/polyfills.ts b/examples/user-management/angular-user-management/src/polyfills.ts deleted file mode 100644 index 429bb9ef2d3..00000000000 --- a/examples/user-management/angular-user-management/src/polyfills.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * This file includes polyfills needed by Angular and is loaded before the app. - * You can add your own extra polyfills to this file. - * - * This file is divided into 2 sections: - * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. - * 2. Application imports. Files imported after ZoneJS that should be loaded before your main - * file. - * - * The current setup is for so-called "evergreen" browsers; the last versions of browsers that - * automatically update themselves. This includes recent versions of Safari, Chrome (including - * Opera), Edge on the desktop, and iOS and Chrome on mobile. - * - * Learn more in https://angular.io/guide/browser-support - */ - -/*************************************************************************************************** - * BROWSER POLYFILLS - */ - -/** - * By default, zone.js will patch all possible macroTask and DomEvents - * user can disable parts of macroTask/DomEvents patch by setting following flags - * because those flags need to be set before `zone.js` being loaded, and webpack - * will put import in the top of bundle, so user need to create a separate file - * in this directory (for example: zone-flags.ts), and put the following flags - * into that file, and then add the following code before importing zone.js. - * import './zone-flags'; - * - * The flags allowed in zone-flags.ts are listed here. - * - * The following flags will work for all browsers. - * - * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames - * - * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js - * with the following flag, it will bypass `zone.js` patch for IE/Edge - * - * (window as any).__Zone_enable_cross_context_check = true; - * - */ - -/*************************************************************************************************** - * Zone JS is required by default for Angular itself. - */ -import 'zone.js'; // Included with Angular CLI. - - -/*************************************************************************************************** - * APPLICATION IMPORTS - */ diff --git a/examples/user-management/angular-user-management/src/schema.ts b/examples/user-management/angular-user-management/src/schema.ts deleted file mode 100644 index 4593c033977..00000000000 --- a/examples/user-management/angular-user-management/src/schema.ts +++ /dev/null @@ -1,40 +0,0 @@ -export type Json = string | number | boolean | null | { [key: string]: Json } | Json[] - -export interface Database { - public: { - Tables: { - profiles: { - Row: { - id: string - updated_at: string | null - username: string | null - avatar_url: string | null - website: string | null - } - Insert: { - id: string - updated_at?: string | null - username?: string | null - avatar_url?: string | null - website?: string | null - } - Update: { - id?: string - updated_at?: string | null - username?: string | null - avatar_url?: string | null - website?: string | null - } - } - } - Views: { - [_ in never]: never - } - Functions: { - [_ in never]: never - } - Enums: { - [_ in never]: never - } - } -} diff --git a/examples/user-management/angular-user-management/src/styles.css b/examples/user-management/angular-user-management/src/styles.css index 54b465ff8c0..cb0b2e27142 100644 --- a/examples/user-management/angular-user-management/src/styles.css +++ b/examples/user-management/angular-user-management/src/styles.css @@ -1,53 +1,57 @@ +/* You can add global styles to this file, and also import other style files */ html, body { - --custom-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - --custom-bg-color: #101010; - --custom-panel-color: #222; - --custom-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.8); - --custom-color: #fff; - --custom-color-brand: #24b47e; - --custom-color-secondary: #666; - --custom-border: 1px solid #333; - --custom-border-radius: 5px; - --custom-spacing: 5px; + --custom-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, + Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --custom-bg-color: #101010; + --custom-panel-color: #222; + --custom-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.8); + --custom-color: #fff; + --custom-color-brand: #24b47e; + --custom-color-secondary: #666; + --custom-border: 1px solid #333; + --custom-border-radius: 5px; + --custom-spacing: 5px; - padding: 0; - margin: 0; - font-family: var(--custom-font-family); - background-color: var(--custom-bg-color); + padding: 0; + margin: 0; + font-family: var(--custom-font-family); + background-color: var(--custom-bg-color); } * { - color: var(--custom-color); - font-family: var(--custom-font-family); - box-sizing: border-box; + color: var(--custom-color); + font-family: var(--custom-font-family); + box-sizing: border-box; } html, body, #__next { - height: 100vh; - width: 100vw; - overflow-x: hidden; + height: 100vh; + width: 100vw; + overflow-x: hidden; } /* Grid */ .container { - width: 90%; - margin-left: auto; - margin-right: auto; + width: 90%; + margin-left: auto; + margin-right: auto; } + .row { - position: relative; - width: 100%; + position: relative; + width: 100%; } + .row [class^="col"] { - float: left; - margin: 0.5rem 2%; - min-height: 0.125rem; + float: left; + margin: 0.5rem 2%; + min-height: 0.125rem; } + .col-1, .col-2, .col-3, @@ -60,313 +64,363 @@ body, .col-10, .col-11, .col-12 { - width: 96%; + width: 96%; } + .col-1-sm { - width: 4.33%; + width: 4.33%; } + .col-2-sm { - width: 12.66%; + width: 12.66%; } + .col-3-sm { - width: 21%; + width: 21%; } + .col-4-sm { - width: 29.33%; + width: 29.33%; } + .col-5-sm { - width: 37.66%; + width: 37.66%; } + .col-6-sm { - width: 46%; + width: 46%; } + .col-7-sm { - width: 54.33%; + width: 54.33%; } + .col-8-sm { - width: 62.66%; + width: 62.66%; } + .col-9-sm { - width: 71%; + width: 71%; } + .col-10-sm { - width: 79.33%; + width: 79.33%; } + .col-11-sm { - width: 87.66%; + width: 87.66%; } + .col-12-sm { - width: 96%; + width: 96%; } + .row::after { - content: ""; - display: table; - clear: both; + content: ""; + display: table; + clear: both; } + .hidden-sm { - display: none; + display: none; } @media only screen and (min-width: 33.75em) { - /* 540px */ - .container { - width: 80%; - } + + /* 540px */ + .container { + width: 80%; + } } @media only screen and (min-width: 45em) { - /* 720px */ - .col-1 { - width: 4.33%; - } - .col-2 { - width: 12.66%; - } - .col-3 { - width: 21%; - } - .col-4 { - width: 29.33%; - } - .col-5 { - width: 37.66%; - } - .col-6 { - width: 46%; - } - .col-7 { - width: 54.33%; - } - .col-8 { - width: 62.66%; - } - .col-9 { - width: 71%; - } - .col-10 { - width: 79.33%; - } - .col-11 { - width: 87.66%; - } - .col-12 { - width: 96%; - } - .hidden-sm { - display: block; - } + + /* 720px */ + .col-1 { + width: 4.33%; + } + + .col-2 { + width: 12.66%; + } + + .col-3 { + width: 21%; + } + + .col-4 { + width: 29.33%; + } + + .col-5 { + width: 37.66%; + } + + .col-6 { + width: 46%; + } + + .col-7 { + width: 54.33%; + } + + .col-8 { + width: 62.66%; + } + + .col-9 { + width: 71%; + } + + .col-10 { + width: 79.33%; + } + + .col-11 { + width: 87.66%; + } + + .col-12 { + width: 96%; + } + + .hidden-sm { + display: block; + } } @media only screen and (min-width: 60em) { - /* 960px */ - .container { - width: 75%; - max-width: 60rem; - } + + /* 960px */ + .container { + width: 75%; + max-width: 60rem; + } } /* Forms */ label { - display: block; - margin: 5px 0; - color: var(--custom-color-secondary); - font-size: 0.8rem; - text-transform: uppercase; + display: block; + margin: 5px 0; + color: var(--custom-color-secondary); + font-size: 0.8rem; + text-transform: uppercase; } input { - width: 100%; - border-radius: 5px; - border: var(--custom-border); - padding: 8px; - font-size: 0.9rem; - background-color: var(--custom-bg-color); - color: var(--custom-color); + width: 100%; + border-radius: 5px; + border: var(--custom-border); + padding: 8px; + font-size: 0.9rem; + background-color: var(--custom-bg-color); + color: var(--custom-color); } input[disabled] { - color: var(--custom-color-secondary); + color: var(--custom-color-secondary); } /* Utils */ .block { - display: block; - width: 100%; + display: block; + width: 100%; } + .inline-block { - display: inline-block; - width: 100%; + display: inline-block; + width: 100%; } + .flex { - display: flex; + display: flex; } + .flex.column { - flex-direction: column; + flex-direction: column; } + .flex.row { - flex-direction: row; + flex-direction: row; } + .flex.flex-1 { - flex: 1 1 0; + flex: 1 1 0; } + .flex-end { - justify-content: flex-end; + justify-content: flex-end; } + .flex-center { - justify-content: center; + justify-content: center; } + .items-center { - align-items: center; + align-items: center; } + .text-sm { - font-size: 0.8rem; - font-weight: 300; + font-size: 0.8rem; + font-weight: 300; } + .text-right { - text-align: right; + text-align: right; } + .font-light { - font-weight: 300; + font-weight: 300; } + .opacity-half { - opacity: 50%; + opacity: 50%; } /* Button */ button, .button { - color: var(--custom-color); - border: var(--custom-border); - background-color: var(--custom-bg-color); - display: inline-block; - text-align: center; - border-radius: var(--custom-border-radius); - padding: 0.5rem 1rem; - cursor: pointer; - text-align: center; - font-size: 0.9rem; - text-transform: uppercase; + color: var(--custom-color); + border: var(--custom-border); + background-color: var(--custom-bg-color); + display: inline-block; + text-align: center; + border-radius: var(--custom-border-radius); + padding: 0.5rem 1rem; + cursor: pointer; + text-align: center; + font-size: 0.9rem; + text-transform: uppercase; } button.primary, .button.primary { - background-color: var(--custom-color-brand); - border: 1px solid var(--custom-color-brand); + background-color: var(--custom-color-brand); + border: 1px solid var(--custom-color-brand); } /* Widgets */ .card { - width: 100%; - display: block; - border: var(--custom-border); - border-radius: var(--custom-border-radius); - padding: var(--custom-spacing); + width: 100%; + display: block; + border: var(--custom-border); + border-radius: var(--custom-border-radius); + padding: var(--custom-spacing); } .avatar { - border-radius: var(--custom-border-radius); - overflow: hidden; - max-width: 100%; + border-radius: var(--custom-border-radius); + overflow: hidden; + max-width: 100%; } + .avatar.image { - object-fit: cover; + object-fit: cover; } + .avatar.no-image { - background-color: #333; - border: 1px solid rgb(200, 200, 200); - border-radius: 5px; + background-color: #333; + border: 1px solid rgb(200, 200, 200); + border-radius: 5px; } .footer { - position: absolute; - max-width: 100%; - bottom: 0; - left: 0; - right: 0; - display: flex; - flex-flow: row; - border-top: var(--custom-border); - background-color: var(--custom-bg-color); + position: absolute; + max-width: 100%; + bottom: 0; + left: 0; + right: 0; + display: flex; + flex-flow: row; + border-top: var(--custom-border); + background-color: var(--custom-bg-color); } + .footer div { - padding: var(--custom-spacing); - display: flex; - align-items: center; - width: 100%; + padding: var(--custom-spacing); + display: flex; + align-items: center; + width: 100%; } -.footer div > img { - height: 20px; - margin-left: 10px; + +.footer div>img { + height: 20px; + margin-left: 10px; } -.footer > div:first-child { - display: none; + +.footer>div:first-child { + display: none; } -.footer > div:nth-child(2) { - justify-content: left; + +.footer>div:nth-child(2) { + justify-content: left; } @media only screen and (min-width: 60em) { - /* 960px */ - .footer > div:first-child { - display: flex; - } - .footer > div:nth-child(2) { - justify-content: center; - } + + /* 960px */ + .footer>div:first-child { + display: flex; + } + + .footer>div:nth-child(2) { + justify-content: center; + } } @keyframes spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } } .mainHeader { - width: 100%; - font-size: 1.3rem; - margin-bottom: 20px; + width: 100%; + font-size: 1.3rem; + margin-bottom: 20px; } .avatarPlaceholder { - border: var(--custom-border); - border-radius: var(--custom-border-radius); - width: 35px; - height: 35px; - background-color: rgba(255, 255, 255, 0.2); - display: flex; - align-items: center; - justify-content: center; + border: var(--custom-border); + border-radius: var(--custom-border-radius); + width: 35px; + height: 35px; + background-color: rgba(255, 255, 255, 0.2); + display: flex; + align-items: center; + justify-content: center; } .form-widget { - display: flex; - flex-direction: column; - gap: 20px; + display: flex; + flex-direction: column; + gap: 20px; } -.form-widget > .button { - display: flex; - align-items: center; - justify-content: center; - border: none; - background-color: #444444; - text-transform: none !important; - transition: all 0.2s ease; +.form-widget>.button { + display: flex; + align-items: center; + justify-content: center; + border: none; + background-color: #444444; + text-transform: none !important; + transition: all 0.2s ease; } .form-widget .button:hover { - background-color: #2a2a2a; + background-color: #2a2a2a; } -.form-widget .button > .loader { - width: 17px; - animation: spin 1s linear infinite; - filter: invert(1); -} +.form-widget .button>.loader { + width: 17px; + animation: spin 1s linear infinite; + filter: invert(1); +} \ No newline at end of file diff --git a/examples/user-management/angular-user-management/src/test.ts b/examples/user-management/angular-user-management/src/test.ts deleted file mode 100644 index c04c876075f..00000000000 --- a/examples/user-management/angular-user-management/src/test.ts +++ /dev/null @@ -1,26 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/testing'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { - (id: string): T; - keys(): string[]; - }; -}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), -); - -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().forEach(context); diff --git a/examples/user-management/angular-user-management/tsconfig.app.json b/examples/user-management/angular-user-management/tsconfig.app.json index 82d91dc4a4d..264f459bf87 100644 --- a/examples/user-management/angular-user-management/tsconfig.app.json +++ b/examples/user-management/angular-user-management/tsconfig.app.json @@ -1,15 +1,15 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ +/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ +/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/app", "types": [] }, - "files": [ - "src/main.ts", - "src/polyfills.ts" - ], "include": [ - "src/**/*.d.ts" + "src/**/*.ts" + ], + "exclude": [ + "src/**/*.spec.ts" ] } diff --git a/examples/user-management/angular-user-management/tsconfig.json b/examples/user-management/angular-user-management/tsconfig.json index ff06eae10c5..e4955f26b14 100644 --- a/examples/user-management/angular-user-management/tsconfig.json +++ b/examples/user-management/angular-user-management/tsconfig.json @@ -1,32 +1,34 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ +/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ +/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ { "compileOnSave": false, "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "sourceMap": true, - "declaration": false, - "downlevelIteration": true, + "skipLibCheck": true, + "isolatedModules": true, "experimentalDecorators": true, - "moduleResolution": "node", "importHelpers": true, - "target": "es2020", - "module": "es2020", - "lib": [ - "es2020", - "dom" - ] + "target": "ES2022", + "module": "preserve" }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, "strictTemplates": true - } + }, + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] } diff --git a/examples/user-management/angular-user-management/tsconfig.spec.json b/examples/user-management/angular-user-management/tsconfig.spec.json index 092345b02e8..e00e30e6d4f 100644 --- a/examples/user-management/angular-user-management/tsconfig.spec.json +++ b/examples/user-management/angular-user-management/tsconfig.spec.json @@ -1,18 +1,10 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ +/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ +/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] + "types": ["jasmine"] }, - "files": [ - "src/test.ts", - "src/polyfills.ts" - ], - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] + "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] } diff --git a/i18n/README.hr.md b/i18n/README.hr.md new file mode 100644 index 00000000000..5e71e916452 --- /dev/null +++ b/i18n/README.hr.md @@ -0,0 +1,289 @@ +

+ + +

+ +--- + +# Supabase + +[Supabase](https://supabase.com) je open source alternativa Firebaseu. Izgrađujemo funkcionalnosti Firebasea koristeći enterprise-grade open source alate. + +- [x] Hostana Postgres baza podataka. [Dokumentacija](https://supabase.com/docs/guides/database) +- [x] Autentifikacija i autorizacija. [Dokumentacija](https://supabase.com/docs/guides/auth) +- [x] Automatski generirani API-ji. + - [x] REST. [Dokumentacija](https://supabase.com/docs/guides/api#rest-api-overview) + - [x] GraphQL. [Dokumentacija](https://supabase.com/docs/guides/api#graphql-api-overview) + - [x] Pretplate u realnom vremenu. [Dokumentacija](https://supabase.com/docs/guides/api#realtime-api-overview) +- [x] Funkcije. + - [x] Funkcije baza podataka. [Dokumentacija](https://supabase.com/docs/guides/database/functions) + - [x] Edge funkcije [Dokumentacija](https://supabase.com/docs/guides/functions) +- [x] Pohranjivanje datoteka. [Dokumentacija](https://supabase.com/docs/guides/storage) +- [x] Panel + +![Supabase Dashboard](https://raw.githubusercontent.com/supabase/supabase/master/apps/www/public/images/github/supabase-dashboard.png) + +Pratite "izdanja" ovog repozitorija da bi bili obaviješteni o većim ažuriranjima. + +Watch this repo + +## Dokumentacija + +Za cjelovitu dokumentaciju, posjetite [supabase.com/docs](https://supabase.com/docs) + +Za informacije kako doprinijeti razvoju, posjetite [Početak rada](./DEVELOPERS.md) + +## Zajednica & Podrška + +- [Forum zajednice](https://github.com/supabase/supabase/discussions). Najbolje služi za: pomoć pri izgradnji, diskusiji o najboljoj praksi oko baza podataka. +- [GitHub Issues](https://github.com/supabase/supabase/issues). Najbolje služi za: bugove i greške na koje ste naišli koristeći Supabase. +- [Email potpora](https://supabase.com/docs/support#business-support). Najbolje služi za: probleme oko vaše baze podataka ili oko infrastrukture. +- [Discord](https://discord.supabase.com). Najbolje služi za: pokazati vaše aplikacije i druženje sa ostatkom zajednice. + +## Kako funkcionira + +Supabase je kombinacija alata otvorenog koda. Izgrađujemo funkcionalnosti Firebasea koristeći enterprise-grade open source alate. Ako postoje alati i zajednice, sa MIT, Apache 2, ili ekvivalentnim otvorenim licencama, koristit ćemo i podržati taj alat. Ako alat ne postoji, mi ga izgrađujemo i otvaramo taj kod javno. Supabase nije preslika Firebasea. Naš cilj je razvijateljima dati osjećaj kao da koriste Firebase ali sa alatima otvorenog koda. + +**Arhitektura** + +Supabase je [hostana platforma](https://supabase.com/dashboard). Možete se registrirati i odmah počet koristiti Supabase bez ikakvih instalacija. +Također možete ju [samostalno hostati](https://supabase.com/docs/guides/hosting/overview) i [razvijati lokalno](https://supabase.com/docs/guides/local-development). + +![Arhitektura](apps/docs/public/img/supabase-architecture.svg) + +- [Postgres](https://www.postgresql.org/) je objektno-relacijska baza podataka koja je aktivno u razvoju preko 30 godina i na glasu je kao jako pouzdana, robusna i performantna. +- [Realtime](https://github.com/supabase/realtime) je Elixir server koji vam dopušta da prisluškujete unose, ažuriranja i brisanja u PostgreSQL bazi koristeći websockete. Realtime prati Postgres-ovu funkcionalnost repliciranja i osluškuje promjene u bazi podataka, te iste upakira u JSON, na kraju emitira taj JSON preko websocketa do autoriziranih klijenata. +- [PostgREST](http://postgrest.org/) je web server koji pretvara vašu PostgreSQL bazu podataka u RESTful API. +- [GoTrue](https://github.com/supabase/gotrue) je API koji koristi JWT za upravaljanje korisnika i izdavanje JWT tokena. +- [Storage](https://github.com/supabase/storage-api) pruža RESTful sučelje za upravljanje datoteka spremljenih u S3, koristeći Postgres za upravljanje dozvola. +- [pg_graphql](http://github.com/supabase/pg_graphql/) je PostgreSQL ekstenzija koja pruža Graphql API. +- [postgres-meta](https://github.com/supabase/postgres-meta) je RESTful API za upravljanje vaše Postgres baze podatake, dopuštajući vam da dohvatite tablice, dodate uloge, i izvršite upite prema bazi, itd. +- [Kong](https://github.com/Kong/kong) je cloud-native API gateway. + +#### Klijentske knjižnice + +Naš pristup za klijentske knjižnice je modularan. Svaka pod-knjižnica je samostalna implementacija za svaki vanjski sistem. Ovo je jedan od načina kako podržavamo postojeće alate. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
JezikKlijentFeature-Clients (upakirani u Supabase klijent)
SupabasePostgRESTGoTrueRealtimeStorageFunctions
⚡️ Službeno ⚡️
JavaScript (TypeScript)supabase-jspostgrest-jsgotrue-jsrealtime-jsstorage-jsfunctions-js
Fluttersupabase-flutterpostgrest-dartgotrue-dartrealtime-dartstorage-dartfunctions-dart
Swiftsupabase-swiftpostgrest-swiftauth-swiftrealtime-swiftstorage-swiftfunctions-swift
Pythonsupabase-pypostgrest-pygotrue-pyrealtime-pystorage-pyfunctions-py
💚 Zajednica 💚
C#supabase-csharppostgrest-csharpgotrue-csharprealtime-csharpstorage-csharpfunctions-csharp
Go-postgrest-gogotrue-go-storage-gofunctions-go
Java--gotrue-java-storage-java-
Kotlinsupabase-ktpostgrest-ktauth-ktrealtime-ktstorage-ktfunctions-kt
Rubysupabase-rbpostgrest-rb----
Rust-postgrest-rs----
Godot Engine (GDScript)supabase-gdscriptpostgrest-gdscriptgotrue-gdscriptrealtime-gdscriptstorage-gdscriptfunctions-gdscript
+ + + + +## Značke + +![Made with Supabase](./apps/www/public/badge-made-with-supabase.svg) + +```md +[![Made with Supabase](https://supabase.com/badge-made-with-supabase.svg)](https://supabase.com) +``` + +```html + + Made with Supabase + +``` + +![Made with Supabase (dark)](./apps/www/public/badge-made-with-supabase-dark.svg) + +```md +[![Made with Supabase](https://supabase.com/badge-made-with-supabase-dark.svg)](https://supabase.com) +``` + +```html + + Made with Supabase + +``` + +## Prijevodi + +- [Arapski | العربية](/i18n/README.ar.md) +- [Albanski / Shqip](/i18n/README.sq.md) +- [Bengalski / বাংলা](/i18n/README.bn.md) +- [Bugarski / Български](/i18n/README.bg.md) +- [Katalonski / Català](/i18n/README.ca.md) +- [Hrvatski](/i18n/README.ca.md) +- [Češki / čeština](/i18n/README.cs.md) +- [Danski / Dansk](/i18n/README.da.md) +- [Nizozemski / Nederlands](/i18n/README.nl.md) +- [Engleski](https://github.com/supabase/supabase) +- [Estonski / eesti keel](/i18n/README.et.md) +- [Finski / Suomalainen](/i18n/README.fi.md) +- [Francuski / Français](/i18n/README.fr.md) +- [Njemački / Deutsch](/i18n/README.de.md) +- [Grčki / Ελληνικά](/i18n/README.el.md) +- [Gudžaratski / ગુજરાતી](/i18n/README.gu.md) +- [Hebrejski / עברית](/i18n/README.he.md) +- [Hindski / हिंदी](/i18n/README.hi.md) +- [Mađarski / Magyar](/i18n/README.hu.md) +- [Nepalski / नेपाली](/i18n/README.ne.md) +- [Indonezijski / Bahasa Indonezija](/i18n/README.id.md) +- [Talijanski / Italian](/i18n/README.it.md) +- [Japanski / 日本語](/i18n/README.jp.md) +- [korejski / 한국어](/i18n/README.ko.md) +- [Litavski / lietuvių](/i18n/README.lt.md) +- [Latvijski / latviski](/i18n/README.lv.md) +- [Malajski / Bahasa Malaysia](/i18n/README.ms.md) +- [Norveški (Bokmål) / Norsk (Bokmål)](/i18n/README.nb.md) +- [Perzijski / فارسی](/i18n/README.fa.md) +- [Poljski / Polski](/i18n/README.pl.md) +- [Portugalski / Português](/i18n/README.pt.md) +- [Portugalski (Brazilski) / Português Brasileiro](/i18n/README.pt-br.md) +- [Rumunjski / Română](/i18n/README.ro.md) +- [Ruski / Pусский](/i18n/README.ru.md) +- [Srpski / Srpski](/i18n/README.sr.md) +- [Singalski / සිංහල](/i18n/README.si.md) +- [Slovački / slovenský](/i18n/README.sk.md) +- [Slovenski / Slovenščina](/i18n/README.sl.md) +- [Španjolski / Español](/i18n/README.es.md) +- [Pojednostavljeni kineski / 简体中文](/i18n/README.zh-cn.md) +- [Švedski / Svenska](/i18n/README.sv.md) +- [Tajski / ไทย](/i18n/README.th.md) +- [Tradicionalni kineski / 繁體中文](/i18n/README.zh-tw.md) +- [Turski / Türkçe](/i18n/README.tr.md) +- [Ukrajinski / Українська](/i18n/README.uk.md) +- [Vijetnamski / Tiếng Việt](/i18n/README.vi-vn.md) +- [Popis prijevoda](/i18n/languages.md) diff --git a/i18n/README.si.md b/i18n/README.si.md index f89b9805fd2..c995827f8c7 100644 --- a/i18n/README.si.md +++ b/i18n/README.si.md @@ -9,82 +9,281 @@ [Supabase](https://supabase.com) යනු විවෘත පරිශීලක Firebase වෙනුවට ආදේශකයකි.අපි Firebase වල ඇති පහසුකම් enterprise-grade විවෘත පරිශීලක මෘදුකාංග භාවිතා කරමින් නිපදවනු ලබයි. -- [x] Hosted Postgres Database -- [x] Realtime subscriptions -- [x] Authentication and authorization -- [x] Auto-generated APIs +- [x] Hosted Postgres Database. [Docs](https://supabase.com/docs/guides/database) +- [x] Authentication and Authorization. [Docs](https://supabase.com/docs/guides/auth) +- [x] Auto-generated APIs. + - [x] REST. [Docs](https://supabase.com/docs/guides/api) + - [x] GraphQL. [Docs](https://supabase.com/docs/guides/graphql) + - [x] Realtime subscriptions. [Docs](https://supabase.com/docs/guides/realtime) +- [x] Functions. + - [x] Database Functions. [Docs](https://supabase.com/docs/guides/database/functions) + - [x] Edge Functions [Docs](https://supabase.com/docs/guides/functions) +- [x] File Storage. [Docs](https://supabase.com/docs/guides/storage) +- [x] AI + Vector/Embeddings Toolkit. [Docs](https://supabase.com/docs/guides/ai) - [x] Dashboard -- [x] Storage -- [x] Functions ![Supabase Dashboard](https://raw.githubusercontent.com/supabase/supabase/master/apps/www/public/images/github/supabase-dashboard.png) +ප්‍රධාන යාවත්කාල කිරීම් පිළිබඳ දැනුම් දීම සඳහා "releases" පිළිබඳව අවධානයෙන් සිටින්න. + +Watch this repo + ## ප්‍රලේඛනය සම්පූර්ණ විස්තරය කියවන්න ,මෙතනින් [supabase.com/docs](https://supabase.com/docs) +දායක වන ආකාරය බැලීමට, ආරම්භ කිරීම වෙත [පිවිසෙන්න](./DEVELOPERS.md) + ## Community එක හා සහයෝගය ගැනීමට - [Community Forum](https://github.com/supabase/supabase/discussions). වඩාත්ම සුදුසු: දේවල් සෑදීමට උදව් ගැනීම.database best practices පිළිබඳ සාකච්ඡා කිරීමට. - [GitHub Issues](https://github.com/supabase/supabase/issues). වඩාත්ම සුදුසු: Supabase භාවිතා කිරීමේදී ඔබට හමුවන වැරදී හා ප්‍රශ්න. - [Email Support](https://supabase.com/docs/support#business-support). වඩාත්ම සුදුසු: database හා infrastructure පිළිබඳ ඔබේ ඇති ප්‍රශ්න. - -## තත්ත්වය - -- [x] Alpha: අප දැනට Supabase විවෘත නොවන පාරිභෝගිකයන් සමඟ පරීක්ෂා කරනවා -- [x] Public Alpha: ඕනෑම කෙනෙකුට [supabase.com/dashboard](https://supabase.com/dashboard) මඟින් සම්බන්ධ විය හැකිය.නමුත් හෙමිහිට පරීක්ෂා කරන්න, දැනට kinks කිහිපයක් පමණයි ඇත්තේ -- [x] Public Beta: non-enterprise භාවිතයන් ගොඩකට ස්ථාවරයි -- [ ] Public: භාවිතා කිරීම සඳහා සූදානම් - -අප දැනට පොදු beta තත්වයේ සිටින්නෙ. ප්‍රධාන නිකුත්කිරීම් හා දැනුවත් වීම් සඳහා "releases" පිළිබඳව අවධානයෙන් සිටින්න. - -Watch this repo - ---- +- [Discord](https://discord.supabase.com). වඩාත්ම සුදුසු: ඔබගේ applications බෙදාගැනීම සහ community සමඟ රැඳී සිටීම. ## කොහොමද මෙය වැඩකරන්නෙ Supabase යනු විවෘත පරිශීලක උපාංග කිහිපයක එකතුවකි.අප Firebase වල ඇති පහසුකම් enterprise-grade, විවෘත පරිශීලක උපාංග භාවිතා කරමින් නිපදවයි.උපාංග හා communities ඇත්නම්,ඒවා MIT,Apache 2, හෝ ඒ ආකාරයේ open license නම් අප ඒවා භාවිතා කර සහයෝගය දක්වනවා.එවැනි උපාංග නොමැතිනම්,අප ඒවා විවෘත පරිශීලක විදියට නිපදවනවා.Supabase යනු 1-ට-1 Firebase වලට සමාන දෙයක් නොවේ.අපේ අරමුණ developers ලට Firebase වැනි අත්දැකීමක් විවෘත පරිශීලක උපාංග මඟින් ලබාදීමයි. -**Current architecture** +**Architecture** -Supabase යනු [hosted platform](https://supabase.com/dashboard) එකකි.ඔබට දැන් සම්බන්ධ වී කිසිම දෙයක් install නොකර Supabase භාවිත කල හැකිය.අප තවමත් local development අත්දැකීම සාදමින් සිටියි- මෙය තමයි අපේ දැනට ප්‍රධාන අරමුණ,platform එකේ ස්ථාවර බව සමඟ. +Supabase යනු [hosted platform](https://supabase.com/dashboard). ඔබට කිසිවක් ස්ථාපනය නොකර ලියාපදිංචි වී Supabase භාවිතා කිරීම ආරම්භ කළ හැකිය. +ඔබට [self-host](https://supabase.com/docs/guides/hosting/overview) සහ [develop locally](https://supabase.com/docs/guides/local-development) කළ හැකිය. -![Architecture](https://github.com/supabase/supabase/blob/master/apps/docs/public/img/supabase-architecture.svg) +![Architecture](apps/docs/public/img/supabase-architecture.svg) - [PostgreSQL](https://www.postgresql.org/) යනු අවුරුදු 30 වඩා කාලයක් ක්‍රියාත්මක වෙමින් පවතින object-relational database system එකක් වන අතර එය විශ්වාසනීයත්වයට,ක්‍රියාකාරීත්වයට හා feature robustness බවට කීර්තියක් අත්පත්කරගෙන සිටියි -- [Realtime](https://github.com/supabase/realtime) is an Elixir server that allows you to listen to PostgreSQL inserts, updates, and deletes using websockets. Supabase listens to Postgres' built-in replication functionality, converts the replication byte stream into JSON, then broadcasts the JSON over websockets. +- [Realtime](https://github.com/supabase/realtime) is an Elixir server that allows you to listen to PostgreSQL inserts, updates, and deletes using websockets. Realtime polls Postgres' built-in replication functionality for database changes, converts changes to JSON, then broadcasts the JSON over websockets to authorized clients. - [PostgREST](http://postgrest.org/) යනු PostgreSQL database කෙලින්ම RESTful API එකක් බවට පරිවර්තනය කරන web server එකකි. -- [Storage](https://github.com/supabase/storage-api) pS3 වල ගබඩා කර ඇති files හසුරවන්න RESTful interface එකක් ලබාදීම, Postgres භාවිත කරමින් අවසරයන් හැසිරවීමට +- [GoTrue](https://github.com/netlify/gotrue) JWT tokens භාවිත කරන්නන්ව හැසිරවීමට JWT ආශ්‍රිත APi එකකි. +- [Storage](https://github.com/supabase/storage-api) S3 වල ගබඩා කර ඇති files හසුරවන්න RESTful interface එකක් ලබාදීම, Postgres භාවිත කරමින් අවසරයන් හැසිරවීමට +- [pg_graphql](http://github.com/supabase/pg_graphql/) a PostgreSQL extension that exposes a GraphQL API - [postgres-meta](https://github.com/supabase/postgres-meta) Postgres හැසිරවීමට RESTful API එකක් ලබාදෙන අතර table වල දත්ත ලබාගැනීමට,roles add කිරීමට හා queries run කිරීම කර දෙයි -- [GoTrue](https://github.com/netlify/gotrue) SWT tokens භාවිත කරන්නන්ව හැසිරවීමට SWT ආශ්‍රිත APi එකකි/ - [Kong](https://github.com/Kong/kong) is a cloud-native API gateway. #### Client libraries -Our client library is modular. Each sub-library is a standalone implementation for a single external system. This is one of the ways we support existing tools. +Client libraries සඳහා අපගේ ප්‍රවේශය modular වේ. සෑම sub-library තනි බාහිර පද්ධතියක් සඳහා ස්වාධීනව ක්‍රියාත්මක කිරීමකි. අපි දැනට පවතින මෙවලම් සඳහා සහය දක්වන ක්‍රමවලින් එකකි. -- **`supabase-{lang}`**: Combines libraries and adds enrichments. - - `postgrest-{lang}`: Client library to work with [PostgREST](https://github.com/postgrest/postgrest) - - `realtime-{lang}`: Client library to work with [Realtime](https://github.com/supabase/realtime) - - `gotrue-{lang}`: Client library to work with [GoTrue](https://github.com/netlify/gotrue) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LanguageClientFeature-Clients (bundled in Supabase client)
SupabasePostgRESTGoTrueRealtimeStorageFunctions
⚡️ Official ⚡️
JavaScript (TypeScript)supabase-jspostgrest-jsgotrue-jsrealtime-jsstorage-jsfunctions-js
Fluttersupabase-flutterpostgrest-dartgotrue-dartrealtime-dartstorage-dartfunctions-dart
Swiftsupabase-swiftpostgrest-swiftauth-swiftrealtime-swiftstorage-swiftfunctions-swift
Pythonsupabase-pypostgrest-pygotrue-pyrealtime-pystorage-pyfunctions-py
💚 Community 💚
C#supabase-csharppostgrest-csharpgotrue-csharprealtime-csharpstorage-csharpfunctions-csharp
Go-postgrest-gogotrue-go-storage-gofunctions-go
Java--gotrue-java-storage-java-
Kotlinsupabase-ktpostgrest-ktauth-ktrealtime-ktstorage-ktfunctions-kt
Rubysupabase-rbpostgrest-rb----
Rust-postgrest-rs----
Godot Engine (GDScript)supabase-gdscriptpostgrest-gdscriptgotrue-gdscriptrealtime-gdscriptstorage-gdscriptfunctions-gdscript
-| Repo | Official | Community | -| --------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **`supabase-{lang}`** | [`JS`](https://github.com/supabase/supabase-js) | [`C#`](https://github.com/supabase/supabase-csharp) \| [`Flutter`](https://github.com/supabase/supabase-flutter) \| [`Python`](https://github.com/supabase/supabase-py) \| `Rust` \| [`Ruby`](https://github.com/supabase/supabase-rb) \| `Go` | -| `postgrest-{lang}` | [`JS`](https://github.com/supabase/postgrest-js) | [`C#`](https://github.com/supabase/postgrest-csharp) \| [`Dart`](https://github.com/supabase/postgrest-dart) \| [`Python`](https://github.com/supabase/postgrest-py) \| [`Rust`](https://github.com/supabase/postgrest-rs) \| [`Ruby`](https://github.com/supabase/postgrest-rb) \| [`Go`](https://github.com/supabase/postgrest-go) | -| `realtime-{lang}` | [`JS`](https://github.com/supabase/realtime-js) | [`C#`](https://github.com/supabase/realtime-csharp) \| [`Dart`](https://github.com/supabase/realtime-dart) \| [`Python`](https://github.com/supabase/realtime-py) \| `Rust` \| `Ruby` \| `Go` | -| `gotrue-{lang}` | [`JS`](https://github.com/supabase/gotrue-js) | [`C#`](https://github.com/supabase/gotrue-csharp) \| [`Dart`](https://github.com/supabase/gotrue-dart) \| [`Python`](https://github.com/supabase/gotrue-py) \| `Rust` \| `Ruby` \| `Go` | - - + +## Badges + +![Made with Supabase](./apps/www/public/badge-made-with-supabase.svg) + +```md +[![Made with Supabase](https://supabase.com/badge-made-with-supabase.svg)](https://supabase.com) +``` + +```html + + Made with Supabase + +``` + +![Made with Supabase (dark)](./apps/www/public/badge-made-with-supabase-dark.svg) + +```md +[![Made with Supabase](https://supabase.com/badge-made-with-supabase-dark.svg)](https://supabase.com) +``` + +```html + + Made with Supabase + +``` + ## Translations +- [Arabic | العربية](/i18n/README.ar.md) +- [Albanian / Shqip](/i18n/README.sq.md) +- [Bangla / বাংলা](/i18n/README.bn.md) +- [Bulgarian / Български](/i18n/README.bg.md) +- [Catalan / Català](/i18n/README.ca.md) +- [Czech / čeština](/i18n/README.cs.md) +- [Danish / Dansk](/i18n/README.da.md) +- [Dutch / Nederlands](/i18n/README.nl.md) +- [English](https://github.com/supabase/supabase) +- [Estonian / eesti keel](/i18n/README.et.md) +- [Finnish / Suomalainen](/i18n/README.fi.md) +- [French / Français](/i18n/README.fr.md) +- [German / Deutsch](/i18n/README.de.md) +- [Greek / Ελληνικά](/i18n/README.el.md) +- [Gujarati / ગુજરાતી](/i18n/README.gu.md) +- [Hebrew / עברית](/i18n/README.he.md) +- [Hindi / हिंदी](/i18n/README.hi.md) +- [Hungarian / Magyar](/i18n/README.hu.md) +- [Nepali / नेपाली](/i18n/README.ne.md) +- [Indonesian / Bahasa Indonesia](/i18n/README.id.md) +- [Italiano / Italian](/i18n/README.it.md) +- [Japanese / 日本語](/i18n/README.jp.md) +- [Korean / 한국어](/i18n/README.ko.md) +- [Lithuanian / lietuvių](/i18n/README.lt.md) +- [Latvian / latviski](/i18n/README.lv.md) +- [Malay / Bahasa Malaysia](/i18n/README.ms.md) +- [Norwegian (Bokmål) / Norsk (Bokmål)](/i18n/README.nb.md) +- [Persian / فارسی](/i18n/README.fa.md) +- [Polish / Polski](/i18n/README.pl.md) +- [Portuguese / Português](/i18n/README.pt.md) +- [Portuguese (Brazilian) / Português Brasileiro](/i18n/README.pt-br.md) +- [Romanian / Română](/i18n/README.ro.md) +- [Russian / Pусский](/i18n/README.ru.md) +- [Serbian / Srpski](/i18n/README.sr.md) +- [Sinhala / සිංහල](/i18n/README.si.md) +- [Slovak / slovenský](/i18n/README.sk.md) +- [Slovenian / Slovenščina](/i18n/README.sl.md) +- [Spanish / Español](/i18n/README.es.md) +- [Simplified Chinese / 简体中文](/i18n/README.zh-cn.md) +- [Swedish / Svenska](/i18n/README.sv.md) +- [Thai / ไทย](/i18n/README.th.md) +- [Traditional Chinese / 繁體中文](/i18n/README.zh-tw.md) +- [Turkish / Türkçe](/i18n/README.tr.md) +- [Ukrainian / Українська](/i18n/README.uk.md) +- [Vietnamese / Tiếng Việt](/i18n/README.vi-vn.md) - [List of translations](/i18n/languages.md) - ---- - -## Sponsors - -[![New Sponsor](https://user-images.githubusercontent.com/10214025/90518111-e74bbb00-e198-11ea-8f88-c9e3c1aa4b5b.png)](https://github.com/sponsors/supabase) diff --git a/i18n/languages.md b/i18n/languages.md index 1117bb0a02c..a6a7de8cb61 100644 --- a/i18n/languages.md +++ b/i18n/languages.md @@ -5,6 +5,7 @@ - [Bangla / বাংলা](/i18n/README.bn.md) - [Bulgarian / Български](/i18n/README.bg.md) - [Catalan / Català](/i18n/README.ca.md) +- [Croatian / hrvatski](/i18n/README.hr.md) - [Czech / čeština](/i18n/README.cs.md) - [Danish / Dansk](/i18n/README.da.md) - [Dutch / Nederlands](/i18n/README.nl.md) diff --git a/package.json b/package.json index abe0d27ac45..8f9346a77fb 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,8 @@ "@tanstack/directive-functions-plugin>vite": "catalog:", "@tanstack/react-start-plugin>vite": "catalog:", "esbuild": "^0.25.2", - "payload>image-size": "1.2.1" + "payload>image-size": "1.2.1", + "@redocly/respect-core>form-data": "^4.0.4" }, "neverBuiltDependencies": ["libpg-query"] }, diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index 1a901f0e60d..4a56c1365e3 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -2450,6 +2450,11 @@ export interface components { grant_type?: 'authorization_code' | 'refresh_token' redirect_uri?: string refresh_token?: string + /** + * @description Resource indicator for MCP (Model Context Protocol) clients + * @enum {string} + */ + resource?: 'http://localhost:8080/mcp' } OAuthTokenResponse: { access_token: string @@ -3697,7 +3702,11 @@ export interface operations { client_id: string code_challenge?: string code_challenge_method?: 'plain' | 'sha256' | 'S256' + /** @description Organization slug */ + organization_slug?: string redirect_uri: string + /** @description Resource indicator for MCP (Model Context Protocol) clients */ + resource?: 'http://localhost:8080/mcp' response_mode?: string response_type: 'code' | 'token' | 'id_token token' scope?: string diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index b34c046fe09..0eff38d7b21 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -3391,6 +3391,23 @@ export interface paths { patch?: never trace?: never } + '/platform/replication/{ref}/pipelines/{pipeline_id}/replication-status': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Get the status of a replication pipeline. */ + get: operations['ReplicationPipelinesController_getPipelineReplicationStatus'] + put?: never + post?: never + delete?: never + options?: never + head?: never + patch?: never + trace?: never + } '/platform/replication/{ref}/pipelines/{pipeline_id}/start': { parameters: { query?: never @@ -4685,7 +4702,8 @@ export interface components { } CreateProjectBody: { auth_site_url?: string - cloud_provider: string + /** @enum {string} */ + cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' custom_supabase_internal_requests?: { ami: { search_tags?: { @@ -5074,7 +5092,7 @@ export interface components { } DatabaseDetailResponse: { /** @enum {string} */ - cloud_provider: 'AWS' | 'AWS_K8S' | 'FLY' + cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' /** @default null */ connection_string_read_only?: string | null /** @default null */ @@ -5278,10 +5296,6 @@ export interface components { file_url: string fileUrl: string } - GetAvailableRegionsBody: { - cloud_provider: string - organization_slug: string - } GetContentCountResponse: { count: number } @@ -6373,7 +6387,8 @@ export interface components { }[] } OrganizationSlugAvailableVersionsBody: { - provider: string + /** @enum {string} */ + provider: 'AWS' | 'FLY' | 'AWS_K8S' region: string } OrganizationSlugAvailableVersionsResponse: { @@ -7273,7 +7288,7 @@ export interface components { code: string name: string /** @enum {string} */ - provider: 'AWS' | 'AWS_K8S' | 'FLY' + provider: 'AWS' | 'FLY' | 'AWS_K8S' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -7292,7 +7307,7 @@ export interface components { code: string name: string /** @enum {string} */ - provider: 'AWS' | 'AWS_K8S' | 'FLY' + provider: 'AWS' | 'FLY' | 'AWS_K8S' /** @enum {string} */ status?: 'capacity' | 'other' /** @enum {string} */ @@ -7353,6 +7368,41 @@ export interface components { tenant_id: string }[] } + ReplicationPipelineReplicationStatusResponse: { + /** @description Pipeline id */ + pipeline_id: number + /** @description Table statuses */ + table_statuses: { + /** @description Table replication state */ + state: + | { + /** @enum {string} */ + name: 'queued' + } + | { + /** @enum {string} */ + name: 'copying_table' + } + | { + /** @enum {string} */ + name: 'copied_table' + } + | { + lag: number + /** @enum {string} */ + name: 'following_wal' + } + | { + message: string + /** @enum {string} */ + name: 'error' + } + /** @description Table id (internal Postgres OID) */ + table_id: number + /** @description Table name */ + table_name: string + }[] + } ReplicationPipelineResponse: { /** @description Pipeline config */ config: { @@ -11723,6 +11773,12 @@ export interface operations { 'application/json': components['schemas']['InvitationResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get organization invitations */ 500: { headers: { @@ -11754,6 +11810,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to create organization invitation */ 500: { headers: { @@ -16607,6 +16669,12 @@ export interface operations { 'application/json': components['schemas']['GetUserContentResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve project's content */ 500: { headers: { @@ -16638,6 +16706,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to update project's content */ 500: { headers: { @@ -16671,6 +16745,12 @@ export interface operations { 'application/json': components['schemas']['UserContentObject'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to create project's content */ 500: { headers: { @@ -16702,6 +16782,12 @@ export interface operations { 'application/json': components['schemas']['BulkDeleteUserContentResponse'][] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to delete project's contents */ 500: { headers: { @@ -16734,6 +16820,12 @@ export interface operations { 'application/json': components['schemas']['GetContentCountV2Response'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve user's content counts */ 500: { headers: { @@ -16771,6 +16863,12 @@ export interface operations { 'application/json': components['schemas']['GetUserContentFolderResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve project's content root folder */ 500: { headers: { @@ -16804,6 +16902,12 @@ export interface operations { 'application/json': components['schemas']['CreateUserContentFolderResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to create project's content folder */ 500: { headers: { @@ -16830,6 +16934,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to delete project's content folders */ 500: { headers: { @@ -16867,6 +16977,12 @@ export interface operations { 'application/json': components['schemas']['GetUserContentFolderResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve project's content folder */ 500: { headers: { @@ -16900,6 +17016,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to update project's content folder */ 500: { headers: { @@ -16930,6 +17052,12 @@ export interface operations { 'application/json': components['schemas']['GetUserContentByIdResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to retrieve project's content by the given id */ 500: { headers: { @@ -18062,6 +18190,12 @@ export interface operations { } content?: never } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } /** @description Failed to get project's status */ 500: { headers: { @@ -18135,16 +18269,15 @@ export interface operations { } ProjectsController_getRegions: { parameters: { - query?: never + query: { + cloud_provider: 'AWS' | 'FLY' | 'AWS_K8S' + organization_slug: string + } header?: never path?: never cookie?: never } - requestBody: { - content: { - 'application/json': components['schemas']['GetAvailableRegionsBody'] - } - } + requestBody?: never responses: { 200: { headers: { @@ -18175,6 +18308,12 @@ export interface operations { 'application/json': components['schemas']['GetProjectByFlyExtensionIdResponse'] } } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } } } ReplicationDestinationsController_getDestinations: { @@ -18639,6 +18778,44 @@ export interface operations { } } } + ReplicationPipelinesController_getPipelineReplicationStatus: { + parameters: { + query?: never + header?: never + path: { + /** @description Pipeline id */ + pipeline_id: number + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + /** @description Returns the pipeline replication status. */ + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['ReplicationPipelineReplicationStatusResponse'] + } + } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get pipeline replication status. */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } ReplicationPipelinesController_startPipeline: { parameters: { query?: never diff --git a/packages/ui-patterns/package.json b/packages/ui-patterns/package.json index 7aef2c0ba5b..432bc533630 100644 --- a/packages/ui-patterns/package.json +++ b/packages/ui-patterns/package.json @@ -544,6 +544,6 @@ "vitest": "^3.0.5" }, "peerDependencies": { - "next": "*" + "next": "catalog:" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de23cd1f79c..20afe3bccee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,8 +25,8 @@ catalogs: specifier: ^18.3.0 version: 18.3.0 next: - specifier: 15.3.1 - version: 15.3.1 + specifier: 15.3.3 + version: 15.3.3 react: specifier: ^18.3.0 version: 18.3.1 @@ -46,6 +46,7 @@ overrides: '@tanstack/react-start-plugin>vite': ^6.2.7 esbuild: ^0.25.2 payload>image-size: 1.2.1 + '@redocly/respect-core>form-data': ^4.0.4 importers: @@ -89,34 +90,34 @@ importers: dependencies: '@payloadcms/db-postgres': specifier: 3.33.0 - version: 3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/react@18.3.3)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react@18.3.1)(supports-color@8.1.1) + version: 3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/react@18.3.3)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react@18.3.1)(supports-color@8.1.1) '@payloadcms/live-preview-react': specifier: ^3.33.0 version: 3.43.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@payloadcms/next': specifier: 3.33.0 - version: 3.33.0(@types/react@18.3.3)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + version: 3.33.0(@types/react@18.3.3)(graphql@16.11.0)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@payloadcms/payload-cloud': specifier: 3.33.0 - version: 3.33.0(encoding@0.1.13)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3)) + version: 3.33.0(encoding@0.1.13)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3)) '@payloadcms/plugin-form-builder': specifier: 3.33.0 - version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@payloadcms/plugin-nested-docs': specifier: 3.33.0 - version: 3.33.0(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3)) + version: 3.33.0(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3)) '@payloadcms/plugin-seo': specifier: 3.33.0 - version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@payloadcms/richtext-lexical': specifier: 3.33.0 - version: 3.33.0(@faceless-ui/modal@3.0.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@faceless-ui/scroll-info@2.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3))(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)(yjs@13.6.27) + version: 3.33.0(@faceless-ui/modal@3.0.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@faceless-ui/scroll-info@2.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.11.0)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3))(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)(yjs@13.6.27) '@payloadcms/storage-s3': specifier: 3.33.0 - version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@payloadcms/ui': specifier: 3.33.0 - version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + version: 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) common: specifier: workspace:* version: link:../../packages/common @@ -131,13 +132,13 @@ importers: version: link:../../packages/eslint-config-supabase graphql: specifier: ^16.8.1 - version: 16.10.0 + version: 16.11.0 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) payload: specifier: 3.33.0 - version: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + version: 3.33.0(graphql@16.11.0)(typescript@5.7.3) react: specifier: 'catalog:' version: 18.3.1 @@ -186,10 +187,10 @@ importers: version: 1.2.0 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-contentlayer2: specifier: 0.4.6 - version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) + version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -331,7 +332,7 @@ importers: version: 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/nextjs': specifier: ^9.15.0 - version: 9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0) + version: 9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0) '@supabase/supabase-js': specifier: 'catalog:' version: 2.49.3 @@ -370,10 +371,10 @@ importers: version: 2.0.0 graphql: specifier: ^16.10.0 - version: 16.10.0 + version: 16.11.0 graphql-validation-complexity: specifier: ^0.4.2 - version: 0.4.2(graphql@16.10.0) + version: 0.4.2(graphql@16.11.0) gray-matter: specifier: ^4.0.3 version: 4.0.3 @@ -439,7 +440,7 @@ importers: version: 1.0.1 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-mdx-remote: specifier: ^4.4.1 version: 4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) @@ -451,7 +452,7 @@ importers: version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nuqs: specifier: ^1.19.1 - version: 1.19.1(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)) + version: 1.19.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)) openai: specifier: ^4.20.1 version: 4.71.1(encoding@0.1.13)(zod@3.23.8) @@ -533,16 +534,16 @@ importers: devDependencies: '@graphiql/toolkit': specifier: ^0.9.1 - version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0) + version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0) '@graphql-codegen/cli': specifier: 5.0.5 - version: 5.0.5(@parcel/watcher@2.5.1)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0)(supports-color@8.1.1)(typescript@5.5.2) + version: 5.0.5(@parcel/watcher@2.5.1)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(supports-color@8.1.1)(typescript@5.5.2) '@graphql-codegen/typescript': specifier: 4.1.6 - version: 4.1.6(encoding@0.1.13)(graphql@16.10.0) + version: 4.1.6(encoding@0.1.13)(graphql@16.11.0) '@graphql-codegen/typescript-resolvers': specifier: 4.5.0 - version: 4.5.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0) + version: 4.5.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0) '@supabase/supa-mdx-lint': specifier: 0.3.0-alpha version: 0.3.0-alpha @@ -605,7 +606,7 @@ importers: version: 13.2.2 graphiql: specifier: ^4.0.2 - version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) openapi-types: specifier: ^12.1.3 version: 12.1.3 @@ -728,7 +729,7 @@ importers: version: 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/nextjs': specifier: ^8.52.1 - version: 8.52.1(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0) + version: 8.52.1(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0) '@std/path': specifier: npm:@jsr/std__path@^1.0.8 version: '@jsr/std__path@1.0.8' @@ -774,9 +775,6 @@ importers: '@uidotdev/usehooks': specifier: ^2.4.1 version: 2.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@vercel/flags': - specifier: ^2.6.0 - version: 2.6.3(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@vercel/functions': specifier: ^2.1.0 version: 2.1.0(@aws-sdk/credential-provider-web-identity@3.830.0) @@ -869,13 +867,13 @@ importers: version: 0.52.2 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nuqs: specifier: ^2.4.1 - version: 2.4.1(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 2.4.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) openai: specifier: ^4.20.1 version: 4.71.1(encoding@0.1.13)(zod@3.23.8) @@ -1146,7 +1144,7 @@ importers: version: 2.4.11(typescript@5.5.2) next-router-mock: specifier: ^0.9.13 - version: 0.9.13(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1) + version: 0.9.13(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1) postcss: specifier: ^8.5.3 version: 8.5.3 @@ -1314,10 +1312,10 @@ importers: version: 0.436.0(react@18.3.1) next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-contentlayer2: specifier: 0.4.6 - version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) + version: 0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1570,16 +1568,16 @@ importers: version: 1.2.0 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-contentlayer2: specifier: 0.5.3 - version: 0.5.3(contentlayer2@0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) + version: 0.5.3(contentlayer2@0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) next-mdx-remote: specifier: ^4.4.1 version: 4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) next-seo: specifier: ^6.5.0 - version: 6.5.0(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.5.0(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1842,13 +1840,13 @@ importers: version: 0.7.9 flags: specifier: ^4.0.0 - version: 4.0.1(@opentelemetry/api@1.9.0)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 4.0.1(@opentelemetry/api@1.9.0)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash: specifier: ^4.17.21 version: 4.17.21 next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2126,7 +2124,7 @@ importers: version: 0.436.0(react@18.3.1) next: specifier: 'catalog:' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2294,8 +2292,8 @@ importers: specifier: '*' version: 0.52.2 next: - specifier: '*' - version: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + specifier: 'catalog:' + version: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) next-themes: specifier: '*' version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -2404,7 +2402,7 @@ importers: version: link:../api-types next-router-mock: specifier: ^0.9.13 - version: 0.9.13(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1) + version: 0.9.13(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1) tsx: specifier: ^4.19.3 version: 4.19.3 @@ -4560,6 +4558,9 @@ packages: '@next/env@15.3.1': resolution: {integrity: sha512-cwK27QdzrMblHSn9DZRV+DQscHXRuJv6MydlJRpFSqJWZrTYMLzKDeyueJNN9MGd8NNiUKzDQADAf+dMLXX7YQ==} + '@next/env@15.3.3': + resolution: {integrity: sha512-OdiMrzCl2Xi0VTjiQQUK0Xh7bJHnOuET2s+3V+Y40WJBAXrJeGA3f+I8MZJ/YQ3mVGi5XGR1L66oFlgqXhQ4Vw==} + '@next/eslint-plugin-next@15.3.1': resolution: {integrity: sha512-oEs4dsfM6iyER3jTzMm4kDSbrQJq8wZw5fmT6fg2V3SMo+kgG+cShzLfEV20senZzv8VF+puNLheiGPlBGsv2A==} @@ -4574,50 +4575,50 @@ packages: '@mdx-js/react': optional: true - '@next/swc-darwin-arm64@15.3.1': - resolution: {integrity: sha512-hjDw4f4/nla+6wysBL07z52Gs55Gttp5Bsk5/8AncQLJoisvTBP0pRIBK/B16/KqQyH+uN4Ww8KkcAqJODYH3w==} + '@next/swc-darwin-arm64@15.3.3': + resolution: {integrity: sha512-WRJERLuH+O3oYB4yZNVahSVFmtxRNjNF1I1c34tYMoJb0Pve+7/RaLAJJizyYiFhjYNGHRAE1Ri2Fd23zgDqhg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.3.1': - resolution: {integrity: sha512-q+aw+cJ2ooVYdCEqZVk+T4Ni10jF6Fo5DfpEV51OupMaV5XL6pf3GCzrk6kSSZBsMKZtVC1Zm/xaNBFpA6bJ2g==} + '@next/swc-darwin-x64@15.3.3': + resolution: {integrity: sha512-XHdzH/yBc55lu78k/XwtuFR/ZXUTcflpRXcsu0nKmF45U96jt1tsOZhVrn5YH+paw66zOANpOnFQ9i6/j+UYvw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.3.1': - resolution: {integrity: sha512-wBQ+jGUI3N0QZyWmmvRHjXjTWFy8o+zPFLSOyAyGFI94oJi+kK/LIZFJXeykvgXUk1NLDAEFDZw/NVINhdk9FQ==} + '@next/swc-linux-arm64-gnu@15.3.3': + resolution: {integrity: sha512-VZ3sYL2LXB8znNGcjhocikEkag/8xiLgnvQts41tq6i+wql63SMS1Q6N8RVXHw5pEUjiof+II3HkDd7GFcgkzw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.3.1': - resolution: {integrity: sha512-IIxXEXRti/AulO9lWRHiCpUUR8AR/ZYLPALgiIg/9ENzMzLn3l0NSxVdva7R/VDcuSEBo0eGVCe3evSIHNz0Hg==} + '@next/swc-linux-arm64-musl@15.3.3': + resolution: {integrity: sha512-h6Y1fLU4RWAp1HPNJWDYBQ+e3G7sLckyBXhmH9ajn8l/RSMnhbuPBV/fXmy3muMcVwoJdHL+UtzRzs0nXOf9SA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.3.1': - resolution: {integrity: sha512-bfI4AMhySJbyXQIKH5rmLJ5/BP7bPwuxauTvVEiJ/ADoddaA9fgyNNCcsbu9SlqfHDoZmfI6g2EjzLwbsVTr5A==} + '@next/swc-linux-x64-gnu@15.3.3': + resolution: {integrity: sha512-jJ8HRiF3N8Zw6hGlytCj5BiHyG/K+fnTKVDEKvUCyiQ/0r5tgwO7OgaRiOjjRoIx2vwLR+Rz8hQoPrnmFbJdfw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.3.1': - resolution: {integrity: sha512-FeAbR7FYMWR+Z+M5iSGytVryKHiAsc0x3Nc3J+FD5NVbD5Mqz7fTSy8CYliXinn7T26nDMbpExRUI/4ekTvoiA==} + '@next/swc-linux-x64-musl@15.3.3': + resolution: {integrity: sha512-HrUcTr4N+RgiiGn3jjeT6Oo208UT/7BuTr7K0mdKRBtTbT4v9zJqCDKO97DUqqoBK1qyzP1RwvrWTvU6EPh/Cw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.3.1': - resolution: {integrity: sha512-yP7FueWjphQEPpJQ2oKmshk/ppOt+0/bB8JC8svPUZNy0Pi3KbPx2Llkzv1p8CoQa+D2wknINlJpHf3vtChVBw==} + '@next/swc-win32-arm64-msvc@15.3.3': + resolution: {integrity: sha512-SxorONgi6K7ZUysMtRF3mIeHC5aA3IQLmKFQzU0OuhuUYwpOBc1ypaLJLP5Bf3M9k53KUUUj4vTPwzGvl/NwlQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.3.1': - resolution: {integrity: sha512-3PMvF2zRJAifcRNni9uMk/gulWfWS+qVI/pagd+4yLF5bcXPZPPH2xlYRYOsUjmCJOXSTAC2PjRzbhsRzR2fDQ==} + '@next/swc-win32-x64-msvc@15.3.3': + resolution: {integrity: sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -9033,24 +9034,6 @@ packages: '@usercentrics/cmp-browser-sdk@4.42.0': resolution: {integrity: sha512-/cik01TdeiYUV1+EasK83Ip05TDqmowM5tmWGfRDdaOrneSic5BedBdJHKya4pP2vwiYAtzDYVJe4BwPt2M16g==} - '@vercel/flags@2.6.3': - resolution: {integrity: sha512-knLDYS8MCc/zx4FF6KRzHQzAKdo8VQ3V0PEBI5WvRlFIhcqhcEomxHoK41/xMnNEQvUzETACHw610/i/pVwYSA==} - deprecated: This package has been renamed to flags. It offers the same functionality under a new name. Please follow the upgrade guide https://github.com/vercel/flags/blob/main/packages/flags/guides/upgrade-to-v4.md - peerDependencies: - '@sveltejs/kit': '*' - next: '*' - react: '*' - react-dom: '*' - peerDependenciesMeta: - '@sveltejs/kit': - optional: true - next: - optional: true - react: - optional: true - react-dom: - optional: true - '@vercel/functions@2.1.0': resolution: {integrity: sha512-1gSbK9zfrbJxk1JTBVERDhLi01mK3fz+gw4GjOjZwHnqs0zsBhQA70HGVtXQX/Z3BTRMfbpAEMVDfhecRw0lDA==} engines: {node: '>= 18'} @@ -9744,11 +9727,11 @@ packages: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -11655,8 +11638,8 @@ packages: fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} - fastify@4.29.0: - resolution: {integrity: sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ==} + fastify@4.29.1: + resolution: {integrity: sha512-m2kMNHIG92tSNWv+Z3UeTR9AWLLuo7KctC7mlFPtMEVrfjIhmQhkQnT9v15qA/BfVq3vvj134Y0jl9SBje3jXQ==} fastq@1.18.0: resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} @@ -11809,12 +11792,8 @@ packages: form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - - form-data@4.0.2: - resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} format@0.2.2: @@ -11956,14 +11935,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - - get-intrinsic@1.2.7: - resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==} - engines: {node: '>= 0.4'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -12204,10 +12175,6 @@ packages: ws: optional: true - graphql@16.10.0: - resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - graphql@16.11.0: resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} @@ -12269,10 +12236,6 @@ packages: resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - has-symbols@1.1.0: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} @@ -13100,9 +13063,6 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true - jose@5.2.1: - resolution: {integrity: sha512-qiaQhtQRw6YrOaOj0v59h3R6hUY9NvxBmmnMfKemkqYmBB0tEc97NbLP7ix44VP5p9/0YHG8Vyhzuo5YBNwviA==} - jose@5.9.6: resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==} @@ -14369,8 +14329,8 @@ packages: next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - next@15.3.1: - resolution: {integrity: sha512-8+dDV0xNLOgHlyBxP1GwHGVaNXsmp+2NhZEYrXr24GWLHtt27YrBPbPuHvzlhi7kZNYjeJNR93IF5zfFu5UL0g==} + next@15.3.3: + resolution: {integrity: sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -18549,22 +18509,6 @@ snapshots: '@types/json-schema': 7.0.15 js-yaml: 4.1.0 - '@ardatan/relay-compiler@12.0.3(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@babel/generator': 7.27.0 - '@babel/parser': 7.27.0 - '@babel/runtime': 7.26.10 - chalk: 4.1.2 - fb-watchman: 2.0.2 - graphql: 16.10.0 - immutable: 3.7.6 - invariant: 2.2.4 - nullthrows: 1.1.1 - relay-runtime: 12.0.0(encoding@0.1.13) - signedsource: 1.0.0 - transitivePeerDependencies: - - encoding - '@ardatan/relay-compiler@12.0.3(encoding@0.1.13)(graphql@16.11.0)': dependencies: '@babel/generator': 7.27.0 @@ -20813,8 +20757,8 @@ snapshots: '@fastify/ajv-compiler@3.6.0': dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) fast-uri: 2.4.0 '@fastify/busboy@3.1.1': {} @@ -20897,11 +20841,11 @@ snapshots: '@gar/promisify@1.1.3': {} - '@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@headlessui/react': 2.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - graphql: 16.10.0 + graphql: 16.11.0 react: 18.3.1 react-compiler-runtime: 19.1.0-rc.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1) @@ -20913,10 +20857,10 @@ snapshots: - '@types/react-dom' - graphql-ws - '@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0) + '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0) react: 18.3.1 react-compiler-runtime: 19.1.0-rc.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1) @@ -20956,9 +20900,9 @@ snapshots: - '@types/react-dom' - graphql-ws - '@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0) + '@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0) '@radix-ui/react-dialog': 1.1.11(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': 2.1.12(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': 1.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -20966,12 +20910,12 @@ snapshots: '@types/codemirror': 5.60.10 clsx: 1.2.1 codemirror: 5.65.15 - codemirror-graphql: 2.2.1(@codemirror/language@6.11.0)(codemirror@5.65.15)(graphql@16.10.0) + codemirror-graphql: 2.2.1(@codemirror/language@6.11.0)(codemirror@5.65.15)(graphql@16.11.0) copy-to-clipboard: 3.3.3 framer-motion: 12.9.5(@emotion/is-prop-valid@1.2.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) get-value: 3.0.1 - graphql: 16.10.0 - graphql-language-service: 5.3.1(graphql@16.10.0) + graphql: 16.11.0 + graphql-language-service: 5.3.1(graphql@16.11.0) markdown-it: 14.1.0 react: 18.3.1 react-compiler-runtime: 19.1.0-rc.1(react@18.3.1) @@ -20985,13 +20929,13 @@ snapshots: - '@types/react-dom' - graphql-ws - '@graphiql/toolkit@0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)': + '@graphiql/toolkit@0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)': dependencies: '@n1ru4l/push-pull-async-iterable-iterator': 3.2.0 - graphql: 16.10.0 + graphql: 16.11.0 meros: 1.3.0(@types/node@22.13.14) optionalDependencies: - graphql-ws: 6.0.4(graphql@16.10.0)(ws@8.18.1) + graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.1) transitivePeerDependencies: - '@types/node' @@ -21005,81 +20949,22 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)': + '@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)': dependencies: '@n1ru4l/push-pull-async-iterable-iterator': 3.2.0 - graphql: 16.10.0 + graphql: 16.11.0 meros: 1.3.0(@types/node@22.13.14) optionalDependencies: - graphql-ws: 6.0.4(graphql@16.10.0)(ws@8.18.1) + graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.1) transitivePeerDependencies: - '@types/node' - '@graphql-codegen/add@5.0.3(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.6.2 - '@graphql-codegen/add@5.0.3(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) graphql: 16.11.0 tslib: 2.6.2 - '@graphql-codegen/cli@5.0.5(@parcel/watcher@2.5.1)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0)(supports-color@8.1.1)(typescript@5.5.2)': - dependencies: - '@babel/generator': 7.27.0 - '@babel/template': 7.27.0 - '@babel/types': 7.27.0 - '@graphql-codegen/client-preset': 4.8.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0) - '@graphql-codegen/core': 4.0.2(graphql@16.10.0) - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-tools/apollo-engine-loader': 8.0.20(graphql@16.10.0) - '@graphql-tools/code-file-loader': 8.1.20(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/git-loader': 8.0.24(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/github-loader': 8.0.20(@types/node@22.13.14)(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/graphql-file-loader': 8.0.19(graphql@16.10.0) - '@graphql-tools/json-file-loader': 8.0.18(graphql@16.10.0) - '@graphql-tools/load': 8.1.0(graphql@16.10.0) - '@graphql-tools/prisma-loader': 8.0.17(@types/node@22.13.14)(encoding@0.1.13)(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/url-loader': 8.0.31(@types/node@22.13.14)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/fetch': 0.10.6 - chalk: 4.1.2 - cosmiconfig: 8.3.6(typescript@5.5.2) - debounce: 1.2.1 - detect-indent: 6.1.0 - graphql: 16.10.0 - graphql-config: 5.1.4(@types/node@22.13.14)(graphql@16.10.0)(typescript@5.5.2) - inquirer: 8.2.6 - is-glob: 4.0.3 - jiti: 1.21.7 - json-to-pretty-yaml: 1.2.2 - listr2: 4.0.5 - log-symbols: 4.1.0 - micromatch: 4.0.8 - shell-quote: 1.8.1 - string-env-interpolation: 1.0.1 - ts-log: 2.2.7 - tslib: 2.8.1 - yaml: 2.4.5 - yargs: 17.7.2 - optionalDependencies: - '@parcel/watcher': 2.5.1 - transitivePeerDependencies: - - '@fastify/websocket' - - '@types/node' - - bufferutil - - cosmiconfig-toml-loader - - encoding - - enquirer - - graphql-sock - - supports-color - - typescript - - uWebSockets.js - - utf-8-validate - '@graphql-codegen/cli@5.0.5(@parcel/watcher@2.5.1)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(supports-color@8.1.1)(typescript@5.5.2)': dependencies: '@babel/generator': 7.27.0 @@ -21133,26 +21018,6 @@ snapshots: - uWebSockets.js - utf-8-validate - '@graphql-codegen/client-preset@4.8.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0)': - dependencies: - '@babel/helper-plugin-utils': 7.26.5 - '@babel/template': 7.27.0 - '@graphql-codegen/add': 5.0.3(graphql@16.10.0) - '@graphql-codegen/gql-tag-operations': 4.0.17(encoding@0.1.13)(graphql@16.10.0) - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/typed-document-node': 5.1.1(encoding@0.1.13)(graphql@16.10.0) - '@graphql-codegen/typescript': 4.1.6(encoding@0.1.13)(graphql@16.10.0) - '@graphql-codegen/typescript-operations': 4.6.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - '@graphql-tools/documents': 1.0.1(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) - graphql: 16.10.0 - graphql-sock: 1.0.1(graphql@16.10.0) - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - '@graphql-codegen/client-preset@4.8.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)': dependencies: '@babel/helper-plugin-utils': 7.26.5 @@ -21173,14 +21038,6 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-codegen/core@4.0.2(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-tools/schema': 10.0.23(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.6.2 - '@graphql-codegen/core@4.0.2(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21189,17 +21046,6 @@ snapshots: graphql: 16.11.0 tslib: 2.6.2 - '@graphql-codegen/gql-tag-operations@4.0.17(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - auto-bind: 4.0.0 - graphql: 16.10.0 - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - '@graphql-codegen/gql-tag-operations@4.0.17(encoding@0.1.13)(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21211,16 +21057,6 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-codegen/plugin-helpers@5.1.0(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - change-case-all: 1.0.15 - common-tags: 1.8.2 - graphql: 16.10.0 - import-from: 4.0.0 - lodash: 4.17.21 - tslib: 2.6.2 - '@graphql-codegen/plugin-helpers@5.1.0(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21231,13 +21067,6 @@ snapshots: lodash: 4.17.21 tslib: 2.6.2 - '@graphql-codegen/schema-ast@4.1.0(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.6.2 - '@graphql-codegen/schema-ast@4.1.0(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21245,17 +21074,6 @@ snapshots: graphql: 16.11.0 tslib: 2.6.2 - '@graphql-codegen/typed-document-node@5.1.1(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - auto-bind: 4.0.0 - change-case-all: 1.0.15 - graphql: 16.10.0 - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - '@graphql-codegen/typed-document-node@5.1.1(encoding@0.1.13)(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21267,18 +21085,6 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-codegen/typescript-operations@4.6.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/typescript': 4.1.6(encoding@0.1.13)(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - auto-bind: 4.0.0 - graphql: 16.10.0 - graphql-sock: 1.0.1(graphql@16.10.0) - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - '@graphql-codegen/typescript-operations@4.6.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21291,26 +21097,15 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-codegen/typescript-resolvers@4.5.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.10.0))(graphql@16.10.0)': + '@graphql-codegen/typescript-resolvers@4.5.0(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)': dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/typescript': 4.1.6(encoding@0.1.13)(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) + '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) + '@graphql-codegen/typescript': 4.1.6(encoding@0.1.13)(graphql@16.11.0) + '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.11.0) + '@graphql-tools/utils': 10.8.6(graphql@16.11.0) auto-bind: 4.0.0 - graphql: 16.10.0 - graphql-sock: 1.0.1(graphql@16.10.0) - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - - '@graphql-codegen/typescript@4.1.6(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-codegen/schema-ast': 4.1.0(graphql@16.10.0) - '@graphql-codegen/visitor-plugin-common': 5.8.0(encoding@0.1.13)(graphql@16.10.0) - auto-bind: 4.0.0 - graphql: 16.10.0 + graphql: 16.11.0 + graphql-sock: 1.0.1(graphql@16.11.0) tslib: 2.6.2 transitivePeerDependencies: - encoding @@ -21326,22 +21121,6 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-codegen/visitor-plugin-common@5.8.0(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.10.0) - '@graphql-tools/optimize': 2.0.0(graphql@16.10.0) - '@graphql-tools/relay-operation-optimizer': 7.0.19(encoding@0.1.13)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - auto-bind: 4.0.0 - change-case-all: 1.0.15 - dependency-graph: 0.11.0 - graphql: 16.10.0 - graphql-tag: 2.12.6(graphql@16.10.0) - parse-filepath: 1.0.2 - tslib: 2.6.2 - transitivePeerDependencies: - - encoding - '@graphql-codegen/visitor-plugin-common@5.8.0(encoding@0.1.13)(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -21360,14 +21139,6 @@ snapshots: '@graphql-hive/signal@1.0.0': {} - '@graphql-tools/apollo-engine-loader@8.0.20(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/fetch': 0.10.6 - graphql: 16.10.0 - sync-fetch: 0.6.0-2 - tslib: 2.8.1 - '@graphql-tools/apollo-engine-loader@8.0.20(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21376,14 +21147,6 @@ snapshots: sync-fetch: 0.6.0-2 tslib: 2.8.1 - '@graphql-tools/batch-execute@9.0.15(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/promise-helpers': 1.3.1 - dataloader: 2.2.3 - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/batch-execute@9.0.15(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21392,17 +21155,6 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/code-file-loader@8.1.20(graphql@16.10.0)(supports-color@8.1.1)': - dependencies: - '@graphql-tools/graphql-tag-pluck': 8.3.19(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - globby: 11.1.0 - graphql: 16.10.0 - tslib: 2.8.1 - unixify: 1.0.0 - transitivePeerDependencies: - - supports-color - '@graphql-tools/code-file-loader@8.1.20(graphql@16.11.0)(supports-color@8.1.1)': dependencies: '@graphql-tools/graphql-tag-pluck': 8.3.19(graphql@16.11.0)(supports-color@8.1.1) @@ -21414,19 +21166,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@graphql-tools/delegate@10.2.17(graphql@16.10.0)': - dependencies: - '@graphql-tools/batch-execute': 9.0.15(graphql@16.10.0) - '@graphql-tools/executor': 1.4.7(graphql@16.10.0) - '@graphql-tools/schema': 10.0.23(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@repeaterjs/repeater': 3.0.6 - '@whatwg-node/promise-helpers': 1.3.1 - dataloader: 2.2.3 - dset: 3.1.4 - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/delegate@10.2.17(graphql@16.11.0)': dependencies: '@graphql-tools/batch-execute': 9.0.15(graphql@16.11.0) @@ -21440,46 +21179,18 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/documents@1.0.1(graphql@16.10.0)': - dependencies: - graphql: 16.10.0 - lodash.sortby: 4.7.0 - tslib: 2.8.1 - '@graphql-tools/documents@1.0.1(graphql@16.11.0)': dependencies: graphql: 16.11.0 lodash.sortby: 4.7.0 tslib: 2.8.1 - '@graphql-tools/executor-common@0.0.4(graphql@16.10.0)': - dependencies: - '@envelop/core': 5.2.3 - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - '@graphql-tools/executor-common@0.0.4(graphql@16.11.0)': dependencies: '@envelop/core': 5.2.3 '@graphql-tools/utils': 10.8.6(graphql@16.11.0) graphql: 16.11.0 - '@graphql-tools/executor-graphql-ws@2.0.5(graphql@16.10.0)': - dependencies: - '@graphql-tools/executor-common': 0.0.4(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/disposablestack': 0.0.6 - graphql: 16.10.0 - graphql-ws: 6.0.4(graphql@16.10.0)(ws@8.18.3) - isomorphic-ws: 5.0.0(ws@8.18.3) - tslib: 2.8.1 - ws: 8.18.3 - transitivePeerDependencies: - - '@fastify/websocket' - - bufferutil - - uWebSockets.js - - utf-8-validate - '@graphql-tools/executor-graphql-ws@2.0.5(graphql@16.11.0)': dependencies: '@graphql-tools/executor-common': 0.0.4(graphql@16.11.0) @@ -21496,21 +21207,6 @@ snapshots: - uWebSockets.js - utf-8-validate - '@graphql-tools/executor-http@1.3.3(@types/node@22.13.14)(graphql@16.10.0)': - dependencies: - '@graphql-hive/signal': 1.0.0 - '@graphql-tools/executor-common': 0.0.4(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@repeaterjs/repeater': 3.0.6 - '@whatwg-node/disposablestack': 0.0.6 - '@whatwg-node/fetch': 0.10.6 - '@whatwg-node/promise-helpers': 1.3.1 - graphql: 16.10.0 - meros: 1.3.0(@types/node@22.13.14) - tslib: 2.8.1 - transitivePeerDependencies: - - '@types/node' - '@graphql-tools/executor-http@1.3.3(@types/node@22.13.14)(graphql@16.11.0)': dependencies: '@graphql-hive/signal': 1.0.0 @@ -21526,18 +21222,6 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@graphql-tools/executor-legacy-ws@1.1.17(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@types/ws': 8.5.10 - graphql: 16.10.0 - isomorphic-ws: 5.0.0(ws@8.18.3) - tslib: 2.8.1 - ws: 8.18.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - '@graphql-tools/executor-legacy-ws@1.1.17(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21550,16 +21234,6 @@ snapshots: - bufferutil - utf-8-validate - '@graphql-tools/executor@1.4.7(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) - '@repeaterjs/repeater': 3.0.6 - '@whatwg-node/disposablestack': 0.0.6 - '@whatwg-node/promise-helpers': 1.3.1 - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/executor@1.4.7(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21570,18 +21244,6 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/git-loader@8.0.24(graphql@16.10.0)(supports-color@8.1.1)': - dependencies: - '@graphql-tools/graphql-tag-pluck': 8.3.19(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - is-glob: 4.0.3 - micromatch: 4.0.8 - tslib: 2.8.1 - unixify: 1.0.0 - transitivePeerDependencies: - - supports-color - '@graphql-tools/git-loader@8.0.24(graphql@16.11.0)(supports-color@8.1.1)': dependencies: '@graphql-tools/graphql-tag-pluck': 8.3.19(graphql@16.11.0)(supports-color@8.1.1) @@ -21594,20 +21256,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@graphql-tools/github-loader@8.0.20(@types/node@22.13.14)(graphql@16.10.0)(supports-color@8.1.1)': - dependencies: - '@graphql-tools/executor-http': 1.3.3(@types/node@22.13.14)(graphql@16.10.0) - '@graphql-tools/graphql-tag-pluck': 8.3.19(graphql@16.10.0)(supports-color@8.1.1) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/fetch': 0.10.6 - '@whatwg-node/promise-helpers': 1.3.1 - graphql: 16.10.0 - sync-fetch: 0.6.0-2 - tslib: 2.8.1 - transitivePeerDependencies: - - '@types/node' - - supports-color - '@graphql-tools/github-loader@8.0.20(@types/node@22.13.14)(graphql@16.11.0)(supports-color@8.1.1)': dependencies: '@graphql-tools/executor-http': 1.3.3(@types/node@22.13.14)(graphql@16.11.0) @@ -21622,15 +21270,6 @@ snapshots: - '@types/node' - supports-color - '@graphql-tools/graphql-file-loader@8.0.19(graphql@16.10.0)': - dependencies: - '@graphql-tools/import': 7.0.18(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - globby: 11.1.0 - graphql: 16.10.0 - tslib: 2.8.1 - unixify: 1.0.0 - '@graphql-tools/graphql-file-loader@8.0.19(graphql@16.11.0)': dependencies: '@graphql-tools/import': 7.0.18(graphql@16.11.0) @@ -21640,19 +21279,6 @@ snapshots: tslib: 2.8.1 unixify: 1.0.0 - '@graphql-tools/graphql-tag-pluck@8.3.19(graphql@16.10.0)(supports-color@8.1.1)': - dependencies: - '@babel/core': 7.26.10(supports-color@8.1.1) - '@babel/parser': 7.27.0 - '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.10(supports-color@8.1.1)) - '@babel/traverse': 7.27.0(supports-color@8.1.1) - '@babel/types': 7.27.0 - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.8.1 - transitivePeerDependencies: - - supports-color - '@graphql-tools/graphql-tag-pluck@8.3.19(graphql@16.11.0)(supports-color@8.1.1)': dependencies: '@babel/core': 7.26.10(supports-color@8.1.1) @@ -21666,13 +21292,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@graphql-tools/import@7.0.18(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - resolve-from: 5.0.0 - tslib: 2.8.1 - '@graphql-tools/import@7.0.18(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21680,14 +21299,6 @@ snapshots: resolve-from: 5.0.0 tslib: 2.8.1 - '@graphql-tools/json-file-loader@8.0.18(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - globby: 11.1.0 - graphql: 16.10.0 - tslib: 2.8.1 - unixify: 1.0.0 - '@graphql-tools/json-file-loader@8.0.18(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) @@ -21696,14 +21307,6 @@ snapshots: tslib: 2.8.1 unixify: 1.0.0 - '@graphql-tools/load@8.1.0(graphql@16.10.0)': - dependencies: - '@graphql-tools/schema': 10.0.23(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - p-limit: 3.1.0 - tslib: 2.8.1 - '@graphql-tools/load@8.1.0(graphql@16.11.0)': dependencies: '@graphql-tools/schema': 10.0.23(graphql@16.11.0) @@ -21712,56 +21315,17 @@ snapshots: p-limit: 3.1.0 tslib: 2.8.1 - '@graphql-tools/merge@9.0.24(graphql@16.10.0)': - dependencies: - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/merge@9.0.24(graphql@16.11.0)': dependencies: '@graphql-tools/utils': 10.8.6(graphql@16.11.0) graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/optimize@2.0.0(graphql@16.10.0)': - dependencies: - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/optimize@2.0.0(graphql@16.11.0)': dependencies: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/prisma-loader@8.0.17(@types/node@22.13.14)(encoding@0.1.13)(graphql@16.10.0)(supports-color@8.1.1)': - dependencies: - '@graphql-tools/url-loader': 8.0.31(@types/node@22.13.14)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@types/js-yaml': 4.0.6 - '@whatwg-node/fetch': 0.10.6 - chalk: 4.1.2 - debug: 4.4.0(supports-color@8.1.1) - dotenv: 16.5.0 - graphql: 16.10.0 - graphql-request: 6.1.0(encoding@0.1.13)(graphql@16.10.0) - http-proxy-agent: 7.0.2(supports-color@8.1.1) - https-proxy-agent: 7.0.6(supports-color@8.1.1) - jose: 5.9.6 - js-yaml: 4.1.0 - lodash: 4.17.21 - scuid: 1.1.0 - tslib: 2.8.1 - yaml-ast-parser: 0.0.43 - transitivePeerDependencies: - - '@fastify/websocket' - - '@types/node' - - bufferutil - - encoding - - supports-color - - uWebSockets.js - - utf-8-validate - '@graphql-tools/prisma-loader@8.0.17(@types/node@22.13.14)(encoding@0.1.13)(graphql@16.11.0)(supports-color@8.1.1)': dependencies: '@graphql-tools/url-loader': 8.0.31(@types/node@22.13.14)(graphql@16.11.0) @@ -21790,15 +21354,6 @@ snapshots: - uWebSockets.js - utf-8-validate - '@graphql-tools/relay-operation-optimizer@7.0.19(encoding@0.1.13)(graphql@16.10.0)': - dependencies: - '@ardatan/relay-compiler': 12.0.3(encoding@0.1.13)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - '@graphql-tools/relay-operation-optimizer@7.0.19(encoding@0.1.13)(graphql@16.11.0)': dependencies: '@ardatan/relay-compiler': 12.0.3(encoding@0.1.13)(graphql@16.11.0) @@ -21808,13 +21363,6 @@ snapshots: transitivePeerDependencies: - encoding - '@graphql-tools/schema@10.0.23(graphql@16.10.0)': - dependencies: - '@graphql-tools/merge': 9.0.24(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/schema@10.0.23(graphql@16.11.0)': dependencies: '@graphql-tools/merge': 9.0.24(graphql@16.11.0) @@ -21822,28 +21370,6 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/url-loader@8.0.31(@types/node@22.13.14)(graphql@16.10.0)': - dependencies: - '@graphql-tools/executor-graphql-ws': 2.0.5(graphql@16.10.0) - '@graphql-tools/executor-http': 1.3.3(@types/node@22.13.14)(graphql@16.10.0) - '@graphql-tools/executor-legacy-ws': 1.1.17(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@graphql-tools/wrap': 10.0.35(graphql@16.10.0) - '@types/ws': 8.5.10 - '@whatwg-node/fetch': 0.10.6 - '@whatwg-node/promise-helpers': 1.3.1 - graphql: 16.10.0 - isomorphic-ws: 5.0.0(ws@8.18.1) - sync-fetch: 0.6.0-2 - tslib: 2.8.1 - ws: 8.18.1 - transitivePeerDependencies: - - '@fastify/websocket' - - '@types/node' - - bufferutil - - uWebSockets.js - - utf-8-validate - '@graphql-tools/url-loader@8.0.31(@types/node@22.13.14)(graphql@16.11.0)': dependencies: '@graphql-tools/executor-graphql-ws': 2.0.5(graphql@16.11.0) @@ -21866,15 +21392,6 @@ snapshots: - uWebSockets.js - utf-8-validate - '@graphql-tools/utils@10.8.6(graphql@16.10.0)': - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) - '@whatwg-node/promise-helpers': 1.3.1 - cross-inspect: 1.0.1 - dset: 3.1.4 - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/utils@10.8.6(graphql@16.11.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) @@ -21884,15 +21401,6 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-tools/wrap@10.0.35(graphql@16.10.0)': - dependencies: - '@graphql-tools/delegate': 10.2.17(graphql@16.10.0) - '@graphql-tools/schema': 10.0.23(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - '@whatwg-node/promise-helpers': 1.3.1 - graphql: 16.10.0 - tslib: 2.8.1 - '@graphql-tools/wrap@10.0.35(graphql@16.11.0)': dependencies: '@graphql-tools/delegate': 10.2.17(graphql@16.11.0) @@ -21902,10 +21410,6 @@ snapshots: graphql: 16.11.0 tslib: 2.8.1 - '@graphql-typed-document-node/core@3.2.0(graphql@16.10.0)': - dependencies: - graphql: 16.10.0 - '@graphql-typed-document-node/core@3.2.0(graphql@16.11.0)': dependencies: graphql: 16.11.0 @@ -21918,8 +21422,8 @@ snapshots: '@sinclair/typebox': 0.31.28 close-with-grace: 1.3.0 crypto-js: 4.2.0 - fastify: 4.29.0 - fastify-metrics: 10.6.0(fastify@4.29.0) + fastify: 4.29.1 + fastify-metrics: 10.6.0(fastify@4.29.1) pg: 8.11.3 pg-connection-string: 2.6.2 pg-format: 1.0.4 @@ -22650,6 +22154,8 @@ snapshots: '@next/env@15.3.1': {} + '@next/env@15.3.3': {} + '@next/eslint-plugin-next@15.3.1': dependencies: fast-glob: 3.3.1 @@ -22668,28 +22174,28 @@ snapshots: '@mdx-js/loader': 2.3.0(supports-color@8.1.1)(webpack@5.94.0) '@mdx-js/react': 2.3.0(react@18.3.1) - '@next/swc-darwin-arm64@15.3.1': + '@next/swc-darwin-arm64@15.3.3': optional: true - '@next/swc-darwin-x64@15.3.1': + '@next/swc-darwin-x64@15.3.3': optional: true - '@next/swc-linux-arm64-gnu@15.3.1': + '@next/swc-linux-arm64-gnu@15.3.3': optional: true - '@next/swc-linux-arm64-musl@15.3.1': + '@next/swc-linux-arm64-musl@15.3.3': optional: true - '@next/swc-linux-x64-gnu@15.3.1': + '@next/swc-linux-x64-gnu@15.3.3': optional: true - '@next/swc-linux-x64-musl@15.3.1': + '@next/swc-linux-x64-musl@15.3.3': optional: true - '@next/swc-win32-arm64-msvc@15.3.1': + '@next/swc-win32-arm64-msvc@15.3.3': optional: true - '@next/swc-win32-x64-msvc@15.3.1': + '@next/swc-win32-x64-msvc@15.3.3': optional: true '@nodelib/fs.scandir@2.1.5': @@ -23625,14 +23131,14 @@ snapshots: '@parcel/watcher-win32-ia32': 2.5.1 '@parcel/watcher-win32-x64': 2.5.1 - '@payloadcms/db-postgres@3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/react@18.3.3)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react@18.3.1)(supports-color@8.1.1)': + '@payloadcms/db-postgres@3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/react@18.3.3)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react@18.3.1)(supports-color@8.1.1)': dependencies: - '@payloadcms/drizzle': 3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(pg@8.11.3)(react@18.3.1) + '@payloadcms/drizzle': 3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(pg@8.11.3)(react@18.3.1) '@types/pg': 8.10.2 console-table-printer: 2.12.1 drizzle-kit: 0.28.0(supports-color@8.1.1) drizzle-orm: 0.36.1(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(pg@8.11.3)(react@18.3.1) - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) pg: 8.11.3 prompts: 2.4.2 to-snake-case: 1.0.0 @@ -23668,11 +23174,11 @@ snapshots: - sqlite3 - supports-color - '@payloadcms/drizzle@3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(pg@8.11.3)(react@18.3.1)': + '@payloadcms/drizzle@3.33.0(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(pg@8.11.3)(react@18.3.1)': dependencies: console-table-printer: 2.12.1 drizzle-orm: 0.36.1(@electric-sql/pglite@0.2.15)(@opentelemetry/api@1.9.0)(@types/pg@8.10.2)(@types/react@18.3.3)(pg@8.11.3)(react@18.3.1) - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) prompts: 2.4.2 to-snake-case: 1.0.0 uuid: 9.0.0 @@ -23707,16 +23213,16 @@ snapshots: - sql.js - sqlite3 - '@payloadcms/email-nodemailer@3.33.0(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))': + '@payloadcms/email-nodemailer@3.33.0(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))': dependencies: nodemailer: 6.9.16 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) - '@payloadcms/graphql@3.33.0(graphql@16.10.0)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(typescript@5.7.3)': + '@payloadcms/graphql@3.33.0(graphql@16.11.0)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(typescript@5.7.3)': dependencies: - graphql: 16.10.0 - graphql-scalars: 1.22.2(graphql@16.10.0) - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + graphql: 16.11.0 + graphql-scalars: 1.22.2(graphql@16.11.0) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) pluralize: 8.0.0 ts-essentials: 10.0.3(typescript@5.7.3) tsx: 4.19.2 @@ -23731,22 +23237,22 @@ snapshots: '@payloadcms/live-preview@3.43.0': {} - '@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.11.0)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: '@dnd-kit/core': 6.0.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@payloadcms/graphql': 3.33.0(graphql@16.10.0)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(typescript@5.7.3) + '@payloadcms/graphql': 3.33.0(graphql@16.11.0)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(typescript@5.7.3) '@payloadcms/translations': 3.33.0 - '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) busboy: 1.6.0 dequal: 2.0.3 file-type: 19.3.0 - graphql: 16.10.0 - graphql-http: 1.22.4(graphql@16.10.0) + graphql: 16.11.0 + graphql-http: 1.22.4(graphql@16.11.0) graphql-playground-html: 1.6.30 http-status: 2.1.0 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) path-to-regexp: 6.3.0 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) qs-esm: 7.0.2 react-diff-viewer-continued: 4.0.5(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1) sass: 1.77.4 @@ -23759,25 +23265,25 @@ snapshots: - supports-color - typescript - '@payloadcms/payload-cloud@3.33.0(encoding@0.1.13)(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))': + '@payloadcms/payload-cloud@3.33.0(encoding@0.1.13)(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))': dependencies: '@aws-sdk/client-cognito-identity': 3.830.0 '@aws-sdk/client-s3': 3.830.0 '@aws-sdk/credential-providers': 3.830.0 '@aws-sdk/lib-storage': 3.830.0(@aws-sdk/client-s3@3.830.0) - '@payloadcms/email-nodemailer': 3.33.0(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3)) + '@payloadcms/email-nodemailer': 3.33.0(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3)) amazon-cognito-identity-js: 6.3.15(encoding@0.1.13) nodemailer: 6.9.16 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) transitivePeerDependencies: - aws-crt - encoding - '@payloadcms/plugin-cloud-storage@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/plugin-cloud-storage@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: - '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) find-node-modules: 2.1.3 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) range-parser: 1.2.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -23788,11 +23294,11 @@ snapshots: - supports-color - typescript - '@payloadcms/plugin-form-builder@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/plugin-form-builder@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: - '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) escape-html: 1.0.3 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -23802,15 +23308,15 @@ snapshots: - supports-color - typescript - '@payloadcms/plugin-nested-docs@3.33.0(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))': + '@payloadcms/plugin-nested-docs@3.33.0(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))': dependencies: - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) - '@payloadcms/plugin-seo@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/plugin-seo@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: '@payloadcms/translations': 3.33.0 - '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -23820,7 +23326,7 @@ snapshots: - supports-color - typescript - '@payloadcms/richtext-lexical@3.33.0(@faceless-ui/modal@3.0.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@faceless-ui/scroll-info@2.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3))(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)(yjs@13.6.27)': + '@payloadcms/richtext-lexical@3.33.0(@faceless-ui/modal@3.0.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@faceless-ui/scroll-info@2.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@payloadcms/next@3.33.0(@types/react@18.3.3)(graphql@16.11.0)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3))(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)(yjs@13.6.27)': dependencies: '@faceless-ui/modal': 3.0.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@faceless-ui/scroll-info': 2.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -23834,9 +23340,9 @@ snapshots: '@lexical/selection': 0.28.0 '@lexical/table': 0.28.0 '@lexical/utils': 0.28.0 - '@payloadcms/next': 3.33.0(@types/react@18.3.3)(graphql@16.10.0)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + '@payloadcms/next': 3.33.0(@types/react@18.3.3)(graphql@16.11.0)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@payloadcms/translations': 3.33.0 - '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + '@payloadcms/ui': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) '@types/uuid': 10.0.0 acorn: 8.12.1 bson-objectid: 2.0.4 @@ -23847,7 +23353,7 @@ snapshots: mdast-util-from-markdown: 2.0.2(supports-color@8.1.1) mdast-util-mdx-jsx: 3.1.3(supports-color@8.1.1) micromark-extension-mdx-jsx: 3.0.1 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) qs-esm: 7.0.2 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -23862,13 +23368,13 @@ snapshots: - typescript - yjs - '@payloadcms/storage-s3@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/storage-s3@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: '@aws-sdk/client-s3': 3.830.0 '@aws-sdk/lib-storage': 3.830.0(@aws-sdk/client-s3@3.830.0) '@aws-sdk/s3-request-presigner': 3.830.0 - '@payloadcms/plugin-cloud-storage': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + '@payloadcms/plugin-cloud-storage': 3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) transitivePeerDependencies: - '@types/react' - aws-crt @@ -23883,7 +23389,7 @@ snapshots: dependencies: date-fns: 4.1.0 - '@payloadcms/ui@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.10.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': + '@payloadcms/ui@3.33.0(@types/react@18.3.3)(monaco-editor@0.52.2)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(payload@3.33.0(graphql@16.11.0)(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1)(typescript@5.7.3)': dependencies: '@date-fns/tz': 1.2.0 '@dnd-kit/core': 6.0.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -23897,9 +23403,9 @@ snapshots: date-fns: 4.1.0 dequal: 2.0.3 md5: 2.3.0 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) object-to-formdata: 4.5.1 - payload: 3.33.0(graphql@16.10.0)(typescript@5.7.3) + payload: 3.33.0(graphql@16.11.0)(typescript@5.7.3) qs-esm: 7.0.2 react: 18.3.1 react-datepicker: 7.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -25639,7 +25145,7 @@ snapshots: colorette: 1.4.0 core-js: 3.35.0 dotenv: 16.5.0 - form-data: 4.0.2 + form-data: 4.0.4 get-port-please: 3.1.2 glob: 7.2.3 handlebars: 4.7.8 @@ -25718,7 +25224,7 @@ snapshots: concat-stream: 2.0.0 cookie: 0.7.2 dotenv: 16.4.5 - form-data: 4.0.0 + form-data: 4.0.4 jest-diff: 29.7.0 jest-matcher-utils: 29.7.0 js-yaml: 4.1.0 @@ -26129,7 +25635,7 @@ snapshots: '@sentry/core@9.15.0': {} - '@sentry/nextjs@8.52.1(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)': + '@sentry/nextjs@8.52.1(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.56.0(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.28.0 @@ -26142,7 +25648,7 @@ snapshots: '@sentry/vercel-edge': 8.52.1 '@sentry/webpack-plugin': 2.22.7(encoding@0.1.13)(supports-color@8.1.1)(webpack@5.94.0) chalk: 3.0.0 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) resolve: 1.22.8 rollup: 3.29.5 stacktrace-parser: 0.1.10 @@ -26155,7 +25661,7 @@ snapshots: - supports-color - webpack - '@sentry/nextjs@9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)': + '@sentry/nextjs@9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.32.0 @@ -26168,7 +25674,7 @@ snapshots: '@sentry/vercel-edge': 9.15.0 '@sentry/webpack-plugin': 3.3.1(encoding@0.1.13)(supports-color@8.1.1)(webpack@5.94.0) chalk: 3.0.0 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) resolve: 1.22.8 rollup: 4.35.0 stacktrace-parser: 0.1.10 @@ -28099,7 +27605,7 @@ snapshots: '@types/graphql-validation-complexity@0.4.4': dependencies: - graphql: 16.10.0 + graphql: 16.11.0 '@types/hast@2.3.6': dependencies: @@ -28183,7 +27689,7 @@ snapshots: '@types/node-fetch@2.6.6': dependencies: '@types/node': 22.13.14 - form-data: 4.0.2 + form-data: 4.0.4 '@types/node@18.18.13': dependencies: @@ -28504,14 +28010,6 @@ snapshots: lz-string: 1.5.0 uuid: 9.0.1 - '@vercel/flags@2.6.3(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - jose: 5.2.1 - optionalDependencies: - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@vercel/functions@2.1.0(@aws-sdk/credential-provider-web-identity@3.830.0)': optionalDependencies: '@aws-sdk/credential-provider-web-identity': 3.830.0 @@ -28966,9 +28464,9 @@ snapshots: optionalDependencies: ajv: 8.17.1 - ajv-formats@3.0.1(ajv@8.12.0): + ajv-formats@3.0.1(ajv@8.17.1): optionalDependencies: - ajv: 8.12.0 + ajv: 8.17.1 ajv-keywords@3.5.2(ajv@6.12.6): dependencies: @@ -29128,7 +28626,7 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.3 es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 is-string: 1.0.7 array-timsort@1.0.3: {} @@ -29189,7 +28687,7 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.3 es-errors: 1.3.0 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 @@ -29274,7 +28772,7 @@ snapshots: axios@1.10.0: dependencies: follow-redirects: 1.15.9 - form-data: 4.0.2 + form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -29406,12 +28904,12 @@ snapshots: widest-line: 4.0.1 wrap-ansi: 8.1.0 - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -29536,14 +29034,14 @@ snapshots: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 set-function-length: 1.2.2 call-bind@1.0.8: dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 set-function-length: 1.2.2 call-bound@1.0.4: @@ -29826,13 +29324,13 @@ snapshots: graphql: 16.11.0 graphql-language-service: 5.2.0(graphql@16.11.0) - codemirror-graphql@2.2.1(@codemirror/language@6.11.0)(codemirror@5.65.15)(graphql@16.10.0): + codemirror-graphql@2.2.1(@codemirror/language@6.11.0)(codemirror@5.65.15)(graphql@16.11.0): dependencies: '@codemirror/language': 6.11.0 '@types/codemirror': 0.0.90 codemirror: 5.65.15 - graphql: 16.10.0 - graphql-language-service: 5.3.1(graphql@16.10.0) + graphql: 16.11.0 + graphql-language-service: 5.3.1(graphql@16.11.0) codemirror@5.65.15: {} @@ -30413,9 +29911,9 @@ snapshots: define-data-property@1.1.4: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 - gopd: 1.0.1 + gopd: 1.2.0 define-lazy-prop@2.0.0: {} @@ -30672,13 +30170,13 @@ snapshots: es-set-tostringtag: 2.1.0 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 get-symbol-description: 1.0.2 globalthis: 1.0.3 gopd: 1.0.1 has-property-descriptors: 1.0.2 has-proto: 1.0.3 - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown: 2.0.2 internal-slot: 1.0.7 is-array-buffer: 3.0.4 @@ -30765,7 +30263,7 @@ snapshots: es-define-property@1.0.0: dependencies: - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 es-define-property@1.0.1: {} @@ -30780,7 +30278,7 @@ snapshots: es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 globalthis: 1.0.4 gopd: 1.2.0 has-property-descriptors: 1.0.2 @@ -31435,8 +30933,8 @@ snapshots: fast-json-stringify@5.16.1: dependencies: '@fastify/merge-json-schemas': 0.1.1 - ajv: 8.12.0 - ajv-formats: 3.0.1(ajv@8.12.0) + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) fast-deep-equal: 3.1.3 fast-uri: 2.4.0 json-schema-ref-resolver: 1.0.1 @@ -31474,15 +30972,15 @@ snapshots: fastest-stable-stringify@2.0.2: {} - fastify-metrics@10.6.0(fastify@4.29.0): + fastify-metrics@10.6.0(fastify@4.29.1): dependencies: - fastify: 4.29.0 + fastify: 4.29.1 fastify-plugin: 4.5.1 prom-client: 14.2.0 fastify-plugin@4.5.1: {} - fastify@4.29.0: + fastify@4.29.1: dependencies: '@fastify/ajv-compiler': 3.6.0 '@fastify/error': 3.4.1 @@ -31618,13 +31116,13 @@ snapshots: micromatch: 4.0.8 resolve-dir: 1.0.1 - flags@4.0.1(@opentelemetry/api@1.9.0)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + flags@4.0.1(@opentelemetry/api@1.9.0)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@edge-runtime/cookies': 5.0.2 jose: 5.9.6 optionalDependencies: '@opentelemetry/api': 1.9.0 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -31661,17 +31159,12 @@ snapshots: form-data-encoder@1.7.2: {} - form-data@4.0.0: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - - form-data@4.0.2: + form-data@4.0.4: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 + hasown: 2.0.2 mime-types: 2.1.35 format@0.2.2: {} @@ -31824,27 +31317,6 @@ snapshots: get-caller-file@2.0.5: {} - get-intrinsic@1.2.4: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - get-intrinsic@1.2.7: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -31883,7 +31355,7 @@ snapshots: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 get-symbol-description@1.1.0: dependencies: @@ -32036,7 +31508,7 @@ snapshots: gopd@1.0.1: dependencies: - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 gopd@1.2.0: {} @@ -32044,12 +31516,12 @@ snapshots: graphemer@1.4.0: {} - graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - graphql: 16.10.0 + '@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + graphql: 16.11.0 react: 18.3.1 react-compiler-runtime: 19.1.0-rc.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1) @@ -32061,28 +31533,6 @@ snapshots: - '@types/react-dom' - graphql-ws - graphql-config@5.1.4(@types/node@22.13.14)(graphql@16.10.0)(typescript@5.5.2): - dependencies: - '@graphql-tools/graphql-file-loader': 8.0.19(graphql@16.10.0) - '@graphql-tools/json-file-loader': 8.0.18(graphql@16.10.0) - '@graphql-tools/load': 8.1.0(graphql@16.10.0) - '@graphql-tools/merge': 9.0.24(graphql@16.10.0) - '@graphql-tools/url-loader': 8.0.31(@types/node@22.13.14)(graphql@16.10.0) - '@graphql-tools/utils': 10.8.6(graphql@16.10.0) - cosmiconfig: 9.0.0(typescript@5.5.2) - graphql: 16.10.0 - jiti: 2.4.2 - minimatch: 10.0.1 - string-env-interpolation: 1.0.1 - tslib: 2.8.1 - transitivePeerDependencies: - - '@fastify/websocket' - - '@types/node' - - bufferutil - - typescript - - uWebSockets.js - - utf-8-validate - graphql-config@5.1.4(@types/node@22.13.14)(graphql@16.11.0)(typescript@5.5.2): dependencies: '@graphql-tools/graphql-file-loader': 8.0.19(graphql@16.11.0) @@ -32105,9 +31555,9 @@ snapshots: - uWebSockets.js - utf-8-validate - graphql-http@1.22.4(graphql@16.10.0): + graphql-http@1.22.4(graphql@16.11.0): dependencies: - graphql: 16.10.0 + graphql: 16.11.0 graphql-language-service@5.2.0(graphql@16.11.0): dependencies: @@ -32115,10 +31565,10 @@ snapshots: nullthrows: 1.1.1 vscode-languageserver-types: 3.17.5 - graphql-language-service@5.3.1(graphql@16.10.0): + graphql-language-service@5.3.1(graphql@16.11.0): dependencies: debounce-promise: 3.1.2 - graphql: 16.10.0 + graphql: 16.11.0 nullthrows: 1.1.1 vscode-languageserver-types: 3.17.5 @@ -32126,14 +31576,6 @@ snapshots: dependencies: xss: 1.0.15 - graphql-request@6.1.0(encoding@0.1.13)(graphql@16.10.0): - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) - cross-fetch: 3.2.0(encoding@0.1.13) - graphql: 16.10.0 - transitivePeerDependencies: - - encoding - graphql-request@6.1.0(encoding@0.1.13)(graphql@16.11.0): dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) @@ -32142,59 +31584,42 @@ snapshots: transitivePeerDependencies: - encoding - graphql-scalars@1.22.2(graphql@16.10.0): + graphql-scalars@1.22.2(graphql@16.11.0): dependencies: - graphql: 16.10.0 + graphql: 16.11.0 tslib: 2.8.1 - graphql-sock@1.0.1(graphql@16.10.0): - dependencies: - graphql: 16.10.0 - graphql-sock@1.0.1(graphql@16.11.0): dependencies: graphql: 16.11.0 - graphql-tag@2.12.6(graphql@16.10.0): - dependencies: - graphql: 16.10.0 - tslib: 2.8.1 - graphql-tag@2.12.6(graphql@16.11.0): dependencies: graphql: 16.11.0 tslib: 2.8.1 - graphql-validation-complexity@0.4.2(graphql@16.10.0): + graphql-validation-complexity@0.4.2(graphql@16.11.0): dependencies: - graphql: 16.10.0 + graphql: 16.11.0 warning: 4.0.3 graphql-ws@5.14.1(graphql@16.11.0): dependencies: graphql: 16.11.0 - graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.1): + graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1): dependencies: - graphql: 16.10.0 + graphql: 16.11.0 optionalDependencies: ws: 8.18.1 optional: true - graphql-ws@6.0.4(graphql@16.10.0)(ws@8.18.3): - dependencies: - graphql: 16.10.0 - optionalDependencies: - ws: 8.18.3 - graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3): dependencies: graphql: 16.11.0 optionalDependencies: ws: 8.18.3 - graphql@16.10.0: {} - graphql@16.11.0: {} gray-matter@2.1.1: @@ -32270,7 +31695,7 @@ snapshots: has-property-descriptors@1.0.2: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 has-proto@1.0.3: {} @@ -32278,8 +31703,6 @@ snapshots: dependencies: dunder-proto: 1.0.1 - has-symbols@1.0.3: {} - has-symbols@1.1.0: {} has-tostringtag@1.0.2: @@ -32858,7 +32281,7 @@ snapshots: is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 is-array-buffer@3.0.5: dependencies: @@ -33076,7 +32499,7 @@ snapshots: is-symbol@1.0.4: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 is-symbol@1.1.1: dependencies: @@ -33202,7 +32625,7 @@ snapshots: dependencies: define-data-property: 1.1.4 es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 get-proto: 1.0.1 has-symbols: 1.1.0 set-function-name: 2.0.2 @@ -33252,8 +32675,6 @@ snapshots: jiti@2.4.2: {} - jose@5.2.1: {} - jose@5.9.6: {} jotai@2.8.1(@types/react@18.3.3)(react@18.3.1): @@ -33312,7 +32733,7 @@ snapshots: decimal.js: 10.5.0 domexception: 4.0.0 escodegen: 2.1.0 - form-data: 4.0.2 + form-data: 4.0.4 html-encoding-sniffer: 3.0.0 http-proxy-agent: 5.0.0(supports-color@8.1.1) https-proxy-agent: 5.0.1(supports-color@8.1.1) @@ -34875,31 +34296,31 @@ snapshots: minimatch@10.0.1: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 1.1.12 minimatch@5.1.6: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@7.4.6: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@8.0.4: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.3: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} @@ -35034,7 +34455,7 @@ snapshots: '@types/cookie': 0.6.0 '@types/statuses': 2.0.5 chalk: 4.1.2 - graphql: 16.10.0 + graphql: 16.11.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 @@ -35056,7 +34477,7 @@ snapshots: '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 '@types/statuses': 2.0.5 - graphql: 16.10.0 + graphql: 16.11.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 @@ -35117,12 +34538,12 @@ snapshots: neo-async@2.6.2: {} - next-contentlayer2@0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1): + next-contentlayer2@0.4.6(contentlayer2@0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1): dependencies: '@contentlayer2/core': 0.4.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1) '@contentlayer2/utils': 0.4.3 contentlayer2: 0.4.6(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1) - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -35131,12 +34552,12 @@ snapshots: - markdown-wasm - supports-color - next-contentlayer2@0.5.3(contentlayer2@0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1): + next-contentlayer2@0.5.3(contentlayer2@0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1))(esbuild@0.25.2)(markdown-wasm@1.2.0)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(supports-color@8.1.1): dependencies: '@contentlayer2/core': 0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1) '@contentlayer2/utils': 0.5.3 contentlayer2: 0.5.3(esbuild@0.25.2)(markdown-wasm@1.2.0)(supports-color@8.1.1) - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -35160,14 +34581,14 @@ snapshots: dependencies: js-yaml-loader: 1.2.2 - next-router-mock@0.9.13(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1): + next-router-mock@0.9.13(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1): dependencies: - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react: 18.3.1 - next-seo@6.5.0(next@15.3.1(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-seo@6.5.0(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -35178,9 +34599,9 @@ snapshots: next-tick@1.1.0: {} - next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4): + next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4): dependencies: - '@next/env': 15.3.1 + '@next/env': 15.3.3 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 @@ -35190,14 +34611,14 @@ snapshots: react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.6(@babel/core@7.26.10(supports-color@8.1.1))(babel-plugin-macros@3.1.0)(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.3.1 - '@next/swc-darwin-x64': 15.3.1 - '@next/swc-linux-arm64-gnu': 15.3.1 - '@next/swc-linux-arm64-musl': 15.3.1 - '@next/swc-linux-x64-gnu': 15.3.1 - '@next/swc-linux-x64-musl': 15.3.1 - '@next/swc-win32-arm64-msvc': 15.3.1 - '@next/swc-win32-x64-msvc': 15.3.1 + '@next/swc-darwin-arm64': 15.3.3 + '@next/swc-darwin-x64': 15.3.3 + '@next/swc-linux-arm64-gnu': 15.3.3 + '@next/swc-linux-arm64-musl': 15.3.3 + '@next/swc-linux-x64-gnu': 15.3.3 + '@next/swc-linux-x64-musl': 15.3.3 + '@next/swc-win32-arm64-msvc': 15.3.3 + '@next/swc-win32-x64-msvc': 15.3.3 '@opentelemetry/api': 1.9.0 '@playwright/test': 1.53.0 sass: 1.77.4 @@ -35501,17 +34922,17 @@ snapshots: number-flow@0.3.7: {} - nuqs@1.19.1(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)): + nuqs@1.19.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)): dependencies: mitt: 3.0.1 - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) - nuqs@2.4.1(next@15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + nuqs@2.4.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react-router@7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: mitt: 3.0.1 react: 18.3.1 optionalDependencies: - next: 15.3.1(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) + next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4) react-router: 7.5.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nwsapi@2.2.20: @@ -35572,7 +34993,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - has-symbols: 1.0.3 + has-symbols: 1.1.0 object-keys: 1.1.1 object.assign@4.1.7: @@ -35949,7 +35370,7 @@ snapshots: pathval@2.0.0: {} - payload@3.33.0(graphql@16.10.0)(typescript@5.7.3): + payload@3.33.0(graphql@16.11.0)(typescript@5.7.3): dependencies: '@next/env': 15.3.1 '@payloadcms/translations': 3.33.0 @@ -35964,7 +35385,7 @@ snapshots: deepmerge: 4.3.1 file-type: 19.3.0 get-tsconfig: 4.8.1 - graphql: 16.10.0 + graphql: 16.11.0 http-status: 2.1.0 image-size: 1.2.1 jose: 5.9.6 @@ -37112,7 +36533,7 @@ snapshots: redoc@2.4.0(core-js@3.35.0)(encoding@0.1.13)(mobx@6.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@6.1.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(supports-color@8.1.1): dependencies: '@redocly/openapi-core': 1.34.1(supports-color@8.1.1) - classnames: 2.3.2 + classnames: 2.5.1 core-js: 3.35.0 decko: 1.2.0 dompurify: 3.2.4 @@ -37127,7 +36548,7 @@ snapshots: path-browserify: 1.0.1 perfect-scrollbar: 1.5.5 polished: 4.2.2 - prismjs: 1.29.0 + prismjs: 1.30.0 prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -37606,15 +37027,15 @@ snapshots: safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 isarray: 2.0.5 safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 call-bound: 1.0.4 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 has-symbols: 1.1.0 isarray: 2.0.5 @@ -37804,8 +37225,8 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 has-property-descriptors: 1.0.2 set-function-name@2.0.2: @@ -38255,7 +37676,7 @@ snapshots: dependencies: '@open-draft/deferred-promise': 2.2.0 dotenv: 16.5.0 - mime-db: 1.53.0 + mime-db: 1.54.0 outvariant: 1.4.3 statuses@2.0.1: {} @@ -38323,7 +37744,7 @@ snapshots: es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 - get-intrinsic: 1.2.7 + get-intrinsic: 1.3.0 gopd: 1.2.0 has-symbols: 1.1.0 internal-slot: 1.1.0 @@ -38357,7 +37778,7 @@ snapshots: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 - es-object-atoms: 1.0.0 + es-object-atoms: 1.1.1 string.prototype.trimend@1.0.8: dependencies: @@ -38376,7 +37797,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-object-atoms: 1.0.0 + es-object-atoms: 1.1.1 string_decoder@1.1.1: dependencies: @@ -39126,7 +38547,7 @@ snapshots: dependencies: call-bind: 1.0.7 for-each: 0.3.3 - gopd: 1.0.1 + gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 @@ -39143,7 +38564,7 @@ snapshots: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 - gopd: 1.0.1 + gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 @@ -39161,7 +38582,7 @@ snapshots: dependencies: call-bind: 1.0.7 for-each: 0.3.3 - gopd: 1.0.1 + gopd: 1.2.0 has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 @@ -39204,7 +38625,7 @@ snapshots: dependencies: call-bind: 1.0.7 has-bigints: 1.0.2 - has-symbols: 1.0.3 + has-symbols: 1.1.0 which-boxed-primitive: 1.0.2 unbox-primitive@1.1.0: @@ -40123,7 +39544,7 @@ snapshots: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 - gopd: 1.0.1 + gopd: 1.2.0 has-tostringtag: 1.0.2 which-typed-array@1.1.19: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 8ebffb10ef1..29c70e50264 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -8,7 +8,7 @@ catalog: '@supabase/auth-js': 2.71.1-rc.1 '@supabase/supabase-js': ^2.47.14 '@supabase/realtime-js': ^2.11.3 - next: 15.3.1 + next: 15.3.3 'react': '^18.3.0' 'react-dom': '^18.3.0' '@types/react': '^18.3.0' diff --git a/supa-mdx-lint/Rule001HeadingCase.toml b/supa-mdx-lint/Rule001HeadingCase.toml index c5afd292546..770ce4ba94f 100644 --- a/supa-mdx-lint/Rule001HeadingCase.toml +++ b/supa-mdx-lint/Rule001HeadingCase.toml @@ -124,6 +124,7 @@ may_uppercase = [ "Llamafile", "Logs Explorer", "Magic Link", + "Mailpit", "Management API", "Mixpeek", "Mixpeek Embed", diff --git a/supa-mdx-lint/Rule003Spelling.toml b/supa-mdx-lint/Rule003Spelling.toml index 449ffc5cf04..c38cdf3637e 100644 --- a/supa-mdx-lint/Rule003Spelling.toml +++ b/supa-mdx-lint/Rule003Spelling.toml @@ -204,6 +204,7 @@ allow_list = [ "Logflare", "Lua", "Mailgun", + "Mailpit", "Mailtrap", "Mansueli", "Metabase", diff --git a/turbo.json b/turbo.json index 0e9c09686f0..c1a8a6dc53f 100644 --- a/turbo.json +++ b/turbo.json @@ -102,7 +102,7 @@ "AI_PRO_MODEL", "AI_NORMAL_MODEL" ], - "passThroughEnv": ["CURRENT_CLI_VERSION"], + "passThroughEnv": ["CURRENT_CLI_VERSION", "VERCEL_GIT_COMMIT_SHA"], "outputs": [".next/**", "!.next/cache/**"] }, "www#build": {