From 01d0035360b5c387113909ce9feeb343ce331a96 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 3 Oct 2024 19:09:20 +0200 Subject: [PATCH 01/59] wip --- .../migrations/20241003131953_deployment.sql | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 supabase/migrations/20241003131953_deployment.sql diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql new file mode 100644 index 00000000..b133bb64 --- /dev/null +++ b/supabase/migrations/20241003131953_deployment.sql @@ -0,0 +1,122 @@ +create extension if not exists moddatetime; + +-- table for deployment providers +create table deployment_providers ( + id bigint primary key generated always as identity, + name text unique not null, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create trigger deployment_providers_updated_at before update on deployment_providers + for each row execute procedure moddatetime (updated_at); + +-- insert the first deployment provider: supabase +insert into deployment_providers (name) values ('Supabase'); + +-- table for storing deployment provider integrations +create table deployment_provider_integrations ( + id bigint primary key generated always as identity, + user_id uuid not null references auth.users(id), + deployment_provider_id bigint references deployment_providers(id), + -- stores the credentials like the refresh token + credentials jsonb, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now(), + unique(user_id, deployment_provider_id) +); + +create trigger deployment_provider_integrations_updated_at before update on deployment_provider_integrations + for each row execute procedure moddatetime (updated_at); + +-- table for storing deployed databases +create table deployed_databases ( + id bigint primary key generated always as identity, + user_id uuid not null references auth.users(id), + local_database_id text not null, + deployment_provider_id bigint not null references deployment_providers(id), + provider_metadata jsonb, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now(), + unique(user_id, local_database_id, deployment_provider_id) +); + +create trigger deployed_databases_updated_at before update on deployed_databases + for each row execute procedure moddatetime (updated_at); + +create type deployment_status as enum ('in_progress', 'success', 'failed'); + +-- table for storing individual deployments +create table deployments ( + id bigint primary key generated always as identity, + deployed_database_id bigint not null references deployed_databases(id), + status deployment_status not null, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create trigger deployments_updated_at before update on deployments + for each row execute procedure moddatetime (updated_at); + +-- Enable RLS on deployment_provider_integrations +alter table deployment_provider_integrations enable row level security; + +-- RLS policies for deployment_provider_integrations +create policy "Users can read their own integrations" + on deployment_provider_integrations for select + using (auth.uid() = user_id); + +create policy "Users can create their own integrations" + on deployment_provider_integrations for insert + with check (auth.uid() = user_id); + +create policy "Users can update their own integrations" + on deployment_provider_integrations for update + using (auth.uid() = user_id) + with check (auth.uid() = user_id); + +create policy "Users can delete their own integrations" + on deployment_provider_integrations for delete + using (auth.uid() = user_id); + +-- Enable RLS on deployed_databases +alter table deployed_databases enable row level security; + +-- RLS policies for deployed_databases +create policy "Users can read their own deployed databases" + on deployed_databases for select + using (auth.uid() = user_id); + +create policy "Users can create their own deployed databases" + on deployed_databases for insert + with check (auth.uid() = user_id); + +create policy "Users can update their own deployed databases" + on deployed_databases for update + using (auth.uid() = user_id) + with check (auth.uid() = user_id); + +create policy "Users can delete their own deployed databases" + on deployed_databases for delete + using (auth.uid() = user_id); + +-- Enable RLS on deployments +alter table deployments enable row level security; + +-- RLS policies for deployments +create policy "Users can read their own deployments" + on deployments for select + using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + +create policy "Users can create their own deployments" + on deployments for insert + with check (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + +create policy "Users can update their own deployments" + on deployments for update + using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)) + with check (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + +create policy "Users can delete their own deployments" + on deployments for delete + using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); \ No newline at end of file From dfdbecb7d09946b492a14fe6111c3c421004126d Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 3 Oct 2024 19:09:30 +0200 Subject: [PATCH 02/59] wip --- apps/postgres-new/app/api/deploy/route.ts | 24 +++++++++++++++++++++++ apps/postgres-new/components/sidebar.tsx | 4 ++-- apps/postgres-new/utils/supabase/admin.ts | 9 +++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 apps/postgres-new/app/api/deploy/route.ts create mode 100644 apps/postgres-new/utils/supabase/admin.ts diff --git a/apps/postgres-new/app/api/deploy/route.ts b/apps/postgres-new/app/api/deploy/route.ts new file mode 100644 index 00000000..2af94df6 --- /dev/null +++ b/apps/postgres-new/app/api/deploy/route.ts @@ -0,0 +1,24 @@ +import { createClient as createAdminClient } from '~/utils/supabase/admin' +import { createClient } from '~/utils/supabase/server' + +export async function POST(req: Request) { + const supabase = createClient() + + const { data, error } = await supabase.auth.getUser() + + // We have middleware, so this should never happen (used for type narrowing) + if (error) { + return new Response('Unauthorized', { status: 401 }) + } + + const { user } = data + + const supabaseAdmin = createAdminClient() + + // get user's refresh token for Supabase + const { data: database, error: databaseError } = await supabaseAdmin + .from('vault') + .select('*') + .eq('id', databaseId) + .single() +} diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index f519eaf4..2cdd1ee9 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -469,8 +469,8 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3" onClick={async (e) => { e.preventDefault() - - setIsDeployDialogOpen(true) + // check is user has a Supabase token, if not do OAuth flow + // initiate Supabase Oauth flow setIsPopoverOpen(false) }} disabled={user === undefined} diff --git a/apps/postgres-new/utils/supabase/admin.ts b/apps/postgres-new/utils/supabase/admin.ts new file mode 100644 index 00000000..fb7e234e --- /dev/null +++ b/apps/postgres-new/utils/supabase/admin.ts @@ -0,0 +1,9 @@ +import { createClient as createSupabaseClient } from '@supabase/supabase-js' +import { Database } from './db-types' + +export function createClient() { + return createSupabaseClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! + ) +} From e388693a7713b9b487d59144e208d03e5fad9ccf Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Mon, 7 Oct 2024 17:47:17 +0200 Subject: [PATCH 03/59] wip --- apps/postgres-new/app/api/deploy/route.ts | 113 ++++++++++++- apps/postgres-new/utils/supabase/db-types.ts | 151 +++++++++++++++++- .../20241007141040_deployment_lock.sql | 44 +++++ 3 files changed, 298 insertions(+), 10 deletions(-) create mode 100644 supabase/migrations/20241007141040_deployment_lock.sql diff --git a/apps/postgres-new/app/api/deploy/route.ts b/apps/postgres-new/app/api/deploy/route.ts index 2af94df6..04605e84 100644 --- a/apps/postgres-new/app/api/deploy/route.ts +++ b/apps/postgres-new/app/api/deploy/route.ts @@ -1,9 +1,9 @@ -import { createClient as createAdminClient } from '~/utils/supabase/admin' import { createClient } from '~/utils/supabase/server' +import { NextResponse } from 'next/server' -export async function POST(req: Request) { - const supabase = createClient() +const supabase = createClient() +export async function POST(req: Request) { const { data, error } = await supabase.auth.getUser() // We have middleware, so this should never happen (used for type narrowing) @@ -13,12 +13,109 @@ export async function POST(req: Request) { const { user } = data - const supabaseAdmin = createAdminClient() + const { providerId, databaseId } = await req.json() - // get user's refresh token for Supabase - const { data: database, error: databaseError } = await supabaseAdmin - .from('vault') + // get provider + const providerResult = await supabase + .from('deployment_providers') .select('*') - .eq('id', databaseId) + .eq('id', providerId) .single() + + if (providerResult.error) { + return NextResponse.json( + { code: 'error_fetching_provider', message: providerResult.error }, + { status: 500 } + ) + } + + // We will eventually support more providers, but for now, we only support Supabase + if (providerResult.data.name !== 'Supabase') { + return NextResponse.json( + { code: 'provider_not_supported', message: 'Provider not supported' }, + { status: 400 } + ) + } + + // Get the user's refresh token for Supabase + const deploymentProviderIntegrationResult = await supabase + .from('deployment_provider_integrations') + .select('id, credentials') + .eq('deployment_provider_id', providerId) + .eq('user_id', user.id) + .maybeSingle() + + if (deploymentProviderIntegrationResult.error) { + return NextResponse.json( + { + code: 'error_fetching_provider_credentials', + message: deploymentProviderIntegrationResult.error, + }, + { status: 500 } + ) + } + + // First time setup, tell the client to initiate the OAuth flow to get the refresh token + if (deploymentProviderIntegrationResult.data === null) { + return NextResponse.json( + { + code: 'oauth_required', + message: 'OAuth flow needs to be initiated', + }, + { status: 428 } + ) + } + + const refreshToken = ( + deploymentProviderIntegrationResult.data.credentials as null | { refreshToken: string } + )?.refreshToken + + if (!refreshToken) { + return NextResponse.json( + { code: 'refresh_token_not_found', message: 'Refresh token not found' }, + { status: 400 } + ) + } + + // exchange the refresh token for an access token + const response = await fetch('https://api.supabase.com/v1/oauth/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + client_id: process.env.NEXT_PUBLIC_SUPABASE_CLIENT_ID!, + client_secret: process.env.SUPABASE_CLIENT_SECRET!, + refresh_token: refreshToken, + }), + }) + + if (response.status >= 400) { + return NextResponse.json( + { code: 'error_exchanging_refresh_token', message: response.statusText }, + { status: response.status } + ) + } + + const refreshTokenResponse = (await response.json()) as { + access_token: string + refresh_token: string + expires_in: number + token_type: 'Bearer' + } + + // Update the refresh token in the database + await supabase + .from('deployment_provider_integrations') + .update({ + credentials: { + refreshToken: refreshTokenResponse.refresh_token, + }, + }) + .eq('id', deploymentProviderIntegrationResult.data.id) + + // TODO: Store the access token in the database as well? + + // Create } diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts index 91b6688f..c1bcc466 100644 --- a/apps/postgres-new/utils/supabase/db-types.ts +++ b/apps/postgres-new/utils/supabase/db-types.ts @@ -60,15 +60,162 @@ export type Database = { }, ] } + deployed_databases: { + Row: { + created_at: string + deployment_provider_id: number + id: number + local_database_id: string + provider_metadata: Json | null + updated_at: string + user_id: string + } + Insert: { + created_at?: string + deployment_provider_id: number + id?: never + local_database_id: string + provider_metadata?: Json | null + updated_at?: string + user_id: string + } + Update: { + created_at?: string + deployment_provider_id?: number + id?: never + local_database_id?: string + provider_metadata?: Json | null + updated_at?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "deployed_databases_deployment_provider_id_fkey" + columns: ["deployment_provider_id"] + isOneToOne: false + referencedRelation: "deployment_providers" + referencedColumns: ["id"] + }, + { + foreignKeyName: "deployed_databases_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + ] + } + deployment_provider_integrations: { + Row: { + created_at: string + credentials: Json | null + deployment_provider_id: number | null + id: number + updated_at: string + user_id: string + } + Insert: { + created_at?: string + credentials?: Json | null + deployment_provider_id?: number | null + id?: never + updated_at?: string + user_id: string + } + Update: { + created_at?: string + credentials?: Json | null + deployment_provider_id?: number | null + id?: never + updated_at?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "deployment_provider_integrations_deployment_provider_id_fkey" + columns: ["deployment_provider_id"] + isOneToOne: false + referencedRelation: "deployment_providers" + referencedColumns: ["id"] + }, + { + foreignKeyName: "deployment_provider_integrations_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + ] + } + deployment_providers: { + Row: { + created_at: string + id: number + name: string + updated_at: string + } + Insert: { + created_at?: string + id?: never + name: string + updated_at?: string + } + Update: { + created_at?: string + id?: never + name?: string + updated_at?: string + } + Relationships: [] + } + deployments: { + Row: { + created_at: string + deployed_database_id: number + id: number + status: Database["public"]["Enums"]["deployment_status"] + updated_at: string + } + Insert: { + created_at?: string + deployed_database_id: number + id?: never + status: Database["public"]["Enums"]["deployment_status"] + updated_at?: string + } + Update: { + created_at?: string + deployed_database_id?: number + id?: never + status?: Database["public"]["Enums"]["deployment_status"] + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "deployments_deployed_database_id_fkey" + columns: ["deployed_database_id"] + isOneToOne: false + referencedRelation: "deployed_databases" + referencedColumns: ["id"] + }, + ] + } } Views: { [_ in never]: never } Functions: { - [_ in never]: never + supabase_functions_certificate_secret: { + Args: Record + Returns: string + } + supabase_url: { + Args: Record + Returns: string + } } Enums: { - [_ in never]: never + deployment_status: "in_progress" | "success" | "failed" } CompositeTypes: { [_ in never]: never diff --git a/supabase/migrations/20241007141040_deployment_lock.sql b/supabase/migrations/20241007141040_deployment_lock.sql new file mode 100644 index 00000000..705bab91 --- /dev/null +++ b/supabase/migrations/20241007141040_deployment_lock.sql @@ -0,0 +1,44 @@ +-- modify the deployment_status enum to include 'expired' +alter type deployment_status add value if not exists 'expired'; + +-- add deployed_at column +alter table deployments add column if not exists deployed_at timestamptz; + +-- add an index to improve query performance +create index if not exists idx_deployments_status_database on deployments (status, deployed_database_id); + +-- function to acquire a deployment lock +create or replace function acquire_deployment_lock( + p_deployed_database_id bigint +) returns bigint as $$ +declare + v_deployment_id bigint; +begin + -- check if there's an in-progress deployment for this database + if exists ( + select 1 from deployments + where deployed_database_id = p_deployed_database_id and status = 'in_progress' + ) then + return null; -- deployment already in progress + end if; + + -- create a new deployment record with 'in_progress' status + insert into deployments (deployed_database_id, status) + values (p_deployed_database_id, 'in_progress') + returning id into v_deployment_id; + + return v_deployment_id; +end; +$$ language plpgsql; + +-- function to clean up expired locks +create or replace function cleanup_expired_deployment_locks() returns void as $$ +begin + update deployments + set status = 'expired' + where status = 'in_progress' and created_at < now() - interval '10 minutes'; +end; +$$ language plpgsql; + +-- schedule the cleanup function to run every 10 minutes +select cron.schedule('*/5 * * * *', 'select cleanup_expired_deployment_locks()'); \ No newline at end of file From c79ac34c7253030c9a3d1591081b6e86e05f9d79 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Mon, 14 Oct 2024 17:20:10 +0200 Subject: [PATCH 04/59] wip --- apps/postgres-new/app/api/deploy/route.ts | 2 +- .../app/api/oauth/callback/route.ts | 47 ++ apps/postgres-new/components/sidebar.tsx | 13 +- package.json | 7 +- pnpm-lock.yaml | 485 ++++++++++++++++++ .../20241007141040_deployment_lock.sql | 44 -- 6 files changed, 548 insertions(+), 50 deletions(-) create mode 100644 apps/postgres-new/app/api/oauth/callback/route.ts create mode 100644 pnpm-lock.yaml delete mode 100644 supabase/migrations/20241007141040_deployment_lock.sql diff --git a/apps/postgres-new/app/api/deploy/route.ts b/apps/postgres-new/app/api/deploy/route.ts index 04605e84..4f51bcf3 100644 --- a/apps/postgres-new/app/api/deploy/route.ts +++ b/apps/postgres-new/app/api/deploy/route.ts @@ -3,7 +3,7 @@ import { NextResponse } from 'next/server' const supabase = createClient() -export async function POST(req: Request) { +export async function GET(req: Request) { const { data, error } = await supabase.auth.getUser() // We have middleware, so this should never happen (used for type narrowing) diff --git a/apps/postgres-new/app/api/oauth/callback/route.ts b/apps/postgres-new/app/api/oauth/callback/route.ts new file mode 100644 index 00000000..10371033 --- /dev/null +++ b/apps/postgres-new/app/api/oauth/callback/route.ts @@ -0,0 +1,47 @@ +import { createClient } from '~/utils/supabase/server' +import { NextRequest, NextResponse } from 'next/server' +import { env } from 'process' + +const supabase = createClient() + +export async function GET(req: NextRequest) { + const { data, error } = await supabase.auth.getUser() + console.log({ data, error }) + // We have middleware, so this should never happen (used for type narrowing) + if (error) { + return new Response('Unauthorized', { status: 401 }) + } + + const { user } = data + + console.log(req.nextUrl.searchParams) + + const code = req.nextUrl.searchParams.get('code') as string | null + + if (!code) { + return new Response('No code provided', { status: 400 }) + } + + const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + redirect_uri: req.nextUrl.origin + '/api/oauth/callback', + }), + }) + + const tokens = (await tokensResponse.json()) as { + access_token: string + refresh_token: string + expires_in: number + token_type: 'Bearer' + } + + return NextResponse.json({ user, tokens }) +} diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 194f215b..6fc29b67 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -489,9 +489,16 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3" onClick={async (e) => { e.preventDefault() - // check is user has a Supabase token, if not do OAuth flow - // initiate Supabase Oauth flow - setIsPopoverOpen(false) + const params = new URLSearchParams({ + client_id: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, + redirect_uri: `${window.location.origin}/api/oauth/callback`, + response_type: 'code', + state: JSON.stringify({ + databaseId: database.id, + }), + }) + window.location.href = + 'https://api.supabase.com/v1/oauth/authorize' + '?' + params.toString() }} disabled={user === undefined} > diff --git a/package.json b/package.json index 04bf2e12..3880706d 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "scripts": { "dev": "npm run dev --workspace postgres-new" }, - "workspaces": ["apps/*"], + "workspaces": [ + "apps/*" + ], "devDependencies": { "supabase": "^1.191.3" - } + }, + "packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..33a05df3 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,485 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + supabase: + specifier: ^1.191.3 + version: 1.204.3 + +packages: + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bin-links@5.0.0: + resolution: {integrity: sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==} + engines: {node: ^18.17.0 || >=20.5.0} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + cmd-shim@7.0.0: + resolution: {integrity: sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==} + engines: {node: ^18.17.0 || >=20.5.0} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + https-proxy-agent@7.0.5: + resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} + engines: {node: '>= 14'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@3.0.1: + resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} + engines: {node: '>= 18'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npm-normalize-package-bin@4.0.0: + resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} + engines: {node: ^18.17.0 || >=20.5.0} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + proc-log@5.0.0: + resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + read-cmd-shim@5.0.0: + resolution: {integrity: sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==} + engines: {node: ^18.17.0 || >=20.5.0} + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + supabase@1.204.3: + resolution: {integrity: sha512-uO09eyAw7TZAX/7wPeieQBWrl4QAJ0WLF+HTkFy35GWBmQULP5nkJR93LcuhSyooYiqwEUKlChEF/PGAEmTCKw==} + engines: {npm: '>=8'} + hasBin: true + + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + write-file-atomic@6.0.0: + resolution: {integrity: sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==} + engines: {node: ^18.17.0 || >=20.5.0} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + +snapshots: + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@pkgjs/parseargs@0.11.0': + optional: true + + agent-base@7.1.1: + dependencies: + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + balanced-match@1.0.2: {} + + bin-links@5.0.0: + dependencies: + cmd-shim: 7.0.0 + npm-normalize-package-bin: 4.0.0 + proc-log: 5.0.0 + read-cmd-shim: 5.0.0 + write-file-atomic: 6.0.0 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + chownr@3.0.0: {} + + cmd-shim@7.0.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@4.0.1: {} + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + eastasianwidth@0.2.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + https-proxy-agent@7.0.5: + dependencies: + agent-base: 7.1.1 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + imurmurhash@0.1.4: {} + + is-fullwidth-code-point@3.0.0: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + lru-cache@10.4.3: {} + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + minizlib@3.0.1: + dependencies: + minipass: 7.1.2 + rimraf: 5.0.10 + + mkdirp@3.0.1: {} + + ms@2.1.3: {} + + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + npm-normalize-package-bin@4.0.0: {} + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + proc-log@5.0.0: {} + + read-cmd-shim@5.0.0: {} + + rimraf@5.0.10: + dependencies: + glob: 10.4.5 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@4.1.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + supabase@1.204.3: + dependencies: + bin-links: 5.0.0 + https-proxy-agent: 7.0.5 + node-fetch: 3.3.2 + tar: 7.4.3 + transitivePeerDependencies: + - supports-color + + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.1 + mkdirp: 3.0.1 + yallist: 5.0.0 + + web-streams-polyfill@3.3.3: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + write-file-atomic@6.0.0: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + yallist@5.0.0: {} diff --git a/supabase/migrations/20241007141040_deployment_lock.sql b/supabase/migrations/20241007141040_deployment_lock.sql deleted file mode 100644 index 705bab91..00000000 --- a/supabase/migrations/20241007141040_deployment_lock.sql +++ /dev/null @@ -1,44 +0,0 @@ --- modify the deployment_status enum to include 'expired' -alter type deployment_status add value if not exists 'expired'; - --- add deployed_at column -alter table deployments add column if not exists deployed_at timestamptz; - --- add an index to improve query performance -create index if not exists idx_deployments_status_database on deployments (status, deployed_database_id); - --- function to acquire a deployment lock -create or replace function acquire_deployment_lock( - p_deployed_database_id bigint -) returns bigint as $$ -declare - v_deployment_id bigint; -begin - -- check if there's an in-progress deployment for this database - if exists ( - select 1 from deployments - where deployed_database_id = p_deployed_database_id and status = 'in_progress' - ) then - return null; -- deployment already in progress - end if; - - -- create a new deployment record with 'in_progress' status - insert into deployments (deployed_database_id, status) - values (p_deployed_database_id, 'in_progress') - returning id into v_deployment_id; - - return v_deployment_id; -end; -$$ language plpgsql; - --- function to clean up expired locks -create or replace function cleanup_expired_deployment_locks() returns void as $$ -begin - update deployments - set status = 'expired' - where status = 'in_progress' and created_at < now() - interval '10 minutes'; -end; -$$ language plpgsql; - --- schedule the cleanup function to run every 10 minutes -select cron.schedule('*/5 * * * *', 'select cleanup_expired_deployment_locks()'); \ No newline at end of file From 9116fef526dba1516babff6128e4bd87fa453f0b Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Mon, 14 Oct 2024 19:03:27 +0200 Subject: [PATCH 05/59] refresh + access token --- .../app/api/oauth/callback/route.ts | 5 +- apps/postgres-new/package.json | 2 +- package-lock.json | 16 +- pnpm-lock.yaml | 485 ------------------ 4 files changed, 11 insertions(+), 497 deletions(-) delete mode 100644 pnpm-lock.yaml diff --git a/apps/postgres-new/app/api/oauth/callback/route.ts b/apps/postgres-new/app/api/oauth/callback/route.ts index 10371033..c3b41763 100644 --- a/apps/postgres-new/app/api/oauth/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/callback/route.ts @@ -1,10 +1,9 @@ import { createClient } from '~/utils/supabase/server' import { NextRequest, NextResponse } from 'next/server' -import { env } from 'process' - -const supabase = createClient() export async function GET(req: NextRequest) { + const supabase = createClient() + const { data, error } = await supabase.auth.getUser() console.log({ data, error }) // We have middleware, so this should never happen (used for type narrowing) diff --git a/apps/postgres-new/package.json b/apps/postgres-new/package.json index 45ef309c..12cf6836 100644 --- a/apps/postgres-new/package.json +++ b/apps/postgres-new/package.json @@ -24,7 +24,7 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", - "@std/tar": "npm:@jsr/std__tar@^0.1.1", + "@std/tar": "npm:@jsr/std__tar@^0.1.2", "@supabase/postgres-meta": "^0.81.2", "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.45.0", diff --git a/package-lock.json b/package-lock.json index efb0fa42..b3e720d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,7 +92,7 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", - "@std/tar": "npm:@jsr/std__tar@^0.1.1", + "@std/tar": "npm:@jsr/std__tar@^0.1.2", "@supabase/postgres-meta": "^0.81.2", "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.45.0", @@ -1677,9 +1677,9 @@ "integrity": "sha512-bkZ1rllRB1qsxFbPqtO1VAYTW2+3ZDmf6pcy8xihKS33r0Z1ly6/E/5DoapnJsNy05LdnANUySWt5kj/awgGdg==" }, "node_modules/@jsr/std__streams": { - "version": "1.0.6", - "resolved": "https://npm.jsr.io/~/11/@jsr/std__streams/1.0.6.tgz", - "integrity": "sha512-dY+/k1K6AAp3xcygUthkl+6CwMA0f/bwMzRbK0SvTb/Ub6Ze7s2fQnux/e1k8N6T549RmRLEhgFp1hmj594kAQ==", + "version": "1.0.7", + "resolved": "https://npm.jsr.io/~/11/@jsr/std__streams/1.0.7.tgz", + "integrity": "sha512-zDtVENagtl34HPDwU+NJGNxbXw2xP5WV54b16bGTMd+Qanhc7hBGSvDu1rteG/DZaivVdyiPq6Ix4BzUNVAPXA==", "dependencies": { "@jsr/std__bytes": "^1.0.2" } @@ -3471,11 +3471,11 @@ }, "node_modules/@std/tar": { "name": "@jsr/std__tar", - "version": "0.1.1", - "resolved": "https://npm.jsr.io/~/11/@jsr/std__tar/0.1.1.tgz", - "integrity": "sha512-AJfCoLwz1Alme/nzrIAPTFdVNuLO5F6H49aH5/HIpGcC18muOP/LayvLRH4tiJVQJ6j/eRb4/D8+uciED9kCIA==", + "version": "0.1.2", + "resolved": "https://npm.jsr.io/~/11/@jsr/std__tar/0.1.2.tgz", + "integrity": "sha512-l864xcDhhpJHsD7X4XzU1pUeAEH6RRe/zAh21PAQd9LJsJk/9jEGi3l2YWHEY4qLLLX5Gs9L6+66h2ddjoUv9A==", "dependencies": { - "@jsr/std__streams": "^1.0.5" + "@jsr/std__streams": "^1.0.7" } }, "node_modules/@supabase/auth-js": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 33a05df3..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,485 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - supabase: - specifier: ^1.191.3 - version: 1.204.3 - -packages: - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@isaacs/fs-minipass@4.0.1': - resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} - engines: {node: '>=18.0.0'} - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - agent-base@7.1.1: - resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} - engines: {node: '>= 14'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - bin-links@5.0.0: - resolution: {integrity: sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==} - engines: {node: ^18.17.0 || >=20.5.0} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - chownr@3.0.0: - resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} - engines: {node: '>=18'} - - cmd-shim@7.0.0: - resolution: {integrity: sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==} - engines: {node: ^18.17.0 || >=20.5.0} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} - engines: {node: '>=14'} - - formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - - https-proxy-agent@7.0.5: - resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} - engines: {node: '>= 14'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@3.0.1: - resolution: {integrity: sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==} - engines: {node: '>= 18'} - - mkdirp@3.0.1: - resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} - engines: {node: '>=10'} - hasBin: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - - node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - npm-normalize-package-bin@4.0.0: - resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==} - engines: {node: ^18.17.0 || >=20.5.0} - - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - proc-log@5.0.0: - resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==} - engines: {node: ^18.17.0 || >=20.5.0} - - read-cmd-shim@5.0.0: - resolution: {integrity: sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==} - engines: {node: ^18.17.0 || >=20.5.0} - - rimraf@5.0.10: - resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - supabase@1.204.3: - resolution: {integrity: sha512-uO09eyAw7TZAX/7wPeieQBWrl4QAJ0WLF+HTkFy35GWBmQULP5nkJR93LcuhSyooYiqwEUKlChEF/PGAEmTCKw==} - engines: {npm: '>=8'} - hasBin: true - - tar@7.4.3: - resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} - engines: {node: '>=18'} - - web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - write-file-atomic@6.0.0: - resolution: {integrity: sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==} - engines: {node: ^18.17.0 || >=20.5.0} - - yallist@5.0.0: - resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} - engines: {node: '>=18'} - -snapshots: - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@isaacs/fs-minipass@4.0.1': - dependencies: - minipass: 7.1.2 - - '@pkgjs/parseargs@0.11.0': - optional: true - - agent-base@7.1.1: - dependencies: - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - - ansi-regex@5.0.1: {} - - ansi-regex@6.1.0: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.1: {} - - balanced-match@1.0.2: {} - - bin-links@5.0.0: - dependencies: - cmd-shim: 7.0.0 - npm-normalize-package-bin: 4.0.0 - proc-log: 5.0.0 - read-cmd-shim: 5.0.0 - write-file-atomic: 6.0.0 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - chownr@3.0.0: {} - - cmd-shim@7.0.0: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - data-uri-to-buffer@4.0.1: {} - - debug@4.3.7: - dependencies: - ms: 2.1.3 - - eastasianwidth@0.2.0: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - fetch-blob@3.2.0: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - - foreground-child@3.3.0: - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - - formdata-polyfill@4.0.10: - dependencies: - fetch-blob: 3.2.0 - - glob@10.4.5: - dependencies: - foreground-child: 3.3.0 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - https-proxy-agent@7.0.5: - dependencies: - agent-base: 7.1.1 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - - imurmurhash@0.1.4: {} - - is-fullwidth-code-point@3.0.0: {} - - isexe@2.0.0: {} - - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - lru-cache@10.4.3: {} - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minipass@7.1.2: {} - - minizlib@3.0.1: - dependencies: - minipass: 7.1.2 - rimraf: 5.0.10 - - mkdirp@3.0.1: {} - - ms@2.1.3: {} - - node-domexception@1.0.0: {} - - node-fetch@3.3.2: - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - - npm-normalize-package-bin@4.0.0: {} - - package-json-from-dist@1.0.1: {} - - path-key@3.1.1: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - proc-log@5.0.0: {} - - read-cmd-shim@5.0.0: {} - - rimraf@5.0.10: - dependencies: - glob: 10.4.5 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - signal-exit@4.1.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - - supabase@1.204.3: - dependencies: - bin-links: 5.0.0 - https-proxy-agent: 7.0.5 - node-fetch: 3.3.2 - tar: 7.4.3 - transitivePeerDependencies: - - supports-color - - tar@7.4.3: - dependencies: - '@isaacs/fs-minipass': 4.0.1 - chownr: 3.0.0 - minipass: 7.1.2 - minizlib: 3.0.1 - mkdirp: 3.0.1 - yallist: 5.0.0 - - web-streams-polyfill@3.3.3: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - - write-file-atomic@6.0.0: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 4.1.0 - - yallist@5.0.0: {} From 0c92415062025a486b7d90beee92880e222585dc Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 16 Oct 2024 12:43:41 +0200 Subject: [PATCH 06/59] wip --- apps/postgres-new/app/api/deploy/route.ts | 121 ---------------- .../app/api/oauth/callback/route.ts | 46 ------ .../app/api/oauth/supabase/callback/route.ts | 135 ++++++++++++++++++ .../app/deploy/[databaseId]/page.tsx | 49 +++++++ apps/postgres-new/components/app-provider.tsx | 6 +- apps/postgres-new/components/sidebar.tsx | 52 +++++-- apps/postgres-new/utils/supabase/db-types.ts | 41 +++++- .../migrations/20241003131953_deployment.sql | 72 +++++++++- 8 files changed, 335 insertions(+), 187 deletions(-) delete mode 100644 apps/postgres-new/app/api/deploy/route.ts delete mode 100644 apps/postgres-new/app/api/oauth/callback/route.ts create mode 100644 apps/postgres-new/app/api/oauth/supabase/callback/route.ts create mode 100644 apps/postgres-new/app/deploy/[databaseId]/page.tsx diff --git a/apps/postgres-new/app/api/deploy/route.ts b/apps/postgres-new/app/api/deploy/route.ts deleted file mode 100644 index 4f51bcf3..00000000 --- a/apps/postgres-new/app/api/deploy/route.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { createClient } from '~/utils/supabase/server' -import { NextResponse } from 'next/server' - -const supabase = createClient() - -export async function GET(req: Request) { - const { data, error } = await supabase.auth.getUser() - - // We have middleware, so this should never happen (used for type narrowing) - if (error) { - return new Response('Unauthorized', { status: 401 }) - } - - const { user } = data - - const { providerId, databaseId } = await req.json() - - // get provider - const providerResult = await supabase - .from('deployment_providers') - .select('*') - .eq('id', providerId) - .single() - - if (providerResult.error) { - return NextResponse.json( - { code: 'error_fetching_provider', message: providerResult.error }, - { status: 500 } - ) - } - - // We will eventually support more providers, but for now, we only support Supabase - if (providerResult.data.name !== 'Supabase') { - return NextResponse.json( - { code: 'provider_not_supported', message: 'Provider not supported' }, - { status: 400 } - ) - } - - // Get the user's refresh token for Supabase - const deploymentProviderIntegrationResult = await supabase - .from('deployment_provider_integrations') - .select('id, credentials') - .eq('deployment_provider_id', providerId) - .eq('user_id', user.id) - .maybeSingle() - - if (deploymentProviderIntegrationResult.error) { - return NextResponse.json( - { - code: 'error_fetching_provider_credentials', - message: deploymentProviderIntegrationResult.error, - }, - { status: 500 } - ) - } - - // First time setup, tell the client to initiate the OAuth flow to get the refresh token - if (deploymentProviderIntegrationResult.data === null) { - return NextResponse.json( - { - code: 'oauth_required', - message: 'OAuth flow needs to be initiated', - }, - { status: 428 } - ) - } - - const refreshToken = ( - deploymentProviderIntegrationResult.data.credentials as null | { refreshToken: string } - )?.refreshToken - - if (!refreshToken) { - return NextResponse.json( - { code: 'refresh_token_not_found', message: 'Refresh token not found' }, - { status: 400 } - ) - } - - // exchange the refresh token for an access token - const response = await fetch('https://api.supabase.com/v1/oauth/token', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: new URLSearchParams({ - grant_type: 'refresh_token', - client_id: process.env.NEXT_PUBLIC_SUPABASE_CLIENT_ID!, - client_secret: process.env.SUPABASE_CLIENT_SECRET!, - refresh_token: refreshToken, - }), - }) - - if (response.status >= 400) { - return NextResponse.json( - { code: 'error_exchanging_refresh_token', message: response.statusText }, - { status: response.status } - ) - } - - const refreshTokenResponse = (await response.json()) as { - access_token: string - refresh_token: string - expires_in: number - token_type: 'Bearer' - } - - // Update the refresh token in the database - await supabase - .from('deployment_provider_integrations') - .update({ - credentials: { - refreshToken: refreshTokenResponse.refresh_token, - }, - }) - .eq('id', deploymentProviderIntegrationResult.data.id) - - // TODO: Store the access token in the database as well? - - // Create -} diff --git a/apps/postgres-new/app/api/oauth/callback/route.ts b/apps/postgres-new/app/api/oauth/callback/route.ts deleted file mode 100644 index c3b41763..00000000 --- a/apps/postgres-new/app/api/oauth/callback/route.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { createClient } from '~/utils/supabase/server' -import { NextRequest, NextResponse } from 'next/server' - -export async function GET(req: NextRequest) { - const supabase = createClient() - - const { data, error } = await supabase.auth.getUser() - console.log({ data, error }) - // We have middleware, so this should never happen (used for type narrowing) - if (error) { - return new Response('Unauthorized', { status: 401 }) - } - - const { user } = data - - console.log(req.nextUrl.searchParams) - - const code = req.nextUrl.searchParams.get('code') as string | null - - if (!code) { - return new Response('No code provided', { status: 400 }) - } - - const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', - Authorization: `Basic ${btoa(`${process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, - }, - body: new URLSearchParams({ - grant_type: 'authorization_code', - code, - redirect_uri: req.nextUrl.origin + '/api/oauth/callback', - }), - }) - - const tokens = (await tokensResponse.json()) as { - access_token: string - refresh_token: string - expires_in: number - token_type: 'Bearer' - } - - return NextResponse.json({ user, tokens }) -} diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts new file mode 100644 index 00000000..de069f3b --- /dev/null +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -0,0 +1,135 @@ +import { createClient } from '~/utils/supabase/server' +import { createClient as createAdminClient } from '~/utils/supabase/admin' +import { NextRequest, NextResponse } from 'next/server' + +export async function GET(req: NextRequest) { + const supabase = createClient() + + const { data, error } = await supabase.auth.getUser() + + // We have middleware, so this should never happen (used for type narrowing) + if (error) { + return new Response('Unauthorized', { status: 401 }) + } + + const { user } = data + + const code = req.nextUrl.searchParams.get('code') as string | null + + if (!code) { + return new Response('No code provided', { status: 400 }) + } + + const stateParam = req.nextUrl.searchParams.get('state') + + if (!stateParam) { + return new Response('No state provided', { status: 400 }) + } + + const state = JSON.parse(stateParam) + + if (!state.databaseId) { + return new Response('No database id provided', { status: 400 }) + } + + const now = Date.now() + + // get tokens + const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', + }), + }) + + const tokens = (await tokensResponse.json()) as { + access_token: string + refresh_token: string + // usually 86400 seconds = 1 day + expires_in: number + token_type: 'Bearer' + } + + // get org + const [org] = (await fetch('https://api.supabase.com/v1/organizations', { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${tokens.access_token}`, + }, + }).then((res) => res.json())) as { + id: string + name: string + }[] + + const adminClient = createAdminClient() + + // store the tokens as secrets + const { data: refreshTokenSecretId, error: refreshTokenSecretError } = await adminClient.rpc( + 'insert_secret', + { + name: `supabase_oauth_refresh_token_${org.id}`, + secret: tokens.refresh_token, + } + ) + + if (refreshTokenSecretError) { + return new Response('Failed to store refresh token as secret', { status: 500 }) + } + const { data: accessTokenSecretId, error: accessTokenSecretError } = await adminClient.rpc( + 'insert_secret', + { + name: `supabase_oauth_access_token_${org.id}`, + secret: tokens.access_token, + } + ) + + if (accessTokenSecretError) { + return new Response('Failed to store access token as secret', { status: 500 }) + } + + // store the credentials and relevant metadata + const { data: deploymentProvider, error: deploymentProviderError } = await supabase + .from('deployment_providers') + .select('id') + .eq('name', 'Supabase') + .single() + + if (deploymentProviderError) { + return new Response('Failed to get deployment provider', { status: 500 }) + } + + const integration = await supabase + .from('deployment_provider_integrations') + .insert({ + user_id: user.id, + deployment_provider_id: deploymentProvider.id, + credentials: { + accessToken: accessTokenSecretId, + expiresAt: new Date(now + tokens.expires_in * 1000).toISOString(), + refreshToken: refreshTokenSecretId, + }, + scope: { + organizationId: org.id, + }, + }) + .select('id') + .single() + + if (integration.error) { + return new Response('Failed to create integration', { status: 500 }) + } + + const params = new URLSearchParams({ + integration: integration.data.id.toString(), + }) + + return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) +} diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx new file mode 100644 index 00000000..b734e17e --- /dev/null +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -0,0 +1,49 @@ +'use client' + +import { useRouter } from 'next/navigation' +import { useEffect } from 'react' +import { useApp } from '~/components/app-provider' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' + +export default function Page({ params }: { params: { databaseId: string } }) { + const databaseId = params.databaseId + const router = useRouter() + const { dbManager, liveShare } = useApp() + + useEffect(() => { + async function run() { + if (!dbManager) { + throw new Error('dbManager is not available') + } + + try { + await dbManager.getDbInstance(databaseId) + } catch (err) { + router.push('/') + } + + // make the database available to the deployment worker + const databaseUrl = await liveShare.start(databaseId) + + // trigger deployment + } + run() + return () => { + liveShare.stop() + } + }, [dbManager, databaseId, router, liveShare]) + + return ( + + + + Deploying your database +
+ +
+

Your database is being deployed. Please do not close this page.

+
+ +
+ ) +} diff --git a/apps/postgres-new/components/app-provider.tsx b/apps/postgres-new/components/app-provider.tsx index df9358d8..df43accd 100644 --- a/apps/postgres-new/components/app-provider.tsx +++ b/apps/postgres-new/components/app-provider.tsx @@ -193,6 +193,10 @@ export default function AppProvider({ children }: AppProps) { } setLiveShareWebsocket(ws) + + const databaseUrl = `postgres://postgres@${databaseHostname}/postgres?sslmode=require` + + return databaseUrl }, [cleanUp, supabase.auth] ) @@ -268,7 +272,7 @@ export type AppContextValues = { pgliteVersion?: string pgVersion?: string liveShare: { - start: (databaseId: string) => Promise + start: (databaseId: string) => Promise stop: () => void databaseId: string | null clientIp: string | null diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 6fc29b67..a1f7bb0f 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -43,6 +43,7 @@ import { } from './ui/dropdown-menu' import { TooltipPortal } from '@radix-ui/react-tooltip' import { LiveShareIcon } from './live-share-icon' +import { createClient } from '~/utils/supabase/client' export default function Sidebar() { const { @@ -489,16 +490,51 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { className="bg-inherit justify-start hover:bg-neutral-200 flex gap-3" onClick={async (e) => { e.preventDefault() + const supabase = createClient() + const { data: provider, error: providerError } = await supabase + .from('deployment_providers') + .select('id') + .eq('name', 'Supabase') + .single() + + if (providerError) { + console.error(providerError) + return + } + + // check existing integration, we currently assume a single integration per user and provider + // later we will allow for multiple integrations per provider with different scopes + const { data: integration, error: integrationError } = await supabase + .from('deployment_provider_integrations') + .select('id') + .eq('deployment_provider_id', provider.id) + .eq('user_id', user!.id) + .maybeSingle() + + if (integrationError) { + console.error(integrationError) + return + } + + if (!integration) { + const params = new URLSearchParams({ + client_id: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, + redirect_uri: `${window.location.origin}/api/oauth/supabase/callback`, + response_type: 'code', + state: JSON.stringify({ + databaseId: database.id, + }), + }) + window.location.href = + 'https://api.supabase.com/v1/oauth/authorize' + '?' + params.toString() + return + } + const params = new URLSearchParams({ - client_id: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, - redirect_uri: `${window.location.origin}/api/oauth/callback`, - response_type: 'code', - state: JSON.stringify({ - databaseId: database.id, - }), + integration: integration.id.toString(), }) - window.location.href = - 'https://api.supabase.com/v1/oauth/authorize' + '?' + params.toString() + + router.push(`/deploy/${database.id}?${params.toString()}`) }} disabled={user === undefined} > diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts index c1bcc466..10dd9d41 100644 --- a/apps/postgres-new/utils/supabase/db-types.ts +++ b/apps/postgres-new/utils/supabase/db-types.ts @@ -66,7 +66,7 @@ export type Database = { deployment_provider_id: number id: number local_database_id: string - provider_metadata: Json | null + provider_metadata: Json updated_at: string user_id: string } @@ -75,7 +75,7 @@ export type Database = { deployment_provider_id: number id?: never local_database_id: string - provider_metadata?: Json | null + provider_metadata?: Json updated_at?: string user_id: string } @@ -84,7 +84,7 @@ export type Database = { deployment_provider_id?: number id?: never local_database_id?: string - provider_metadata?: Json | null + provider_metadata?: Json updated_at?: string user_id?: string } @@ -108,25 +108,28 @@ export type Database = { deployment_provider_integrations: { Row: { created_at: string - credentials: Json | null + credentials: Json deployment_provider_id: number | null id: number + scope: Json updated_at: string user_id: string } Insert: { created_at?: string - credentials?: Json | null + credentials: Json deployment_provider_id?: number | null id?: never + scope?: Json updated_at?: string user_id: string } Update: { created_at?: string - credentials?: Json | null + credentials?: Json deployment_provider_id?: number | null id?: never + scope?: Json updated_at?: string user_id?: string } @@ -205,6 +208,25 @@ export type Database = { [_ in never]: never } Functions: { + delete_secret: { + Args: { + secret_id: string + } + Returns: string + } + insert_secret: { + Args: { + secret: string + name: string + } + Returns: string + } + read_secret: { + Args: { + secret_id: string + } + Returns: string + } supabase_functions_certificate_secret: { Args: Record Returns: string @@ -213,6 +235,13 @@ export type Database = { Args: Record Returns: string } + update_secret: { + Args: { + secret_id: string + new_secret: string + } + Returns: string + } } Enums: { deployment_status: "in_progress" | "success" | "failed" diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index b133bb64..b42729af 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -19,11 +19,11 @@ create table deployment_provider_integrations ( id bigint primary key generated always as identity, user_id uuid not null references auth.users(id), deployment_provider_id bigint references deployment_providers(id), - -- stores the credentials like the refresh token - credentials jsonb, + scope jsonb not null default '{}'::jsonb, + credentials jsonb not null, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), - unique(user_id, deployment_provider_id) + unique(user_id, deployment_provider_id, scope) ); create trigger deployment_provider_integrations_updated_at before update on deployment_provider_integrations @@ -35,7 +35,7 @@ create table deployed_databases ( user_id uuid not null references auth.users(id), local_database_id text not null, deployment_provider_id bigint not null references deployment_providers(id), - provider_metadata jsonb, + provider_metadata jsonb not null default '{}'::jsonb, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique(user_id, local_database_id, deployment_provider_id) @@ -119,4 +119,66 @@ create policy "Users can update their own deployments" create policy "Users can delete their own deployments" on deployments for delete - using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); \ No newline at end of file + using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + +create or replace function insert_secret(secret text, name text) +returns uuid +language plpgsql +security definer +set search_path = public +as $$ +begin + if current_setting('role') != 'service_role' then + raise exception 'authentication required'; + end if; + + return vault.create_secret(secret, name); +end; +$$; + +create or replace function update_secret(secret_id uuid, new_secret text) +returns text +language plpgsql +security definer +set search_path = public +as $$ +begin + if current_setting('role') != 'service_role' then + raise exception 'authentication required'; + end if; + + return vault.update_secret(secret_id, new_secret); +end; +$$; + +create function read_secret(secret_id uuid) +returns text +language plpgsql +security definer set search_path = public +as $$ +declare + secret text; +begin + if current_setting('role') != 'service_role' then + raise exception 'authentication required'; + end if; + + select decrypted_secret from vault.decrypted_secrets where id = + secret_id into secret; + return secret; +end; +$$; + +create function delete_secret(secret_id uuid) +returns text +language plpgsql +security definer set search_path = public +as $$ +begin + if current_setting('role') != 'service_role' then + raise exception 'authentication required'; + end if; + + return delete from vault.decrypted_secrets where id = secret_id; +end; +$$; \ No newline at end of file From 43df57c1c91b67579d99adc10a6144c2e21e5321 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 16 Oct 2024 19:08:11 +0200 Subject: [PATCH 07/59] wip --- apps/deploy-worker/.gitignore | 28 ++ apps/deploy-worker/Dockerfile | 15 + apps/deploy-worker/README.md | 8 + apps/deploy-worker/fly.toml | 23 ++ apps/deploy-worker/package.json | 25 ++ apps/deploy-worker/src/debug.ts | 3 + apps/deploy-worker/src/index.ts | 66 ++++ apps/deploy-worker/src/supabase/client.ts | 11 + apps/deploy-worker/src/supabase/db-types.ts | 326 ++++++++++++++++++ apps/deploy-worker/src/supabase/deploy.ts | 147 ++++++++ .../src/supabase/generate-password.ts | 10 + apps/deploy-worker/src/supabase/oauth.ts | 78 +++++ apps/deploy-worker/src/supabase/types.ts | 38 ++ .../supabase/wait-for-database-to-be-ready.ts | 61 ++++ apps/deploy-worker/tsconfig.json | 9 + .../app/api/oauth/supabase/callback/route.ts | 1 - apps/postgres-new/utils/supabase/db-types.ts | 24 +- package-lock.json | 81 +++++ .../migrations/20241003131953_deployment.sql | 48 ++- 19 files changed, 969 insertions(+), 33 deletions(-) create mode 100644 apps/deploy-worker/.gitignore create mode 100644 apps/deploy-worker/Dockerfile create mode 100644 apps/deploy-worker/README.md create mode 100644 apps/deploy-worker/fly.toml create mode 100644 apps/deploy-worker/package.json create mode 100644 apps/deploy-worker/src/debug.ts create mode 100644 apps/deploy-worker/src/index.ts create mode 100644 apps/deploy-worker/src/supabase/client.ts create mode 100644 apps/deploy-worker/src/supabase/db-types.ts create mode 100644 apps/deploy-worker/src/supabase/deploy.ts create mode 100644 apps/deploy-worker/src/supabase/generate-password.ts create mode 100644 apps/deploy-worker/src/supabase/oauth.ts create mode 100644 apps/deploy-worker/src/supabase/types.ts create mode 100644 apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts create mode 100644 apps/deploy-worker/tsconfig.json diff --git a/apps/deploy-worker/.gitignore b/apps/deploy-worker/.gitignore new file mode 100644 index 00000000..36fabb6c --- /dev/null +++ b/apps/deploy-worker/.gitignore @@ -0,0 +1,28 @@ +# dev +.yarn/ +!.yarn/releases +.vscode/* +!.vscode/launch.json +!.vscode/*.code-snippets +.idea/workspace.xml +.idea/usage.statistics.xml +.idea/shelf + +# deps +node_modules/ + +# env +.env +.env.production + +# logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# misc +.DS_Store diff --git a/apps/deploy-worker/Dockerfile b/apps/deploy-worker/Dockerfile new file mode 100644 index 00000000..b269878a --- /dev/null +++ b/apps/deploy-worker/Dockerfile @@ -0,0 +1,15 @@ +FROM node:22-alpine + +RUN apk add --no-cache postgresql-client + +WORKDIR /app + +COPY --link package.json ./ +COPY --link src/ ./src/ + +RUN npm install + +EXPOSE 443 +EXPOSE 5432 + +CMD ["node", "--experimental-strip-types", "src/index.ts"] \ No newline at end of file diff --git a/apps/deploy-worker/README.md b/apps/deploy-worker/README.md new file mode 100644 index 00000000..e12b31db --- /dev/null +++ b/apps/deploy-worker/README.md @@ -0,0 +1,8 @@ +``` +npm install +npm run dev +``` + +``` +open http://localhost:3000 +``` diff --git a/apps/deploy-worker/fly.toml b/apps/deploy-worker/fly.toml new file mode 100644 index 00000000..e23f6c12 --- /dev/null +++ b/apps/deploy-worker/fly.toml @@ -0,0 +1,23 @@ +primary_region = 'iad' + +[[services]] +internal_port = 5432 +protocol = "tcp" +[[services.ports]] +handlers = ["proxy_proto"] +port = 5432 + +[[services]] +internal_port = 443 +protocol = "tcp" +[[services.ports]] +port = 443 + +[[restart]] +policy = "always" +retries = 10 + +[[vm]] +memory = '512mb' +cpu_kind = 'shared' +cpus = 1 diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json new file mode 100644 index 00000000..89dc0a0b --- /dev/null +++ b/apps/deploy-worker/package.json @@ -0,0 +1,25 @@ +{ + "name": "@database.build/deploy-worker", + "type": "module", + "scripts": { + "start": "node --env-file=.env --experimental-strip-types src/index.ts", + "dev": "node --watch --env-file=.env --experimental-strip-types src/index.ts", + "type-check": "tsc", + "generate:types": "npx supabase gen types --lang=typescript --local > src/supabase/db-types.ts" + }, + "dependencies": { + "@hono/node-server": "^1.13.2", + "@hono/zod-validator": "^0.4.1", + "@supabase/supabase-js": "^2.45.4", + "debug": "^4.3.7", + "hono": "^4.6.5", + "neverthrow": "^8.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@total-typescript/tsconfig": "^1.0.4", + "@types/debug": "^4.1.12", + "@types/node": "^22.5.4", + "typescript": "^5.5.4" + } +} diff --git a/apps/deploy-worker/src/debug.ts b/apps/deploy-worker/src/debug.ts new file mode 100644 index 00000000..e03388ac --- /dev/null +++ b/apps/deploy-worker/src/debug.ts @@ -0,0 +1,3 @@ +import createDebug from 'debug' + +export const debug = createDebug('deploy-worker') diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts new file mode 100644 index 00000000..b85e2993 --- /dev/null +++ b/apps/deploy-worker/src/index.ts @@ -0,0 +1,66 @@ +import { serve } from '@hono/node-server' +import { Hono } from 'hono' +import { z } from 'zod' +import { zValidator } from '@hono/zod-validator' +import { createClient } from './supabase/client.ts' +import { HTTPException } from 'hono/http-exception' +import { deployOnSupabase } from './supabase/deploy.ts' + +const app = new Hono() + +app.get( + '/', + zValidator( + 'json', + z.object({ + databaseId: z.string(), + integrationId: z.string(), + databaseUrl: z.string(), + }) + ), + async (c) => { + const { databaseId, integrationId, databaseUrl: localDatabaseUrl } = c.req.valid('json') + + const token = c.req.header('Authorization')?.replace('Bearer ', '') + + if (!token) { + throw new HTTPException(401, { message: 'Unauthorized' }) + } + + const supabase = createClient() + + const { error } = await supabase.auth.getUser(token) + + if (error) { + throw new HTTPException(401, { message: 'Unauthorized' }) + } + + // TODO: create a lock in postgres to prevent multiple deployments + // await supabase.from('deployment_locks').insert({ + // local_database_id: databaseId, + // }) + try { + const { databaseUrl } = await deployOnSupabase( + { supabase }, + { databaseId, integrationId, localDatabaseUrl } + ) + return c.json({ databaseUrl }) + } catch (error: unknown) { + if (error instanceof Error) { + throw new HTTPException(500, { message: error.message }) + } + throw new HTTPException(500, { message: 'Internal server error' }) + } finally { + // TODO: remove the lock + // await supabase.from('deployment_locks').delete().eq('local_database_id', databaseId) + } + } +) + +const port = 4000 +console.log(`Server is running on port ${port}`) + +serve({ + fetch: app.fetch, + port, +}) diff --git a/apps/deploy-worker/src/supabase/client.ts b/apps/deploy-worker/src/supabase/client.ts new file mode 100644 index 00000000..516a44bf --- /dev/null +++ b/apps/deploy-worker/src/supabase/client.ts @@ -0,0 +1,11 @@ +import { createClient as createSupabaseClient } from '@supabase/supabase-js' +import type { Database } from './db-types.ts' + +export const supabaseAdmin = createSupabaseClient( + process.env.SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! +) + +export function createClient() { + return createSupabaseClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!) +} diff --git a/apps/deploy-worker/src/supabase/db-types.ts b/apps/deploy-worker/src/supabase/db-types.ts new file mode 100644 index 00000000..66bd32f0 --- /dev/null +++ b/apps/deploy-worker/src/supabase/db-types.ts @@ -0,0 +1,326 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[] + +export type Database = { + graphql_public: { + Tables: { + [_ in never]: never + } + Views: { + [_ in never]: never + } + Functions: { + graphql: { + Args: { + operationName?: string + query?: string + variables?: Json + extensions?: Json + } + Returns: Json + } + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } + public: { + Tables: { + deploy_waitlist: { + Row: { + created_at: string + id: number + user_id: string + } + Insert: { + created_at?: string + id?: never + user_id?: string + } + Update: { + created_at?: string + id?: never + user_id?: string + } + Relationships: [ + { + foreignKeyName: "deploy_waitlist_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + ] + } + deployed_databases: { + Row: { + created_at: string + deployment_provider_integration_id: number + id: number + local_database_id: string + provider_metadata: Json + updated_at: string + } + Insert: { + created_at?: string + deployment_provider_integration_id: number + id?: never + local_database_id: string + provider_metadata?: Json + updated_at?: string + } + Update: { + created_at?: string + deployment_provider_integration_id?: number + id?: never + local_database_id?: string + provider_metadata?: Json + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "deployed_databases_deployment_provider_integration_id_fkey" + columns: ["deployment_provider_integration_id"] + isOneToOne: false + referencedRelation: "deployment_provider_integrations" + referencedColumns: ["id"] + }, + ] + } + deployment_provider_integrations: { + Row: { + created_at: string + credentials: Json + deployment_provider_id: number | null + id: number + scope: Json + updated_at: string + user_id: string + } + Insert: { + created_at?: string + credentials: Json + deployment_provider_id?: number | null + id?: never + scope?: Json + updated_at?: string + user_id?: string + } + Update: { + created_at?: string + credentials?: Json + deployment_provider_id?: number | null + id?: never + scope?: Json + updated_at?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "deployment_provider_integrations_deployment_provider_id_fkey" + columns: ["deployment_provider_id"] + isOneToOne: false + referencedRelation: "deployment_providers" + referencedColumns: ["id"] + }, + { + foreignKeyName: "deployment_provider_integrations_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + ] + } + deployment_providers: { + Row: { + created_at: string + id: number + name: string + updated_at: string + } + Insert: { + created_at?: string + id?: never + name: string + updated_at?: string + } + Update: { + created_at?: string + id?: never + name?: string + updated_at?: string + } + Relationships: [] + } + deployments: { + Row: { + created_at: string + deployed_database_id: number + id: number + status: Database["public"]["Enums"]["deployment_status"] + updated_at: string + } + Insert: { + created_at?: string + deployed_database_id: number + id?: never + status: Database["public"]["Enums"]["deployment_status"] + updated_at?: string + } + Update: { + created_at?: string + deployed_database_id?: number + id?: never + status?: Database["public"]["Enums"]["deployment_status"] + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "deployments_deployed_database_id_fkey" + columns: ["deployed_database_id"] + isOneToOne: false + referencedRelation: "deployed_databases" + referencedColumns: ["id"] + }, + ] + } + } + Views: { + [_ in never]: never + } + Functions: { + delete_secret: { + Args: { + secret_id: string + } + Returns: string + } + insert_secret: { + Args: { + secret: string + name: string + } + Returns: string + } + read_secret: { + Args: { + secret_id: string + } + Returns: string + } + supabase_functions_certificate_secret: { + Args: Record + Returns: string + } + supabase_url: { + Args: Record + Returns: string + } + update_secret: { + Args: { + secret_id: string + new_secret: string + } + Returns: string + } + } + Enums: { + deployment_status: "in_progress" | "success" | "failed" + } + CompositeTypes: { + [_ in never]: never + } + } +} + +type PublicSchema = Database[Extract] + +export type Tables< + PublicTableNameOrOptions extends + | keyof (PublicSchema["Tables"] & PublicSchema["Views"]) + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] & + Database[PublicTableNameOrOptions["schema"]]["Views"]) + : never = never, +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? (Database[PublicTableNameOrOptions["schema"]]["Tables"] & + Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends { + Row: infer R + } + ? R + : never + : PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] & + PublicSchema["Views"]) + ? (PublicSchema["Tables"] & + PublicSchema["Views"])[PublicTableNameOrOptions] extends { + Row: infer R + } + ? R + : never + : never + +export type TablesInsert< + PublicTableNameOrOptions extends + | keyof PublicSchema["Tables"] + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Insert: infer I + } + ? I + : never + : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] + ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { + Insert: infer I + } + ? I + : never + : never + +export type TablesUpdate< + PublicTableNameOrOptions extends + | keyof PublicSchema["Tables"] + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Update: infer U + } + ? U + : never + : PublicTableNameOrOptions extends keyof PublicSchema["Tables"] + ? PublicSchema["Tables"][PublicTableNameOrOptions] extends { + Update: infer U + } + ? U + : never + : never + +export type Enums< + PublicEnumNameOrOptions extends + | keyof PublicSchema["Enums"] + | { schema: keyof Database }, + EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"] + : never = never, +> = PublicEnumNameOrOptions extends { schema: keyof Database } + ? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName] + : PublicEnumNameOrOptions extends keyof PublicSchema["Enums"] + ? PublicSchema["Enums"][PublicEnumNameOrOptions] + : never + diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts new file mode 100644 index 00000000..81328230 --- /dev/null +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -0,0 +1,147 @@ +import { supabaseAdmin, type createClient } from './client.ts' +import { getAccessToken } from './oauth.ts' +import { waitForDatabaseToBeReady } from './wait-for-database-to-be-ready.ts' +import type { Project, SupabaseProviderMetadata } from './types.ts' +import { generatePassword } from './generate-password.ts' +import { exec as execSync } from 'node:child_process' +import { promisify } from 'node:util' +const exec = promisify(execSync) + +type Context = { + supabase: Awaited> +} + +export async function deployOnSupabase( + ctx: Context, + params: { databaseId: string; integrationId: string; localDatabaseUrl: string } +) { + // check if there is the database was already deployed + let deployedDatabase = await ctx.supabase + .from('deployed_databases') + .select('*') + .eq('local_database_id', params.databaseId) + .eq('deployment_provider_integration_id', params.integrationId) + .maybeSingle() + + if (deployedDatabase.error) { + throw new Error('Cannot find deployed database', { cause: deployedDatabase.error }) + } + + if (!deployedDatabase.data) { + const integration = await ctx.supabase + .from('deployment_provider_integrations') + .select('id,credentials,scope') + .eq('id', params.integrationId) + .single() + + if (integration.error) { + throw new Error('Cannot find integration', { cause: integration.error }) + } + + // first we need to create a new project on Supabase using the Management API + const credentials = integration.data.credentials as { + expiresAt: string + refreshToken: string + accessToken: string + } + + const accessToken = await getAccessToken(integration.data.id, credentials) + + const databasePassword = generatePassword() + + // create a new project on Supabase using the Management API + const projectResponse = await fetch('https://api.supabase.com/v1/projects', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify({ + db_pass: databasePassword, + name: `database-build-${params.databaseId}`, + organization_id: (integration.data.scope as { organizationId: string }).organizationId, + region: 'us-east-1', + desired_instance_size: 'micro', + }), + }) + + if (!projectResponse.ok) { + throw new Error('Failed to create project on Supabase', { + cause: { + status: projectResponse.status, + statusText: projectResponse.statusText, + }, + }) + } + + const project = (await projectResponse.json()) as Project + + // wait for the database to be ready + await waitForDatabaseToBeReady(project, accessToken) + + // store the database password as a secret + const databasePasswordSecret = await supabaseAdmin.rpc('insert_secret', { + name: `supabase_database_password_${params.databaseId}`, + secret: databasePassword, + }) + + if (databasePasswordSecret.error) { + throw new Error('Cannot store database password as secret', { + cause: databasePasswordSecret.error, + }) + } + + const metadata: SupabaseProviderMetadata = { + project: { + ...project, + database: { + ...project.database, + password: databasePasswordSecret.data, + }, + }, + } + + deployedDatabase = await ctx.supabase + .from('deployed_databases') + .insert({ + deployment_provider_integration_id: integration.data.id, + local_database_id: params.databaseId, + provider_metadata: metadata, + }) + .select() + .single() + + if (deployedDatabase.error) { + throw new Error('Cannot create deployed database', { cause: deployedDatabase.error }) + } + } + + // get the remote database url + const { project } = deployedDatabase.data!.provider_metadata as SupabaseProviderMetadata + + const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { + secret_id: project.database.password, + }) + + if (databasePasswordSecret.error) { + throw new Error('Cannot read database password secret', { + cause: databasePasswordSecret.error, + }) + } + + const remoteDatabaseUrl = `postgresql://postgres.${project.id}:${databasePasswordSecret.data}@${project.database.host}:5432/postgres` + + // use pg_dump and pg_restore to transfer the data from the local database to the remote database + const command = `pg_dump "${params.localDatabaseUrl}" -Fc -C | pg_restore --dbname=${remoteDatabaseUrl}` + try { + await exec(command) + } catch (error) { + throw new Error('Cannot transfer the data from the local database to the remote database', { + cause: error, + }) + } + + return { + databaseUrl: remoteDatabaseUrl, + } +} diff --git a/apps/deploy-worker/src/supabase/generate-password.ts b/apps/deploy-worker/src/supabase/generate-password.ts new file mode 100644 index 00000000..9be3efca --- /dev/null +++ b/apps/deploy-worker/src/supabase/generate-password.ts @@ -0,0 +1,10 @@ +export function generatePassword(): string { + const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + const length = 16 + const randomValues = new Uint8Array(length) + crypto.getRandomValues(randomValues) + + return Array.from(randomValues) + .map((value) => charset[value % charset.length]) + .join('') +} diff --git a/apps/deploy-worker/src/supabase/oauth.ts b/apps/deploy-worker/src/supabase/oauth.ts new file mode 100644 index 00000000..d44d76b8 --- /dev/null +++ b/apps/deploy-worker/src/supabase/oauth.ts @@ -0,0 +1,78 @@ +import { supabaseAdmin } from './client.ts' + +type Credentials = { expiresAt: string; refreshToken: string; accessToken: string } + +export async function getAccessToken( + integrationId: number, + credentials: Credentials +): Promise { + // the expiresAt expires in less than 1 hour, refresh the token + if (new Date(credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { + const refreshToken = await supabaseAdmin.rpc('read_secret', { + secret_id: credentials.refreshToken, + }) + + if (refreshToken.error) { + console.error(refreshToken.error) + throw new Error('Failed to read refresh token') + } + + const now = Date.now() + + const newCredentialsResponse = await fetch('https://api.supabase.com/v1/oauth/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: credentials.refreshToken, + }), + }) + + if (!newCredentialsResponse.ok) { + console.error(newCredentialsResponse) + throw new Error('Failed to fetch new credentials') + } + + const newCredentials = (await newCredentialsResponse.json()) as { + access_token: string + refresh_token: string + expires_in: number + } + + const expiresAt = new Date(now + newCredentials.expires_in * 1000) + + await supabaseAdmin.rpc('update_secret', { + secret_id: credentials.refreshToken, + new_secret: newCredentials.refresh_token, + }) + await supabaseAdmin.rpc('update_secret', { + secret_id: credentials.accessToken, + new_secret: newCredentials.access_token, + }) + await supabaseAdmin + .from('deployment_provider_integrations') + .update({ + credentials: { + accessToken: credentials.accessToken, + expiresAt: expiresAt.toISOString(), + refreshToken: credentials.refreshToken, + }, + }) + .eq('id', integrationId) + } + + const accessToken = await supabaseAdmin.rpc('read_secret', { + secret_id: credentials.accessToken, + }) + + if (accessToken.error) { + console.error(accessToken.error) + throw new Error('Failed to read access token') + } + + return accessToken.data +} diff --git a/apps/deploy-worker/src/supabase/types.ts b/apps/deploy-worker/src/supabase/types.ts new file mode 100644 index 00000000..31e3e508 --- /dev/null +++ b/apps/deploy-worker/src/supabase/types.ts @@ -0,0 +1,38 @@ +type ProjectStatus = + | 'ACTIVE_HEALTHY' + | 'ACTIVE_UNHEALTHY' + | 'COMING_UP' + | 'GOING_DOWN' + | 'INACTIVE' + | 'INIT_FAILED' + | 'REMOVED' + | 'RESTARTING' + | 'UNKNOWN' + | 'UPGRADING' + | 'PAUSING' + | 'RESTORING' + | 'RESTORE_FAILED' + | 'PAUSE_FAILED' + +export type Project = { + id: string + organization_id: string + name: string + region: string + created_at: string + database: { + host: string + version: string + postgres_engine: string + release_channel: string + } + status: ProjectStatus +} + +export type SupabaseProviderMetadata = { + project: Project & { + database: Project['database'] & { + password: string + } + } +} diff --git a/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts b/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts new file mode 100644 index 00000000..c997b14a --- /dev/null +++ b/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts @@ -0,0 +1,61 @@ +import type { Project } from './types.ts' +import { setTimeout } from 'timers/promises' + +const MAX_POLLING_TIME = 120000 // 2 minutes in milliseconds +const POLLING_INTERVAL = 5000 // 5 seconds in milliseconds + +type DatabaseStatus = 'COMING_UP' | 'ACTIVE_HEALTHY' | 'UNHEALTHY' + +export async function waitForDatabaseToBeReady(project: Project, accessToken: string) { + const params = new URLSearchParams({ services: ['db'] }).toString() + + const startTime = Date.now() + + while (true) { + try { + const servicesHealthResponse = await fetch( + `https://api.supabase.com/v1/projects/${project.id}/health?${params}`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + }, + } + ) + + if (!servicesHealthResponse.ok) { + throw new Error("Failed to get Supabase project's database health status") + } + + const servicesHealth = (await servicesHealthResponse.json()) as { + name: 'db' + status: DatabaseStatus + error: string + }[] + + const databaseService = servicesHealth.find((service) => service.name === 'db') + + if (!databaseService) { + throw new Error('Database service not found on Supabase for health check') + } + + if (databaseService.status === 'UNHEALTHY') { + throw new Error('Database is unhealthy on Supabase', { + cause: databaseService.error, + }) + } + + if (databaseService.status === 'ACTIVE_HEALTHY') { + return + } + + if (Date.now() - startTime > MAX_POLLING_TIME) { + throw new Error('Polling timeout: Database did not become active within 2 minutes') + } + + await setTimeout(POLLING_INTERVAL) + } catch (error) { + throw error + } + } +} diff --git a/apps/deploy-worker/tsconfig.json b/apps/deploy-worker/tsconfig.json new file mode 100644 index 00000000..c7e60e1c --- /dev/null +++ b/apps/deploy-worker/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@total-typescript/tsconfig/tsc/no-dom/app", + "include": ["src/**/*.ts"], + "compilerOptions": { + "noEmit": true, + "allowImportingTsExtensions": true, + "outDir": "dist" + } +} diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index de069f3b..97e13fe2 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -109,7 +109,6 @@ export async function GET(req: NextRequest) { const integration = await supabase .from('deployment_provider_integrations') .insert({ - user_id: user.id, deployment_provider_id: deploymentProvider.id, credentials: { accessToken: accessTokenSecretId, diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts index 10dd9d41..66bd32f0 100644 --- a/apps/postgres-new/utils/supabase/db-types.ts +++ b/apps/postgres-new/utils/supabase/db-types.ts @@ -63,44 +63,34 @@ export type Database = { deployed_databases: { Row: { created_at: string - deployment_provider_id: number + deployment_provider_integration_id: number id: number local_database_id: string provider_metadata: Json updated_at: string - user_id: string } Insert: { created_at?: string - deployment_provider_id: number + deployment_provider_integration_id: number id?: never local_database_id: string provider_metadata?: Json updated_at?: string - user_id: string } Update: { created_at?: string - deployment_provider_id?: number + deployment_provider_integration_id?: number id?: never local_database_id?: string provider_metadata?: Json updated_at?: string - user_id?: string } Relationships: [ { - foreignKeyName: "deployed_databases_deployment_provider_id_fkey" - columns: ["deployment_provider_id"] + foreignKeyName: "deployed_databases_deployment_provider_integration_id_fkey" + columns: ["deployment_provider_integration_id"] isOneToOne: false - referencedRelation: "deployment_providers" - referencedColumns: ["id"] - }, - { - foreignKeyName: "deployed_databases_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" + referencedRelation: "deployment_provider_integrations" referencedColumns: ["id"] }, ] @@ -122,7 +112,7 @@ export type Database = { id?: never scope?: Json updated_at?: string - user_id: string + user_id?: string } Update: { created_at?: string diff --git a/package-lock.json b/package-lock.json index b3e720d4..502f7c20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,6 +75,41 @@ "typescript": "^5.5.3" } }, + "apps/deploy-worker": { + "name": "@database.build/deploy-worker", + "dependencies": { + "@hono/node-server": "^1.13.2", + "@hono/zod-validator": "^0.4.1", + "@supabase/supabase-js": "^2.45.4", + "debug": "^4.3.7", + "hono": "^4.6.5", + "neverthrow": "^8.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@total-typescript/tsconfig": "^1.0.4", + "@types/debug": "^4.1.12", + "@types/node": "^22.5.4", + "typescript": "^5.5.4" + } + }, + "apps/deploy-worker/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "apps/deploy-worker/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "apps/postgres-new": { "version": "0.0.0", "dependencies": { @@ -1322,6 +1357,10 @@ "resolved": "apps/browser-proxy", "link": true }, + "node_modules/@database.build/deploy-worker": { + "resolved": "apps/deploy-worker", + "link": true + }, "node_modules/@electric-sql/pglite": { "version": "0.2.0-alpha.9", "license": "Apache-2.0" @@ -1536,6 +1575,28 @@ "npm": ">=9" } }, + "node_modules/@hono/node-server": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.13.2.tgz", + "integrity": "sha512-0w8nEmAyx0Ul0CQp8BL2VtAG4YVdpzXd/mvvM+l0G5Oq22pUyHS+KeFFPSY+czLOF5NAiV3MUNPD1n14Ol5svg==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@hono/zod-validator": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.4.1.tgz", + "integrity": "sha512-I8LyfeJfvVmC5hPjZ2Iij7RjexlgSBT7QJudZ4JvNPLxn0JQ3sqclz2zydlwISAnw21D2n4LQ0nfZdoiv9fQQA==", + "license": "MIT", + "peerDependencies": { + "hono": ">=3.9.0", + "zod": "^3.19.1" + } + }, "node_modules/@huggingface/jinja": { "version": "0.2.2", "license": "MIT", @@ -7749,6 +7810,15 @@ "version": "1.3.0", "license": "Apache-2.0" }, + "node_modules/hono": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.6.5.tgz", + "integrity": "sha512-qsmN3V5fgtwdKARGLgwwHvcdLKursMd+YOt69eGpl1dUCJb8mCd7hZfyZnBYjxCegBG7qkJRQRUy2oO25yHcyQ==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, "node_modules/html-url-attributes": { "version": "3.0.0", "license": "MIT", @@ -9946,6 +10016,15 @@ "dev": true, "license": "MIT" }, + "node_modules/neverthrow": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-8.0.0.tgz", + "integrity": "sha512-SX2Z50+U27I+CF3NwHE9J8MB6+bYRRub3U+1nAKxnL6c+2vW2l/WsYEC0e3Wqg8DwiJvrquqE0YhxlVTzGJGsg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/next": { "version": "14.2.3", "license": "MIT", @@ -14248,6 +14327,8 @@ }, "node_modules/zod": { "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index b42729af..22851804 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -17,7 +17,7 @@ insert into deployment_providers (name) values ('Supabase'); -- table for storing deployment provider integrations create table deployment_provider_integrations ( id bigint primary key generated always as identity, - user_id uuid not null references auth.users(id), + user_id uuid not null references auth.users(id) default auth.uid(), deployment_provider_id bigint references deployment_providers(id), scope jsonb not null default '{}'::jsonb, credentials jsonb not null, @@ -32,13 +32,12 @@ create trigger deployment_provider_integrations_updated_at before update on depl -- table for storing deployed databases create table deployed_databases ( id bigint primary key generated always as identity, - user_id uuid not null references auth.users(id), local_database_id text not null, - deployment_provider_id bigint not null references deployment_providers(id), + deployment_provider_integration_id bigint not null references deployment_provider_integrations(id), provider_metadata jsonb not null default '{}'::jsonb, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), - unique(user_id, local_database_id, deployment_provider_id) + unique(local_database_id, deployment_provider_integration_id) ); create trigger deployed_databases_updated_at before update on deployed_databases @@ -85,20 +84,20 @@ alter table deployed_databases enable row level security; -- RLS policies for deployed_databases create policy "Users can read their own deployed databases" on deployed_databases for select - using (auth.uid() = user_id); + using (auth.uid() = (select user_id from deployment_provider_integrations where id = deployed_databases.deployment_provider_integration_id)); create policy "Users can create their own deployed databases" on deployed_databases for insert - with check (auth.uid() = user_id); + with check (auth.uid() = (select user_id from deployment_provider_integrations where id = deployment_provider_integration_id)); create policy "Users can update their own deployed databases" on deployed_databases for update - using (auth.uid() = user_id) - with check (auth.uid() = user_id); + using (auth.uid() = (select user_id from deployment_provider_integrations where id = deployed_databases.deployment_provider_integration_id)) + with check (auth.uid() = (select user_id from deployment_provider_integrations where id = deployment_provider_integration_id)); create policy "Users can delete their own deployed databases" on deployed_databases for delete - using (auth.uid() = user_id); + using (auth.uid() = (select user_id from deployment_provider_integrations where id = deployed_databases.deployment_provider_integration_id)); -- Enable RLS on deployments alter table deployments enable row level security; @@ -106,20 +105,39 @@ alter table deployments enable row level security; -- RLS policies for deployments create policy "Users can read their own deployments" on deployments for select - using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + using (auth.uid() = ( + select dpi.user_id + from deployed_databases dd + join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id + where dd.id = deployments.deployed_database_id + )); create policy "Users can create their own deployments" on deployments for insert - with check (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + with check (auth.uid() = ( + select dpi.user_id + from deployed_databases dd + join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id + where dd.id = deployments.deployed_database_id + )); create policy "Users can update their own deployments" on deployments for update - using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)) - with check (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + using (auth.uid() = ( + select dpi.user_id + from deployed_databases dd + join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id + where dd.id = deployments.deployed_database_id + )); create policy "Users can delete their own deployments" on deployments for delete - using (auth.uid() = (select user_id from deployed_databases where id = deployments.deployed_database_id)); + using (auth.uid() = ( + select dpi.user_id + from deployed_databases dd + join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id + where dd.id = deployments.deployed_database_id + )); create or replace function insert_secret(secret text, name text) returns uuid @@ -181,4 +199,4 @@ begin return delete from vault.decrypted_secrets where id = secret_id; end; -$$; \ No newline at end of file +$$; From 0901d111a25472c0f06e0341093e5068a235794d Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 16 Oct 2024 19:09:29 +0200 Subject: [PATCH 08/59] adjust polling --- .../src/supabase/wait-for-database-to-be-ready.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts b/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts index c997b14a..2247ccf2 100644 --- a/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts +++ b/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts @@ -1,8 +1,8 @@ import type { Project } from './types.ts' import { setTimeout } from 'timers/promises' -const MAX_POLLING_TIME = 120000 // 2 minutes in milliseconds -const POLLING_INTERVAL = 5000 // 5 seconds in milliseconds +const MAX_POLLING_TIME = 3 * 60 * 1000 // 3 minutes in milliseconds +const POLLING_INTERVAL = 10 * 1000 // 10 seconds in milliseconds type DatabaseStatus = 'COMING_UP' | 'ACTIVE_HEALTHY' | 'UNHEALTHY' From c07c1d88e553602e207f8ed5805a230b097ffc53 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 17 Oct 2024 07:40:51 +0200 Subject: [PATCH 09/59] delete db-service --- apps/db-service/.dockerignore | 5 - apps/db-service/Dockerfile | 68 -------------- apps/db-service/README.md | 101 -------------------- apps/db-service/docker-compose.yml | 63 ------------- apps/db-service/entrypoint.sh | 38 -------- apps/db-service/package.json | 20 ---- apps/db-service/scripts/generate-certs.sh | 18 ---- apps/db-service/src/index.ts | 109 ---------------------- apps/db-service/tsconfig.json | 103 -------------------- 9 files changed, 525 deletions(-) delete mode 100644 apps/db-service/.dockerignore delete mode 100644 apps/db-service/Dockerfile delete mode 100644 apps/db-service/README.md delete mode 100644 apps/db-service/docker-compose.yml delete mode 100755 apps/db-service/entrypoint.sh delete mode 100644 apps/db-service/package.json delete mode 100755 apps/db-service/scripts/generate-certs.sh delete mode 100644 apps/db-service/src/index.ts delete mode 100644 apps/db-service/tsconfig.json diff --git a/apps/db-service/.dockerignore b/apps/db-service/.dockerignore deleted file mode 100644 index 47719bef..00000000 --- a/apps/db-service/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -fly.toml -Dockerfile -.dockerignore -node_modules -.git diff --git a/apps/db-service/Dockerfile b/apps/db-service/Dockerfile deleted file mode 100644 index 9476c5f9..00000000 --- a/apps/db-service/Dockerfile +++ /dev/null @@ -1,68 +0,0 @@ -# syntax = docker/dockerfile:1 - -# Adjust NODE_VERSION as desired -ARG NODE_VERSION=20.4.0 -FROM node:${NODE_VERSION}-bookworm as base - -LABEL fly_launch_runtime="NodeJS" - -# NodeJS app lives here -WORKDIR /app - -# Set production environment -ENV NODE_ENV=production - -# Build S3FS -FROM base as build-s3fs - -# Install dependencies -RUN apt-get update && \ - apt-get install -y \ - libfuse-dev - -RUN git clone https://github.com/s3fs-fuse/s3fs-fuse.git --branch v1.94 && \ - cd s3fs-fuse && \ - ./autogen.sh && \ - ./configure && \ - make && \ - make install - -# Build app -FROM base as build-app - -# Install packages needed to build node modules -RUN apt-get update -qq && \ - apt-get install -y \ - python-is-python3 \ - pkg-config \ - build-essential - -# Install node modules -COPY --link package.json . -RUN npm install --production=false - -# Copy application code -COPY --link . . - -# Build app -RUN npm run build - -# Remove development dependencies -RUN npm prune --production - -# Final stage for app image -FROM base - -# Install dependencies -RUN apt-get update && \ - apt-get install -y \ - fuse \ - && rm -rf /var/lib/apt/lists/* - -COPY --from=build-s3fs /usr/local/bin/s3fs /usr/local/bin/s3fs -COPY --from=build-app /app /app - -ENTRYPOINT [ "./entrypoint.sh" ] - -# Start the server by default, this can be overwritten at runtime -CMD [ "node", "dist/index.js" ] diff --git a/apps/db-service/README.md b/apps/db-service/README.md deleted file mode 100644 index b4383a68..00000000 --- a/apps/db-service/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# DB Service - -This service is still WIP. It uses [`s3fs`](https://github.com/s3fs-fuse/s3fs-fuse) to mount an S3-compatible storage to `/mnt/s3` then serve PGlite instances via the PGDATA that lives under `/mnt/s3/dbs/`. - -It also requires TLS certs, since we use SNI to reverse proxy DB connections (eg. `12345.db.example.com` serves `/mnt/s3/dbs/12345`). These certs live under `/mnt/s3/tls`. - -## TODO - -- [x] Containerize -- [ ] Connect to Supabase DB to validate creds/dbs -- [ ] DB versioning -- [ ] PGlite upload service - -## Development - -### Without `s3fs` - -If want to develop locally without dealing with containers or underlying storage: - -1. Generate certs that live under `./tls`: - ```shell - npm run generate:certs - ``` -1. Run the `pg-gateway` server: - ```shell - npm run dev - ``` - All DBs will live under `./dbs`. -1. Connect to the server via `psql`: - - ```shell - psql "host=localhost port=5432 user=postgres" - ``` - - or to test a real database ID, add a loopback entry to your `/etc/hosts` file: - - ``` - # ... - - 127.0.0.1 12345.db.example.com - ``` - - and connect to that host: - - ```shell - psql "host=12345.db.example.com port=5432 user=postgres" - ``` - -### With `s3fs` - -To simulate an environment closer to production, you can test the service with DBs backed by `s3fs` using Minio and Docker. - -1. Start Minio as a local s3-compatible server: - ```shell - docker compose up -d minio - ``` -1. Initialize test bucket: - ```shell - docker compose up minio-init - ``` - This will run to completion then exit. -1. Initialize local TLS certs: - - ```shell - docker compose up --build tls-init - ``` - - This will build the container (if it's not cached) then run to completion and exit. Certs are stored under `/mnt/s3/tls`. - -1. Run the `pg-gateway` server: - ```shell - docker compose up --build db-service - ``` - This will build the container (if it's not cached) then run the Node `db-service`. All DBs will live under `/mnt/s3/dbs`. -1. Connect to the server via `psql`: - - ```shell - psql "host=localhost port=5432 user=postgres" - ``` - - > Note the very first time a DB is created will be very slow (`s3fs` writes are slow with that many file handles) so expect this to hang for a while. Subsequent requests will be much quicker. This is temporary anyway - in the future the DB will have to already exist in `/mnt/s3/dbs/` in order to connect. - - or to test a real database ID, add a loopback entry to your `/etc/hosts` file: - - ``` - # ... - - 127.0.0.1 12345.db.example.com - ``` - - and connect to that host: - - ```shell - psql "host=12345.db.example.com port=5432 user=postgres" - ``` - -To stop all Docker containers, run: - -```shell -docker compose down -``` diff --git a/apps/db-service/docker-compose.yml b/apps/db-service/docker-compose.yml deleted file mode 100644 index 13e26335..00000000 --- a/apps/db-service/docker-compose.yml +++ /dev/null @@ -1,63 +0,0 @@ -services: - db-service: - image: db-service - build: - context: . - environment: - S3FS_ENDPOINT: http://minio:9000 - S3FS_BUCKET: test - S3FS_REGION: us-east-1 # default region for s3-compatible APIs - S3FS_MOUNT: /mnt/s3 - AWS_ACCESS_KEY_ID: minioadmin - AWS_SECRET_ACCESS_KEY: minioadmin - ports: - - 5432:5432 - devices: - - /dev/fuse - cap_add: - - SYS_ADMIN - depends_on: - minio: - condition: service_healthy - tls-init: - image: tls-init - build: - context: . - environment: - S3FS_ENDPOINT: http://minio:9000 - S3FS_BUCKET: test - S3FS_REGION: us-east-1 # default region for s3-compatible APIs - S3FS_MOUNT: /mnt/s3 - AWS_ACCESS_KEY_ID: minioadmin - AWS_SECRET_ACCESS_KEY: minioadmin - devices: - - /dev/fuse - cap_add: - - SYS_ADMIN - command: ./scripts/generate-certs.sh - depends_on: - minio: - condition: service_healthy - minio: - image: minio/minio - environment: - MINIO_ROOT_USER: minioadmin - MINIO_ROOT_PASSWORD: minioadmin - ports: - - 9000:9000 - command: server /data - healthcheck: - test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1 - interval: 5s - timeout: 5s - retries: 1 - minio-init: - image: minio/mc - entrypoint: > - /bin/sh -c " - mc alias set local http://minio:9000 minioadmin minioadmin; - (mc ls local/test || mc mb local/test); - " - depends_on: - minio: - condition: service_healthy diff --git a/apps/db-service/entrypoint.sh b/apps/db-service/entrypoint.sh deleted file mode 100755 index be930a28..00000000 --- a/apps/db-service/entrypoint.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -cleanup() { - echo "Unmounting s3fs..." - fusermount -u $S3FS_MOUNT - exit 0 -} - -forward_signal() { - kill -$1 "$MAIN_PID" -} - -trap 'forward_signal SIGINT' SIGINT -trap 'forward_signal SIGTERM' SIGTERM -trap 'cleanup' EXIT - -# Create the mount point directory -mkdir -p $S3FS_MOUNT - -# Mount the S3 bucket -s3fs $S3FS_BUCKET $S3FS_MOUNT -o use_path_request_style -o url=$S3FS_ENDPOINT -o endpoint=$S3FS_REGION - -# Check if the mount was successful -if mountpoint -q $S3FS_MOUNT; then - echo "S3 bucket mounted successfully at $S3FS_MOUNT" -else - echo "Failed to mount S3 bucket" - exit 1 -fi - -# Execute the original command -"$@" & -MAIN_PID=$! - -wait $MAIN_PID diff --git a/apps/db-service/package.json b/apps/db-service/package.json deleted file mode 100644 index 1003cc7f..00000000 --- a/apps/db-service/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "db-service", - "type": "module", - "scripts": { - "start": "node dist/index.js", - "dev": "tsx src/index.ts", - "build": "tsc -b", - "generate:certs": "scripts/generate-certs.sh", - "psql": "psql 'host=localhost port=5432 user=postgres sslmode=verify-ca sslrootcert=ca-cert.pem'" - }, - "dependencies": { - "@electric-sql/pglite": "0.2.0-alpha.9", - "pg-gateway": "^0.2.5-alpha.2" - }, - "devDependencies": { - "@types/node": "^20.14.11", - "tsx": "^4.16.2", - "typescript": "^5.5.3" - } -} diff --git a/apps/db-service/scripts/generate-certs.sh b/apps/db-service/scripts/generate-certs.sh deleted file mode 100755 index 8e474774..00000000 --- a/apps/db-service/scripts/generate-certs.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -S3FS_MOUNT=${S3FS_MOUNT:=.} -CERT_DIR="$S3FS_MOUNT/tls" - -mkdir -p $CERT_DIR -cd $CERT_DIR - -openssl genpkey -algorithm RSA -out ca-key.pem -openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 365 -subj "/CN=MyCA" - -openssl genpkey -algorithm RSA -out key.pem -openssl req -new -key key.pem -out csr.pem -subj "/CN=*.db.example.com" - -openssl x509 -req -in csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -days 365 diff --git a/apps/db-service/src/index.ts b/apps/db-service/src/index.ts deleted file mode 100644 index 9e28a20c..00000000 --- a/apps/db-service/src/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { PGlite, PGliteInterface } from '@electric-sql/pglite' -import { mkdir, readFile } from 'node:fs/promises' -import net from 'node:net' -import { hashMd5Password, PostgresConnection, TlsOptions } from 'pg-gateway' - -const s3fsMount = process.env.S3FS_MOUNT ?? '.' -const dbDir = `${s3fsMount}/dbs` -const tlsDir = `${s3fsMount}/tls` - -await mkdir(dbDir, { recursive: true }) -await mkdir(tlsDir, { recursive: true }) - -const tls: TlsOptions = { - key: await readFile(`${tlsDir}/key.pem`), - cert: await readFile(`${tlsDir}/cert.pem`), - ca: await readFile(`${tlsDir}/ca-cert.pem`), -} - -function getIdFromServerName(serverName: string) { - // The left-most subdomain contains the ID - // ie. 12345.db.example.com -> 12345 - const [id] = serverName.split('.') - return id -} - -const server = net.createServer((socket) => { - let db: PGliteInterface - - const connection = new PostgresConnection(socket, { - serverVersion: '16.3 (PGlite 0.2.0)', - authMode: 'md5Password', - tls, - async validateCredentials(credentials) { - if (credentials.authMode === 'md5Password') { - const { hash, salt } = credentials - const expectedHash = await hashMd5Password('postgres', 'postgres', salt) - return hash === expectedHash - } - return false - }, - async onTlsUpgrade({ tlsInfo }) { - if (!tlsInfo) { - connection.sendError({ - severity: 'FATAL', - code: '08000', - message: `ssl connection required`, - }) - connection.socket.end() - return - } - - if (!tlsInfo.sniServerName) { - connection.sendError({ - severity: 'FATAL', - code: '08000', - message: `ssl sni extension required`, - }) - connection.socket.end() - return - } - - const databaseId = getIdFromServerName(tlsInfo.sniServerName) - - console.log(`Serving database '${databaseId}'`) - - db = new PGlite(`${dbDir}/${databaseId}`) - }, - async onStartup() { - if (!db) { - console.log('PGlite instance undefined. Was onTlsUpgrade never called?') - connection.sendError({ - severity: 'FATAL', - code: 'XX000', - message: `error loading database`, - }) - connection.socket.end() - return true - } - - // Wait for PGlite to be ready before further processing - await db.waitReady - return false - }, - async onMessage(data, { isAuthenticated }) { - // Only forward messages to PGlite after authentication - if (!isAuthenticated) { - return false - } - - // Forward raw message to PGlite - try { - const responseData = await db.execProtocolRaw(data) - connection.sendData(responseData) - } catch (err) { - console.error(err) - } - return true - }, - }) - - socket.on('end', async () => { - console.log('Client disconnected') - await db?.close() - }) -}) - -server.listen(5432, async () => { - console.log('Server listening on port 5432') -}) diff --git a/apps/db-service/tsconfig.json b/apps/db-service/tsconfig.json deleted file mode 100644 index 0876a623..00000000 --- a/apps/db-service/tsconfig.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - /* Modules */ - "module": "NodeNext", /* Specify what module code is generated. */ - "rootDir": "./src", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": [ - "src/**/*" - ] -} \ No newline at end of file From a5c634533f9564ffce47aae2e8f53c1fa9022c97 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 17 Oct 2024 19:11:56 +0200 Subject: [PATCH 10/59] it works!!! --- apps/deploy-worker/package.json | 5 +- apps/deploy-worker/src/index.ts | 23 +- apps/deploy-worker/src/supabase/client.ts | 2 +- .../src/supabase/create-deployed-database.ts | 139 + .../{db-types.ts => database-types.ts} | 0 apps/deploy-worker/src/supabase/deploy.ts | 136 +- .../src/supabase/generate-password.ts | 3 + .../src/supabase/get-access-token.ts | 99 + .../src/supabase/get-database-url.ts | 21 + .../src/supabase/management-api.ts | 0 .../src/supabase/management-api/client.ts | 11 + .../src/supabase/management-api/types.ts | 4723 +++++++++++++++++ apps/deploy-worker/src/supabase/oauth.ts | 78 - apps/deploy-worker/src/supabase/types.ts | 59 +- .../supabase/wait-for-database-to-be-ready.ts | 61 - .../src/supabase/wait-for-health.ts | 117 + .../app/deploy/[databaseId]/page.tsx | 95 +- apps/postgres-new/next.config.mjs | 1 + package-lock.json | 480 +- 19 files changed, 5648 insertions(+), 405 deletions(-) create mode 100644 apps/deploy-worker/src/supabase/create-deployed-database.ts rename apps/deploy-worker/src/supabase/{db-types.ts => database-types.ts} (100%) create mode 100644 apps/deploy-worker/src/supabase/get-access-token.ts create mode 100644 apps/deploy-worker/src/supabase/get-database-url.ts create mode 100644 apps/deploy-worker/src/supabase/management-api.ts create mode 100644 apps/deploy-worker/src/supabase/management-api/client.ts create mode 100644 apps/deploy-worker/src/supabase/management-api/types.ts delete mode 100644 apps/deploy-worker/src/supabase/oauth.ts delete mode 100644 apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts create mode 100644 apps/deploy-worker/src/supabase/wait-for-health.ts diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json index 89dc0a0b..5beaa8fa 100644 --- a/apps/deploy-worker/package.json +++ b/apps/deploy-worker/package.json @@ -5,7 +5,8 @@ "start": "node --env-file=.env --experimental-strip-types src/index.ts", "dev": "node --watch --env-file=.env --experimental-strip-types src/index.ts", "type-check": "tsc", - "generate:types": "npx supabase gen types --lang=typescript --local > src/supabase/db-types.ts" + "generate:database-types": "npx supabase gen types --lang=typescript --local > src/supabase/db-types.ts", + "generate:management-api-types": "npx openapi-typescript https://api.supabase.com/api/v1-json -o ./src/supabase/management-api/types.ts" }, "dependencies": { "@hono/node-server": "^1.13.2", @@ -14,12 +15,14 @@ "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", + "openapi-fetch": "^0.12.2", "zod": "^3.23.8" }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/debug": "^4.1.12", "@types/node": "^22.5.4", + "openapi-typescript": "^7.4.1", "typescript": "^5.5.4" } } diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index b85e2993..892daeae 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -1,35 +1,41 @@ import { serve } from '@hono/node-server' import { Hono } from 'hono' +import { cors } from 'hono/cors' import { z } from 'zod' import { zValidator } from '@hono/zod-validator' import { createClient } from './supabase/client.ts' import { HTTPException } from 'hono/http-exception' -import { deployOnSupabase } from './supabase/deploy.ts' +import { deploy } from './supabase/deploy.ts' const app = new Hono() -app.get( +app.use('*', cors()) + +app.post( '/', zValidator( 'json', z.object({ databaseId: z.string(), - integrationId: z.string(), + integrationId: z.number().int(), databaseUrl: z.string(), }) ), async (c) => { const { databaseId, integrationId, databaseUrl: localDatabaseUrl } = c.req.valid('json') - const token = c.req.header('Authorization')?.replace('Bearer ', '') - - if (!token) { + const accessToken = c.req.header('Authorization')?.replace('Bearer ', '') + const refreshToken = c.req.header('X-Refresh-Token') + if (!accessToken || !refreshToken) { throw new HTTPException(401, { message: 'Unauthorized' }) } const supabase = createClient() - const { error } = await supabase.auth.getUser(token) + const { error } = await supabase.auth.setSession({ + access_token: accessToken, + refresh_token: refreshToken, + }) if (error) { throw new HTTPException(401, { message: 'Unauthorized' }) @@ -40,12 +46,13 @@ app.get( // local_database_id: databaseId, // }) try { - const { databaseUrl } = await deployOnSupabase( + const { databaseUrl } = await deploy( { supabase }, { databaseId, integrationId, localDatabaseUrl } ) return c.json({ databaseUrl }) } catch (error: unknown) { + console.error(error) if (error instanceof Error) { throw new HTTPException(500, { message: error.message }) } diff --git a/apps/deploy-worker/src/supabase/client.ts b/apps/deploy-worker/src/supabase/client.ts index 516a44bf..bdd8fc0c 100644 --- a/apps/deploy-worker/src/supabase/client.ts +++ b/apps/deploy-worker/src/supabase/client.ts @@ -1,5 +1,5 @@ import { createClient as createSupabaseClient } from '@supabase/supabase-js' -import type { Database } from './db-types.ts' +import type { Database } from './database-types.ts' export const supabaseAdmin = createSupabaseClient( process.env.SUPABASE_URL!, diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts new file mode 100644 index 00000000..c5ea4582 --- /dev/null +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -0,0 +1,139 @@ +import { supabaseAdmin } from './client.ts' +import { generatePassword } from './generate-password.ts' +import { getAccessToken } from './get-access-token.ts' +import { createManagementApiClient } from './management-api/client.ts' +import type { Credentials, SupabaseClient, SupabaseProviderMetadata } from './types.ts' +import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.ts' + +/** + * Create a new project on Supabase and store the relevant metadata in the database. + */ +export async function createDeployedDatabase( + ctx: { + supabase: SupabaseClient + }, + params: { + databaseId: string + integrationId: number + } +) { + const integration = await ctx.supabase + .from('deployment_provider_integrations') + .select('id,credentials,scope') + .eq('id', params.integrationId) + .single() + + if (integration.error) { + throw new Error('Cannot find integration', { cause: integration.error }) + } + + // first we need to create a new project on Supabase using the Management API + const credentials = integration.data.credentials as Credentials + + const accessToken = await getAccessToken( + { + supabase: ctx.supabase, + }, + { + integrationId: integration.data.id, + credentials, + } + ) + + const managementApiClient = createManagementApiClient(accessToken) + + const databasePassword = generatePassword() + + // create a new project on Supabase using the Management API + const { data: createdProject, error: createdProjectError } = await managementApiClient.POST( + '/v1/projects', + { + body: { + db_pass: databasePassword, + name: `database-build-${params.databaseId}`, + organization_id: (integration.data.scope as { organizationId: string }).organizationId, + region: 'us-east-1', + }, + } + ) + + if (createdProjectError) { + throw new Error('Failed to create project on Supabase', { + cause: createdProjectError, + }) + } + + await waitForProjectToBeHealthy({ managementApiClient }, { project: createdProject }) + + await waitForDatabaseToBeHealthy({ managementApiClient }, { project: createdProject }) + + // get the pooler details + const { data: pooler, error: poolerError } = await managementApiClient.GET( + '/v1/projects/{ref}/config/database/pooler', + { + params: { + path: { + ref: createdProject.id, + }, + }, + } + ) + + if (poolerError) { + throw new Error('Failed to get pooler details', { + cause: poolerError, + }) + } + + const primaryDatabase = pooler.find((db) => db.database_type === 'PRIMARY') + + if (!primaryDatabase) { + throw new Error('Primary database not found') + } + + // store the database password as a secret + const databasePasswordSecret = await supabaseAdmin.rpc('insert_secret', { + name: `supabase_database_password_${params.databaseId}`, + secret: databasePassword, + }) + + if (databasePasswordSecret.error) { + throw new Error('Cannot store database password as secret', { + cause: databasePasswordSecret.error, + }) + } + + const metadata: SupabaseProviderMetadata = { + project: { + id: createdProject.id, + organizationId: createdProject.organization_id, + name: createdProject.name, + region: createdProject.region, + createdAt: createdProject.created_at, + database: { + host: primaryDatabase.db_host, + name: primaryDatabase.db_name, + password: databasePasswordSecret.data, + // use session mode for prepared statements + port: 5432, + user: primaryDatabase.db_user, + }, + }, + } + + const deployedDatabase = await ctx.supabase + .from('deployed_databases') + .insert({ + deployment_provider_integration_id: integration.data.id, + local_database_id: params.databaseId, + provider_metadata: metadata, + }) + .select() + .single() + + if (deployedDatabase.error) { + throw new Error('Cannot create deployed database', { cause: deployedDatabase.error }) + } + + return deployedDatabase.data +} diff --git a/apps/deploy-worker/src/supabase/db-types.ts b/apps/deploy-worker/src/supabase/database-types.ts similarity index 100% rename from apps/deploy-worker/src/supabase/db-types.ts rename to apps/deploy-worker/src/supabase/database-types.ts diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index 81328230..3d56cfb6 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -1,22 +1,21 @@ import { supabaseAdmin, type createClient } from './client.ts' -import { getAccessToken } from './oauth.ts' -import { waitForDatabaseToBeReady } from './wait-for-database-to-be-ready.ts' -import type { Project, SupabaseProviderMetadata } from './types.ts' -import { generatePassword } from './generate-password.ts' +import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' +import { createDeployedDatabase } from './create-deployed-database.ts' +import { getDatabaseUrl } from './get-database-url.ts' const exec = promisify(execSync) -type Context = { - supabase: Awaited> -} - -export async function deployOnSupabase( - ctx: Context, - params: { databaseId: string; integrationId: string; localDatabaseUrl: string } +/** + * Deploy a local database on Supabase + * If the database was already deployed, it will overwrite the existing database data + */ +export async function deploy( + ctx: { supabase: SupabaseClient }, + params: { databaseId: string; integrationId: number; localDatabaseUrl: string } ) { - // check if there is the database was already deployed - let deployedDatabase = await ctx.supabase + // check if the database was already deployed + const deployedDatabase = await ctx.supabase .from('deployed_databases') .select('*') .eq('local_database_id', params.databaseId) @@ -28,111 +27,20 @@ export async function deployOnSupabase( } if (!deployedDatabase.data) { - const integration = await ctx.supabase - .from('deployment_provider_integrations') - .select('id,credentials,scope') - .eq('id', params.integrationId) - .single() - - if (integration.error) { - throw new Error('Cannot find integration', { cause: integration.error }) - } - - // first we need to create a new project on Supabase using the Management API - const credentials = integration.data.credentials as { - expiresAt: string - refreshToken: string - accessToken: string - } - - const accessToken = await getAccessToken(integration.data.id, credentials) - - const databasePassword = generatePassword() - - // create a new project on Supabase using the Management API - const projectResponse = await fetch('https://api.supabase.com/v1/projects', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${accessToken}`, - }, - body: JSON.stringify({ - db_pass: databasePassword, - name: `database-build-${params.databaseId}`, - organization_id: (integration.data.scope as { organizationId: string }).organizationId, - region: 'us-east-1', - desired_instance_size: 'micro', - }), - }) - - if (!projectResponse.ok) { - throw new Error('Failed to create project on Supabase', { - cause: { - status: projectResponse.status, - statusText: projectResponse.statusText, - }, - }) - } - - const project = (await projectResponse.json()) as Project - - // wait for the database to be ready - await waitForDatabaseToBeReady(project, accessToken) - - // store the database password as a secret - const databasePasswordSecret = await supabaseAdmin.rpc('insert_secret', { - name: `supabase_database_password_${params.databaseId}`, - secret: databasePassword, - }) - - if (databasePasswordSecret.error) { - throw new Error('Cannot store database password as secret', { - cause: databasePasswordSecret.error, - }) - } - - const metadata: SupabaseProviderMetadata = { - project: { - ...project, - database: { - ...project.database, - password: databasePasswordSecret.data, - }, - }, - } - - deployedDatabase = await ctx.supabase - .from('deployed_databases') - .insert({ - deployment_provider_integration_id: integration.data.id, - local_database_id: params.databaseId, - provider_metadata: metadata, - }) - .select() - .single() - - if (deployedDatabase.error) { - throw new Error('Cannot create deployed database', { cause: deployedDatabase.error }) - } + deployedDatabase.data = await createDeployedDatabase( + { supabase: ctx.supabase }, + { databaseId: params.databaseId, integrationId: params.integrationId } + ) } - // get the remote database url - const { project } = deployedDatabase.data!.provider_metadata as SupabaseProviderMetadata - - const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { - secret_id: project.database.password, + // get the database url + const databaseUrl = await getDatabaseUrl({ + project: (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project, }) - if (databasePasswordSecret.error) { - throw new Error('Cannot read database password secret', { - cause: databasePasswordSecret.error, - }) - } - - const remoteDatabaseUrl = `postgresql://postgres.${project.id}:${databasePasswordSecret.data}@${project.database.host}:5432/postgres` - // use pg_dump and pg_restore to transfer the data from the local database to the remote database - const command = `pg_dump "${params.localDatabaseUrl}" -Fc -C | pg_restore --dbname=${remoteDatabaseUrl}` + const command = `pg_dump "${params.localDatabaseUrl}" -Fc | pg_restore -d "${databaseUrl}" --clean --if-exists` + console.log(command) try { await exec(command) } catch (error) { @@ -142,6 +50,6 @@ export async function deployOnSupabase( } return { - databaseUrl: remoteDatabaseUrl, + databaseUrl, } } diff --git a/apps/deploy-worker/src/supabase/generate-password.ts b/apps/deploy-worker/src/supabase/generate-password.ts index 9be3efca..aedf60d8 100644 --- a/apps/deploy-worker/src/supabase/generate-password.ts +++ b/apps/deploy-worker/src/supabase/generate-password.ts @@ -1,3 +1,6 @@ +/** + * Generate a random password with a length of 16 characters. + */ export function generatePassword(): string { const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' const length = 16 diff --git a/apps/deploy-worker/src/supabase/get-access-token.ts b/apps/deploy-worker/src/supabase/get-access-token.ts new file mode 100644 index 00000000..a936e454 --- /dev/null +++ b/apps/deploy-worker/src/supabase/get-access-token.ts @@ -0,0 +1,99 @@ +import { supabaseAdmin } from './client.ts' +import type { Credentials, SupabaseClient } from './types.ts' + +/** + * Get the access token for a given Supabase integration. + */ +export async function getAccessToken( + ctx: { supabase: SupabaseClient }, + params: { + integrationId: number + credentials: Credentials + } +): Promise { + // if the token expires in less than 1 hour, refresh it + if (new Date(params.credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { + const refreshToken = await supabaseAdmin.rpc('read_secret', { + secret_id: params.credentials.refreshToken, + }) + + if (refreshToken.error) { + throw new Error('Failed to read refresh token', { cause: refreshToken.error }) + } + + const now = Date.now() + + const newCredentialsResponse = await fetch('https://api.supabase.com/v1/oauth/token', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: params.credentials.refreshToken, + }), + }) + + if (!newCredentialsResponse.ok) { + throw new Error('Failed to fetch new credentials', { + cause: { + status: newCredentialsResponse.status, + statusText: newCredentialsResponse.statusText, + }, + }) + } + + const newCredentials = (await newCredentialsResponse.json()) as { + access_token: string + refresh_token: string + expires_in: number + } + + const expiresAt = new Date(now + newCredentials.expires_in * 1000) + + const updateRefreshToken = await supabaseAdmin.rpc('update_secret', { + secret_id: params.credentials.refreshToken, + new_secret: newCredentials.refresh_token, + }) + + if (updateRefreshToken.error) { + throw new Error('Failed to update refresh token', { cause: updateRefreshToken.error }) + } + + const updateAccessToken = await supabaseAdmin.rpc('update_secret', { + secret_id: params.credentials.accessToken, + new_secret: newCredentials.access_token, + }) + + if (updateAccessToken.error) { + throw new Error('Failed to update access token', { cause: updateAccessToken.error }) + } + + const updateIntegration = await ctx.supabase + .from('deployment_provider_integrations') + .update({ + credentials: { + accessToken: params.credentials.accessToken, + expiresAt: expiresAt.toISOString(), + refreshToken: params.credentials.refreshToken, + }, + }) + .eq('id', params.integrationId) + + if (updateIntegration.error) { + throw new Error('Failed to update integration', { cause: updateIntegration.error }) + } + } + + const accessToken = await supabaseAdmin.rpc('read_secret', { + secret_id: params.credentials.accessToken, + }) + + if (accessToken.error) { + throw new Error('Failed to read access token', { cause: accessToken.error }) + } + + return accessToken.data +} diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/apps/deploy-worker/src/supabase/get-database-url.ts new file mode 100644 index 00000000..f311290d --- /dev/null +++ b/apps/deploy-worker/src/supabase/get-database-url.ts @@ -0,0 +1,21 @@ +import { supabaseAdmin } from './client.ts' +import type { SupabaseProviderMetadata } from './types.ts' + +/** + * Get the database url for a given Supabase project. + */ +export async function getDatabaseUrl(params: { project: SupabaseProviderMetadata['project'] }) { + const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { + secret_id: params.project.database.password, + }) + + if (databasePasswordSecret.error) { + throw new Error('Cannot read database password secret', { + cause: databasePasswordSecret.error, + }) + } + + const { database } = params.project + + return `postgresql://${database.user}:${databasePasswordSecret.data}@${database.host}:${database.port}/${database.name}` +} diff --git a/apps/deploy-worker/src/supabase/management-api.ts b/apps/deploy-worker/src/supabase/management-api.ts new file mode 100644 index 00000000..e69de29b diff --git a/apps/deploy-worker/src/supabase/management-api/client.ts b/apps/deploy-worker/src/supabase/management-api/client.ts new file mode 100644 index 00000000..c43e62c0 --- /dev/null +++ b/apps/deploy-worker/src/supabase/management-api/client.ts @@ -0,0 +1,11 @@ +import createClient from 'openapi-fetch' +import type { paths } from './types.ts' + +export const createManagementApiClient = (accessToken: string) => + createClient({ + baseUrl: 'https://api.supabase.com/', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }) diff --git a/apps/deploy-worker/src/supabase/management-api/types.ts b/apps/deploy-worker/src/supabase/management-api/types.ts new file mode 100644 index 00000000..42e6310b --- /dev/null +++ b/apps/deploy-worker/src/supabase/management-api/types.ts @@ -0,0 +1,4723 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/v1/branches/{branch_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get database branch config + * @description Fetches configurations of the specified database branch + */ + get: operations["v1-get-a-branch-config"]; + put?: never; + post?: never; + /** + * Delete a database branch + * @description Deletes the specified database branch + */ + delete: operations["v1-delete-a-branch"]; + options?: never; + head?: never; + /** + * Update database branch config + * @description Updates the configuration of the specified database branch + */ + patch: operations["v1-update-a-branch-config"]; + trace?: never; + }; + "/v1/branches/{branch_id}/reset": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Resets a database branch + * @description Resets the specified database branch + */ + post: operations["v1-reset-a-branch"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all projects + * @description Returns a list of all projects you've previously created. + */ + get: operations["v1-list-all-projects"]; + put?: never; + /** Create a project */ + post: operations["v1-create-a-project"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/organizations": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all organizations + * @description Returns a list of organizations that you currently belong to. + */ + get: operations["v1-list-all-organizations"]; + put?: never; + /** Create an organization */ + post: operations["v1-create-an-organization"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/oauth/authorize": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Authorize user through oauth */ + get: operations["v1-authorize-user"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/oauth/token": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Exchange auth code for user's access and refresh token */ + post: operations["v1-exchange-oauth-token"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/snippets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Lists SQL snippets for the logged in user */ + get: operations["v1-list-all-snippets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/snippets/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets a specific SQL snippet */ + get: operations["v1-get-a-snippet"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/api-keys": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get project api keys */ + get: operations["v1-get-project-api-keys"]; + put?: never; + /** [Alpha] Creates a new API key for the project */ + post: operations["createApiKey"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/api-keys/{id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** [Alpha] Deletes an API key for the project */ + delete: operations["deleteApiKey"]; + options?: never; + head?: never; + /** [Alpha] Updates an API key for the project */ + patch: operations["updateApiKey"]; + trace?: never; + }; + "/v1/projects/{ref}/branches": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all database branches + * @description Returns all database branches of the specified project. + */ + get: operations["v1-list-all-branches"]; + put?: never; + /** + * Create a database branch + * @description Creates a database branch from the specified project. + */ + post: operations["v1-create-a-branch"]; + /** + * Disables preview branching + * @description Disables preview branching for the specified project + */ + delete: operations["v1-disable-preview-branching"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/custom-hostname": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Gets project's custom hostname config */ + get: operations["v1-get-hostname-config"]; + put?: never; + post?: never; + /** [Beta] Deletes a project's custom hostname configuration */ + delete: operations["v1-Delete hostname config"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/custom-hostname/initialize": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Updates project's custom hostname configuration */ + post: operations["v1-update-hostname-config"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/custom-hostname/reverify": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Attempts to verify the DNS configuration for project's custom hostname configuration */ + post: operations["v1-verify-dns-config"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/custom-hostname/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Activates a custom hostname for a project. */ + post: operations["v1-activate-custom-hostname"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/network-bans/retrieve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Gets project's network bans */ + post: operations["v1-list-all-network-bans"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/network-bans": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** [Beta] Remove network bans. */ + delete: operations["v1-delete-network-bans"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/network-restrictions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Gets project's network restrictions */ + get: operations["v1-get-network-restrictions"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/network-restrictions/apply": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Updates project's network restrictions */ + post: operations["v1-update-network-restrictions"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/pgsodium": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Gets project's pgsodium config */ + get: operations["v1-get-pgsodium-config"]; + /** [Beta] Updates project's pgsodium config. Updating the root_key can cause all data encrypted with the older key to become inaccessible. */ + put: operations["v1-update-pgsodium-config"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/postgrest": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's postgrest config */ + get: operations["v1-get-postgrest-service-config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates project's postgrest config */ + patch: operations["v1-update-postgrest-service-config"]; + trace?: never; + }; + "/v1/projects/{ref}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets a specific project that belongs to the authenticated user */ + get: operations["v1-get-project"]; + put?: never; + post?: never; + /** Deletes the given project */ + delete: operations["v1-delete-a-project"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/secrets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all secrets + * @description Returns all secrets you've previously added to the specified project. + */ + get: operations["v1-list-all-secrets"]; + put?: never; + /** + * Bulk create secrets + * @description Creates multiple secrets and adds them to the specified project. + */ + post: operations["v1-bulk-create-secrets"]; + /** + * Bulk delete secrets + * @description Deletes all secrets with the given names from the specified project + */ + delete: operations["v1-bulk-delete-secrets"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/ssl-enforcement": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Get project's SSL enforcement configuration. */ + get: operations["v1-get-ssl-enforcement-config"]; + /** [Beta] Update project's SSL enforcement configuration. */ + put: operations["v1-update-ssl-enforcement-config"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/types/typescript": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Generate TypeScript types + * @description Returns the TypeScript types of your schema for use with supabase-js. + */ + get: operations["v1-generate-typescript-types"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/vanity-subdomain": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Gets current vanity subdomain config */ + get: operations["v1-get-vanity-subdomain-config"]; + put?: never; + post?: never; + /** [Beta] Deletes a project's vanity subdomain configuration */ + delete: operations["v1-deactivate-vanity-subdomain-config"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/vanity-subdomain/check-availability": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Checks vanity subdomain availability */ + post: operations["v1-check-vanity-subdomain-availability"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/vanity-subdomain/activate": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Activates a vanity subdomain for a project. */ + post: operations["v1-activate-vanity-subdomain-config"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/upgrade": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Upgrades the project's Postgres version */ + post: operations["v1-upgrade-postgres-version"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/upgrade/eligibility": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Returns the project's eligibility for upgrades */ + get: operations["v1-get-postgres-upgrade-eligibility"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/upgrade/status": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Beta] Gets the latest status of the project's upgrade */ + get: operations["v1-get-postgres-upgrade-status"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/readonly": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Returns project's readonly mode status */ + get: operations["v1-get-readonly-mode-status"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/readonly/temporary-disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Disables project's readonly mode for the next 15 minutes */ + post: operations["v1-disable-readonly-mode-temporarily"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/read-replicas/setup": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Set up a read replica */ + post: operations["v1-setup-a-read-replica"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/read-replicas/remove": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Remove a read replica */ + post: operations["v1-remove-a-read-replica"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's service health status */ + get: operations["v1-get-services-health"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/database/postgres": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's Postgres config */ + get: operations["v1-get-postgres-config"]; + /** Updates project's Postgres config */ + put: operations["v1-update-postgres-config"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/database/pgbouncer": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Get project's pgbouncer config */ + get: operations["v1-get-project-pgbouncer-config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/database/pooler": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's supavisor config */ + get: operations["v1-get-supavisor-config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates project's supavisor config */ + patch: operations["v1-update-supavisor-config"]; + trace?: never; + }; + "/v1/projects/{ref}/config/auth": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's auth config */ + get: operations["v1-get-auth-service-config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates a project's auth config */ + patch: operations["v1-update-auth-service-config"]; + trace?: never; + }; + "/v1/projects/{ref}/config/auth/third-party-auth": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Alpha] Lists all third-party auth integrations */ + get: operations["listTPAForProject"]; + put?: never; + /** Creates a new third-party auth integration */ + post: operations["createTPAForProject"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/auth/third-party-auth/{tpa_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** [Alpha] Get a third-party integration */ + get: operations["getTPAForProject"]; + put?: never; + post?: never; + /** [Alpha] Removes a third-party auth integration */ + delete: operations["deleteTPAForProject"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/database/query": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Run sql query */ + post: operations["v1-run-a-query"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/database/webhooks/enable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** [Beta] Enables Database Webhooks on the project */ + post: operations["v1-enable-database-webhook"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/functions": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List all functions + * @description Returns all functions you've previously added to the specified project. + */ + get: operations["v1-list-all-functions"]; + put?: never; + /** + * Create a function + * @description Creates a function and adds it to the specified project. + */ + post: operations["v1-create-a-function"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/functions/{function_slug}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Retrieve a function + * @description Retrieves a function with the specified slug and project. + */ + get: operations["v1-get-a-function"]; + put?: never; + post?: never; + /** + * Delete a function + * @description Deletes a function with the specified slug from the specified project. + */ + delete: operations["v1-delete-a-function"]; + options?: never; + head?: never; + /** + * Update a function + * @description Updates a function with the specified slug and project. + */ + patch: operations["v1-update-a-function"]; + trace?: never; + }; + "/v1/projects/{ref}/functions/{function_slug}/body": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Retrieve a function body + * @description Retrieves a function body for the specified slug and project. + */ + get: operations["v1-get-a-function-body"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/storage/buckets": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Lists all buckets */ + get: operations["v1-list-all-buckets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/auth/sso/providers": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Lists all SSO providers */ + get: operations["v1-list-all-sso-provider"]; + put?: never; + /** Creates a new SSO provider */ + post: operations["v1-create-a-sso-provider"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/config/auth/sso/providers/{provider_id}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets a SSO provider by its UUID */ + get: operations["v1-get-a-sso-provider"]; + /** Updates a SSO provider by its UUID */ + put: operations["v1-update-a-sso-provider"]; + post?: never; + /** Removes a SSO provider by its UUID */ + delete: operations["v1-delete-a-sso-provider"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/database/backups": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Lists all backups */ + get: operations["v1-list-all-backups"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/projects/{ref}/database/backups/restore-pitr": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Restores a PITR backup for a database */ + post: operations["v1-restore-pitr-backup"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/organizations/{slug}/members": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** List members of an organization */ + get: operations["v1-list-organization-members"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/v1/organizations/{slug}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets information about the organization */ + get: operations["v1-get-an-organization"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + BranchDetailResponse: { + db_port: number; + ref: string; + postgres_version: string; + postgres_engine: string; + release_channel: string; + /** @enum {string} */ + status: "ACTIVE_HEALTHY" | "ACTIVE_UNHEALTHY" | "COMING_UP" | "GOING_DOWN" | "INACTIVE" | "INIT_FAILED" | "REMOVED" | "RESTARTING" | "UNKNOWN" | "UPGRADING" | "PAUSING" | "RESTORING" | "RESTORE_FAILED" | "PAUSE_FAILED" | "RESIZING"; + db_host: string; + db_user?: string; + db_pass?: string; + jwt_secret?: string; + }; + UpdateBranchBody: { + branch_name?: string; + git_branch?: string; + reset_on_push?: boolean; + persistent?: boolean; + /** @enum {string} */ + status?: "CREATING_PROJECT" | "RUNNING_MIGRATIONS" | "MIGRATIONS_PASSED" | "MIGRATIONS_FAILED" | "FUNCTIONS_DEPLOYED" | "FUNCTIONS_FAILED"; + }; + BranchResponse: { + id: string; + name: string; + project_ref: string; + parent_project_ref: string; + is_default: boolean; + git_branch?: string; + pr_number?: number; + latest_check_run_id?: number; + reset_on_push: boolean; + persistent: boolean; + /** @enum {string} */ + status: "CREATING_PROJECT" | "RUNNING_MIGRATIONS" | "MIGRATIONS_PASSED" | "MIGRATIONS_FAILED" | "FUNCTIONS_DEPLOYED" | "FUNCTIONS_FAILED"; + created_at: string; + updated_at: string; + }; + BranchDeleteResponse: { + message: string; + }; + BranchResetResponse: { + message: string; + }; + V1DatabaseResponse: { + /** @description Database host */ + host: string; + /** @description Database version */ + version: string; + /** @description Database engine */ + postgres_engine: string; + /** @description Release channel */ + release_channel: string; + }; + V1ProjectResponse: { + /** @description Id of your project */ + id: string; + /** @description Slug of your organization */ + organization_id: string; + /** @description Name of your project */ + name: string; + /** + * @description Region of your project + * @example us-east-1 + */ + region: string; + /** + * @description Creation timestamp + * @example 2023-03-29T16:32:59Z + */ + created_at: string; + database?: components["schemas"]["V1DatabaseResponse"]; + /** @enum {string} */ + status: "ACTIVE_HEALTHY" | "ACTIVE_UNHEALTHY" | "COMING_UP" | "GOING_DOWN" | "INACTIVE" | "INIT_FAILED" | "REMOVED" | "RESTARTING" | "UNKNOWN" | "UPGRADING" | "PAUSING" | "RESTORING" | "RESTORE_FAILED" | "PAUSE_FAILED" | "RESIZING"; + }; + /** @enum {string} */ + DesiredInstanceSize: "micro" | "small" | "medium" | "large" | "xlarge" | "2xlarge" | "4xlarge" | "8xlarge" | "12xlarge" | "16xlarge"; + /** @enum {string} */ + ReleaseChannel: "internal" | "alpha" | "beta" | "ga" | "withdrawn"; + /** + * @description Postgres engine version. If not provided, the latest version will be used. + * @enum {string} + */ + PostgresEngine: "15"; + V1CreateProjectBody: { + /** @description Database password */ + db_pass: string; + /** @description Name of your project, should not contain dots */ + name: string; + /** @description Slug of your organization */ + organization_id: string; + /** + * @deprecated + * @description Subscription Plan is now set on organization level and is ignored in this request + * @example free + * @enum {string} + */ + plan?: "free" | "pro"; + /** + * @description Region you want your server to reside in + * @example us-east-1 + * @enum {string} + */ + region: "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2" | "ap-east-1" | "ap-southeast-1" | "ap-northeast-1" | "ap-northeast-2" | "ap-southeast-2" | "eu-west-1" | "eu-west-2" | "eu-west-3" | "eu-north-1" | "eu-central-1" | "eu-central-2" | "ca-central-1" | "ap-south-1" | "sa-east-1"; + /** + * @deprecated + * @description This field is deprecated and is ignored in this request + */ + kps_enabled?: boolean; + desired_instance_size?: components["schemas"]["DesiredInstanceSize"]; + /** + * @description Template URL used to create the project from the CLI. + * @example https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone + */ + template_url?: string; + release_channel?: components["schemas"]["ReleaseChannel"]; + postgres_engine?: components["schemas"]["PostgresEngine"]; + }; + OrganizationResponseV1: { + id: string; + name: string; + }; + CreateOrganizationBodyV1: { + name: string; + }; + OAuthTokenBody: { + /** @enum {string} */ + grant_type: "authorization_code" | "refresh_token"; + client_id: string; + client_secret: string; + code?: string; + code_verifier?: string; + redirect_uri?: string; + refresh_token?: string; + }; + OAuthTokenResponse: { + /** @enum {string} */ + token_type: "Bearer"; + access_token: string; + refresh_token: string; + expires_in: number; + }; + SnippetProject: { + id: number; + name: string; + }; + SnippetUser: { + id: number; + username: string; + }; + SnippetMeta: { + id: string; + inserted_at: string; + updated_at: string; + /** @enum {string} */ + type: "sql"; + /** @enum {string} */ + visibility: "user" | "project" | "org" | "public"; + name: string; + description?: string; + project: components["schemas"]["SnippetProject"]; + owner: components["schemas"]["SnippetUser"]; + updated_by: components["schemas"]["SnippetUser"]; + }; + SnippetList: { + data: components["schemas"]["SnippetMeta"][]; + }; + SnippetContent: { + favorite: boolean; + schema_version: string; + sql: string; + }; + SnippetResponse: { + id: string; + inserted_at: string; + updated_at: string; + /** @enum {string} */ + type: "sql"; + /** @enum {string} */ + visibility: "user" | "project" | "org" | "public"; + name: string; + description?: string; + project: components["schemas"]["SnippetProject"]; + owner: components["schemas"]["SnippetUser"]; + updated_by: components["schemas"]["SnippetUser"]; + content: components["schemas"]["SnippetContent"]; + }; + ApiKeySecretJWTTemplate: { + role: string; + }; + ApiKeyResponse: { + name: string; + api_key: string; + id?: string | null; + type?: Record; + prefix?: string | null; + description?: string | null; + hash?: string | null; + secret_jwt_template?: components["schemas"]["ApiKeySecretJWTTemplate"] | null; + inserted_at?: string | null; + updated_at?: string | null; + }; + CreateApiKeyBody: { + /** @enum {string} */ + type: "publishable" | "secret"; + description?: string | null; + secret_jwt_template?: components["schemas"]["ApiKeySecretJWTTemplate"] | null; + }; + UpdateApiKeyBody: { + description?: string | null; + secret_jwt_template?: components["schemas"]["ApiKeySecretJWTTemplate"] | null; + }; + CreateBranchBody: { + desired_instance_size?: components["schemas"]["DesiredInstanceSize"]; + release_channel?: components["schemas"]["ReleaseChannel"]; + postgres_engine?: components["schemas"]["PostgresEngine"]; + branch_name: string; + git_branch?: string; + persistent?: boolean; + region?: string; + }; + ValidationRecord: { + txt_name: string; + txt_value: string; + }; + ValidationError: { + message: string; + }; + SslValidation: { + status: string; + validation_records: components["schemas"]["ValidationRecord"][]; + validation_errors?: components["schemas"]["ValidationError"][]; + }; + OwnershipVerification: { + type: string; + name: string; + value: string; + }; + CustomHostnameDetails: { + id: string; + hostname: string; + ssl: components["schemas"]["SslValidation"]; + ownership_verification: components["schemas"]["OwnershipVerification"]; + custom_origin_server: string; + verification_errors?: string[]; + status: string; + }; + CfResponse: { + success: boolean; + errors: Record[]; + messages: Record[]; + result: components["schemas"]["CustomHostnameDetails"]; + }; + UpdateCustomHostnameResponse: { + /** @enum {string} */ + status: "1_not_started" | "2_initiated" | "3_challenge_verified" | "4_origin_setup_completed" | "5_services_reconfigured"; + custom_hostname: string; + data: components["schemas"]["CfResponse"]; + }; + UpdateCustomHostnameBody: { + custom_hostname: string; + }; + NetworkBanResponse: { + banned_ipv4_addresses: string[]; + }; + RemoveNetworkBanRequest: { + ipv4_addresses: string[]; + }; + NetworkRestrictionsRequest: { + dbAllowedCidrs?: string[]; + dbAllowedCidrsV6?: string[]; + }; + NetworkRestrictionsResponse: { + /** @enum {string} */ + entitlement: "disallowed" | "allowed"; + config: components["schemas"]["NetworkRestrictionsRequest"]; + old_config?: components["schemas"]["NetworkRestrictionsRequest"]; + /** @enum {string} */ + status: "stored" | "applied"; + }; + PgsodiumConfigResponse: { + root_key: string; + }; + UpdatePgsodiumConfigBody: { + root_key: string; + }; + PostgrestConfigWithJWTSecretResponse: { + max_rows: number; + /** @description If `null`, the value is automatically configured based on compute size. */ + db_pool: number | null; + db_schema: string; + db_extra_search_path: string; + jwt_secret?: string; + }; + UpdatePostgrestConfigBody: { + max_rows?: number; + db_pool?: number; + db_extra_search_path?: string; + db_schema?: string; + }; + V1PostgrestConfigResponse: { + max_rows: number; + /** @description If `null`, the value is automatically configured based on compute size. */ + db_pool: number | null; + db_schema: string; + db_extra_search_path: string; + }; + V1ProjectRefResponse: { + id: number; + ref: string; + name: string; + }; + SecretResponse: { + name: string; + value: string; + }; + CreateSecretBody: { + /** + * @description Secret name must not start with the SUPABASE_ prefix. + * @example string + */ + name: string; + value: string; + }; + SslEnforcements: { + database: boolean; + }; + SslEnforcementResponse: { + currentConfig: components["schemas"]["SslEnforcements"]; + appliedSuccessfully: boolean; + }; + SslEnforcementRequest: { + requestedConfig: components["schemas"]["SslEnforcements"]; + }; + TypescriptResponse: { + types: string; + }; + VanitySubdomainConfigResponse: { + /** @enum {string} */ + status: "not-used" | "custom-domain-used" | "active"; + custom_domain?: string; + }; + VanitySubdomainBody: { + vanity_subdomain: string; + }; + SubdomainAvailabilityResponse: { + available: boolean; + }; + ActivateVanitySubdomainResponse: { + custom_domain: string; + }; + UpgradeDatabaseBody: { + release_channel: components["schemas"]["ReleaseChannel"]; + target_version: string; + }; + ProjectUpgradeInitiateResponse: { + tracking_id: string; + }; + ProjectVersion: { + postgres_version: components["schemas"]["PostgresEngine"]; + release_channel: components["schemas"]["ReleaseChannel"]; + app_version: string; + }; + ProjectUpgradeEligibilityResponse: { + current_app_version_release_channel: components["schemas"]["ReleaseChannel"]; + eligible: boolean; + current_app_version: string; + latest_app_version: string; + target_upgrade_versions: components["schemas"]["ProjectVersion"][]; + potential_breaking_changes: string[]; + duration_estimate_hours: number; + legacy_auth_custom_roles: string[]; + extension_dependent_objects: string[]; + }; + DatabaseUpgradeStatus: { + initiated_at: string; + latest_status_at: string; + target_version: number; + /** @enum {string} */ + error?: "1_upgraded_instance_launch_failed" | "2_volume_detachchment_from_upgraded_instance_failed" | "3_volume_attachment_to_original_instance_failed" | "4_data_upgrade_initiation_failed" | "5_data_upgrade_completion_failed" | "6_volume_detachchment_from_original_instance_failed" | "7_volume_attachment_to_upgraded_instance_failed" | "8_upgrade_completion_failed" | "9_post_physical_backup_failed"; + /** @enum {string} */ + progress?: "0_requested" | "1_started" | "2_launched_upgraded_instance" | "3_detached_volume_from_upgraded_instance" | "4_attached_volume_to_original_instance" | "5_initiated_data_upgrade" | "6_completed_data_upgrade" | "7_detached_volume_from_original_instance" | "8_attached_volume_to_upgraded_instance" | "9_completed_upgrade" | "10_completed_post_physical_backup"; + /** @enum {number} */ + status: 0 | 1 | 2; + }; + DatabaseUpgradeStatusResponse: { + databaseUpgradeStatus: components["schemas"]["DatabaseUpgradeStatus"] | null; + }; + ReadOnlyStatusResponse: { + enabled: boolean; + override_enabled: boolean; + override_active_until: string; + }; + SetUpReadReplicaBody: { + /** + * @description Region you want your read replica to reside in + * @example us-east-1 + * @enum {string} + */ + read_replica_region: "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2" | "ap-east-1" | "ap-southeast-1" | "ap-northeast-1" | "ap-northeast-2" | "ap-southeast-2" | "eu-west-1" | "eu-west-2" | "eu-west-3" | "eu-north-1" | "eu-central-1" | "eu-central-2" | "ca-central-1" | "ap-south-1" | "sa-east-1"; + }; + RemoveReadReplicaBody: { + database_identifier: string; + }; + AuthHealthResponse: { + name: string; + version: string; + description: string; + }; + RealtimeHealthResponse: { + healthy: boolean; + db_connected: boolean; + connected_cluster: number; + }; + V1ServiceHealthResponse: { + info?: components["schemas"]["AuthHealthResponse"] | components["schemas"]["RealtimeHealthResponse"]; + /** @enum {string} */ + name: "auth" | "db" | "pooler" | "realtime" | "rest" | "storage"; + healthy: boolean; + /** @enum {string} */ + status: "COMING_UP" | "ACTIVE_HEALTHY" | "UNHEALTHY"; + error?: string; + }; + PostgresConfigResponse: { + effective_cache_size?: string; + logical_decoding_work_mem?: string; + maintenance_work_mem?: string; + max_connections?: number; + max_locks_per_transaction?: number; + max_parallel_maintenance_workers?: number; + max_parallel_workers?: number; + max_parallel_workers_per_gather?: number; + max_replication_slots?: number; + max_slot_wal_keep_size?: string; + max_standby_archive_delay?: string; + max_standby_streaming_delay?: string; + max_wal_size?: string; + max_wal_senders?: number; + max_worker_processes?: number; + shared_buffers?: string; + statement_timeout?: string; + wal_keep_size?: string; + wal_sender_timeout?: string; + work_mem?: string; + /** @enum {string} */ + session_replication_role?: "origin" | "replica" | "local"; + }; + UpdatePostgresConfigBody: { + effective_cache_size?: string; + logical_decoding_work_mem?: string; + maintenance_work_mem?: string; + max_connections?: number; + max_locks_per_transaction?: number; + max_parallel_maintenance_workers?: number; + max_parallel_workers?: number; + max_parallel_workers_per_gather?: number; + max_replication_slots?: number; + max_slot_wal_keep_size?: string; + max_standby_archive_delay?: string; + max_standby_streaming_delay?: string; + max_wal_size?: string; + max_wal_senders?: number; + max_worker_processes?: number; + shared_buffers?: string; + statement_timeout?: string; + wal_keep_size?: string; + wal_sender_timeout?: string; + work_mem?: string; + restart_database?: boolean; + /** @enum {string} */ + session_replication_role?: "origin" | "replica" | "local"; + }; + V1PgbouncerConfigResponse: { + /** @enum {string} */ + pool_mode?: "transaction" | "session" | "statement"; + default_pool_size?: number; + ignore_startup_parameters?: string; + max_client_conn?: number; + connection_string?: string; + }; + SupavisorConfigResponse: { + identifier: string; + /** @enum {string} */ + database_type: "PRIMARY" | "READ_REPLICA"; + is_using_scram_auth: boolean; + db_user: string; + db_host: string; + db_port: number; + db_name: string; + connectionString: string; + default_pool_size: number | null; + max_client_conn: number | null; + /** @enum {string} */ + pool_mode: "transaction" | "session"; + }; + UpdateSupavisorConfigBody: { + default_pool_size?: number | null; + /** + * @deprecated + * @description This field is deprecated and is ignored in this request + * @enum {string} + */ + pool_mode?: "transaction" | "session"; + }; + UpdateSupavisorConfigResponse: { + default_pool_size: number | null; + /** @enum {string} */ + pool_mode: "transaction" | "session"; + }; + AuthConfigResponse: { + api_max_request_duration: number | null; + db_max_pool_size: number | null; + disable_signup: boolean | null; + external_anonymous_users_enabled: boolean | null; + external_apple_additional_client_ids: string | null; + external_apple_client_id: string | null; + external_apple_enabled: boolean | null; + external_apple_secret: string | null; + external_azure_client_id: string | null; + external_azure_enabled: boolean | null; + external_azure_secret: string | null; + external_azure_url: string | null; + external_bitbucket_client_id: string | null; + external_bitbucket_enabled: boolean | null; + external_bitbucket_secret: string | null; + external_discord_client_id: string | null; + external_discord_enabled: boolean | null; + external_discord_secret: string | null; + external_email_enabled: boolean | null; + external_facebook_client_id: string | null; + external_facebook_enabled: boolean | null; + external_facebook_secret: string | null; + external_figma_client_id: string | null; + external_figma_enabled: boolean | null; + external_figma_secret: string | null; + external_github_client_id: string | null; + external_github_enabled: boolean | null; + external_github_secret: string | null; + external_gitlab_client_id: string | null; + external_gitlab_enabled: boolean | null; + external_gitlab_secret: string | null; + external_gitlab_url: string | null; + external_google_additional_client_ids: string | null; + external_google_client_id: string | null; + external_google_enabled: boolean | null; + external_google_secret: string | null; + external_google_skip_nonce_check: boolean | null; + external_kakao_client_id: string | null; + external_kakao_enabled: boolean | null; + external_kakao_secret: string | null; + external_keycloak_client_id: string | null; + external_keycloak_enabled: boolean | null; + external_keycloak_secret: string | null; + external_keycloak_url: string | null; + external_linkedin_oidc_client_id: string | null; + external_linkedin_oidc_enabled: boolean | null; + external_linkedin_oidc_secret: string | null; + external_slack_oidc_client_id: string | null; + external_slack_oidc_enabled: boolean | null; + external_slack_oidc_secret: string | null; + external_notion_client_id: string | null; + external_notion_enabled: boolean | null; + external_notion_secret: string | null; + external_phone_enabled: boolean | null; + external_slack_client_id: string | null; + external_slack_enabled: boolean | null; + external_slack_secret: string | null; + external_spotify_client_id: string | null; + external_spotify_enabled: boolean | null; + external_spotify_secret: string | null; + external_twitch_client_id: string | null; + external_twitch_enabled: boolean | null; + external_twitch_secret: string | null; + external_twitter_client_id: string | null; + external_twitter_enabled: boolean | null; + external_twitter_secret: string | null; + external_workos_client_id: string | null; + external_workos_enabled: boolean | null; + external_workos_secret: string | null; + external_workos_url: string | null; + external_zoom_client_id: string | null; + external_zoom_enabled: boolean | null; + external_zoom_secret: string | null; + hook_custom_access_token_enabled: boolean | null; + hook_custom_access_token_uri: string | null; + hook_custom_access_token_secrets: string | null; + hook_mfa_verification_attempt_enabled: boolean | null; + hook_mfa_verification_attempt_uri: string | null; + hook_mfa_verification_attempt_secrets: string | null; + hook_password_verification_attempt_enabled: boolean | null; + hook_password_verification_attempt_uri: string | null; + hook_password_verification_attempt_secrets: string | null; + hook_send_sms_enabled: boolean | null; + hook_send_sms_uri: string | null; + hook_send_sms_secrets: string | null; + hook_send_email_enabled: boolean | null; + hook_send_email_uri: string | null; + hook_send_email_secrets: string | null; + jwt_exp: number | null; + mailer_allow_unverified_email_sign_ins: boolean | null; + mailer_autoconfirm: boolean | null; + mailer_otp_exp: number; + mailer_otp_length: number | null; + mailer_secure_email_change_enabled: boolean | null; + mailer_subjects_confirmation: string | null; + mailer_subjects_email_change: string | null; + mailer_subjects_invite: string | null; + mailer_subjects_magic_link: string | null; + mailer_subjects_reauthentication: string | null; + mailer_subjects_recovery: string | null; + mailer_templates_confirmation_content: string | null; + mailer_templates_email_change_content: string | null; + mailer_templates_invite_content: string | null; + mailer_templates_magic_link_content: string | null; + mailer_templates_reauthentication_content: string | null; + mailer_templates_recovery_content: string | null; + mfa_max_enrolled_factors: number | null; + mfa_totp_enroll_enabled: boolean | null; + mfa_totp_verify_enabled: boolean | null; + mfa_phone_enroll_enabled: boolean | null; + mfa_phone_verify_enabled: boolean | null; + mfa_web_authn_enroll_enabled: boolean | null; + mfa_web_authn_verify_enabled: boolean | null; + mfa_phone_otp_length: number; + mfa_phone_template: string | null; + mfa_phone_max_frequency: number | null; + password_hibp_enabled: boolean | null; + password_min_length: number | null; + password_required_characters: string | null; + rate_limit_anonymous_users: number | null; + rate_limit_email_sent: number | null; + rate_limit_sms_sent: number | null; + rate_limit_token_refresh: number | null; + rate_limit_verify: number | null; + rate_limit_otp: number | null; + refresh_token_rotation_enabled: boolean | null; + saml_enabled: boolean | null; + saml_external_url: string | null; + saml_allow_encrypted_assertions: boolean | null; + security_captcha_enabled: boolean | null; + security_captcha_provider: string | null; + security_captcha_secret: string | null; + security_manual_linking_enabled: boolean | null; + security_refresh_token_reuse_interval: number | null; + security_update_password_require_reauthentication: boolean | null; + sessions_inactivity_timeout: number | null; + sessions_single_per_user: boolean | null; + sessions_tags: string | null; + sessions_timebox: number | null; + site_url: string | null; + sms_autoconfirm: boolean | null; + sms_max_frequency: number | null; + sms_messagebird_access_key: string | null; + sms_messagebird_originator: string | null; + sms_otp_exp: number | null; + sms_otp_length: number; + sms_provider: string | null; + sms_template: string | null; + sms_test_otp: string | null; + sms_test_otp_valid_until: string | null; + sms_textlocal_api_key: string | null; + sms_textlocal_sender: string | null; + sms_twilio_account_sid: string | null; + sms_twilio_auth_token: string | null; + sms_twilio_content_sid: string | null; + sms_twilio_message_service_sid: string | null; + sms_twilio_verify_account_sid: string | null; + sms_twilio_verify_auth_token: string | null; + sms_twilio_verify_message_service_sid: string | null; + sms_vonage_api_key: string | null; + sms_vonage_api_secret: string | null; + sms_vonage_from: string | null; + smtp_admin_email: string | null; + smtp_host: string | null; + smtp_max_frequency: number | null; + smtp_pass: string | null; + smtp_port: string | null; + smtp_sender_name: string | null; + smtp_user: string | null; + uri_allow_list: string | null; + }; + UpdateAuthConfigBody: { + site_url?: string; + disable_signup?: boolean; + jwt_exp?: number; + smtp_admin_email?: string; + smtp_host?: string; + smtp_port?: string; + smtp_user?: string; + smtp_pass?: string; + smtp_max_frequency?: number; + smtp_sender_name?: string; + mailer_allow_unverified_email_sign_ins?: boolean; + mailer_autoconfirm?: boolean; + mailer_subjects_invite?: string; + mailer_subjects_confirmation?: string; + mailer_subjects_recovery?: string; + mailer_subjects_email_change?: string; + mailer_subjects_magic_link?: string; + mailer_subjects_reauthentication?: string; + mailer_templates_invite_content?: string; + mailer_templates_confirmation_content?: string; + mailer_templates_recovery_content?: string; + mailer_templates_email_change_content?: string; + mailer_templates_magic_link_content?: string; + mailer_templates_reauthentication_content?: string; + mfa_max_enrolled_factors?: number; + uri_allow_list?: string; + external_anonymous_users_enabled?: boolean; + external_email_enabled?: boolean; + external_phone_enabled?: boolean; + saml_enabled?: boolean; + saml_external_url?: string; + security_captcha_enabled?: boolean; + security_captcha_provider?: string; + security_captcha_secret?: string; + sessions_timebox?: number; + sessions_inactivity_timeout?: number; + sessions_single_per_user?: boolean; + sessions_tags?: string; + rate_limit_anonymous_users?: number; + rate_limit_email_sent?: number; + rate_limit_sms_sent?: number; + rate_limit_verify?: number; + rate_limit_token_refresh?: number; + rate_limit_otp?: number; + mailer_secure_email_change_enabled?: boolean; + refresh_token_rotation_enabled?: boolean; + password_hibp_enabled?: boolean; + password_min_length?: number; + /** @enum {string} */ + password_required_characters?: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789" | "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789" | "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~" | ""; + security_manual_linking_enabled?: boolean; + security_update_password_require_reauthentication?: boolean; + security_refresh_token_reuse_interval?: number; + mailer_otp_exp?: number; + mailer_otp_length?: number; + sms_autoconfirm?: boolean; + sms_max_frequency?: number; + sms_otp_exp?: number; + sms_otp_length?: number; + sms_provider?: string; + sms_messagebird_access_key?: string; + sms_messagebird_originator?: string; + sms_test_otp?: string; + sms_test_otp_valid_until?: string; + sms_textlocal_api_key?: string; + sms_textlocal_sender?: string; + sms_twilio_account_sid?: string; + sms_twilio_auth_token?: string; + sms_twilio_content_sid?: string; + sms_twilio_message_service_sid?: string; + sms_twilio_verify_account_sid?: string; + sms_twilio_verify_auth_token?: string; + sms_twilio_verify_message_service_sid?: string; + sms_vonage_api_key?: string; + sms_vonage_api_secret?: string; + sms_vonage_from?: string; + sms_template?: string; + hook_mfa_verification_attempt_enabled?: boolean; + hook_mfa_verification_attempt_uri?: string; + hook_mfa_verification_attempt_secrets?: string; + hook_password_verification_attempt_enabled?: boolean; + hook_password_verification_attempt_uri?: string; + hook_password_verification_attempt_secrets?: string; + hook_custom_access_token_enabled?: boolean; + hook_custom_access_token_uri?: string; + hook_custom_access_token_secrets?: string; + hook_send_sms_enabled?: boolean; + hook_send_sms_uri?: string; + hook_send_sms_secrets?: string; + hook_send_email_enabled?: boolean; + hook_send_email_uri?: string; + hook_send_email_secrets?: string; + external_apple_enabled?: boolean; + external_apple_client_id?: string; + external_apple_secret?: string; + external_apple_additional_client_ids?: string; + external_azure_enabled?: boolean; + external_azure_client_id?: string; + external_azure_secret?: string; + external_azure_url?: string; + external_bitbucket_enabled?: boolean; + external_bitbucket_client_id?: string; + external_bitbucket_secret?: string; + external_discord_enabled?: boolean; + external_discord_client_id?: string; + external_discord_secret?: string; + external_facebook_enabled?: boolean; + external_facebook_client_id?: string; + external_facebook_secret?: string; + external_figma_enabled?: boolean; + external_figma_client_id?: string; + external_figma_secret?: string; + external_github_enabled?: boolean; + external_github_client_id?: string; + external_github_secret?: string; + external_gitlab_enabled?: boolean; + external_gitlab_client_id?: string; + external_gitlab_secret?: string; + external_gitlab_url?: string; + external_google_enabled?: boolean; + external_google_client_id?: string; + external_google_secret?: string; + external_google_additional_client_ids?: string; + external_google_skip_nonce_check?: boolean; + external_kakao_enabled?: boolean; + external_kakao_client_id?: string; + external_kakao_secret?: string; + external_keycloak_enabled?: boolean; + external_keycloak_client_id?: string; + external_keycloak_secret?: string; + external_keycloak_url?: string; + external_linkedin_oidc_enabled?: boolean; + external_linkedin_oidc_client_id?: string; + external_linkedin_oidc_secret?: string; + external_slack_oidc_enabled?: boolean; + external_slack_oidc_client_id?: string; + external_slack_oidc_secret?: string; + external_notion_enabled?: boolean; + external_notion_client_id?: string; + external_notion_secret?: string; + external_slack_enabled?: boolean; + external_slack_client_id?: string; + external_slack_secret?: string; + external_spotify_enabled?: boolean; + external_spotify_client_id?: string; + external_spotify_secret?: string; + external_twitch_enabled?: boolean; + external_twitch_client_id?: string; + external_twitch_secret?: string; + external_twitter_enabled?: boolean; + external_twitter_client_id?: string; + external_twitter_secret?: string; + external_workos_enabled?: boolean; + external_workos_client_id?: string; + external_workos_secret?: string; + external_workos_url?: string; + external_zoom_enabled?: boolean; + external_zoom_client_id?: string; + external_zoom_secret?: string; + db_max_pool_size?: number; + api_max_request_duration?: number; + mfa_totp_enroll_enabled?: boolean; + mfa_totp_verify_enabled?: boolean; + mfa_web_authn_enroll_enabled?: boolean; + mfa_web_authn_verify_enabled?: boolean; + mfa_phone_enroll_enabled?: boolean; + mfa_phone_verify_enabled?: boolean; + mfa_phone_max_frequency?: number; + mfa_phone_otp_length?: number; + mfa_phone_template?: string; + }; + CreateThirdPartyAuthBody: { + oidc_issuer_url?: string; + jwks_url?: string; + custom_jwks?: Record; + }; + ThirdPartyAuth: { + id: string; + type: string; + oidc_issuer_url?: string | null; + jwks_url?: string | null; + custom_jwks?: Record; + resolved_jwks?: Record; + inserted_at: string; + updated_at: string; + resolved_at?: string | null; + }; + V1RunQueryBody: { + query: string; + }; + V1CreateFunctionBody: { + slug: string; + name: string; + body: string; + verify_jwt?: boolean; + }; + FunctionResponse: { + id: string; + slug: string; + name: string; + /** @enum {string} */ + status: "ACTIVE" | "REMOVED" | "THROTTLED"; + version: number; + created_at: number; + updated_at: number; + verify_jwt?: boolean; + import_map?: boolean; + entrypoint_path?: string; + import_map_path?: string; + }; + FunctionSlugResponse: { + id: string; + slug: string; + name: string; + /** @enum {string} */ + status: "ACTIVE" | "REMOVED" | "THROTTLED"; + version: number; + created_at: number; + updated_at: number; + verify_jwt?: boolean; + import_map?: boolean; + entrypoint_path?: string; + import_map_path?: string; + }; + V1UpdateFunctionBody: { + name?: string; + body?: string; + verify_jwt?: boolean; + }; + V1StorageBucketResponse: { + id: string; + name: string; + owner: string; + created_at: string; + updated_at: string; + public: boolean; + }; + AttributeValue: { + default?: Record | number | string | boolean; + name?: string; + names?: string[]; + array?: boolean; + }; + AttributeMapping: { + keys: { + [key: string]: components["schemas"]["AttributeValue"]; + }; + }; + CreateProviderBody: { + /** + * @description What type of provider will be created + * @enum {string} + */ + type: "saml"; + metadata_xml?: string; + metadata_url?: string; + domains?: string[]; + attribute_mapping?: components["schemas"]["AttributeMapping"]; + }; + SamlDescriptor: { + id: string; + entity_id: string; + metadata_url?: string; + metadata_xml?: string; + attribute_mapping?: components["schemas"]["AttributeMapping"]; + }; + Domain: { + id: string; + domain?: string; + created_at?: string; + updated_at?: string; + }; + CreateProviderResponse: { + id: string; + saml?: components["schemas"]["SamlDescriptor"]; + domains?: components["schemas"]["Domain"][]; + created_at?: string; + updated_at?: string; + }; + Provider: { + id: string; + saml?: components["schemas"]["SamlDescriptor"]; + domains?: components["schemas"]["Domain"][]; + created_at?: string; + updated_at?: string; + }; + ListProvidersResponse: { + items: components["schemas"]["Provider"][]; + }; + GetProviderResponse: { + id: string; + saml?: components["schemas"]["SamlDescriptor"]; + domains?: components["schemas"]["Domain"][]; + created_at?: string; + updated_at?: string; + }; + UpdateProviderBody: { + metadata_xml?: string; + metadata_url?: string; + domains?: string[]; + attribute_mapping?: components["schemas"]["AttributeMapping"]; + }; + UpdateProviderResponse: { + id: string; + saml?: components["schemas"]["SamlDescriptor"]; + domains?: components["schemas"]["Domain"][]; + created_at?: string; + updated_at?: string; + }; + DeleteProviderResponse: { + id: string; + saml?: components["schemas"]["SamlDescriptor"]; + domains?: components["schemas"]["Domain"][]; + created_at?: string; + updated_at?: string; + }; + V1Backup: { + /** @enum {string} */ + status: "COMPLETED" | "FAILED" | "PENDING" | "REMOVED" | "ARCHIVED" | "CANCELLED"; + is_physical_backup: boolean; + inserted_at: string; + }; + V1PhysicalBackup: { + earliest_physical_backup_date_unix?: number; + latest_physical_backup_date_unix?: number; + }; + V1BackupsResponse: { + region: string; + walg_enabled: boolean; + pitr_enabled: boolean; + backups: components["schemas"]["V1Backup"][]; + physical_backup_data: components["schemas"]["V1PhysicalBackup"]; + }; + V1RestorePitrBody: { + recovery_time_target_unix: number; + }; + V1OrganizationMemberResponse: { + user_id: string; + user_name: string; + email?: string; + role_name: string; + mfa_enabled: boolean; + }; + /** @enum {string} */ + BillingPlanId: "free" | "pro" | "team" | "enterprise"; + V1OrganizationSlugResponse: { + plan?: components["schemas"]["BillingPlanId"]; + opt_in_tags: "AI_SQL_GENERATOR_OPT_IN"[]; + allowed_release_channels: components["schemas"]["ReleaseChannel"][]; + id: string; + name: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + "v1-get-a-branch-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Branch ID */ + branch_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchDetailResponse"]; + }; + }; + /** @description Failed to retrieve database branch */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-delete-a-branch": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Branch ID */ + branch_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchDeleteResponse"]; + }; + }; + /** @description Failed to delete database branch */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-a-branch-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Branch ID */ + branch_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateBranchBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchResponse"]; + }; + }; + /** @description Failed to update database branch */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-reset-a-branch": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Branch ID */ + branch_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchResetResponse"]; + }; + }; + /** @description Failed to reset database branch */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-projects": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1ProjectResponse"][]; + }; + }; + }; + }; + "v1-create-a-project": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["V1CreateProjectBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1ProjectResponse"]; + }; + }; + }; + }; + "v1-list-all-organizations": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OrganizationResponseV1"][]; + }; + }; + /** @description Unexpected error listing organizations */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-create-an-organization": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateOrganizationBodyV1"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OrganizationResponseV1"]; + }; + }; + /** @description Unexpected error creating an organization */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-authorize-user": { + parameters: { + query: { + client_id: string; + response_type: "code" | "token" | "id_token token"; + redirect_uri: string; + scope?: string; + state?: string; + response_mode?: string; + code_challenge?: string; + code_challenge_method?: "plain" | "sha256" | "S256"; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 303: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-exchange-oauth-token": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/x-www-form-urlencoded": components["schemas"]["OAuthTokenBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["OAuthTokenResponse"]; + }; + }; + }; + }; + "v1-list-all-snippets": { + parameters: { + query?: { + project_ref?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SnippetList"]; + }; + }; + /** @description Failed to list user's SQL snippets */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-a-snippet": { + parameters: { + query?: never; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SnippetResponse"]; + }; + }; + /** @description Failed to retrieve SQL snippet */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-project-api-keys": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApiKeyResponse"][]; + }; + }; + }; + }; + createApiKey: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateApiKeyBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApiKeyResponse"]; + }; + }; + }; + }; + deleteApiKey: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApiKeyResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + updateApiKey: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateApiKeyBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApiKeyResponse"]; + }; + }; + }; + }; + "v1-list-all-branches": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchResponse"][]; + }; + }; + /** @description Failed to retrieve database branches */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-create-a-branch": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateBranchBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["BranchResponse"]; + }; + }; + /** @description Failed to create database branch */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-disable-preview-branching": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to disable preview branching */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-hostname-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateCustomHostnameResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's custom hostname config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-Delete hostname config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to delete project custom hostname configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-hostname-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateCustomHostnameBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateCustomHostnameResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project custom hostname configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-verify-dns-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateCustomHostnameResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to verify project custom hostname configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-activate-custom-hostname": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateCustomHostnameResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to activate project custom hostname configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-network-bans": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["NetworkBanResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's network bans */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-delete-network-bans": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RemoveNetworkBanRequest"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to remove network bans. */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-network-restrictions": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["NetworkRestrictionsResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's network restrictions */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-network-restrictions": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["NetworkRestrictionsRequest"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["NetworkRestrictionsResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project network restrictions */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-pgsodium-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PgsodiumConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's pgsodium config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-pgsodium-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePgsodiumConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PgsodiumConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's pgsodium config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-postgrest-service-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PostgrestConfigWithJWTSecretResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's postgrest config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-postgrest-service-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePostgrestConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1PostgrestConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's postgrest config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-project": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1ProjectResponse"]; + }; + }; + /** @description Failed to retrieve project */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-delete-a-project": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1ProjectRefResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-secrets": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SecretResponse"][]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's secrets */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-bulk-create-secrets": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateSecretBody"][]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to create project's secrets */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-bulk-delete-secrets": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": string[]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to delete secrets with given names */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-ssl-enforcement-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SslEnforcementResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's SSL enforcement config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-ssl-enforcement-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SslEnforcementRequest"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SslEnforcementResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's SSL enforcement configuration. */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-generate-typescript-types": { + parameters: { + query?: { + included_schemas?: string; + }; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TypescriptResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to generate TypeScript types */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-vanity-subdomain-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["VanitySubdomainConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to get project vanity subdomain configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-deactivate-vanity-subdomain-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to delete project vanity subdomain configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-check-vanity-subdomain-availability": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VanitySubdomainBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SubdomainAvailabilityResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to check project vanity subdomain configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-activate-vanity-subdomain-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["VanitySubdomainBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ActivateVanitySubdomainResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to activate project vanity subdomain configuration */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-upgrade-postgres-version": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpgradeDatabaseBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProjectUpgradeInitiateResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to initiate project upgrade */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-postgres-upgrade-eligibility": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ProjectUpgradeEligibilityResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to determine project upgrade eligibility */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-postgres-upgrade-status": { + parameters: { + query?: { + tracking_id?: string; + }; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DatabaseUpgradeStatusResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project upgrade status */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-readonly-mode-status": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ReadOnlyStatusResponse"]; + }; + }; + /** @description Failed to get project readonly mode status */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-disable-readonly-mode-temporarily": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to disable project's readonly mode */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-setup-a-read-replica": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetUpReadReplicaBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to set up read replica */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-remove-a-read-replica": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["RemoveReadReplicaBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to remove read replica */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-services-health": { + parameters: { + query: { + timeout_ms?: number; + services: ("auth" | "db" | "pooler" | "realtime" | "rest" | "storage")[]; + }; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1ServiceHealthResponse"][]; + }; + }; + /** @description Failed to retrieve project's service health status */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-postgres-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PostgresConfigResponse"]; + }; + }; + /** @description Failed to retrieve project's Postgres config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-postgres-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdatePostgresConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PostgresConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's Postgres config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-project-pgbouncer-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1PgbouncerConfigResponse"]; + }; + }; + /** @description Failed to retrieve project's pgbouncer config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-supavisor-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SupavisorConfigResponse"][]; + }; + }; + /** @description Failed to retrieve project's supavisor config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-supavisor-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateSupavisorConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateSupavisorConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's supavisor config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-auth-service-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's auth config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-auth-service-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateAuthConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuthConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's auth config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + listTPAForProject: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ThirdPartyAuth"][]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + createTPAForProject: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateThirdPartyAuthBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ThirdPartyAuth"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + getTPAForProject: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + tpa_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ThirdPartyAuth"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + deleteTPAForProject: { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + tpa_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ThirdPartyAuth"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-run-a-query": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["V1RunQueryBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": Record; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to run sql query */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-enable-database-webhook": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to enable Database Webhooks on the project */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-functions": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FunctionResponse"][]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's functions */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-create-a-function": { + parameters: { + query?: { + slug?: string; + name?: string; + verify_jwt?: boolean; + import_map?: boolean; + entrypoint_path?: string; + import_map_path?: string; + }; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["V1CreateFunctionBody"]; + "application/vnd.denoland.eszip": components["schemas"]["V1CreateFunctionBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FunctionResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to create project's function */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-a-function": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + /** @description Function slug */ + function_slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FunctionSlugResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve function with given slug */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-delete-a-function": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + /** @description Function slug */ + function_slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to delete function with given slug */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-a-function": { + parameters: { + query?: { + slug?: string; + name?: string; + verify_jwt?: boolean; + import_map?: boolean; + entrypoint_path?: string; + import_map_path?: string; + }; + header?: never; + path: { + /** @description Project ref */ + ref: string; + /** @description Function slug */ + function_slug: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["V1UpdateFunctionBody"]; + "application/vnd.denoland.eszip": components["schemas"]["V1UpdateFunctionBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["FunctionResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update function with given slug */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-a-function-body": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + /** @description Function slug */ + function_slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve function body with given slug */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-buckets": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1StorageBucketResponse"][]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to get list of buckets */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-sso-provider": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListProvidersResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description SAML 2.0 support is not enabled for this project */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-create-a-sso-provider": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateProviderBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CreateProviderResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description SAML 2.0 support is not enabled for this project */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-get-a-sso-provider": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + provider_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["GetProviderResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Either SAML 2.0 was not enabled for this project, or the provider does not exist */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-a-sso-provider": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + provider_id: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateProviderBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UpdateProviderResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Either SAML 2.0 was not enabled for this project, or the provider does not exist */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-delete-a-sso-provider": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + provider_id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DeleteProviderResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Either SAML 2.0 was not enabled for this project, or the provider does not exist */ + 404: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-all-backups": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1BackupsResponse"]; + }; + }; + /** @description Failed to get backups */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-restore-pitr-backup": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["V1RestorePitrBody"]; + }; + }; + responses: { + 201: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-list-organization-members": { + parameters: { + query?: never; + header?: never; + path: { + slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1OrganizationMemberResponse"][]; + }; + }; + }; + }; + "v1-get-an-organization": { + parameters: { + query?: never; + header?: never; + path: { + slug: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["V1OrganizationSlugResponse"]; + }; + }; + }; + }; +} diff --git a/apps/deploy-worker/src/supabase/oauth.ts b/apps/deploy-worker/src/supabase/oauth.ts deleted file mode 100644 index d44d76b8..00000000 --- a/apps/deploy-worker/src/supabase/oauth.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { supabaseAdmin } from './client.ts' - -type Credentials = { expiresAt: string; refreshToken: string; accessToken: string } - -export async function getAccessToken( - integrationId: number, - credentials: Credentials -): Promise { - // the expiresAt expires in less than 1 hour, refresh the token - if (new Date(credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { - const refreshToken = await supabaseAdmin.rpc('read_secret', { - secret_id: credentials.refreshToken, - }) - - if (refreshToken.error) { - console.error(refreshToken.error) - throw new Error('Failed to read refresh token') - } - - const now = Date.now() - - const newCredentialsResponse = await fetch('https://api.supabase.com/v1/oauth/token', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', - Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, - }, - body: new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: credentials.refreshToken, - }), - }) - - if (!newCredentialsResponse.ok) { - console.error(newCredentialsResponse) - throw new Error('Failed to fetch new credentials') - } - - const newCredentials = (await newCredentialsResponse.json()) as { - access_token: string - refresh_token: string - expires_in: number - } - - const expiresAt = new Date(now + newCredentials.expires_in * 1000) - - await supabaseAdmin.rpc('update_secret', { - secret_id: credentials.refreshToken, - new_secret: newCredentials.refresh_token, - }) - await supabaseAdmin.rpc('update_secret', { - secret_id: credentials.accessToken, - new_secret: newCredentials.access_token, - }) - await supabaseAdmin - .from('deployment_provider_integrations') - .update({ - credentials: { - accessToken: credentials.accessToken, - expiresAt: expiresAt.toISOString(), - refreshToken: credentials.refreshToken, - }, - }) - .eq('id', integrationId) - } - - const accessToken = await supabaseAdmin.rpc('read_secret', { - secret_id: credentials.accessToken, - }) - - if (accessToken.error) { - console.error(accessToken.error) - throw new Error('Failed to read access token') - } - - return accessToken.data -} diff --git a/apps/deploy-worker/src/supabase/types.ts b/apps/deploy-worker/src/supabase/types.ts index 31e3e508..11fc93f0 100644 --- a/apps/deploy-worker/src/supabase/types.ts +++ b/apps/deploy-worker/src/supabase/types.ts @@ -1,38 +1,35 @@ -type ProjectStatus = - | 'ACTIVE_HEALTHY' - | 'ACTIVE_UNHEALTHY' - | 'COMING_UP' - | 'GOING_DOWN' - | 'INACTIVE' - | 'INIT_FAILED' - | 'REMOVED' - | 'RESTARTING' - | 'UNKNOWN' - | 'UPGRADING' - | 'PAUSING' - | 'RESTORING' - | 'RESTORE_FAILED' - | 'PAUSE_FAILED' +import type { createClient } from './client.ts' +import type { createManagementApiClient } from './management-api/client.ts' +import type { paths } from './management-api/types.ts' -export type Project = { - id: string - organization_id: string - name: string - region: string - created_at: string - database: { - host: string - version: string - postgres_engine: string - release_channel: string - } - status: ProjectStatus -} +export type Credentials = { expiresAt: string; refreshToken: string; accessToken: string } + +export type Project = + paths['/v1/projects/{ref}']['get']['responses']['200']['content']['application/json'] + +type Unpacked = T extends (infer U)[] ? U : T + +type Database = Unpacked< + paths['/v1/projects/{ref}/config/database/pooler']['get']['responses']['200']['content']['application/json'] +> export type SupabaseProviderMetadata = { - project: Project & { - database: Project['database'] & { + project: { + id: Project['id'] + organizationId: Project['organization_id'] + name: Project['name'] + region: Project['region'] + createdAt: Project['created_at'] + database: { + host: Database['db_host'] + name: Database['db_name'] password: string + port: number + user: Database['db_user'] } } } + +export type SupabaseClient = Awaited> + +export type ManagementApiClient = Awaited> diff --git a/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts b/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts deleted file mode 100644 index 2247ccf2..00000000 --- a/apps/deploy-worker/src/supabase/wait-for-database-to-be-ready.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { Project } from './types.ts' -import { setTimeout } from 'timers/promises' - -const MAX_POLLING_TIME = 3 * 60 * 1000 // 3 minutes in milliseconds -const POLLING_INTERVAL = 10 * 1000 // 10 seconds in milliseconds - -type DatabaseStatus = 'COMING_UP' | 'ACTIVE_HEALTHY' | 'UNHEALTHY' - -export async function waitForDatabaseToBeReady(project: Project, accessToken: string) { - const params = new URLSearchParams({ services: ['db'] }).toString() - - const startTime = Date.now() - - while (true) { - try { - const servicesHealthResponse = await fetch( - `https://api.supabase.com/v1/projects/${project.id}/health?${params}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'application/json', - }, - } - ) - - if (!servicesHealthResponse.ok) { - throw new Error("Failed to get Supabase project's database health status") - } - - const servicesHealth = (await servicesHealthResponse.json()) as { - name: 'db' - status: DatabaseStatus - error: string - }[] - - const databaseService = servicesHealth.find((service) => service.name === 'db') - - if (!databaseService) { - throw new Error('Database service not found on Supabase for health check') - } - - if (databaseService.status === 'UNHEALTHY') { - throw new Error('Database is unhealthy on Supabase', { - cause: databaseService.error, - }) - } - - if (databaseService.status === 'ACTIVE_HEALTHY') { - return - } - - if (Date.now() - startTime > MAX_POLLING_TIME) { - throw new Error('Polling timeout: Database did not become active within 2 minutes') - } - - await setTimeout(POLLING_INTERVAL) - } catch (error) { - throw error - } - } -} diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts new file mode 100644 index 00000000..4576bd49 --- /dev/null +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -0,0 +1,117 @@ +import type { ManagementApiClient, Project } from './types.ts' +import { setTimeout } from 'timers/promises' + +/** + * Wait for a Supabase project to be ready. + */ +export async function waitForProjectToBeHealthy( + ctx: { managementApiClient: ManagementApiClient }, + params: { project: Project } +) { + const MAX_POLLING_TIME = 2 // 2 minutes + const POLLING_INTERVAL = 5 * 1000 // 5 seconds in milliseconds + + const startTime = Date.now() + + while (true) { + try { + const { data: project, error } = await ctx.managementApiClient.GET('/v1/projects/{ref}', { + params: { + path: { + ref: params.project.id, + }, + }, + }) + + if (error) { + throw new Error('Failed to get Supabase project health status', { + cause: error, + }) + } + + if (project.status === 'ACTIVE_HEALTHY') { + return + } + + if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { + throw new Error(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`, { + cause: { + status: project.status, + }, + }) + } + + await setTimeout(POLLING_INTERVAL) + } catch (error) { + throw error + } + } +} + +/** + * Wait for a Supabase project's database to be ready. + */ +export async function waitForDatabaseToBeHealthy( + ctx: { managementApiClient: ManagementApiClient }, + params: { project: Project } +) { + const MAX_POLLING_TIME = 2 // 2 minutes + const POLLING_INTERVAL = 5 * 1000 // 5 seconds in milliseconds + + const startTime = Date.now() + + while (true) { + try { + const { data: servicesHealth, error } = await ctx.managementApiClient.GET( + '/v1/projects/{ref}/health', + { + params: { + path: { + ref: params.project.id, + }, + query: { + services: ['db', 'pooler'], + }, + }, + } + ) + + if (error) { + throw new Error("Failed to get Supabase project's database health status", { + cause: error, + }) + } + + const databaseService = servicesHealth.find((service) => service.name === 'db') + const poolerService = servicesHealth.find((service) => service.name === 'pooler') + + if (!databaseService) { + throw new Error('Database service not found on Supabase for health check') + } + + if (!poolerService) { + throw new Error('Pooler service not found on Supabase for health check') + } + + if ( + databaseService.status === 'ACTIVE_HEALTHY' && + poolerService.status === 'ACTIVE_HEALTHY' + ) { + return + } + + if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { + throw new Error(`Database did not become healthy within ${MAX_POLLING_TIME} minutes`, { + cause: { + status: databaseService.status, + error: databaseService.error, + }, + }) + } + + await setTimeout(POLLING_INTERVAL) + } catch (error) { + throw error + } + } +} diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index b734e17e..df287977 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -1,47 +1,92 @@ 'use client' -import { useRouter } from 'next/navigation' -import { useEffect } from 'react' +import { useMutation } from '@tanstack/react-query' +import { useParams, useRouter, useSearchParams } from 'next/navigation' +import { useEffect, useState } from 'react' import { useApp } from '~/components/app-provider' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' +import { createClient } from '~/utils/supabase/client' -export default function Page({ params }: { params: { databaseId: string } }) { - const databaseId = params.databaseId - const router = useRouter() - const { dbManager, liveShare } = useApp() +export default function Page() { + const params = useParams<{ databaseId: string }>() + const searchParams = useSearchParams() + const { liveShare } = useApp() + const [databaseUrl, setDatabaseUrl] = useState() + const { mutate: deploy, error } = useMutation({ + mutationFn: async () => { + // make the database available to the deployment worker + const localDatabaseUrl = await liveShare.start(params.databaseId) - useEffect(() => { - async function run() { - if (!dbManager) { - throw new Error('dbManager is not available') - } + const supabase = createClient() - try { - await dbManager.getDbInstance(databaseId) - } catch (err) { - router.push('/') + const { + data: { session }, + } = await supabase.auth.getSession() + + if (!session) { + throw new Error('You must be signed in to deploy') } - // make the database available to the deployment worker - const databaseUrl = await liveShare.start(databaseId) + // trigger the deployment + const response = await fetch(process.env.NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN!, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${session.access_token}`, + 'X-Refresh-Token': session.refresh_token, + }, + body: JSON.stringify({ + databaseId: params.databaseId, + databaseUrl: localDatabaseUrl, + integrationId: parseInt(searchParams.get('integration')!), + }), + }) - // trigger deployment - } - run() - return () => { + if (!response.ok) { + throw new Error(response.statusText) + } + + return (await response.json()) as { + databaseUrl: string + } + }, + onSuccess(data) { + setDatabaseUrl(data.databaseUrl) + }, + onError(error) { + console.error(error) + }, + onSettled() { + console.log('stopping live share') liveShare.stop() - } - }, [dbManager, databaseId, router, liveShare]) + }, + }) + useEffect(() => { + deploy() + }, [deploy]) + + const text = error + ? { title: 'Database deployment failed', content: error.message } + : databaseUrl + ? { + title: 'Database deployed', + content: 'Your database is deployed at the following URL:', + url: databaseUrl, + } + : { + title: 'Deploying your database', + content: 'Your database is being deployed. Please do not close this page.', + } return ( - Deploying your database + {text.title}
-

Your database is being deployed. Please do not close this page.

+

{text.content}

diff --git a/apps/postgres-new/next.config.mjs b/apps/postgres-new/next.config.mjs index 5a01fb2b..5a3438a4 100644 --- a/apps/postgres-new/next.config.mjs +++ b/apps/postgres-new/next.config.mjs @@ -5,6 +5,7 @@ import webpack from 'webpack' /** @type {import('next').NextConfig} */ const nextConfig = { + reactStrictMode: false, env: { NEXT_PUBLIC_PGLITE_VERSION: await getPackageVersion('@electric-sql/pglite'), }, diff --git a/package-lock.json b/package-lock.json index 502f7c20..9ebc6408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "license": "MIT" }, "apps/db-service": { + "extraneous": true, "dependencies": { "@electric-sql/pglite": "0.2.0-alpha.9", "pg-gateway": "^0.2.5-alpha.2" @@ -84,12 +85,14 @@ "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", + "openapi-fetch": "^0.12.2", "zod": "^3.23.8" }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/debug": "^4.1.12", "@types/node": "^22.5.4", + "openapi-typescript": "^7.4.1", "typescript": "^5.5.4" } }, @@ -1318,6 +1321,124 @@ "node": ">=16.0.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { "version": "7.24.8", "license": "MIT", @@ -1361,10 +1482,6 @@ "resolved": "apps/deploy-worker", "link": true }, - "node_modules/@electric-sql/pglite": { - "version": "0.2.0-alpha.9", - "license": "Apache-2.0" - }, "node_modules/@emnapi/runtime": { "version": "0.43.1", "license": "MIT", @@ -1372,21 +1489,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "dev": true, @@ -2931,6 +3033,111 @@ "react-dom": ">=17" } }, + "node_modules/@redocly/ajv": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz", + "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js-replace": "^1.0.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/config": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.12.1.tgz", + "integrity": "sha512-RW3rSirfsPdr0uvATijRDU3f55SuZV3m7/ppdTDvGw4IB0cmeZRkFmqTrchxMqWP50Gfg1tpHnjdxUCNo0E2qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core": { + "version": "1.25.7", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.25.7.tgz", + "integrity": "sha512-qidGKk4Bq0Ud0O8gRuXnDSLwVopwrf5+roNvpkvdQPVIHFSYJ5dscJkThdsn7OW8bNqahumQPWWczEh9l93FZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/ajv": "^8.11.2", + "@redocly/config": "^0.12.1", + "colorette": "^1.2.0", + "https-proxy-agent": "^7.0.4", + "js-levenshtein": "^1.1.6", + "js-yaml": "^4.1.0", + "lodash.isequal": "^4.5.0", + "minimatch": "^5.0.1", + "node-fetch": "^2.6.1", + "pluralize": "^8.0.0", + "yaml-ast-parser": "0.0.43" + }, + "engines": { + "node": ">=14.19.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@redocly/openapi-core/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@redocly/openapi-core/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.3", "dev": true, @@ -4712,6 +4919,16 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "license": "MIT", @@ -5353,6 +5570,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/character-entities": { "version": "2.0.2", "license": "MIT", @@ -5555,6 +5779,13 @@ "color-support": "bin.js" } }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true, + "license": "MIT" + }, "node_modules/comlink": { "version": "4.4.1", "license": "Apache-2.0" @@ -5808,10 +6039,6 @@ "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/db-service": { - "resolved": "apps/db-service", - "link": true - }, "node_modules/debug": { "version": "4.3.7", "license": "MIT", @@ -6255,44 +6482,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild": { - "version": "0.23.1", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, "node_modules/escalade": { "version": "3.1.2", "dev": true, @@ -7940,6 +8129,19 @@ "node": ">=8" } }, + "node_modules/index-to-position": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz", + "integrity": "sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/infer-owner": { "version": "1.0.4", "license": "ISC" @@ -8501,6 +8703,16 @@ "version": "2.2.1", "license": "MIT" }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -8747,6 +8959,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "dev": true, @@ -10462,10 +10681,59 @@ "version": "4.0.0", "license": "Apache-2.0" }, + "node_modules/openapi-fetch": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.12.2.tgz", + "integrity": "sha512-ctMQ4LkkSWfIDUMuf1SYuPMsQ7ePcWAkYaMPW1lCDdk4WlV3Vulq1zoyGrwnFVvrBs5t7OOqNF+EKa8SAaovEA==", + "license": "MIT", + "dependencies": { + "openapi-typescript-helpers": "^0.0.13" + } + }, "node_modules/openapi-types": { "version": "12.1.3", "license": "MIT" }, + "node_modules/openapi-typescript": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.4.1.tgz", + "integrity": "sha512-HrRoWveViADezHCNgQqZmPKmQ74q7nuH/yg9ursFucZaYQNUqsX38fE/V2sKBHVM+pws4tAHpuh/ext2UJ/AoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@redocly/openapi-core": "^1.25.3", + "ansi-colors": "^4.1.3", + "change-case": "^5.4.4", + "parse-json": "^8.1.0", + "supports-color": "^9.4.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "openapi-typescript": "bin/cli.js" + }, + "peerDependencies": { + "typescript": "^5.x" + } + }, + "node_modules/openapi-typescript-helpers": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.13.tgz", + "integrity": "sha512-z44WK2e7ygW3aUtAtiurfEACohf/Qt9g6BsejmIYgEoY4REHeRzgFJmO3ium0libsuzPc145I+8lE9aiiZrQvQ==", + "license": "MIT" + }, + "node_modules/openapi-typescript/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/optionator": { "version": "0.9.4", "dev": true, @@ -10587,6 +10855,37 @@ "version": "2.0.10", "license": "MIT" }, + "node_modules/parse-json": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz", + "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "index-to-position": "^0.1.2", + "type-fest": "^4.7.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "7.1.2", "license": "MIT", @@ -10696,13 +10995,6 @@ "node": ">=4.0" } }, - "node_modules/pg-gateway": { - "version": "0.2.5-alpha.2", - "license": "MIT", - "dependencies": { - "pg-protocol": "^1.6.1" - } - }, "node_modules/pg-int8": { "version": "1.0.1", "license": "ISC", @@ -11135,6 +11427,16 @@ "version": "1.3.6", "license": "MIT" }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "dev": true, @@ -13514,24 +13816,6 @@ "version": "2.6.3", "license": "0BSD" }, - "node_modules/tsx": { - "version": "4.19.1", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.23.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "license": "Apache-2.0", @@ -13818,6 +14102,13 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js-replace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz", + "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==", + "dev": true, + "license": "MIT" + }, "node_modules/use-callback-ref": { "version": "1.3.2", "license": "MIT", @@ -14314,6 +14605,23 @@ "node": ">= 14" } }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, From ce8df793820943b3f9282175e509288938873426 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 18 Oct 2024 17:14:26 +0200 Subject: [PATCH 11/59] protect against double concurrent deployments --- apps/deploy-worker/package.json | 2 +- apps/deploy-worker/src/index.ts | 7 -- .../src/supabase/database-types.ts | 14 ++- apps/deploy-worker/src/supabase/deploy.ts | 96 +++++++++++++------ package-lock.json | 57 +++++++---- package.json | 9 +- .../migrations/20241003131953_deployment.sql | 10 +- 7 files changed, 127 insertions(+), 68 deletions(-) diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json index 5beaa8fa..806658c0 100644 --- a/apps/deploy-worker/package.json +++ b/apps/deploy-worker/package.json @@ -5,7 +5,7 @@ "start": "node --env-file=.env --experimental-strip-types src/index.ts", "dev": "node --watch --env-file=.env --experimental-strip-types src/index.ts", "type-check": "tsc", - "generate:database-types": "npx supabase gen types --lang=typescript --local > src/supabase/db-types.ts", + "generate:database-types": "npx supabase gen types --lang=typescript --local > src/supabase/database-types.ts", "generate:management-api-types": "npx openapi-typescript https://api.supabase.com/api/v1-json -o ./src/supabase/management-api/types.ts" }, "dependencies": { diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index 892daeae..89e49eb3 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -41,10 +41,6 @@ app.post( throw new HTTPException(401, { message: 'Unauthorized' }) } - // TODO: create a lock in postgres to prevent multiple deployments - // await supabase.from('deployment_locks').insert({ - // local_database_id: databaseId, - // }) try { const { databaseUrl } = await deploy( { supabase }, @@ -57,9 +53,6 @@ app.post( throw new HTTPException(500, { message: error.message }) } throw new HTTPException(500, { message: 'Internal server error' }) - } finally { - // TODO: remove the lock - // await supabase.from('deployment_locks').delete().eq('local_database_id', databaseId) } } ) diff --git a/apps/deploy-worker/src/supabase/database-types.ts b/apps/deploy-worker/src/supabase/database-types.ts index 66bd32f0..2e461f32 100644 --- a/apps/deploy-worker/src/supabase/database-types.ts +++ b/apps/deploy-worker/src/supabase/database-types.ts @@ -164,22 +164,28 @@ export type Database = { deployments: { Row: { created_at: string - deployed_database_id: number + deployed_database_id: number | null + events: Json id: number + local_database_id: string status: Database["public"]["Enums"]["deployment_status"] updated_at: string } Insert: { created_at?: string - deployed_database_id: number + deployed_database_id?: number | null + events?: Json id?: never - status: Database["public"]["Enums"]["deployment_status"] + local_database_id: string + status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string } Update: { created_at?: string - deployed_database_id?: number + deployed_database_id?: number | null + events?: Json id?: never + local_database_id?: string status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string } diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index 3d56cfb6..a09e556a 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -14,42 +14,76 @@ export async function deploy( ctx: { supabase: SupabaseClient }, params: { databaseId: string; integrationId: number; localDatabaseUrl: string } ) { - // check if the database was already deployed - const deployedDatabase = await ctx.supabase - .from('deployed_databases') - .select('*') - .eq('local_database_id', params.databaseId) - .eq('deployment_provider_integration_id', params.integrationId) - .maybeSingle() - - if (deployedDatabase.error) { - throw new Error('Cannot find deployed database', { cause: deployedDatabase.error }) - } + const { data: deployment, error: createDeploymentError } = await ctx.supabase + .from('deployments') + .insert({ + local_database_id: params.databaseId, + }) + .select('id') + .single() - if (!deployedDatabase.data) { - deployedDatabase.data = await createDeployedDatabase( - { supabase: ctx.supabase }, - { databaseId: params.databaseId, integrationId: params.integrationId } - ) - } + if (createDeploymentError) { + if (createDeploymentError.code === '23505') { + throw new Error('Deployment already in progress', { cause: createDeploymentError }) + } - // get the database url - const databaseUrl = await getDatabaseUrl({ - project: (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project, - }) + throw new Error('Cannot create deployment', { cause: createDeploymentError }) + } - // use pg_dump and pg_restore to transfer the data from the local database to the remote database - const command = `pg_dump "${params.localDatabaseUrl}" -Fc | pg_restore -d "${databaseUrl}" --clean --if-exists` - console.log(command) try { - await exec(command) - } catch (error) { - throw new Error('Cannot transfer the data from the local database to the remote database', { - cause: error, + // check if the database was already deployed + const deployedDatabase = await ctx.supabase + .from('deployed_databases') + .select('*') + .eq('local_database_id', params.databaseId) + .eq('deployment_provider_integration_id', params.integrationId) + .maybeSingle() + + if (deployedDatabase.error) { + throw new Error('Cannot find deployed database', { cause: deployedDatabase.error }) + } + + if (!deployedDatabase.data) { + deployedDatabase.data = await createDeployedDatabase( + { supabase: ctx.supabase }, + { databaseId: params.databaseId, integrationId: params.integrationId } + ) + } + + // get the database url + const databaseUrl = await getDatabaseUrl({ + project: (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project, }) - } - return { - databaseUrl, + // use pg_dump and pg_restore to transfer the data from the local database to the remote database + const command = `pg_dump "${params.localDatabaseUrl}" -Fc | pg_restore -d "${databaseUrl}" --clean --if-exists` + + try { + await exec(command) + } catch (error) { + throw new Error('Cannot transfer the data from the local database to the remote database', { + cause: error, + }) + } + + await ctx.supabase + .from('deployments') + .update({ + status: 'success', + }) + .eq('id', deployment.id) + + return { + databaseUrl, + } + } catch (error) { + await ctx.supabase + .from('deployments') + .update({ + status: 'failed', + }) + .eq('id', deployment.id) + + throw error } } diff --git a/package-lock.json b/package-lock.json index 9ebc6408..c52a004b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "apps/*" ], "devDependencies": { - "supabase": "^1.191.3" + "supabase": "^1.204.3" } }, "apps/browser-proxy": { @@ -5326,17 +5326,30 @@ } }, "node_modules/bin-links": { - "version": "4.0.4", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-5.0.0.tgz", + "integrity": "sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==", "dev": true, "license": "ISC", "dependencies": { - "cmd-shim": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "read-cmd-shim": "^4.0.0", - "write-file-atomic": "^5.0.0" + "cmd-shim": "^7.0.0", + "npm-normalize-package-bin": "^4.0.0", + "proc-log": "^5.0.0", + "read-cmd-shim": "^5.0.0", + "write-file-atomic": "^6.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/bin-links/node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/binary-extensions": { @@ -5720,11 +5733,13 @@ } }, "node_modules/cmd-shim": { - "version": "6.0.3", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-7.0.0.tgz", + "integrity": "sha512-rtpaCbr164TPPh+zFdkWpCyZuKkjpAzODfaZCf/SVJZzJN+4bHQb/LP3Jzq5/+84um3XXY8r548XiWKSborwVw==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/code-red": { @@ -10482,11 +10497,13 @@ } }, "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npmlog": { @@ -12140,11 +12157,13 @@ } }, "node_modules/read-cmd-shim": { - "version": "4.0.0", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-5.0.0.tgz", + "integrity": "sha512-SEbJV7tohp3DAAILbEMPXavBjAnMN0tVnh4+9G8ihV4Pq3HYF9h8QNez9zkJ1ILkv9G2BjdzwctznGZXgu/HGw==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/readable-stream": { @@ -13292,12 +13311,14 @@ } }, "node_modules/supabase": { - "version": "1.200.3", + "version": "1.204.3", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.204.3.tgz", + "integrity": "sha512-uO09eyAw7TZAX/7wPeieQBWrl4QAJ0WLF+HTkFy35GWBmQULP5nkJR93LcuhSyooYiqwEUKlChEF/PGAEmTCKw==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "bin-links": "^4.0.3", + "bin-links": "^5.0.0", "https-proxy-agent": "^7.0.2", "node-fetch": "^3.3.2", "tar": "7.4.3" @@ -14554,7 +14575,9 @@ "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "5.0.1", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz", + "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==", "dev": true, "license": "ISC", "dependencies": { @@ -14562,7 +14585,7 @@ "signal-exit": "^4.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/ws": { diff --git a/package.json b/package.json index 3880706d..256d059f 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,8 @@ "scripts": { "dev": "npm run dev --workspace postgres-new" }, - "workspaces": [ - "apps/*" - ], + "workspaces": ["apps/*"], "devDependencies": { - "supabase": "^1.191.3" - }, - "packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4" + "supabase": "^1.204.3" + } } diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index 22851804..bb0e4041 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -48,12 +48,18 @@ create type deployment_status as enum ('in_progress', 'success', 'failed'); -- table for storing individual deployments create table deployments ( id bigint primary key generated always as identity, - deployed_database_id bigint not null references deployed_databases(id), - status deployment_status not null, + local_database_id text not null, + status deployment_status not null default 'in_progress', + deployed_database_id bigint references deployed_databases(id), + events jsonb not null default '[]'::jsonb, created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); +create unique index idx_deployments_in_progress +on deployments (local_database_id) +where status = 'in_progress'; + create trigger deployments_updated_at before update on deployments for each row execute procedure moddatetime (updated_at); From bb1b1564df208f6ab42a257b2ea29cec1d22b74b Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Tue, 22 Oct 2024 16:47:10 +0200 Subject: [PATCH 12/59] use dialogs to go back to the main app --- apps/deploy-worker/src/index.ts | 7 +-- apps/deploy-worker/src/supabase/deploy.ts | 6 +- apps/postgres-new/app/(main)/db/[id]/page.tsx | 11 +++- .../app/deploy/[databaseId]/page.tsx | 63 ++++++++++++------- .../components/deploy-failure-dialog.tsx | 34 ++++++++++ .../components/deploy-success-dialog.tsx | 57 +++++++++++++++++ 6 files changed, 147 insertions(+), 31 deletions(-) create mode 100644 apps/postgres-new/components/deploy-failure-dialog.tsx create mode 100644 apps/postgres-new/components/deploy-success-dialog.tsx diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index 89e49eb3..afe7ab9c 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -42,11 +42,8 @@ app.post( } try { - const { databaseUrl } = await deploy( - { supabase }, - { databaseId, integrationId, localDatabaseUrl } - ) - return c.json({ databaseUrl }) + const project = await deploy({ supabase }, { databaseId, integrationId, localDatabaseUrl }) + return c.json({ project }) } catch (error: unknown) { console.error(error) if (error instanceof Error) { diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index a09e556a..32c44514 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -50,9 +50,11 @@ export async function deploy( ) } + const project = (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project + // get the database url const databaseUrl = await getDatabaseUrl({ - project: (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project, + project, }) // use pg_dump and pg_restore to transfer the data from the local database to the remote database @@ -74,6 +76,8 @@ export async function deploy( .eq('id', deployment.id) return { + name: project.name, + url: `https://supabase.com/dashboard/project/${project.id}`, databaseUrl, } } catch (error) { diff --git a/apps/postgres-new/app/(main)/db/[id]/page.tsx b/apps/postgres-new/app/(main)/db/[id]/page.tsx index cd13c697..64fce78b 100644 --- a/apps/postgres-new/app/(main)/db/[id]/page.tsx +++ b/apps/postgres-new/app/(main)/db/[id]/page.tsx @@ -3,10 +3,13 @@ import { useRouter } from 'next/navigation' import { useEffect } from 'react' import { useApp } from '~/components/app-provider' +import { DeployFailureDialog } from '~/components/deploy-failure-dialog' +import { DeploySuccessDialog } from '~/components/deploy-success-dialog' import Workspace from '~/components/workspace' export default function Page({ params }: { params: { id: string } }) { const databaseId = params.id + const router = useRouter() const { dbManager } = useApp() @@ -25,5 +28,11 @@ export default function Page({ params }: { params: { id: string } }) { run() }, [dbManager, databaseId, router]) - return + return ( + <> + + + + + ) } diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index df287977..72a84c54 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -2,16 +2,18 @@ import { useMutation } from '@tanstack/react-query' import { useParams, useRouter, useSearchParams } from 'next/navigation' -import { useEffect, useState } from 'react' +import { useEffect } from 'react' import { useApp } from '~/components/app-provider' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' import { createClient } from '~/utils/supabase/client' +import { Loader2 } from 'lucide-react' export default function Page() { const params = useParams<{ databaseId: string }>() - const searchParams = useSearchParams() + const router = useRouter() const { liveShare } = useApp() - const [databaseUrl, setDatabaseUrl] = useState() + const searchParams = useSearchParams() + const { mutate: deploy, error } = useMutation({ mutationFn: async () => { // make the database available to the deployment worker @@ -43,21 +45,41 @@ export default function Page() { }) if (!response.ok) { + console.log(response) throw new Error(response.statusText) } return (await response.json()) as { - databaseUrl: string + project: { + name: string + url: string + databaseUrl: string + } } }, onSuccess(data) { - setDatabaseUrl(data.databaseUrl) + const searchParams = new URLSearchParams({ + event: 'deploy.success', + project: JSON.stringify(data.project), + }) + const url = new URL( + `/db/${params.databaseId}?${searchParams.toString()}`, + window.location.href + ) + router.push(url.toString()) }, onError(error) { - console.error(error) + const searchParams = new URLSearchParams({ + event: 'deploy.failure', + error: error.message, + }) + const url = new URL( + `/db/${params.databaseId}?${searchParams.toString()}`, + window.location.href + ) + router.push(url.toString()) }, onSettled() { - console.log('stopping live share') liveShare.stop() }, }) @@ -65,28 +87,21 @@ export default function Page() { deploy() }, [deploy]) - const text = error - ? { title: 'Database deployment failed', content: error.message } - : databaseUrl - ? { - title: 'Database deployed', - content: 'Your database is deployed at the following URL:', - url: databaseUrl, - } - : { - title: 'Deploying your database', - content: 'Your database is being deployed. Please do not close this page.', - } - return ( - + - {text.title} + Deploying your database
-
-

{text.content}

+
+
+ +
+

Your database is being deployed. This process typically takes a few minutes.

+

Please keep this page open to ensure successful deployment.

+
+
diff --git a/apps/postgres-new/components/deploy-failure-dialog.tsx b/apps/postgres-new/components/deploy-failure-dialog.tsx new file mode 100644 index 00000000..4a58018b --- /dev/null +++ b/apps/postgres-new/components/deploy-failure-dialog.tsx @@ -0,0 +1,34 @@ +import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' +import { useRouter } from 'next/navigation' +import { useEffect, useState } from 'react' + +export function DeployFailureDialog() { + const router = useRouter() + const [error, setError] = useState(null) + const [open, setOpen] = useState(false) + useEffect(() => { + const searchParams = new URLSearchParams(window.location.search) + + if (searchParams.get('event') === 'deploy.failure') { + setError(searchParams.get('error')) + setOpen(true) + router.replace(window.location.pathname) + } + }, [router]) + + if (!error) { + return null + } + + return ( + + + + Database deployment failed +
+ +

{error}

+ +
+ ) +} diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx new file mode 100644 index 00000000..00faf540 --- /dev/null +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -0,0 +1,57 @@ +import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' +import { useRouter } from 'next/navigation' +import { CopyableField } from './copyable-field' +import Link from 'next/link' +import { useEffect, useState } from 'react' + +export function DeploySuccessDialog() { + const router = useRouter() + const [project, setProject] = useState<{ name: string; url: string; databaseUrl: string } | null>( + null + ) + const [open, setOpen] = useState(false) + useEffect(() => { + const searchParams = new URLSearchParams(window.location.search) + + if (searchParams.get('event') === 'deploy.success') { + setProject(JSON.parse(searchParams.get('project')!)) + setOpen(true) + router.replace(window.location.pathname) + } + }, [router]) + + if (!project) { + return null + } + + return ( + + + + Database deployed +
+ +
+

+ Your database has been deployed to the Supabase project:{' '} + + {project.name} + +

+

+ + + {/* eslint-disable-next-line react/no-unescaped-entities */} + Important: Please save your database password securely as it won't be displayed again. + +

+
+ +
+ ) +} From bf3951ee4d29d0abb9c7e9ea71fb666e80b1df8c Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 23 Oct 2024 12:20:44 +0200 Subject: [PATCH 13/59] wip --- apps/deploy-worker/src/error.ts | 5 + apps/deploy-worker/src/index.ts | 3 +- .../src/supabase/create-deployed-database.ts | 13 +- .../src/supabase/database-types.ts | 35 +- apps/deploy-worker/src/supabase/deploy.ts | 36 +- .../src/supabase/get-access-token.ts | 13 +- .../src/supabase/get-database-url.ts | 27 +- .../src/supabase/wait-for-health.ts | 26 +- .../app/deploy/[databaseId]/page.tsx | 4 +- .../components/deploy-failure-dialog.tsx | 2 + .../components/deploy-success-dialog.tsx | 28 +- .../components/redeploy-alert-dialog.tsx | 42 + apps/postgres-new/components/sidebar.tsx | 39 +- .../components/ui/alert-dialog.tsx | 141 ++ .../deployed-databases-query.ts | 24 + apps/postgres-new/package.json | 3 +- apps/postgres-new/utils/supabase/db-types.ts | 49 +- package-lock.json | 1962 ++++++++++++++++- package.json | 2 +- .../migrations/20241003131953_deployment.sql | 43 +- 20 files changed, 2368 insertions(+), 129 deletions(-) create mode 100644 apps/deploy-worker/src/error.ts create mode 100644 apps/postgres-new/components/redeploy-alert-dialog.tsx create mode 100644 apps/postgres-new/components/ui/alert-dialog.tsx create mode 100644 apps/postgres-new/data/deployed-databases/deployed-databases-query.ts diff --git a/apps/deploy-worker/src/error.ts b/apps/deploy-worker/src/error.ts new file mode 100644 index 00000000..557c5ed7 --- /dev/null +++ b/apps/deploy-worker/src/error.ts @@ -0,0 +1,5 @@ +export class DeployError extends Error { + constructor(message: string, options?: ErrorOptions) { + super(message, options) + } +} diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index afe7ab9c..8af571b4 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -6,6 +6,7 @@ import { zValidator } from '@hono/zod-validator' import { createClient } from './supabase/client.ts' import { HTTPException } from 'hono/http-exception' import { deploy } from './supabase/deploy.ts' +import { DeployError } from './error.ts' const app = new Hono() @@ -46,7 +47,7 @@ app.post( return c.json({ project }) } catch (error: unknown) { console.error(error) - if (error instanceof Error) { + if (error instanceof DeployError) { throw new HTTPException(500, { message: error.message }) } throw new HTTPException(500, { message: 'Internal server error' }) diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index c5ea4582..6dffe54e 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -1,3 +1,4 @@ +import { DeployError } from '../error.ts' import { supabaseAdmin } from './client.ts' import { generatePassword } from './generate-password.ts' import { getAccessToken } from './get-access-token.ts' @@ -24,7 +25,7 @@ export async function createDeployedDatabase( .single() if (integration.error) { - throw new Error('Cannot find integration', { cause: integration.error }) + throw new DeployError('Cannot find integration', { cause: integration.error }) } // first we need to create a new project on Supabase using the Management API @@ -58,7 +59,7 @@ export async function createDeployedDatabase( ) if (createdProjectError) { - throw new Error('Failed to create project on Supabase', { + throw new DeployError('Failed to create project on Supabase', { cause: createdProjectError, }) } @@ -80,7 +81,7 @@ export async function createDeployedDatabase( ) if (poolerError) { - throw new Error('Failed to get pooler details', { + throw new DeployError('Failed to get pooler details', { cause: poolerError, }) } @@ -88,7 +89,7 @@ export async function createDeployedDatabase( const primaryDatabase = pooler.find((db) => db.database_type === 'PRIMARY') if (!primaryDatabase) { - throw new Error('Primary database not found') + throw new DeployError('Primary database not found') } // store the database password as a secret @@ -98,7 +99,7 @@ export async function createDeployedDatabase( }) if (databasePasswordSecret.error) { - throw new Error('Cannot store database password as secret', { + throw new DeployError('Cannot store database password as secret', { cause: databasePasswordSecret.error, }) } @@ -132,7 +133,7 @@ export async function createDeployedDatabase( .single() if (deployedDatabase.error) { - throw new Error('Cannot create deployed database', { cause: deployedDatabase.error }) + throw new DeployError('Cannot create deployed database', { cause: deployedDatabase.error }) } return deployedDatabase.data diff --git a/apps/deploy-worker/src/supabase/database-types.ts b/apps/deploy-worker/src/supabase/database-types.ts index 2e461f32..1ecc9693 100644 --- a/apps/deploy-worker/src/supabase/database-types.ts +++ b/apps/deploy-worker/src/supabase/database-types.ts @@ -50,15 +50,7 @@ export type Database = { id?: never user_id?: string } - Relationships: [ - { - foreignKeyName: "deploy_waitlist_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["id"] - }, - ] + Relationships: [] } deployed_databases: { Row: { @@ -131,13 +123,6 @@ export type Database = { referencedRelation: "deployment_providers" referencedColumns: ["id"] }, - { - foreignKeyName: "deployment_provider_integrations_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["id"] - }, ] } deployment_providers: { @@ -170,6 +155,7 @@ export type Database = { local_database_id: string status: Database["public"]["Enums"]["deployment_status"] updated_at: string + user_id: string } Insert: { created_at?: string @@ -179,6 +165,7 @@ export type Database = { local_database_id: string status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string + user_id?: string } Update: { created_at?: string @@ -188,6 +175,7 @@ export type Database = { local_database_id?: string status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string + user_id?: string } Relationships: [ { @@ -330,3 +318,18 @@ export type Enums< ? PublicSchema["Enums"][PublicEnumNameOrOptions] : never +export type CompositeTypes< + PublicCompositeTypeNameOrOptions extends + | keyof PublicSchema["CompositeTypes"] + | { schema: keyof Database }, + CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { + schema: keyof Database + } + ? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] + : never = never, +> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database } + ? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] + : PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"] + ? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] + : never + diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index 32c44514..f7bc0a5b 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -4,6 +4,7 @@ import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' import { createDeployedDatabase } from './create-deployed-database.ts' import { getDatabaseUrl } from './get-database-url.ts' +import { DeployError } from '../error.ts' const exec = promisify(execSync) /** @@ -24,12 +25,14 @@ export async function deploy( if (createDeploymentError) { if (createDeploymentError.code === '23505') { - throw new Error('Deployment already in progress', { cause: createDeploymentError }) + throw new DeployError('Deployment already in progress', { cause: createDeploymentError }) } - throw new Error('Cannot create deployment', { cause: createDeploymentError }) + throw new DeployError('Cannot create deployment', { cause: createDeploymentError }) } + let isRedeploy = false + try { // check if the database was already deployed const deployedDatabase = await ctx.supabase @@ -40,7 +43,7 @@ export async function deploy( .maybeSingle() if (deployedDatabase.error) { - throw new Error('Cannot find deployed database', { cause: deployedDatabase.error }) + throw new DeployError('Cannot find deployed database', { cause: deployedDatabase.error }) } if (!deployedDatabase.data) { @@ -48,6 +51,21 @@ export async function deploy( { supabase: ctx.supabase }, { databaseId: params.databaseId, integrationId: params.integrationId } ) + } else { + isRedeploy = true + } + + const { error: linkDeploymentError } = await ctx.supabase + .from('deployments') + .update({ + deployed_database_id: deployedDatabase.data.id, + }) + .eq('id', deployment.id) + + if (linkDeploymentError) { + throw new DeployError('Cannot link deployment with deployed database', { + cause: linkDeploymentError, + }) } const project = (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project @@ -63,9 +81,12 @@ export async function deploy( try { await exec(command) } catch (error) { - throw new Error('Cannot transfer the data from the local database to the remote database', { - cause: error, - }) + throw new DeployError( + 'Cannot transfer the data from the local database to the remote database', + { + cause: error, + } + ) } await ctx.supabase @@ -78,7 +99,8 @@ export async function deploy( return { name: project.name, url: `https://supabase.com/dashboard/project/${project.id}`, - databaseUrl, + databaseUrl: await getDatabaseUrl({ project, hidePassword: isRedeploy }), + isRedeploy, } } catch (error) { await ctx.supabase diff --git a/apps/deploy-worker/src/supabase/get-access-token.ts b/apps/deploy-worker/src/supabase/get-access-token.ts index a936e454..a64bb593 100644 --- a/apps/deploy-worker/src/supabase/get-access-token.ts +++ b/apps/deploy-worker/src/supabase/get-access-token.ts @@ -1,3 +1,4 @@ +import { DeployError } from '../error.ts' import { supabaseAdmin } from './client.ts' import type { Credentials, SupabaseClient } from './types.ts' @@ -18,7 +19,7 @@ export async function getAccessToken( }) if (refreshToken.error) { - throw new Error('Failed to read refresh token', { cause: refreshToken.error }) + throw new DeployError('Failed to read refresh token', { cause: refreshToken.error }) } const now = Date.now() @@ -37,7 +38,7 @@ export async function getAccessToken( }) if (!newCredentialsResponse.ok) { - throw new Error('Failed to fetch new credentials', { + throw new DeployError('Failed to fetch new credentials', { cause: { status: newCredentialsResponse.status, statusText: newCredentialsResponse.statusText, @@ -59,7 +60,7 @@ export async function getAccessToken( }) if (updateRefreshToken.error) { - throw new Error('Failed to update refresh token', { cause: updateRefreshToken.error }) + throw new DeployError('Failed to update refresh token', { cause: updateRefreshToken.error }) } const updateAccessToken = await supabaseAdmin.rpc('update_secret', { @@ -68,7 +69,7 @@ export async function getAccessToken( }) if (updateAccessToken.error) { - throw new Error('Failed to update access token', { cause: updateAccessToken.error }) + throw new DeployError('Failed to update access token', { cause: updateAccessToken.error }) } const updateIntegration = await ctx.supabase @@ -83,7 +84,7 @@ export async function getAccessToken( .eq('id', params.integrationId) if (updateIntegration.error) { - throw new Error('Failed to update integration', { cause: updateIntegration.error }) + throw new DeployError('Failed to update integration', { cause: updateIntegration.error }) } } @@ -92,7 +93,7 @@ export async function getAccessToken( }) if (accessToken.error) { - throw new Error('Failed to read access token', { cause: accessToken.error }) + throw new DeployError('Failed to read access token', { cause: accessToken.error }) } return accessToken.data diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/apps/deploy-worker/src/supabase/get-database-url.ts index f311290d..fd447267 100644 --- a/apps/deploy-worker/src/supabase/get-database-url.ts +++ b/apps/deploy-worker/src/supabase/get-database-url.ts @@ -1,21 +1,30 @@ +import { DeployError } from '../error.ts' import { supabaseAdmin } from './client.ts' import type { SupabaseProviderMetadata } from './types.ts' /** * Get the database url for a given Supabase project. */ -export async function getDatabaseUrl(params: { project: SupabaseProviderMetadata['project'] }) { - const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { - secret_id: params.project.database.password, - }) - - if (databasePasswordSecret.error) { - throw new Error('Cannot read database password secret', { - cause: databasePasswordSecret.error, +export async function getDatabaseUrl(params: { + project: SupabaseProviderMetadata['project'] + hidePassword?: boolean +}) { + let password = '[YOUR-PASSWORD]' + if (!params.hidePassword) { + const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { + secret_id: params.project.database.password, }) + + if (databasePasswordSecret.error) { + throw new DeployError('Cannot read database password secret', { + cause: databasePasswordSecret.error, + }) + } + + password = databasePasswordSecret.data } const { database } = params.project - return `postgresql://${database.user}:${databasePasswordSecret.data}@${database.host}:${database.port}/${database.name}` + return `postgresql://${database.user}:${password}@${database.host}:${database.port}/${database.name}` } diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index 4576bd49..9aaa903b 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -1,3 +1,4 @@ +import { DeployError } from '../error.ts' import type { ManagementApiClient, Project } from './types.ts' import { setTimeout } from 'timers/promises' @@ -24,7 +25,7 @@ export async function waitForProjectToBeHealthy( }) if (error) { - throw new Error('Failed to get Supabase project health status', { + throw new DeployError('Failed to get Supabase project health status', { cause: error, }) } @@ -34,7 +35,7 @@ export async function waitForProjectToBeHealthy( } if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { - throw new Error(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`, { + throw new DeployError(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`, { cause: { status: project.status, }, @@ -77,7 +78,7 @@ export async function waitForDatabaseToBeHealthy( ) if (error) { - throw new Error("Failed to get Supabase project's database health status", { + throw new DeployError("Failed to get Supabase project's database health status", { cause: error, }) } @@ -86,11 +87,11 @@ export async function waitForDatabaseToBeHealthy( const poolerService = servicesHealth.find((service) => service.name === 'pooler') if (!databaseService) { - throw new Error('Database service not found on Supabase for health check') + throw new DeployError('Database service not found on Supabase for health check') } if (!poolerService) { - throw new Error('Pooler service not found on Supabase for health check') + throw new DeployError('Pooler service not found on Supabase for health check') } if ( @@ -101,12 +102,15 @@ export async function waitForDatabaseToBeHealthy( } if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { - throw new Error(`Database did not become healthy within ${MAX_POLLING_TIME} minutes`, { - cause: { - status: databaseService.status, - error: databaseService.error, - }, - }) + throw new DeployError( + `Database did not become healthy within ${MAX_POLLING_TIME} minutes`, + { + cause: { + status: databaseService.status, + error: databaseService.error, + }, + } + ) } await setTimeout(POLLING_INTERVAL) diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index 72a84c54..4207ac86 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -45,8 +45,7 @@ export default function Page() { }) if (!response.ok) { - console.log(response) - throw new Error(response.statusText) + throw new Error(await response.text()) } return (await response.json()) as { @@ -54,6 +53,7 @@ export default function Page() { name: string url: string databaseUrl: string + isRedeploy: boolean } } }, diff --git a/apps/postgres-new/components/deploy-failure-dialog.tsx b/apps/postgres-new/components/deploy-failure-dialog.tsx index 4a58018b..4bbb6683 100644 --- a/apps/postgres-new/components/deploy-failure-dialog.tsx +++ b/apps/postgres-new/components/deploy-failure-dialog.tsx @@ -1,3 +1,5 @@ +'use client' + import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' import { useRouter } from 'next/navigation' import { useEffect, useState } from 'react' diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index 00faf540..8dc6051b 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -1,3 +1,5 @@ +'use client' + import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' import { useRouter } from 'next/navigation' import { CopyableField } from './copyable-field' @@ -6,9 +8,12 @@ import { useEffect, useState } from 'react' export function DeploySuccessDialog() { const router = useRouter() - const [project, setProject] = useState<{ name: string; url: string; databaseUrl: string } | null>( - null - ) + const [project, setProject] = useState<{ + name: string + url: string + databaseUrl: string + isRedeploy: boolean + } | null>(null) const [open, setOpen] = useState(false) useEffect(() => { const searchParams = new URLSearchParams(window.location.search) @@ -24,16 +29,18 @@ export function DeploySuccessDialog() { return null } + const deployText = project.isRedeploy ? 'redeployed' : 'deployed' + return ( - Database deployed + Database {deployText}

- Your database has been deployed to the Supabase project:{' '} + Your database has been {deployText} to the Supabase project:{' '}

- - {/* eslint-disable-next-line react/no-unescaped-entities */} - Important: Please save your database password securely as it won't be displayed again. - + {project.isRedeploy ? null : ( + + {/* eslint-disable-next-line react/no-unescaped-entities */} + Important: Please save your database password securely as it won't be displayed + again. + + )}

diff --git a/apps/postgres-new/components/redeploy-alert-dialog.tsx b/apps/postgres-new/components/redeploy-alert-dialog.tsx new file mode 100644 index 00000000..375549d5 --- /dev/null +++ b/apps/postgres-new/components/redeploy-alert-dialog.tsx @@ -0,0 +1,42 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from '~/components/ui/alert-dialog' + +type RedeployAlertDialogProps = { + isOpen: boolean + onOpenChange: (open: boolean) => void + onConfirm: () => void +} + +export function RedeployAlertDialog(props: RedeployAlertDialogProps) { + return ( + + + + Redeploy database? + + Redeploying the database will overwrite the existing deployed database with the latest + version. + + + + Cancel + { + props.onConfirm() + }} + > + Redeploy + + + + + ) +} diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index a1f7bb0f..26508619 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -27,7 +27,7 @@ import { useDatabaseUpdateMutation } from '~/data/databases/database-update-muta import { useDatabasesQuery } from '~/data/databases/databases-query' import { useDeployWaitlistCreateMutation } from '~/data/deploy-waitlist/deploy-waitlist-create-mutation' import { useIsOnDeployWaitlistQuery } from '~/data/deploy-waitlist/deploy-waitlist-query' -import { Database } from '~/lib/db' +import { Database as LocalDatabase } from '~/lib/db' import { downloadFile, titleToKebabCase } from '~/lib/util' import { cn } from '~/lib/utils' import { useApp } from './app-provider' @@ -44,6 +44,12 @@ import { import { TooltipPortal } from '@radix-ui/react-tooltip' import { LiveShareIcon } from './live-share-icon' import { createClient } from '~/utils/supabase/client' +import { RedeployAlertDialog } from './redeploy-alert-dialog' +import { useDeployedDatabasesQuery } from '~/data/deployed-databases/deployed-databases-query' + +type Database = LocalDatabase & { + isDeployed: boolean +} export default function Sidebar() { const { @@ -58,9 +64,16 @@ export default function Sidebar() { } = useApp() let { id: currentDatabaseId } = useParams<{ id: string }>() const router = useRouter() - const { data: databases, isLoading: isLoadingDatabases } = useDatabasesQuery() + const { data: localDatabases, isLoading: isLoadingDatabases } = useDatabasesQuery() + const { data: deployedDatabases } = useDeployedDatabasesQuery() const [showSidebar, setShowSidebar] = useState(true) + const databases = localDatabases?.map((db) => ({ + ...db, + isDeployed: + deployedDatabases?.some((deployedDb) => deployedDb.local_database_id === db.id) ?? false, + })) + return ( <> (null) + return ( <> + { + router.push(deployUrl!) + }} + /> { @@ -534,7 +557,15 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { integration: integration.id.toString(), }) - router.push(`/deploy/${database.id}?${params.toString()}`) + const deployUrl = `/deploy/${database.id}?${params.toString()}` + + setDeployUrl(deployUrl) + + if (database.isDeployed) { + setIsRedeployAlertDialogOpen(true) + } else { + router.push(deployUrl) + } }} disabled={user === undefined} > @@ -543,7 +574,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { strokeWidth={2} className="flex-shrink-0 text-muted-foreground" /> - Deploy + {database.isDeployed ? 'Redeploy' : 'Deploy'} , + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/apps/postgres-new/data/deployed-databases/deployed-databases-query.ts b/apps/postgres-new/data/deployed-databases/deployed-databases-query.ts new file mode 100644 index 00000000..c838f218 --- /dev/null +++ b/apps/postgres-new/data/deployed-databases/deployed-databases-query.ts @@ -0,0 +1,24 @@ +import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { useApp } from '~/components/app-provider' +import { Database } from '~/utils/supabase/db-types' +import { createClient } from '~/utils/supabase/client' + +type DeployedDatabase = Database['public']['Tables']['deployed_databases']['Row'] + +export const useDeployedDatabasesQuery = ( + options: Omit, 'queryKey' | 'queryFn'> = {} +) => { + const { user } = useApp() + console.log('user', user) + return useQuery({ + ...options, + queryKey: getDeployedDatabasesQueryKey(), + queryFn: async () => { + const supabase = createClient() + const deployedDatabases = await supabase.from('deployed_databases').select() + return deployedDatabases.data ?? [] + }, + }) +} + +export const getDeployedDatabasesQueryKey = () => ['deployed-databases', 'authenticated'] diff --git a/apps/postgres-new/package.json b/apps/postgres-new/package.json index 12cf6836..409dad61 100644 --- a/apps/postgres-new/package.json +++ b/apps/postgres-new/package.json @@ -7,7 +7,7 @@ "build": "next build", "start": "next start", "lint": "next lint", - "generate:types": "supabase gen types --lang=typescript --local > utils/supabase/db-types.ts" + "generate:database-types": "supabase gen types --lang=typescript --local > utils/supabase/db-types.ts" }, "dependencies": { "@ai-sdk/openai": "^0.0.21", @@ -16,6 +16,7 @@ "@gregnr/postgres-meta": "^0.82.0-dev.2", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", + "@radix-ui/react-alert-dialog": "^1.1.2", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.1.0", diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts index 66bd32f0..1ecc9693 100644 --- a/apps/postgres-new/utils/supabase/db-types.ts +++ b/apps/postgres-new/utils/supabase/db-types.ts @@ -50,15 +50,7 @@ export type Database = { id?: never user_id?: string } - Relationships: [ - { - foreignKeyName: "deploy_waitlist_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["id"] - }, - ] + Relationships: [] } deployed_databases: { Row: { @@ -131,13 +123,6 @@ export type Database = { referencedRelation: "deployment_providers" referencedColumns: ["id"] }, - { - foreignKeyName: "deployment_provider_integrations_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["id"] - }, ] } deployment_providers: { @@ -164,24 +149,33 @@ export type Database = { deployments: { Row: { created_at: string - deployed_database_id: number + deployed_database_id: number | null + events: Json id: number + local_database_id: string status: Database["public"]["Enums"]["deployment_status"] updated_at: string + user_id: string } Insert: { created_at?: string - deployed_database_id: number + deployed_database_id?: number | null + events?: Json id?: never - status: Database["public"]["Enums"]["deployment_status"] + local_database_id: string + status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string + user_id?: string } Update: { created_at?: string - deployed_database_id?: number + deployed_database_id?: number | null + events?: Json id?: never + local_database_id?: string status?: Database["public"]["Enums"]["deployment_status"] updated_at?: string + user_id?: string } Relationships: [ { @@ -324,3 +318,18 @@ export type Enums< ? PublicSchema["Enums"][PublicEnumNameOrOptions] : never +export type CompositeTypes< + PublicCompositeTypeNameOrOptions extends + | keyof PublicSchema["CompositeTypes"] + | { schema: keyof Database }, + CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { + schema: keyof Database + } + ? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] + : never = never, +> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database } + ? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] + : PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"] + ? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] + : never + diff --git a/package-lock.json b/package-lock.json index c52a004b..ba43df1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "apps/*" ], "devDependencies": { - "supabase": "^1.204.3" + "supabase": "^1.207.9" } }, "apps/browser-proxy": { @@ -41,6 +41,8 @@ }, "apps/browser-proxy/node_modules/nanoid": { "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", "funding": [ { "type": "github", @@ -61,6 +63,8 @@ }, "apps/browser-proxy/node_modules/undici-types": { "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true, "license": "MIT" }, @@ -122,6 +126,7 @@ "@gregnr/postgres-meta": "^0.82.0-dev.2", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-accordion": "^1.2.0", + "@radix-ui/react-alert-dialog": "^1.1.2", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.1.0", @@ -204,6 +209,8 @@ }, "apps/postgres-new/node_modules/nanoid": { "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", "funding": [ { "type": "github", @@ -229,6 +236,8 @@ }, "node_modules/@ai-sdk/openai": { "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-0.0.21.tgz", + "integrity": "sha512-k1sLRDKIsiHFuwPa9xBm4oQZ7JQVPE9+KzwP/E4v4zGwsL8Sp5gt+OTccP5cECVhDcRKDYaj0wXtCcmFyAh5uA==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "0.0.9", @@ -243,6 +252,8 @@ }, "node_modules/@ai-sdk/provider": { "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-0.0.9.tgz", + "integrity": "sha512-SJX9J+wiur/EVSYZ6lHV33YWB/yeZ+RCGg+8gSsKzrxEUCh+TkqM5Af7cw2hDFv65dXyeNOZHhfINoD9StEm6A==", "license": "Apache-2.0", "dependencies": { "json-schema": "0.4.0" @@ -253,6 +264,8 @@ }, "node_modules/@ai-sdk/provider-utils": { "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-0.0.12.tgz", + "integrity": "sha512-jt3RwW68x+fVPrsmcKR3RT+G+ISgsO7mu/M+kCnZmxR4JtbypgS/JsAtnnoD7YtAcqLplbYBzJEsRW4CRqIWMQ==", "license": "Apache-2.0", "dependencies": { "@ai-sdk/provider": "0.0.9", @@ -499,6 +512,8 @@ }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "license": "MIT", "engines": { "node": ">=10" @@ -1484,6 +1499,8 @@ }, "node_modules/@emnapi/runtime": { "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.43.1.tgz", + "integrity": "sha512-Q5sMc4Z4gsD4tlmlyFu+MpNAwpR7Gv2errDhVJ+SOhNjWcx8UTqy+hswb8L31RfC8jBvDgcnT87l3xI2w08rAg==", "license": "MIT", "dependencies": { "tslib": "^2.4.0" @@ -1491,6 +1508,8 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "license": "MIT", "dependencies": { @@ -1513,6 +1532,8 @@ }, "node_modules/@eslint/eslintrc": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1543,6 +1564,8 @@ }, "node_modules/@fastify/ajv-compiler": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz", + "integrity": "sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==", "license": "MIT", "dependencies": { "ajv": "^8.11.0", @@ -1552,6 +1575,8 @@ }, "node_modules/@fastify/ajv-compiler/node_modules/ajv": { "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -1570,10 +1595,14 @@ }, "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, "node_modules/@fastify/cors": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz", + "integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==", "license": "MIT", "dependencies": { "fastify-plugin": "^4.0.0", @@ -1582,10 +1611,14 @@ }, "node_modules/@fastify/error": { "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", "license": "MIT" }, "node_modules/@fastify/fast-json-stringify-compiler": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", "license": "MIT", "dependencies": { "fast-json-stringify": "^5.7.0" @@ -1593,6 +1626,8 @@ }, "node_modules/@fastify/merge-json-schemas": { "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", + "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -1611,6 +1646,8 @@ }, "node_modules/@fastify/type-provider-typebox": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@fastify/type-provider-typebox/-/type-provider-typebox-3.6.0.tgz", + "integrity": "sha512-HTeOLvirfGg0u1KGao3iXn5rZpYNqlrOmyDnXSXAbWVPa+mDQTTBNs/x5uZzOB6vFAqr0Xcf7x1lxOamNSYKjw==", "license": "MIT", "peerDependencies": { "@sinclair/typebox": ">=0.26 <=0.32" @@ -1648,10 +1685,14 @@ }, "node_modules/@gar/promisify": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "license": "MIT" }, "node_modules/@gregnr/postgres-meta": { "version": "0.82.0-dev.2", + "resolved": "https://registry.npmjs.org/@gregnr/postgres-meta/-/postgres-meta-0.82.0-dev.2.tgz", + "integrity": "sha512-RLCMcshNBZi1FBA60PfQTLCvfuYmNXVzRe147j5mlOIXvq+o9K/pJgm49GOEBBYfvH+bwcs3w/mBRCh7BNveng==", "license": "MIT", "dependencies": { "@fastify/cors": "^9.0.1", @@ -1701,6 +1742,8 @@ }, "node_modules/@huggingface/jinja": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.2.2.tgz", + "integrity": "sha512-/KPde26khDUIPkTGU82jdtTW9UAuvUTumCAbFs/7giR0SxsvZC4hru51PBvpijH6BVkHcROcvZM/lpy5h1jRRA==", "license": "MIT", "engines": { "node": ">=18" @@ -1721,6 +1764,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1738,6 +1783,8 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -1763,6 +1810,8 @@ }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -1776,6 +1825,8 @@ }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, "license": "ISC", "dependencies": { @@ -1787,6 +1838,8 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -1799,6 +1852,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1806,6 +1861,8 @@ }, "node_modules/@jridgewell/set-array": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1824,10 +1881,14 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1849,10 +1910,14 @@ }, "node_modules/@kurkle/color": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", "license": "MIT" }, "node_modules/@launchql/protobufjs": { "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@launchql/protobufjs/-/protobufjs-7.2.6.tgz", + "integrity": "sha512-vwi1nG2/heVFsIMHQU1KxTjUp5c757CTtRAZn/jutApCkFlle1iv8tzM/DHlSZJKDldxaYqnNYTg0pTyp8Bbtg==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -1875,6 +1940,8 @@ }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "license": "BSD-3-Clause", "dependencies": { "detect-libc": "^2.0.0", @@ -1893,6 +1960,8 @@ }, "node_modules/@mertasan/tailwindcss-variables": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@mertasan/tailwindcss-variables/-/tailwindcss-variables-2.7.0.tgz", + "integrity": "sha512-rKPhxi/0r6XWP0+OjPmsfrloX/TtQmvONj2Pr3Nl8BNBznQVP3M9sphguDBUDC0AiKYx2xgup3XzAhlIDLPLIA==", "dev": true, "license": "MIT", "dependencies": { @@ -1908,6 +1977,8 @@ }, "node_modules/@monaco-editor/loader": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", "license": "MIT", "dependencies": { "state-local": "^1.0.6" @@ -1918,6 +1989,8 @@ }, "node_modules/@monaco-editor/react": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", "license": "MIT", "dependencies": { "@monaco-editor/loader": "^1.4.0" @@ -1930,10 +2003,14 @@ }, "node_modules/@next/env": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.3.tgz", + "integrity": "sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz", + "integrity": "sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1942,6 +2019,8 @@ }, "node_modules/@next/swc-darwin-arm64": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", + "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", "cpu": [ "arm64" ], @@ -2076,6 +2155,8 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -2087,6 +2168,8 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "license": "MIT", "engines": { "node": ">= 8" @@ -2094,6 +2177,8 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -2105,6 +2190,8 @@ }, "node_modules/@npmcli/agent": { "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", "license": "ISC", "dependencies": { "agent-base": "^7.1.0", @@ -2119,6 +2206,8 @@ }, "node_modules/@npmcli/agent/node_modules/agent-base": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -2129,6 +2218,8 @@ }, "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -2140,6 +2231,8 @@ }, "node_modules/@npmcli/fs": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", "license": "ISC", "dependencies": { "semver": "^7.3.5" @@ -2150,6 +2243,8 @@ }, "node_modules/@npmcli/move-file": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", @@ -2161,6 +2256,8 @@ }, "node_modules/@opentelemetry/api": { "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", "engines": { "node": ">=8.0.0" @@ -2168,10 +2265,14 @@ }, "node_modules/@pgsql/types": { "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@pgsql/types/-/types-15.0.2.tgz", + "integrity": "sha512-K3gtnbqbSUuUVmPm143qx5Gy2EmKuooshV95yMD48EUQ1256sgZBriEfY61OWJnlzdREdqHTIOxQqpZAb7XdZg==", "license": "SEE LICENSE IN LICENSE" }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "license": "MIT", "optional": true, "engines": { @@ -2180,22 +2281,32 @@ }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", @@ -2204,31 +2315,45 @@ }, "node_modules/@protobufjs/float": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, "node_modules/@radix-ui/colors": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/colors/-/colors-3.0.0.tgz", + "integrity": "sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==", "dev": true, "license": "MIT" }, "node_modules/@radix-ui/primitive": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", "license": "MIT" }, "node_modules/@radix-ui/react-accordion": { @@ -2260,8 +2385,53 @@ } } }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.2.tgz", + "integrity": "sha512-eGSlLzPhKO+TErxkiGcCZGuvbVMnLA1MTnyBksGOeGRGkxHiiJUujsjmNTdWTm4iHVSRaUao9/4Ur671auMghQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dialog": "1.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.0.0" @@ -2311,6 +2481,8 @@ }, "node_modules/@radix-ui/react-collection": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.0", @@ -2335,6 +2507,8 @@ }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2348,6 +2522,8 @@ }, "node_modules/@radix-ui/react-context": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2360,23 +2536,67 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.1", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.0", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-slot": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.7" + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -2393,8 +2613,98 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz", + "integrity": "sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.6", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2473,6 +2783,8 @@ }, "node_modules/@radix-ui/react-focus-scope": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.0", @@ -2496,6 +2808,8 @@ }, "node_modules/@radix-ui/react-id": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" @@ -2512,6 +2826,8 @@ }, "node_modules/@radix-ui/react-label": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.0.0" @@ -2606,6 +2922,8 @@ }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", @@ -2680,6 +2998,8 @@ }, "node_modules/@radix-ui/react-primitive": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.1.0" @@ -2725,6 +3045,8 @@ }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", + "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", @@ -2754,6 +3076,8 @@ }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.0" @@ -2830,6 +3154,8 @@ }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2843,6 +3169,8 @@ }, "node_modules/@radix-ui/react-use-controllable-state": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" @@ -2859,6 +3187,8 @@ }, "node_modules/@radix-ui/react-use-escape-keydown": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" @@ -2875,6 +3205,8 @@ }, "node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2888,6 +3220,8 @@ }, "node_modules/@radix-ui/react-use-rect": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", "license": "MIT", "dependencies": { "@radix-ui/rect": "1.1.0" @@ -2904,6 +3238,8 @@ }, "node_modules/@radix-ui/react-use-size": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" @@ -2920,6 +3256,8 @@ }, "node_modules/@radix-ui/react-visually-hidden": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.0.0" @@ -2941,10 +3279,14 @@ }, "node_modules/@radix-ui/rect": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", "license": "MIT" }, "node_modules/@reactflow/background": { "version": "11.3.14", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz", + "integrity": "sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==", "license": "MIT", "dependencies": { "@reactflow/core": "11.11.4", @@ -2958,6 +3300,8 @@ }, "node_modules/@reactflow/controls": { "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.14.tgz", + "integrity": "sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==", "license": "MIT", "dependencies": { "@reactflow/core": "11.11.4", @@ -2971,6 +3315,8 @@ }, "node_modules/@reactflow/core": { "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.11.4.tgz", + "integrity": "sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==", "license": "MIT", "dependencies": { "@types/d3": "^7.4.0", @@ -2990,6 +3336,8 @@ }, "node_modules/@reactflow/minimap": { "version": "11.7.14", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.14.tgz", + "integrity": "sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==", "license": "MIT", "dependencies": { "@reactflow/core": "11.11.4", @@ -3007,6 +3355,8 @@ }, "node_modules/@reactflow/node-resizer": { "version": "2.2.14", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.14.tgz", + "integrity": "sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==", "license": "MIT", "dependencies": { "@reactflow/core": "11.11.4", @@ -3022,6 +3372,8 @@ }, "node_modules/@reactflow/node-toolbar": { "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.14.tgz", + "integrity": "sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==", "license": "MIT", "dependencies": { "@reactflow/core": "11.11.4", @@ -3145,6 +3497,8 @@ }, "node_modules/@sinclair/typebox": { "version": "0.31.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.28.tgz", + "integrity": "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==", "license": "MIT" }, "node_modules/@smithy/abort-controller": { @@ -3762,6 +4116,8 @@ }, "node_modules/@supabase/node-fetch": { "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -3772,6 +4128,8 @@ }, "node_modules/@supabase/postgres-meta": { "version": "0.81.2", + "resolved": "https://registry.npmjs.org/@supabase/postgres-meta/-/postgres-meta-0.81.2.tgz", + "integrity": "sha512-rm7jiLkUrPF+geG9Z6PvfwNaxcZUojvT6SZM6C9y+5mYDGEu5vxda/dNjgKtWWYW30F3VcmDQ7TT8tqOjB97KA==", "license": "MIT", "dependencies": { "@fastify/cors": "^9.0.1", @@ -3848,10 +4206,14 @@ }, "node_modules/@swc/counter": { "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "license": "Apache-2.0" }, "node_modules/@swc/helpers": { "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", @@ -3885,6 +4247,8 @@ }, "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "license": "MIT", "dependencies": { @@ -3919,6 +4283,8 @@ }, "node_modules/@tootallnate/once": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "license": "MIT", "engines": { "node": ">= 6" @@ -3931,11 +4297,15 @@ }, "node_modules/@types/common-tags": { "version": "1.8.4", + "resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.4.tgz", + "integrity": "sha512-S+1hLDJPjWNDhcGxsxEbepzaxWqURP/o+3cP4aa2w7yBXgdcmKGQtZzP8JbyfOd0m+33nh+8+kvxYE2UJtBDkg==", "dev": true, "license": "MIT" }, "node_modules/@types/d3": { "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", "license": "MIT", "dependencies": { "@types/d3-array": "*", @@ -3972,10 +4342,14 @@ }, "node_modules/@types/d3-array": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", "license": "MIT" }, "node_modules/@types/d3-axis": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", "license": "MIT", "dependencies": { "@types/d3-selection": "*" @@ -3983,6 +4357,8 @@ }, "node_modules/@types/d3-brush": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", "license": "MIT", "dependencies": { "@types/d3-selection": "*" @@ -3990,14 +4366,20 @@ }, "node_modules/@types/d3-chord": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", "license": "MIT" }, "node_modules/@types/d3-color": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", "license": "MIT" }, "node_modules/@types/d3-contour": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", "license": "MIT", "dependencies": { "@types/d3-array": "*", @@ -4006,14 +4388,20 @@ }, "node_modules/@types/d3-delaunay": { "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", "license": "MIT" }, "node_modules/@types/d3-dispatch": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", + "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", "license": "MIT" }, "node_modules/@types/d3-drag": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", "license": "MIT", "dependencies": { "@types/d3-selection": "*" @@ -4021,14 +4409,20 @@ }, "node_modules/@types/d3-dsv": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", "license": "MIT" }, "node_modules/@types/d3-ease": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", "license": "MIT" }, "node_modules/@types/d3-fetch": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", "license": "MIT", "dependencies": { "@types/d3-dsv": "*" @@ -4036,14 +4430,20 @@ }, "node_modules/@types/d3-force": { "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", "license": "MIT" }, "node_modules/@types/d3-format": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", "license": "MIT" }, "node_modules/@types/d3-geo": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", "license": "MIT", "dependencies": { "@types/geojson": "*" @@ -4051,10 +4451,14 @@ }, "node_modules/@types/d3-hierarchy": { "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", "license": "MIT" }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", "license": "MIT", "dependencies": { "@types/d3-color": "*" @@ -4062,22 +4466,32 @@ }, "node_modules/@types/d3-path": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==", "license": "MIT" }, "node_modules/@types/d3-polygon": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", "license": "MIT" }, "node_modules/@types/d3-quadtree": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", "license": "MIT" }, "node_modules/@types/d3-random": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", "license": "MIT" }, "node_modules/@types/d3-scale": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", "license": "MIT", "dependencies": { "@types/d3-time": "*" @@ -4085,6 +4499,8 @@ }, "node_modules/@types/d3-scale-chromatic": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", + "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==", "license": "MIT" }, "node_modules/@types/d3-selection": { @@ -4093,6 +4509,8 @@ }, "node_modules/@types/d3-shape": { "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", + "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", "license": "MIT", "dependencies": { "@types/d3-path": "*" @@ -4100,14 +4518,20 @@ }, "node_modules/@types/d3-time": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", + "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==", "license": "MIT" }, "node_modules/@types/d3-time-format": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", "license": "MIT" }, "node_modules/@types/d3-timer": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, "node_modules/@types/d3-transition": { @@ -4119,6 +4543,8 @@ }, "node_modules/@types/d3-zoom": { "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", "license": "MIT", "dependencies": { "@types/d3-interpolate": "*", @@ -4127,6 +4553,8 @@ }, "node_modules/@types/debug": { "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", "dependencies": { "@types/ms": "*" @@ -4134,6 +4562,8 @@ }, "node_modules/@types/diff-match-patch": { "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", + "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", "license": "MIT" }, "node_modules/@types/estree": { @@ -4142,6 +4572,8 @@ }, "node_modules/@types/estree-jsx": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "license": "MIT", "dependencies": { "@types/estree": "*" @@ -4149,10 +4581,14 @@ }, "node_modules/@types/geojson": { "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -4160,6 +4596,8 @@ }, "node_modules/@types/js-cookie": { "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==", "license": "MIT" }, "node_modules/@types/json-schema": { @@ -4171,11 +4609,15 @@ }, "node_modules/@types/json5": { "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true, "license": "MIT" }, "node_modules/@types/katex": { "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", "license": "MIT" }, "node_modules/@types/lodash": { @@ -4185,10 +4627,14 @@ }, "node_modules/@types/long": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT" }, "node_modules/@types/mdast": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -4196,6 +4642,8 @@ }, "node_modules/@types/ms": { "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", "license": "MIT" }, "node_modules/@types/node": { @@ -4207,6 +4655,8 @@ }, "node_modules/@types/phoenix": { "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.5.tgz", + "integrity": "sha512-xegpDuR+z0UqG9fwHqNoy3rI7JDlvaPh2TY47Fl80oq6g+hXT+c/LEuE43X48clZ6lOfANl5WrPur9fYO1RJ/w==", "license": "MIT" }, "node_modules/@types/prop-types": { @@ -4231,6 +4681,8 @@ }, "node_modules/@types/react-syntax-highlighter": { "version": "15.5.13", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", + "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", "dev": true, "license": "MIT", "dependencies": { @@ -4250,6 +4702,8 @@ }, "node_modules/@types/ws": { "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -4257,6 +4711,8 @@ }, "node_modules/@typescript-eslint/parser": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4284,6 +4740,8 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", "dev": true, "license": "MIT", "dependencies": { @@ -4300,6 +4758,8 @@ }, "node_modules/@typescript-eslint/types": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", "dev": true, "license": "MIT", "engines": { @@ -4312,6 +4772,8 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4339,6 +4801,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { @@ -4347,6 +4811,8 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "license": "ISC", "dependencies": { @@ -4361,6 +4827,8 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", "dev": true, "license": "MIT", "dependencies": { @@ -4377,6 +4845,8 @@ }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "license": "ISC" }, "node_modules/@upstash/core-analytics": { @@ -4405,6 +4875,8 @@ }, "node_modules/@vercel/kv": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@vercel/kv/-/kv-2.0.0.tgz", + "integrity": "sha512-zdVrhbzZBYo5d1Hfn4bKtqCeKf0FuzW8rSHauzQVMUgv1+1JOwof2mWcBuI+YMJy8s0G0oqAUfQ7HgUDzb8EbA==", "license": "Apache-2.0", "dependencies": { "@upstash/redis": "^1.31.3" @@ -4677,6 +5149,8 @@ }, "node_modules/@xenova/transformers": { "version": "2.17.2", + "resolved": "https://registry.npmjs.org/@xenova/transformers/-/transformers-2.17.2.tgz", + "integrity": "sha512-lZmHqzrVIkSvZdKZEx7IYY51TK0WDrC8eR0c5IMnBsO8di8are1zzw8BlLhyO2TklZKLN5UffNGs1IJwT6oOqQ==", "license": "Apache-2.0", "dependencies": { "@huggingface/jinja": "^0.2.2", @@ -4689,6 +5163,8 @@ }, "node_modules/@xobotyi/scrollbar-width": { "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", "license": "MIT" }, "node_modules/@xtuc/ieee754": { @@ -4707,10 +5183,14 @@ }, "node_modules/abbrev": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "license": "ISC" }, "node_modules/abort-controller": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -4721,6 +5201,8 @@ }, "node_modules/abstract-logging": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", "license": "MIT" }, "node_modules/acorn": { @@ -4745,6 +5227,8 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4753,6 +5237,8 @@ }, "node_modules/agent-base": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { "debug": "4" @@ -4763,6 +5249,8 @@ }, "node_modules/agentkeepalive": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" @@ -4773,6 +5261,8 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", @@ -4859,6 +5349,8 @@ }, "node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { @@ -4874,6 +5366,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -4889,6 +5383,8 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -4907,6 +5403,8 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, "node_modules/ajv-keywords": { @@ -4931,6 +5429,8 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -4938,6 +5438,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4951,10 +5453,14 @@ }, "node_modules/any-promise": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -4966,10 +5472,14 @@ }, "node_modules/aproba": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "license": "ISC" }, "node_modules/are-we-there-yet": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "license": "ISC", "dependencies": { "delegates": "^1.0.0", @@ -4981,14 +5491,20 @@ }, "node_modules/arg": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/aria-hidden": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -5007,6 +5523,8 @@ }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "license": "MIT", "dependencies": { @@ -5022,6 +5540,8 @@ }, "node_modules/array-includes": { "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5041,6 +5561,8 @@ }, "node_modules/array-union": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", "engines": { @@ -5049,6 +5571,8 @@ }, "node_modules/array.prototype.findlast": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5087,6 +5611,8 @@ }, "node_modules/array.prototype.flat": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "license": "MIT", "dependencies": { @@ -5104,6 +5630,8 @@ }, "node_modules/array.prototype.flatmap": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5121,6 +5649,8 @@ }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, "license": "MIT", "dependencies": { @@ -5136,6 +5666,8 @@ }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "license": "MIT", "dependencies": { @@ -5157,11 +5689,15 @@ }, "node_modules/ast-types-flow": { "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true, "license": "MIT" }, "node_modules/async-mutex": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", "license": "MIT", "dependencies": { "tslib": "^2.4.0" @@ -5169,6 +5705,8 @@ }, "node_modules/atomic-sleep": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "license": "MIT", "engines": { "node": ">=8.0.0" @@ -5212,6 +5750,8 @@ }, "node_modules/available-typed-arrays": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5254,6 +5794,8 @@ }, "node_modules/bail": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "license": "MIT", "funding": { "type": "github", @@ -5262,6 +5804,8 @@ }, "node_modules/balanced-match": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, "node_modules/bare-events": { @@ -5286,6 +5830,8 @@ }, "node_modules/bare-path": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -5302,6 +5848,8 @@ }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -5320,6 +5868,8 @@ }, "node_modules/big-integer": { "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "license": "Unlicense", "engines": { "node": ">=0.6" @@ -5354,6 +5904,8 @@ }, "node_modules/binary-extensions": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "license": "MIT", "engines": { "node": ">=8" @@ -5364,10 +5916,14 @@ }, "node_modules/bintrees": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", "license": "MIT" }, "node_modules/bl": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -5377,6 +5933,8 @@ }, "node_modules/bl/node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -5403,6 +5961,8 @@ }, "node_modules/brace-expansion": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -5411,6 +5971,8 @@ }, "node_modules/braces": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -5452,6 +6014,8 @@ }, "node_modules/buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -5481,6 +6045,8 @@ }, "node_modules/busboy": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { "streamsearch": "^1.1.0" }, @@ -5490,6 +6056,8 @@ }, "node_modules/cacache": { "version": "18.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", + "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", "license": "ISC", "dependencies": { "@npmcli/fs": "^3.1.0", @@ -5511,6 +6079,8 @@ }, "node_modules/call-bind": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "license": "MIT", "dependencies": { @@ -5529,6 +6099,8 @@ }, "node_modules/callsites": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { @@ -5537,6 +6109,8 @@ }, "node_modules/camelcase-css": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "license": "MIT", "engines": { "node": ">= 6" @@ -5562,6 +6136,8 @@ }, "node_modules/ccount": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "license": "MIT", "funding": { "type": "github", @@ -5570,6 +6146,8 @@ }, "node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -5592,6 +6170,8 @@ }, "node_modules/character-entities": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", "funding": { "type": "github", @@ -5600,6 +6180,8 @@ }, "node_modules/character-entities-html4": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", "license": "MIT", "funding": { "type": "github", @@ -5608,6 +6190,8 @@ }, "node_modules/character-entities-legacy": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "license": "MIT", "funding": { "type": "github", @@ -5616,6 +6200,8 @@ }, "node_modules/character-reference-invalid": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "license": "MIT", "funding": { "type": "github", @@ -5634,6 +6220,8 @@ }, "node_modules/chartjs-adapter-date-fns": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz", + "integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==", "license": "MIT", "peerDependencies": { "chart.js": ">=2.8.0", @@ -5642,6 +6230,8 @@ }, "node_modules/chokidar": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -5664,6 +6254,8 @@ }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -5674,6 +6266,8 @@ }, "node_modules/chownr": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "license": "ISC", "engines": { "node": ">=10" @@ -5691,6 +6285,8 @@ }, "node_modules/class-variance-authority": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", "license": "Apache-2.0", "dependencies": { "clsx": "2.0.0" @@ -5701,6 +6297,8 @@ }, "node_modules/class-variance-authority/node_modules/clsx": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", "license": "MIT", "engines": { "node": ">=6" @@ -5708,10 +6306,14 @@ }, "node_modules/classcat": { "version": "5.0.5", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", + "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", "license": "MIT" }, "node_modules/clean-stack": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "license": "MIT", "engines": { "node": ">=6" @@ -5719,14 +6321,20 @@ }, "node_modules/client-only": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, "node_modules/close-with-grace": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/close-with-grace/-/close-with-grace-1.3.0.tgz", + "integrity": "sha512-lvm0rmLIR5bNz4CRKW6YvCfn9Wg5Wb9A8PJ3Bb+hjyikgC1RO1W3J4z9rBXQYw97mAte7dNSQI8BmUsxdlXQyw==", "license": "MIT" }, "node_modules/clsx": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -5756,6 +6364,8 @@ }, "node_modules/color": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1", @@ -5767,6 +6377,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5777,10 +6389,14 @@ }, "node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/color-string": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", "dependencies": { "color-name": "^1.0.0", @@ -5789,6 +6405,8 @@ }, "node_modules/color-support": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "license": "ISC", "bin": { "color-support": "bin.js" @@ -5803,10 +6421,14 @@ }, "node_modules/comlink": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.1.tgz", + "integrity": "sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q==", "license": "Apache-2.0" }, "node_modules/comma-separated-tokens": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", @@ -5815,6 +6437,8 @@ }, "node_modules/commander": { "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "license": "MIT", "engines": { "node": ">= 12" @@ -5822,6 +6446,8 @@ }, "node_modules/common-tags": { "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "license": "MIT", "engines": { "node": ">=4.0.0" @@ -5829,14 +6455,20 @@ }, "node_modules/concat-map": { "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, "node_modules/console-control-strings": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "license": "ISC" }, "node_modules/cookie": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -5844,6 +6476,8 @@ }, "node_modules/copy-to-clipboard": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", "license": "MIT", "dependencies": { "toggle-selection": "^1.0.6" @@ -5851,6 +6485,8 @@ }, "node_modules/cross-spawn": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5863,10 +6499,14 @@ }, "node_modules/crypto-js": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "license": "MIT" }, "node_modules/css-in-js-utils": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", "license": "MIT", "dependencies": { "hyphenate-style-name": "^1.0.3" @@ -5886,6 +6526,8 @@ }, "node_modules/cssesc": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -5896,10 +6538,14 @@ }, "node_modules/csstype": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/d3-color": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", "license": "ISC", "engines": { "node": ">=12" @@ -5907,6 +6553,8 @@ }, "node_modules/d3-dispatch": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", "license": "ISC", "engines": { "node": ">=12" @@ -5914,6 +6562,8 @@ }, "node_modules/d3-drag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -5925,6 +6575,8 @@ }, "node_modules/d3-ease": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", "license": "BSD-3-Clause", "engines": { "node": ">=12" @@ -5932,6 +6584,8 @@ }, "node_modules/d3-interpolate": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", "license": "ISC", "dependencies": { "d3-color": "1 - 3" @@ -5942,6 +6596,8 @@ }, "node_modules/d3-selection": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", "engines": { "node": ">=12" @@ -5949,6 +6605,8 @@ }, "node_modules/d3-timer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "license": "ISC", "engines": { "node": ">=12" @@ -5956,6 +6614,8 @@ }, "node_modules/d3-transition": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", "license": "ISC", "dependencies": { "d3-color": "1 - 3", @@ -5973,6 +6633,8 @@ }, "node_modules/d3-zoom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", @@ -5987,11 +6649,15 @@ }, "node_modules/damerau-levenshtein": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "dev": true, "license": "MIT", "engines": { @@ -6000,6 +6666,8 @@ }, "node_modules/data-view-buffer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "license": "MIT", "dependencies": { @@ -6016,6 +6684,8 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6032,6 +6702,8 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "license": "MIT", "dependencies": { @@ -6048,6 +6720,8 @@ }, "node_modules/date-fns": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "license": "MIT", "funding": { "type": "github", @@ -6056,6 +6730,8 @@ }, "node_modules/debug": { "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6071,6 +6747,8 @@ }, "node_modules/decode-named-character-reference": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -6082,6 +6760,8 @@ }, "node_modules/decompress-response": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" @@ -6126,6 +6806,8 @@ }, "node_modules/deep-extend": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", "engines": { "node": ">=4.0.0" @@ -6133,11 +6815,15 @@ }, "node_modules/deep-is": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", "engines": { @@ -6146,6 +6832,8 @@ }, "node_modules/define-data-property": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { @@ -6162,6 +6850,8 @@ }, "node_modules/define-properties": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -6178,10 +6868,14 @@ }, "node_modules/delegates": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "license": "MIT" }, "node_modules/dequal": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", "engines": { "node": ">=6" @@ -6189,6 +6883,8 @@ }, "node_modules/detect-libc": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -6196,10 +6892,14 @@ }, "node_modules/detect-node-es": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", "license": "MIT" }, "node_modules/devlop": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { "dequal": "^2.0.0" @@ -6211,14 +6911,20 @@ }, "node_modules/didyoumean": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "license": "Apache-2.0" }, "node_modules/diff-match-patch": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", "license": "Apache-2.0" }, "node_modules/dir-glob": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", "dependencies": { @@ -6230,14 +6936,20 @@ }, "node_modules/discontinuous-range": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", "license": "MIT" }, "node_modules/dlv": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "license": "MIT" }, "node_modules/doctrine": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6249,10 +6961,14 @@ }, "node_modules/dotty": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotty/-/dotty-0.1.2.tgz", + "integrity": "sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==", "license": "BSD-3-Clause" }, "node_modules/eastasianwidth": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "license": "MIT" }, "node_modules/electron-to-chromium": { @@ -6262,10 +6978,14 @@ }, "node_modules/emoji-regex": { "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, "node_modules/encoding": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "license": "MIT", "optional": true, "dependencies": { @@ -6274,6 +6994,8 @@ }, "node_modules/end-of-stream": { "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -6295,6 +7017,8 @@ }, "node_modules/entities": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -6305,6 +7029,8 @@ }, "node_modules/env-paths": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "license": "MIT", "engines": { "node": ">=6" @@ -6312,10 +7038,14 @@ }, "node_modules/err-code": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "license": "MIT" }, "node_modules/error-stack-parser": { "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", "license": "MIT", "dependencies": { "stackframe": "^1.3.4" @@ -6323,6 +7053,8 @@ }, "node_modules/es-abstract": { "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "license": "MIT", "dependencies": { @@ -6382,6 +7114,8 @@ }, "node_modules/es-define-property": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6393,6 +7127,8 @@ }, "node_modules/es-errors": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { @@ -6451,6 +7187,8 @@ }, "node_modules/es-object-atoms": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, "license": "MIT", "dependencies": { @@ -6462,6 +7200,8 @@ }, "node_modules/es-set-tostringtag": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6475,6 +7215,8 @@ }, "node_modules/es-shim-unscopables": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "license": "MIT", "dependencies": { @@ -6483,6 +7225,8 @@ }, "node_modules/es-to-primitive": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "license": "MIT", "dependencies": { @@ -6507,6 +7251,8 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { @@ -6572,6 +7318,8 @@ }, "node_modules/eslint-config-next": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.3.tgz", + "integrity": "sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==", "dev": true, "license": "MIT", "dependencies": { @@ -6597,6 +7345,8 @@ }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "license": "MIT", "dependencies": { @@ -6607,6 +7357,8 @@ }, "node_modules/eslint-import-resolver-node/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6655,6 +7407,8 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6693,6 +7447,8 @@ }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6701,6 +7457,8 @@ }, "node_modules/eslint-plugin-import/node_modules/doctrine": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6712,6 +7470,8 @@ }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -6791,6 +7551,8 @@ }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -6802,6 +7564,8 @@ }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "license": "MIT", "dependencies": { @@ -6818,6 +7582,8 @@ }, "node_modules/eslint-plugin-react/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { @@ -6826,6 +7592,8 @@ }, "node_modules/eslint-scope": { "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6841,6 +7609,8 @@ }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6852,6 +7622,8 @@ }, "node_modules/espree": { "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6868,6 +7640,8 @@ }, "node_modules/esquery": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -6879,6 +7653,8 @@ }, "node_modules/esrecurse": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6890,6 +7666,8 @@ }, "node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -6898,6 +7676,8 @@ }, "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", "funding": { "type": "opencollective", @@ -6914,6 +7694,8 @@ }, "node_modules/esutils": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -6922,6 +7704,8 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "engines": { "node": ">=6" @@ -6929,6 +7713,8 @@ }, "node_modules/events": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "license": "MIT", "engines": { "node": ">=0.8.x" @@ -6936,6 +7722,8 @@ }, "node_modules/eventsource-parser": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-1.1.2.tgz", + "integrity": "sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==", "license": "MIT", "engines": { "node": ">=14.18" @@ -6943,6 +7731,8 @@ }, "node_modules/expand-template": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" @@ -6960,30 +7750,44 @@ }, "node_modules/exponential-backoff": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "license": "Apache-2.0" }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, "node_modules/fast-content-type-parse": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==", "license": "MIT" }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, "node_modules/fast-fifo": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -6998,6 +7802,8 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -7008,11 +7814,15 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-json-stringify": { "version": "5.16.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz", + "integrity": "sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==", "license": "MIT", "dependencies": { "@fastify/merge-json-schemas": "^0.1.0", @@ -7026,6 +7836,8 @@ }, "node_modules/fast-json-stringify/node_modules/ajv": { "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -7040,6 +7852,8 @@ }, "node_modules/fast-json-stringify/node_modules/ajv-formats": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -7059,15 +7873,21 @@ }, "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/fast-querystring": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", "license": "MIT", "dependencies": { "fast-decode-uri-component": "^1.0.1" @@ -7075,16 +7895,22 @@ }, "node_modules/fast-redact": { "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/fast-shallow-equal": { - "version": "1.0.0" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" }, "node_modules/fast-uri": { "version": "2.4.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", "license": "MIT" }, "node_modules/fast-xml-parser": { @@ -7109,10 +7935,14 @@ }, "node_modules/fastest-stable-stringify": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==", "license": "MIT" }, "node_modules/fastify": { "version": "4.28.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.28.1.tgz", + "integrity": "sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==", "funding": [ { "type": "github", @@ -7145,6 +7975,8 @@ }, "node_modules/fastify-metrics": { "version": "10.6.0", + "resolved": "https://registry.npmjs.org/fastify-metrics/-/fastify-metrics-10.6.0.tgz", + "integrity": "sha512-QIPncCnwBOEObMn+VaRhsBC1ox8qEsaiYF2sV/A1UbXj7ic70W8/HNn/hlEC2W8JQbBeZMx++o1um2fPfhsFDQ==", "license": "MIT", "dependencies": { "fastify-plugin": "^4.3.0", @@ -7156,6 +7988,8 @@ }, "node_modules/fastify-plugin": { "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==", "license": "MIT" }, "node_modules/fastify/node_modules/pino": { @@ -7180,6 +8014,8 @@ }, "node_modules/fastify/node_modules/pino-std-serializers": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", "license": "MIT" }, "node_modules/fastify/node_modules/sonic-boom": { @@ -7191,6 +8027,8 @@ }, "node_modules/fastify/node_modules/thread-stream": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "license": "MIT", "dependencies": { "real-require": "^0.2.0" @@ -7198,6 +8036,8 @@ }, "node_modules/fastq": { "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -7205,6 +8045,8 @@ }, "node_modules/fault": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", "license": "MIT", "dependencies": { "format": "^0.2.0" @@ -7216,6 +8058,8 @@ }, "node_modules/fetch-blob": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "dev": true, "funding": [ { @@ -7238,6 +8082,8 @@ }, "node_modules/file-entry-cache": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", "dependencies": { @@ -7249,6 +8095,8 @@ }, "node_modules/fill-range": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -7271,6 +8119,8 @@ }, "node_modules/find-up": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { @@ -7296,6 +8146,8 @@ }, "node_modules/flat-cache": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "license": "MIT", "dependencies": { @@ -7309,15 +8161,21 @@ }, "node_modules/flatbuffers": { "version": "1.12.0", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz", + "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==", "license": "SEE LICENSE IN LICENSE.txt" }, "node_modules/flatted": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true, "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "license": "MIT", "dependencies": { @@ -7340,12 +8198,16 @@ }, "node_modules/format": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", "engines": { "node": ">=0.4.x" } }, "node_modules/formdata-polyfill": { "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dev": true, "license": "MIT", "dependencies": { @@ -7357,6 +8219,8 @@ }, "node_modules/forwarded": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7364,6 +8228,8 @@ }, "node_modules/fraction.js": { "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "license": "MIT", "engines": { @@ -7399,10 +8265,14 @@ }, "node_modules/fs-constants": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, "node_modules/fs-minipass": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "license": "ISC", "dependencies": { "minipass": "^7.0.3" @@ -7413,10 +8283,14 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "license": "MIT", "optional": true, "os": [ @@ -7428,6 +8302,8 @@ }, "node_modules/function-bind": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7435,6 +8311,8 @@ }, "node_modules/function.prototype.name": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "license": "MIT", "dependencies": { @@ -7452,6 +8330,8 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "license": "MIT", "funding": { @@ -7460,6 +8340,8 @@ }, "node_modules/gauge": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -7478,14 +8360,20 @@ }, "node_modules/gauge/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/gauge/node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, "node_modules/gauge/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -7498,6 +8386,8 @@ }, "node_modules/get-intrinsic": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7516,6 +8406,8 @@ }, "node_modules/get-nonce": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", "license": "MIT", "engines": { "node": ">=6" @@ -7523,6 +8415,8 @@ }, "node_modules/get-stdin": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "license": "MIT", "engines": { "node": ">=10" @@ -7533,6 +8427,8 @@ }, "node_modules/get-symbol-description": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "license": "MIT", "dependencies": { @@ -7560,10 +8456,14 @@ }, "node_modules/github-from-package": { "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, "node_modules/glob": { "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -7584,6 +8484,8 @@ }, "node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -7601,6 +8503,8 @@ }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -7608,6 +8512,8 @@ }, "node_modules/glob/node_modules/minimatch": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -7621,6 +8527,8 @@ }, "node_modules/globals": { "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7635,6 +8543,8 @@ }, "node_modules/globalthis": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7650,6 +8560,8 @@ }, "node_modules/globby": { "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", "dependencies": { @@ -7669,6 +8581,8 @@ }, "node_modules/gopd": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, "license": "MIT", "dependencies": { @@ -7680,19 +8594,27 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, "node_modules/guid-typescript": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", + "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", "license": "ISC" }, "node_modules/has-bigints": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, "license": "MIT", "funding": { @@ -7701,6 +8623,8 @@ }, "node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -7709,6 +8633,8 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { @@ -7720,6 +8646,8 @@ }, "node_modules/has-proto": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "license": "MIT", "engines": { @@ -7731,6 +8659,8 @@ }, "node_modules/has-symbols": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, "license": "MIT", "engines": { @@ -7742,6 +8672,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", "dependencies": { @@ -7756,10 +8688,14 @@ }, "node_modules/has-unicode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "license": "ISC" }, "node_modules/hasown": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -7770,6 +8706,8 @@ }, "node_modules/hast-util-from-dom": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.0.tgz", + "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", "license": "ISC", "dependencies": { "@types/hast": "^3.0.0", @@ -7783,6 +8721,8 @@ }, "node_modules/hast-util-from-dom/node_modules/hast-util-parse-selector": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -7794,6 +8734,8 @@ }, "node_modules/hast-util-from-dom/node_modules/hastscript": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7825,6 +8767,8 @@ }, "node_modules/hast-util-from-html-isomorphic": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz", + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7839,6 +8783,8 @@ }, "node_modules/hast-util-from-parse5": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7857,6 +8803,8 @@ }, "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -7868,6 +8816,8 @@ }, "node_modules/hast-util-from-parse5/node_modules/hastscript": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7883,6 +8833,8 @@ }, "node_modules/hast-util-is-element": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -7894,6 +8846,8 @@ }, "node_modules/hast-util-parse-selector": { "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -7927,6 +8881,8 @@ }, "node_modules/hast-util-to-text": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7941,6 +8897,8 @@ }, "node_modules/hast-util-whitespace": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -7952,6 +8910,8 @@ }, "node_modules/hastscript": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", "license": "MIT", "dependencies": { "@types/hast": "^2.0.0", @@ -7967,6 +8927,8 @@ }, "node_modules/hastscript/node_modules/@types/hast": { "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", + "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", "license": "MIT", "dependencies": { "@types/unist": "^2" @@ -7978,6 +8940,8 @@ }, "node_modules/hastscript/node_modules/comma-separated-tokens": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", "license": "MIT", "funding": { "type": "github", @@ -7986,6 +8950,8 @@ }, "node_modules/hastscript/node_modules/property-information": { "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", "license": "MIT", "dependencies": { "xtend": "^4.0.0" @@ -7997,6 +8963,8 @@ }, "node_modules/hastscript/node_modules/space-separated-tokens": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", "license": "MIT", "funding": { "type": "github", @@ -8005,6 +8973,8 @@ }, "node_modules/highlight.js": { "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -8012,6 +8982,8 @@ }, "node_modules/highlightjs-curl": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/highlightjs-curl/-/highlightjs-curl-1.3.0.tgz", + "integrity": "sha512-50UEfZq1KR0Lfk2Tr6xb/MUIZH3h10oNC0OTy9g7WELcs5Fgy/mKN1vEhuKTkKbdo8vr5F9GXstu2eLhApfQ3A==", "license": "Apache-2.0" }, "node_modules/hono": { @@ -8033,10 +9005,14 @@ }, "node_modules/http-cache-semantics": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -8048,6 +9024,8 @@ }, "node_modules/http-proxy-agent/node_modules/agent-base": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -8058,6 +9036,8 @@ }, "node_modules/https-proxy-agent": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { "agent-base": "6", @@ -8069,6 +9049,8 @@ }, "node_modules/humanize-ms": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", "dependencies": { "ms": "^2.0.0" @@ -8076,10 +9058,14 @@ }, "node_modules/hyphenate-style-name": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", "license": "BSD-3-Clause" }, "node_modules/iconv-lite": { "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "optional": true, "dependencies": { @@ -8091,6 +9077,8 @@ }, "node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -8117,6 +9105,8 @@ }, "node_modules/import-fresh": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "license": "MIT", "dependencies": { @@ -8132,6 +9122,8 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "license": "MIT", "engines": { "node": ">=0.8.19" @@ -8139,6 +9131,8 @@ }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "license": "MIT", "engines": { "node": ">=8" @@ -8159,10 +9153,14 @@ }, "node_modules/infer-owner": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -8171,10 +9169,14 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, "node_modules/inline-style-parser": { @@ -8183,6 +9185,8 @@ }, "node_modules/inline-style-prefixer": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", "license": "MIT", "dependencies": { "css-in-js-utils": "^3.1.0" @@ -8190,6 +9194,8 @@ }, "node_modules/internal-slot": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "license": "MIT", "dependencies": { @@ -8203,6 +9209,8 @@ }, "node_modules/invariant": { "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" @@ -8210,6 +9218,8 @@ }, "node_modules/ip-address": { "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "license": "MIT", "dependencies": { "jsbn": "1.1.0", @@ -8221,6 +9231,8 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -8228,6 +9240,8 @@ }, "node_modules/is-alphabetical": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "license": "MIT", "funding": { "type": "github", @@ -8236,6 +9250,8 @@ }, "node_modules/is-alphanumerical": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", @@ -8263,6 +9279,8 @@ }, "node_modules/is-array-buffer": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "license": "MIT", "dependencies": { @@ -8278,10 +9296,14 @@ }, "node_modules/is-arrayish": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "license": "MIT" }, "node_modules/is-async-function": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "license": "MIT", "dependencies": { @@ -8296,6 +9318,8 @@ }, "node_modules/is-bigint": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, "license": "MIT", "dependencies": { @@ -8307,6 +9331,8 @@ }, "node_modules/is-binary-path": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -8317,6 +9343,8 @@ }, "node_modules/is-boolean-object": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "license": "MIT", "dependencies": { @@ -8332,6 +9360,8 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", "engines": { @@ -8356,6 +9386,8 @@ }, "node_modules/is-data-view": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "license": "MIT", "dependencies": { @@ -8370,6 +9402,8 @@ }, "node_modules/is-date-object": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8384,6 +9418,8 @@ }, "node_modules/is-decimal": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", "funding": { "type": "github", @@ -8392,6 +9428,8 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8399,6 +9437,8 @@ }, "node_modules/is-finalizationregistry": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, "license": "MIT", "dependencies": { @@ -8410,6 +9450,8 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -8417,6 +9459,8 @@ }, "node_modules/is-generator-function": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "license": "MIT", "dependencies": { @@ -8431,6 +9475,8 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -8441,6 +9487,8 @@ }, "node_modules/is-hexadecimal": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", "funding": { "type": "github", @@ -8449,10 +9497,14 @@ }, "node_modules/is-lambda": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "license": "MIT" }, "node_modules/is-map": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", "engines": { @@ -8464,6 +9516,8 @@ }, "node_modules/is-negative-zero": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", "engines": { @@ -8475,6 +9529,8 @@ }, "node_modules/is-number": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -8482,6 +9538,8 @@ }, "node_modules/is-number-object": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8496,6 +9554,8 @@ }, "node_modules/is-path-inside": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", "engines": { @@ -8504,6 +9564,8 @@ }, "node_modules/is-plain-obj": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "license": "MIT", "engines": { "node": ">=12" @@ -8522,6 +9584,8 @@ }, "node_modules/is-regex": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "license": "MIT", "dependencies": { @@ -8537,6 +9601,8 @@ }, "node_modules/is-set": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", "engines": { @@ -8548,6 +9614,8 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8562,6 +9630,8 @@ }, "node_modules/is-string": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "license": "MIT", "dependencies": { @@ -8576,6 +9646,8 @@ }, "node_modules/is-symbol": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "license": "MIT", "dependencies": { @@ -8590,6 +9662,8 @@ }, "node_modules/is-typed-array": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "license": "MIT", "dependencies": { @@ -8604,6 +9678,8 @@ }, "node_modules/is-weakmap": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { @@ -8615,6 +9691,8 @@ }, "node_modules/is-weakref": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8626,6 +9704,8 @@ }, "node_modules/is-weakset": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8641,11 +9721,15 @@ }, "node_modules/isarray": { "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, "node_modules/iterator.prototype": { @@ -8662,6 +9746,8 @@ }, "node_modules/jackspeak": { "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -8709,6 +9795,8 @@ }, "node_modules/jiti": { "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -8716,6 +9804,8 @@ }, "node_modules/js-cookie": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", "license": "MIT" }, "node_modules/js-levenshtein": { @@ -8730,10 +9820,14 @@ }, "node_modules/js-tokens": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { @@ -8745,10 +9839,14 @@ }, "node_modules/jsbn": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "license": "MIT" }, "node_modules/json-buffer": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, @@ -8761,10 +9859,14 @@ }, "node_modules/json-schema": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-ref-resolver": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -8772,6 +9874,8 @@ }, "node_modules/json-schema-resolver": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-2.0.0.tgz", + "integrity": "sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==", "license": "MIT", "dependencies": { "debug": "^4.1.1", @@ -8787,16 +9891,22 @@ }, "node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json5": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "license": "MIT", "dependencies": { @@ -8808,6 +9918,8 @@ }, "node_modules/jsondiffpatch": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.6.0.tgz", + "integrity": "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==", "license": "MIT", "dependencies": { "@types/diff-match-patch": "^1.0.36", @@ -8823,6 +9935,8 @@ }, "node_modules/jsondiffpatch/node_modules/chalk": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -8840,6 +9954,8 @@ }, "node_modules/jsx-ast-utils": { "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8854,6 +9970,8 @@ }, "node_modules/katex": { "version": "0.16.11", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz", + "integrity": "sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -8868,6 +9986,8 @@ }, "node_modules/keyv": { "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -8876,11 +9996,15 @@ }, "node_modules/language-subtag-registry": { "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", "dev": true, "license": "CC0-1.0" }, "node_modules/language-tags": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "license": "MIT", "dependencies": { @@ -8892,6 +10016,8 @@ }, "node_modules/levn": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8905,6 +10031,8 @@ "node_modules/libpg-query": { "name": "@gregnr/libpg-query", "version": "15.2.0-rc.deparse.3", + "resolved": "https://registry.npmjs.org/@gregnr/libpg-query/-/libpg-query-15.2.0-rc.deparse.3.tgz", + "integrity": "sha512-DjbyAYJmpBuDtP9lNlb0T5RvTTg/B3GBhGf6OJibpT1OS6bYBSDw3ML2rGF7qxiRpQJ9k45YjlAd0TbgHQVYOA==", "hasInstallScript": true, "license": "LICENSE IN LICENSE", "dependencies": { @@ -8927,6 +10055,8 @@ }, "node_modules/lilconfig": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "license": "MIT", "engines": { "node": ">=10" @@ -8934,6 +10064,8 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, "node_modules/loader-runner": { @@ -8953,6 +10085,8 @@ }, "node_modules/locate-path": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -8967,10 +10101,14 @@ }, "node_modules/lodash": { "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, "node_modules/lodash.castarray": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", "dev": true, "license": "MIT" }, @@ -8983,20 +10121,28 @@ }, "node_modules/lodash.isplainobject": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/long": { "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "license": "Apache-2.0" }, "node_modules/longest-streak": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "license": "MIT", "funding": { "type": "github", @@ -9005,6 +10151,8 @@ }, "node_modules/loose-envify": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -9015,6 +10163,8 @@ }, "node_modules/lowlight": { "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", "license": "MIT", "dependencies": { "fault": "^1.0.0", @@ -9027,10 +10177,14 @@ }, "node_modules/lru-cache": { "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, "node_modules/lucide-react": { "version": "0.426.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.426.0.tgz", + "integrity": "sha512-aby5G+Zt+LIIEU0n9900XQNJFJUcs7/S+jOEgIhkV08NX3kGx1zxALKh1JvAKcYqutWLg07exbnYvh66szhrRA==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" @@ -9046,6 +10200,8 @@ }, "node_modules/make-dir": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "license": "MIT", "dependencies": { "semver": "^6.0.0" @@ -9059,6 +10215,8 @@ }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -9066,6 +10224,8 @@ }, "node_modules/make-fetch-happen": { "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", "license": "ISC", "dependencies": { "@npmcli/agent": "^2.0.0", @@ -9105,6 +10265,8 @@ }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9119,6 +10281,8 @@ }, "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { "node": ">=12" @@ -9129,6 +10293,8 @@ }, "node_modules/mdast-util-from-markdown": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9151,6 +10317,8 @@ }, "node_modules/mdast-util-gfm": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", "license": "MIT", "dependencies": { "mdast-util-from-markdown": "^2.0.0", @@ -9183,6 +10351,8 @@ }, "node_modules/mdast-util-gfm-footnote": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9198,6 +10368,8 @@ }, "node_modules/mdast-util-gfm-strikethrough": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9211,6 +10383,8 @@ }, "node_modules/mdast-util-gfm-table": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9226,6 +10400,8 @@ }, "node_modules/mdast-util-gfm-task-list-item": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9240,6 +10416,8 @@ }, "node_modules/mdast-util-math": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -9296,6 +10474,8 @@ }, "node_modules/mdast-util-mdxjs-esm": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -9312,6 +10492,8 @@ }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9324,6 +10506,8 @@ }, "node_modules/mdast-util-to-hast": { "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -9343,6 +10527,8 @@ }, "node_modules/mdast-util-to-markdown": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -9361,6 +10547,8 @@ }, "node_modules/mdast-util-to-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0" @@ -9384,6 +10572,8 @@ }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "license": "MIT", "engines": { "node": ">= 8" @@ -9391,6 +10581,8 @@ }, "node_modules/micromark": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9424,6 +10616,8 @@ }, "node_modules/micromark-core-commonmark": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", "funding": [ { "type": "GitHub Sponsors", @@ -9456,6 +10650,8 @@ }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", "license": "MIT", "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", @@ -9474,6 +10670,8 @@ }, "node_modules/micromark-extension-gfm-autolink-literal": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", @@ -9488,6 +10686,8 @@ }, "node_modules/micromark-extension-gfm-footnote": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -9506,6 +10706,8 @@ }, "node_modules/micromark-extension-gfm-strikethrough": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -9522,6 +10724,8 @@ }, "node_modules/micromark-extension-gfm-table": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -9537,6 +10741,8 @@ }, "node_modules/micromark-extension-gfm-tagfilter": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "license": "MIT", "dependencies": { "micromark-util-types": "^2.0.0" @@ -9548,6 +10754,8 @@ }, "node_modules/micromark-extension-gfm-task-list-item": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -9563,6 +10771,8 @@ }, "node_modules/micromark-extension-math": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", "license": "MIT", "dependencies": { "@types/katex": "^0.16.0", @@ -9580,6 +10790,8 @@ }, "node_modules/micromark-factory-destination": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", "funding": [ { "type": "GitHub Sponsors", @@ -9599,6 +10811,8 @@ }, "node_modules/micromark-factory-label": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", "funding": [ { "type": "GitHub Sponsors", @@ -9619,6 +10833,8 @@ }, "node_modules/micromark-factory-space": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", "funding": [ { "type": "GitHub Sponsors", @@ -9637,6 +10853,8 @@ }, "node_modules/micromark-factory-title": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", "funding": [ { "type": "GitHub Sponsors", @@ -9657,6 +10875,8 @@ }, "node_modules/micromark-factory-whitespace": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", "funding": [ { "type": "GitHub Sponsors", @@ -9677,6 +10897,8 @@ }, "node_modules/micromark-util-character": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9695,6 +10917,8 @@ }, "node_modules/micromark-util-chunked": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", "funding": [ { "type": "GitHub Sponsors", @@ -9712,6 +10936,8 @@ }, "node_modules/micromark-util-classify-character": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", "funding": [ { "type": "GitHub Sponsors", @@ -9731,6 +10957,8 @@ }, "node_modules/micromark-util-combine-extensions": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9749,6 +10977,8 @@ }, "node_modules/micromark-util-decode-numeric-character-reference": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", "funding": [ { "type": "GitHub Sponsors", @@ -9766,6 +10996,8 @@ }, "node_modules/micromark-util-decode-string": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", "funding": [ { "type": "GitHub Sponsors", @@ -9786,6 +11018,8 @@ }, "node_modules/micromark-util-encode": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", "funding": [ { "type": "GitHub Sponsors", @@ -9800,6 +11034,8 @@ }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", "funding": [ { "type": "GitHub Sponsors", @@ -9814,6 +11050,8 @@ }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", "funding": [ { "type": "GitHub Sponsors", @@ -9831,6 +11069,8 @@ }, "node_modules/micromark-util-resolve-all": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", "funding": [ { "type": "GitHub Sponsors", @@ -9848,6 +11088,8 @@ }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", "funding": [ { "type": "GitHub Sponsors", @@ -9867,6 +11109,8 @@ }, "node_modules/micromark-util-subtokenize": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -9887,6 +11131,8 @@ }, "node_modules/micromark-util-symbol": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", "funding": [ { "type": "GitHub Sponsors", @@ -9901,6 +11147,8 @@ }, "node_modules/micromark-util-types": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", "funding": [ { "type": "GitHub Sponsors", @@ -9959,6 +11207,8 @@ }, "node_modules/mimic-response": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "license": "MIT", "engines": { "node": ">=10" @@ -9969,6 +11219,8 @@ }, "node_modules/mini-svg-data-uri": { "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", "dev": true, "license": "MIT", "bin": { @@ -9977,6 +11229,8 @@ }, "node_modules/minimatch": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -9987,6 +11241,8 @@ }, "node_modules/minimist": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9994,6 +11250,8 @@ }, "node_modules/minipass": { "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -10001,6 +11259,8 @@ }, "node_modules/minipass-collect": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "license": "ISC", "dependencies": { "minipass": "^7.0.3" @@ -10011,6 +11271,8 @@ }, "node_modules/minipass-fetch": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", "license": "MIT", "dependencies": { "minipass": "^7.0.3", @@ -10026,6 +11288,8 @@ }, "node_modules/minipass-flush": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -10036,6 +11300,8 @@ }, "node_modules/minipass-flush/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -10046,6 +11312,8 @@ }, "node_modules/minipass-pipeline": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -10056,6 +11324,8 @@ }, "node_modules/minipass-pipeline/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -10066,6 +11336,8 @@ }, "node_modules/minipass-sized": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -10076,6 +11348,8 @@ }, "node_modules/minipass-sized/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -10086,6 +11360,8 @@ }, "node_modules/minizlib": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "license": "MIT", "dependencies": { "minipass": "^3.0.0", @@ -10097,6 +11373,8 @@ }, "node_modules/minizlib/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -10107,6 +11385,8 @@ }, "node_modules/mkdirp": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -10117,10 +11397,14 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "license": "MIT" }, "node_modules/mnemonist": { "version": "0.39.6", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz", + "integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==", "license": "MIT", "dependencies": { "obliterator": "^2.0.1" @@ -10128,18 +11412,26 @@ }, "node_modules/monaco-editor": { "version": "0.49.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.49.0.tgz", + "integrity": "sha512-2I8/T3X/hLxB2oPHgqcNYUVdA/ZEFShT7IAujifIPMfKkNbLOqY8XCoyHCXrsdjb36dW9MwoTwBCFpXKMwNwaQ==", "license": "MIT" }, "node_modules/moo": { "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", "license": "BSD-3-Clause" }, "node_modules/ms": { "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -10149,6 +11441,8 @@ }, "node_modules/nano-css": { "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", "license": "Unlicense", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", @@ -10167,6 +11461,8 @@ }, "node_modules/nano-css/node_modules/css-tree": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "license": "MIT", "dependencies": { "mdn-data": "2.0.14", @@ -10178,10 +11474,14 @@ }, "node_modules/nano-css/node_modules/mdn-data": { "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "license": "CC0-1.0" }, "node_modules/nano-css/node_modules/source-map": { "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -10189,6 +11489,8 @@ }, "node_modules/nanoid": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "funding": [ { "type": "github", @@ -10205,15 +11507,21 @@ }, "node_modules/napi-build-utils": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/nearley": { "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", "license": "MIT", "dependencies": { "commander": "^2.19.0", @@ -10234,6 +11542,8 @@ }, "node_modules/nearley/node_modules/commander": { "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, "node_modules/negotiator": { @@ -10261,6 +11571,8 @@ }, "node_modules/next": { "version": "14.2.3", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", + "integrity": "sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==", "license": "MIT", "dependencies": { "@next/env": "14.2.3", @@ -10309,6 +11621,8 @@ }, "node_modules/next-themes": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", + "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17 || ^18", @@ -10317,6 +11631,8 @@ }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -10353,10 +11669,14 @@ }, "node_modules/node-addon-api": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT" }, "node_modules/node-domexception": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "dev": true, "funding": [ { @@ -10375,6 +11695,8 @@ }, "node_modules/node-fetch": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -10393,6 +11715,8 @@ }, "node_modules/node-gyp": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", + "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", "license": "MIT", "dependencies": { "env-paths": "^2.2.0", @@ -10415,6 +11739,8 @@ }, "node_modules/node-gyp/node_modules/abbrev": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -10422,6 +11748,8 @@ }, "node_modules/node-gyp/node_modules/isexe": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "license": "ISC", "engines": { "node": ">=16" @@ -10429,6 +11757,8 @@ }, "node_modules/node-gyp/node_modules/nopt": { "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "license": "ISC", "dependencies": { "abbrev": "^2.0.0" @@ -10442,6 +11772,8 @@ }, "node_modules/node-gyp/node_modules/which": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "license": "ISC", "dependencies": { "isexe": "^3.1.1" @@ -10460,6 +11792,8 @@ }, "node_modules/node-sql-parser": { "version": "4.18.0", + "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-4.18.0.tgz", + "integrity": "sha512-2YEOR5qlI1zUFbGMLKNfsrR5JUvFg9LxIRVE+xJe962pfVLH0rnItqLzv96XVs1Y1UIR8FxsXAuvX/lYAWZ2BQ==", "license": "Apache-2.0", "dependencies": { "big-integer": "^1.6.48" @@ -10470,6 +11804,8 @@ }, "node_modules/nopt": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "license": "ISC", "dependencies": { "abbrev": "1" @@ -10483,6 +11819,8 @@ }, "node_modules/normalize-path": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10490,6 +11828,8 @@ }, "node_modules/normalize-range": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "license": "MIT", "engines": { @@ -10508,6 +11848,8 @@ }, "node_modules/npmlog": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "license": "ISC", "dependencies": { "are-we-there-yet": "^2.0.0", @@ -10518,6 +11860,8 @@ }, "node_modules/object-assign": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10525,6 +11869,8 @@ }, "node_modules/object-hash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "license": "MIT", "engines": { "node": ">= 6" @@ -10532,6 +11878,8 @@ }, "node_modules/object-inspect": { "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, "license": "MIT", "engines": { @@ -10558,6 +11906,8 @@ }, "node_modules/object-keys": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "engines": { @@ -10566,6 +11916,8 @@ }, "node_modules/object.assign": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10583,6 +11935,8 @@ }, "node_modules/object.entries": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10596,6 +11950,8 @@ }, "node_modules/object.fromentries": { "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10626,6 +11982,8 @@ }, "node_modules/object.values": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10642,10 +12000,14 @@ }, "node_modules/obliterator": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", "license": "MIT" }, "node_modules/on-exit-leak-free": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -10653,6 +12015,8 @@ }, "node_modules/once": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "dependencies": { "wrappy": "1" @@ -10660,6 +12024,8 @@ }, "node_modules/onnx-proto": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/onnx-proto/-/onnx-proto-4.0.4.tgz", + "integrity": "sha512-aldMOB3HRoo6q/phyB6QRQxSt895HNNw82BNyZ2CMh4bjeKv7g/c+VpAFtJuEMVfYLMbRx61hbuqnKceLeDcDA==", "license": "MIT", "dependencies": { "protobufjs": "^6.8.8" @@ -10667,10 +12033,14 @@ }, "node_modules/onnxruntime-common": { "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.14.0.tgz", + "integrity": "sha512-3LJpegM2iMNRX2wUmtYfeX/ytfOzNwAWKSq1HbRrKc9+uqG/FsEA0bbKZl1btQeZaXhC26l44NWpNUeXPII7Ew==", "license": "MIT" }, "node_modules/onnxruntime-node": { "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.14.0.tgz", + "integrity": "sha512-5ba7TWomIV/9b6NH/1x/8QEeowsb+jBEvFzU6z0T4mNsFwdPqXeFUM7uxC6QeSRkEbWu3qEB0VMjrvzN/0S9+w==", "license": "MIT", "optional": true, "os": [ @@ -10684,6 +12054,8 @@ }, "node_modules/onnxruntime-web": { "version": "1.14.0", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.14.0.tgz", + "integrity": "sha512-Kcqf43UMfW8mCydVGcX9OMXI2VN17c0p6XvR7IPSZzBf/6lteBzXHvcEVWDPmCKuGombl997HgLqj91F11DzXw==", "license": "MIT", "dependencies": { "flatbuffers": "^1.12.0", @@ -10696,6 +12068,8 @@ }, "node_modules/onnxruntime-web/node_modules/long": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", "license": "Apache-2.0" }, "node_modules/openapi-fetch": { @@ -10709,6 +12083,8 @@ }, "node_modules/openapi-types": { "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "license": "MIT" }, "node_modules/openapi-typescript": { @@ -10753,6 +12129,8 @@ }, "node_modules/optionator": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -10776,6 +12154,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10790,6 +12170,8 @@ }, "node_modules/p-locate": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -10804,6 +12186,8 @@ }, "node_modules/p-map": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" @@ -10841,6 +12225,8 @@ }, "node_modules/parent-module": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { @@ -10852,6 +12238,8 @@ }, "node_modules/parse-entities": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", @@ -10915,6 +12303,8 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -10923,6 +12313,8 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10930,6 +12322,8 @@ }, "node_modules/path-key": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", "engines": { "node": ">=8" @@ -10937,10 +12331,14 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -10955,6 +12353,8 @@ }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", "engines": { @@ -10998,6 +12398,8 @@ }, "node_modules/pg-cloudflare": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", "license": "MIT", "optional": true }, @@ -11007,6 +12409,8 @@ }, "node_modules/pg-format": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pg-format/-/pg-format-1.0.4.tgz", + "integrity": "sha512-YyKEF78pEA6wwTAqOUaHIN/rWpfzzIuMh9KdAhc3rSLQ/7zkRFcCgYBAEGatDstLyZw4g0s9SNICmaTGnBVeyw==", "license": "MIT", "engines": { "node": ">=4.0" @@ -11014,6 +12418,8 @@ }, "node_modules/pg-int8": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", "license": "ISC", "engines": { "node": ">=4.0.0" @@ -11032,6 +12438,8 @@ }, "node_modules/pg-types": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", "license": "MIT", "dependencies": { "pg-int8": "1.0.1", @@ -11046,6 +12454,8 @@ }, "node_modules/pg-types/node_modules/postgres-array": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", "license": "MIT", "engines": { "node": ">=4" @@ -11053,6 +12463,8 @@ }, "node_modules/pgpass": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", "license": "MIT", "dependencies": { "split2": "^4.1.0" @@ -11060,6 +12472,8 @@ }, "node_modules/pgsql-deparser": { "version": "13.15.0", + "resolved": "https://registry.npmjs.org/pgsql-deparser/-/pgsql-deparser-13.15.0.tgz", + "integrity": "sha512-6d4YeDE/y+AZ/C4tlzTrFwbOqDW4ma/jvYlXRgXYVdPU2WF5IQISksIQ8uhNMXW7QxL/4gw0bzLhRNwckf3t/Q==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@pgsql/types": "^13.9.0", @@ -11069,14 +12483,20 @@ }, "node_modules/pgsql-deparser/node_modules/@pgsql/types": { "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@pgsql/types/-/types-13.9.0.tgz", + "integrity": "sha512-R26mn0zMkwfR8imEQ1Q4NedHwG9gTUfgVnLJUBqPn33JyhOUi2H6iEVTcC9kHAm7gQGpwSBKfuCItWgenAlm9g==", "license": "SEE LICENSE IN LICENSE" }, "node_modules/pgsql-enums": { "version": "13.10.0", + "resolved": "https://registry.npmjs.org/pgsql-enums/-/pgsql-enums-13.10.0.tgz", + "integrity": "sha512-L0vO9RwwPENvB07YlIVTnRu3JMnmjHQhxWR2NQbHOUPIpfF6khhfv+OC51By2ATts3jfZRSi8TLjNf9O6rP9iA==", "license": "SEE LICENSE IN LICENSE" }, "node_modules/pgsql-parser": { "version": "13.16.0", + "resolved": "https://registry.npmjs.org/pgsql-parser/-/pgsql-parser-13.16.0.tgz", + "integrity": "sha512-LdHFWjotgN7y2rEAb2K/LeLZrMJvpLy0Qe+1+8ZByf5C2pmKTo98VXiVfGpxC6vkfWgP9VsT4vYQ4ZlQexHcHw==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "libpg-query": "13.3.2", @@ -11090,6 +12510,8 @@ }, "node_modules/pgsql-parser/node_modules/@npmcli/fs": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", "license": "ISC", "dependencies": { "@gar/promisify": "^1.0.1", @@ -11098,6 +12520,8 @@ }, "node_modules/pgsql-parser/node_modules/are-we-there-yet": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", "license": "ISC", "dependencies": { "delegates": "^1.0.0", @@ -11109,6 +12533,8 @@ }, "node_modules/pgsql-parser/node_modules/cacache": { "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "license": "ISC", "dependencies": { "@npmcli/fs": "^1.0.0", @@ -11136,10 +12562,14 @@ }, "node_modules/pgsql-parser/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/pgsql-parser/node_modules/fs-minipass": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -11150,6 +12580,8 @@ }, "node_modules/pgsql-parser/node_modules/gauge": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -11167,6 +12599,8 @@ }, "node_modules/pgsql-parser/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -11185,6 +12619,8 @@ }, "node_modules/pgsql-parser/node_modules/http-proxy-agent": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", "license": "MIT", "dependencies": { "@tootallnate/once": "1", @@ -11197,6 +12633,8 @@ }, "node_modules/pgsql-parser/node_modules/libpg-query": { "version": "13.3.2", + "resolved": "https://registry.npmjs.org/libpg-query/-/libpg-query-13.3.2.tgz", + "integrity": "sha512-6ft2qyk+LO1hdmPU389RvN7inRGLU0T8Ge4RG+q4usE+dAA4nl+WVp4HVpBC+1Ku4lgxM38PkoW7OzAw8VDebA==", "hasInstallScript": true, "license": "LICENSE IN LICENSE", "dependencies": { @@ -11207,6 +12645,8 @@ }, "node_modules/pgsql-parser/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -11217,6 +12657,8 @@ }, "node_modules/pgsql-parser/node_modules/make-fetch-happen": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "license": "ISC", "dependencies": { "agentkeepalive": "^4.1.3", @@ -11242,6 +12684,8 @@ }, "node_modules/pgsql-parser/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -11252,6 +12696,8 @@ }, "node_modules/pgsql-parser/node_modules/minipass-collect": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -11262,6 +12708,8 @@ }, "node_modules/pgsql-parser/node_modules/minipass-fetch": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", "license": "MIT", "dependencies": { "minipass": "^3.1.0", @@ -11277,10 +12725,14 @@ }, "node_modules/pgsql-parser/node_modules/node-addon-api": { "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", "license": "MIT" }, "node_modules/pgsql-parser/node_modules/node-gyp": { "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", "license": "MIT", "dependencies": { "env-paths": "^2.2.0", @@ -11303,6 +12755,8 @@ }, "node_modules/pgsql-parser/node_modules/npmlog": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", "license": "ISC", "dependencies": { "are-we-there-yet": "^3.0.0", @@ -11316,10 +12770,14 @@ }, "node_modules/pgsql-parser/node_modules/signal-exit": { "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, "node_modules/pgsql-parser/node_modules/socks-proxy-agent": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", "license": "MIT", "dependencies": { "agent-base": "^6.0.2", @@ -11332,6 +12790,8 @@ }, "node_modules/pgsql-parser/node_modules/ssri": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "license": "ISC", "dependencies": { "minipass": "^3.1.1" @@ -11342,6 +12802,8 @@ }, "node_modules/pgsql-parser/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -11354,6 +12816,8 @@ }, "node_modules/pgsql-parser/node_modules/unique-filename": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "license": "ISC", "dependencies": { "unique-slug": "^2.0.0" @@ -11361,6 +12825,8 @@ }, "node_modules/pgsql-parser/node_modules/unique-slug": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" @@ -11372,6 +12838,8 @@ }, "node_modules/picomatch": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -11382,6 +12850,8 @@ }, "node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11389,6 +12859,8 @@ }, "node_modules/pino": { "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", + "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", @@ -11409,6 +12881,8 @@ }, "node_modules/pino-abstract-transport": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", "license": "MIT", "dependencies": { "readable-stream": "^4.0.0", @@ -11417,6 +12891,8 @@ }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", @@ -11431,10 +12907,14 @@ }, "node_modules/pino-std-serializers": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", "license": "MIT" }, "node_modules/pirates": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "license": "MIT", "engines": { "node": ">= 6" @@ -11442,6 +12922,8 @@ }, "node_modules/platform": { "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", "license": "MIT" }, "node_modules/pluralize": { @@ -11456,6 +12938,8 @@ }, "node_modules/possible-typed-array-names": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, "license": "MIT", "engines": { @@ -11490,6 +12974,8 @@ }, "node_modules/postcss-import": { "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", @@ -11505,6 +12991,8 @@ }, "node_modules/postcss-js": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" @@ -11522,6 +13010,8 @@ }, "node_modules/postcss-load-config": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", "funding": [ { "type": "opencollective", @@ -11555,6 +13045,8 @@ }, "node_modules/postcss-load-config/node_modules/lilconfig": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "license": "MIT", "engines": { "node": ">=14" @@ -11565,6 +13057,8 @@ }, "node_modules/postcss-nested": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "funding": [ { "type": "opencollective", @@ -11599,10 +13093,14 @@ }, "node_modules/postcss-value-parser": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, "node_modules/postcss/node_modules/nanoid": { "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -11619,6 +13117,8 @@ }, "node_modules/postgres-array": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", "license": "MIT", "engines": { "node": ">=12" @@ -11626,6 +13126,8 @@ }, "node_modules/postgres-bytea": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11633,6 +13135,8 @@ }, "node_modules/postgres-date": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11640,6 +13144,8 @@ }, "node_modules/postgres-interval": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", "license": "MIT", "dependencies": { "xtend": "^4.0.0" @@ -11654,6 +13160,8 @@ }, "node_modules/prebuild-install": { "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", @@ -11678,10 +13186,14 @@ }, "node_modules/prebuild-install/node_modules/chownr": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "license": "ISC" }, "node_modules/prebuild-install/node_modules/tar-fs": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -11692,6 +13204,8 @@ }, "node_modules/prebuild-install/node_modules/tar-stream": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -11706,6 +13220,8 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -11714,6 +13230,8 @@ }, "node_modules/prettier": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" @@ -11727,6 +13245,8 @@ }, "node_modules/prettier-plugin-sql": { "version": "0.17.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.17.1.tgz", + "integrity": "sha512-CR9UpTkUSC/f69AV597hnYcBo77iUhsBPkUER7BUa4YHRRtRUJGfL5LDoHAlUHWGTZNiJdHHELlzK6I3R9XuAw==", "license": "MIT", "dependencies": { "jsox": "^1.2.118", @@ -11746,6 +13266,8 @@ }, "node_modules/prettier-plugin-sql/node_modules/sql-formatter": { "version": "14.0.0", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-14.0.0.tgz", + "integrity": "sha512-VcHYMRvZqg3RNjjxNB/puT9O1hR5QLXTvgTaBtxXcvmRQwSnH9M+oW2Ti+uFuVVU8HoNlOjU2uKHv8c0FQNsdQ==", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -11758,6 +13280,8 @@ }, "node_modules/prismjs": { "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", "license": "MIT", "engines": { "node": ">=6" @@ -11765,6 +13289,8 @@ }, "node_modules/proc-log": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -11772,6 +13298,8 @@ }, "node_modules/process": { "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "license": "MIT", "engines": { "node": ">= 0.6.0" @@ -11779,10 +13307,14 @@ }, "node_modules/process-warning": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", "license": "MIT" }, "node_modules/prom-client": { "version": "14.2.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", + "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", "license": "Apache-2.0", "dependencies": { "tdigest": "^0.1.1" @@ -11793,10 +13325,14 @@ }, "node_modules/promise-inflight": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "license": "ISC" }, "node_modules/promise-retry": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "license": "MIT", "dependencies": { "err-code": "^2.0.2", @@ -11808,6 +13344,8 @@ }, "node_modules/prop-types": { "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, "license": "MIT", "dependencies": { @@ -11818,6 +13356,8 @@ }, "node_modules/property-information": { "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", "license": "MIT", "funding": { "type": "github", @@ -11826,6 +13366,8 @@ }, "node_modules/protobufjs": { "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -11850,10 +13392,14 @@ }, "node_modules/protobufjs/node_modules/long": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", "license": "Apache-2.0" }, "node_modules/proxy-addr": { "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -11873,6 +13419,8 @@ }, "node_modules/punycode": { "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { "node": ">=6" @@ -11880,6 +13428,8 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "funding": [ { "type": "github", @@ -11898,18 +13448,26 @@ }, "node_modules/queue-tick": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", "license": "MIT" }, "node_modules/quick-format-unescaped": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", "license": "MIT" }, "node_modules/railroad-diagrams": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", "license": "CC0-1.0" }, "node_modules/randexp": { "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "license": "MIT", "dependencies": { "discontinuous-range": "1.0.0", @@ -11921,6 +13479,8 @@ }, "node_modules/randexp/node_modules/ret": { "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "license": "MIT", "engines": { "node": ">=0.12" @@ -11938,6 +13498,8 @@ }, "node_modules/rc": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -11951,6 +13513,8 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11958,6 +13522,8 @@ }, "node_modules/react": { "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -11968,6 +13534,8 @@ }, "node_modules/react-chartjs-2": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", "license": "MIT", "peerDependencies": { "chart.js": "^4.1.1", @@ -11976,6 +13544,8 @@ }, "node_modules/react-dom": { "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -11997,11 +13567,15 @@ }, "node_modules/react-is": { "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true, "license": "MIT" }, "node_modules/react-markdown": { "version": "9.0.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -12049,6 +13623,8 @@ }, "node_modules/react-remove-scroll-bar": { "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", "license": "MIT", "dependencies": { "react-style-singleton": "^2.2.1", @@ -12069,6 +13645,8 @@ }, "node_modules/react-style-singleton": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", "license": "MIT", "dependencies": { "get-nonce": "^1.0.0", @@ -12104,6 +13682,8 @@ }, "node_modules/react-universal-interface": { "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", "peerDependencies": { "react": "*", "tslib": "*" @@ -12111,6 +13691,8 @@ }, "node_modules/react-use": { "version": "17.5.1", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.5.1.tgz", + "integrity": "sha512-LG/uPEVRflLWMwi3j/sZqR00nF6JGqTTDblkXK2nzXsIvij06hXl1V/MZIlwj1OKIQUtlh1l9jK8gLsRyCQxMg==", "license": "Unlicense", "dependencies": { "@types/js-cookie": "^2.2.6", @@ -12135,6 +13717,8 @@ }, "node_modules/reactflow": { "version": "11.11.4", + "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.11.4.tgz", + "integrity": "sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==", "license": "MIT", "dependencies": { "@reactflow/background": "11.3.14", @@ -12151,6 +13735,8 @@ }, "node_modules/read-cache": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "license": "MIT", "dependencies": { "pify": "^2.3.0" @@ -12168,6 +13754,8 @@ }, "node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -12180,6 +13768,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -12190,6 +13780,8 @@ }, "node_modules/real-require": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", "license": "MIT", "engines": { "node": ">= 12.13.0" @@ -12197,6 +13789,8 @@ }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", "dev": true, "license": "MIT", "dependencies": { @@ -12217,6 +13811,8 @@ }, "node_modules/refractor": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", + "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", "license": "MIT", "dependencies": { "hastscript": "^6.0.0", @@ -12230,6 +13826,8 @@ }, "node_modules/refractor/node_modules/character-entities": { "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", "license": "MIT", "funding": { "type": "github", @@ -12238,6 +13836,8 @@ }, "node_modules/refractor/node_modules/character-entities-legacy": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", "license": "MIT", "funding": { "type": "github", @@ -12246,6 +13846,8 @@ }, "node_modules/refractor/node_modules/character-reference-invalid": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "license": "MIT", "funding": { "type": "github", @@ -12254,6 +13856,8 @@ }, "node_modules/refractor/node_modules/is-alphabetical": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", "license": "MIT", "funding": { "type": "github", @@ -12262,6 +13866,8 @@ }, "node_modules/refractor/node_modules/is-alphanumerical": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "license": "MIT", "dependencies": { "is-alphabetical": "^1.0.0", @@ -12274,6 +13880,8 @@ }, "node_modules/refractor/node_modules/is-decimal": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", "license": "MIT", "funding": { "type": "github", @@ -12282,6 +13890,8 @@ }, "node_modules/refractor/node_modules/is-hexadecimal": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", "license": "MIT", "funding": { "type": "github", @@ -12290,6 +13900,8 @@ }, "node_modules/refractor/node_modules/parse-entities": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "license": "MIT", "dependencies": { "character-entities": "^1.0.0", @@ -12306,6 +13918,8 @@ }, "node_modules/refractor/node_modules/prismjs": { "version": "1.27.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", + "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", "license": "MIT", "engines": { "node": ">=6" @@ -12313,6 +13927,8 @@ }, "node_modules/regenerator-runtime": { "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "license": "MIT" }, "node_modules/regexp.prototype.flags": { @@ -12351,6 +13967,8 @@ }, "node_modules/remark-gfm": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -12367,6 +13985,8 @@ }, "node_modules/remark-math": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -12381,6 +14001,8 @@ }, "node_modules/remark-parse": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -12410,6 +14032,8 @@ }, "node_modules/remark-stringify": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -12423,6 +14047,8 @@ }, "node_modules/require-from-string": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12430,10 +14056,14 @@ }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", "license": "MIT" }, "node_modules/resolve": { "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", @@ -12449,6 +14079,8 @@ }, "node_modules/resolve-from": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { @@ -12457,6 +14089,8 @@ }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "license": "MIT", "funding": { @@ -12465,6 +14099,8 @@ }, "node_modules/ret": { "version": "0.4.3", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", + "integrity": "sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==", "license": "MIT", "engines": { "node": ">=10" @@ -12472,6 +14108,8 @@ }, "node_modules/retry": { "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "license": "MIT", "engines": { "node": ">= 4" @@ -12479,6 +14117,8 @@ }, "node_modules/reusify": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -12487,10 +14127,14 @@ }, "node_modules/rfdc": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -12504,6 +14148,8 @@ }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -12522,6 +14168,8 @@ }, "node_modules/rtl-css-js": { "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.1.2" @@ -12529,6 +14177,8 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "funding": [ { "type": "github", @@ -12550,6 +14200,8 @@ }, "node_modules/safe-array-concat": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -12567,6 +14219,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -12585,6 +14239,8 @@ }, "node_modules/safe-regex-test": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "license": "MIT", "dependencies": { @@ -12601,6 +14257,8 @@ }, "node_modules/safe-regex2": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", + "integrity": "sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==", "license": "MIT", "dependencies": { "ret": "~0.4.0" @@ -12615,11 +14273,15 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT", "optional": true }, "node_modules/scheduler": { "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -12646,6 +14308,8 @@ }, "node_modules/screenfull": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12656,10 +14320,14 @@ }, "node_modules/secure-json-parse": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "license": "BSD-3-Clause" }, "node_modules/semver": { "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -12680,6 +14348,8 @@ }, "node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, "node_modules/set-cookie-parser": { @@ -12688,6 +14358,8 @@ }, "node_modules/set-function-length": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { @@ -12704,6 +14376,8 @@ }, "node_modules/set-function-name": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12718,6 +14392,8 @@ }, "node_modules/set-harmonic-interval": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==", "license": "Unlicense", "engines": { "node": ">=6.9" @@ -12725,6 +14401,8 @@ }, "node_modules/sharp": { "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -12746,10 +14424,14 @@ }, "node_modules/sharp/node_modules/node-addon-api": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "license": "MIT" }, "node_modules/shebang-command": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -12760,6 +14442,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", "engines": { "node": ">=8" @@ -12767,6 +14451,8 @@ }, "node_modules/side-channel": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "license": "MIT", "dependencies": { @@ -12784,6 +14470,8 @@ }, "node_modules/signal-exit": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "license": "ISC", "engines": { "node": ">=14" @@ -12794,6 +14482,8 @@ }, "node_modules/simple-concat": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "funding": [ { "type": "github", @@ -12812,6 +14502,8 @@ }, "node_modules/simple-get": { "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "funding": [ { "type": "github", @@ -12835,6 +14527,8 @@ }, "node_modules/simple-swizzle": { "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" @@ -12842,6 +14536,8 @@ }, "node_modules/slash": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", "engines": { @@ -12850,6 +14546,8 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "license": "MIT", "engines": { "node": ">= 6.0.0", @@ -12858,6 +14556,8 @@ }, "node_modules/socks": { "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -12870,6 +14570,8 @@ }, "node_modules/socks-proxy-agent": { "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "license": "MIT", "dependencies": { "agent-base": "^7.1.1", @@ -12882,6 +14584,8 @@ }, "node_modules/socks-proxy-agent/node_modules/agent-base": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "license": "MIT", "dependencies": { "debug": "^4.3.4" @@ -12892,6 +14596,8 @@ }, "node_modules/sonic-boom": { "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" @@ -12899,6 +14605,8 @@ }, "node_modules/source-map": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -12934,6 +14642,8 @@ }, "node_modules/space-separated-tokens": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", @@ -12942,6 +14652,8 @@ }, "node_modules/split2": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "license": "ISC", "engines": { "node": ">= 10.x" @@ -12949,6 +14661,8 @@ }, "node_modules/sprintf-js": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, "node_modules/sql-formatter": { @@ -12965,6 +14679,8 @@ }, "node_modules/ssri": { "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "license": "ISC", "dependencies": { "minipass": "^7.0.3" @@ -12975,6 +14691,8 @@ }, "node_modules/sswr": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sswr/-/sswr-2.1.0.tgz", + "integrity": "sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ==", "license": "MIT", "dependencies": { "swrev": "^4.0.0" @@ -12985,6 +14703,8 @@ }, "node_modules/stack-generator": { "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", "license": "MIT", "dependencies": { "stackframe": "^1.3.4" @@ -12992,10 +14712,14 @@ }, "node_modules/stackframe": { "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "license": "MIT" }, "node_modules/stacktrace-gps": { "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", "license": "MIT", "dependencies": { "source-map": "0.5.6", @@ -13004,6 +14728,8 @@ }, "node_modules/stacktrace-js": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", "license": "MIT", "dependencies": { "error-stack-parser": "^2.0.6", @@ -13013,6 +14739,8 @@ }, "node_modules/state-local": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", "license": "MIT" }, "node_modules/stop-iteration-iterator": { @@ -13028,6 +14756,8 @@ }, "node_modules/streamsearch": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { "node": ">=10.0.0" } @@ -13046,6 +14776,8 @@ }, "node_modules/string_decoder": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" @@ -13053,6 +14785,8 @@ }, "node_modules/string-width": { "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -13069,6 +14803,8 @@ "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -13081,6 +14817,8 @@ }, "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/string-width/node_modules/ansi-regex": { @@ -13095,6 +14833,8 @@ }, "node_modules/string-width/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -13117,6 +14857,8 @@ }, "node_modules/string.prototype.matchall": { "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dev": true, "license": "MIT", "dependencies": { @@ -13142,6 +14884,8 @@ }, "node_modules/string.prototype.repeat": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "license": "MIT", "dependencies": { @@ -13151,6 +14895,8 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "license": "MIT", "dependencies": { @@ -13168,6 +14914,8 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13181,6 +14929,8 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { @@ -13197,6 +14947,8 @@ }, "node_modules/stringify-entities": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -13209,6 +14961,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -13220,6 +14974,8 @@ "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -13230,6 +14986,8 @@ }, "node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { @@ -13238,6 +14996,8 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -13260,6 +15020,8 @@ }, "node_modules/styled-jsx": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -13285,6 +15047,8 @@ }, "node_modules/sucrase": { "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -13305,15 +15069,17 @@ }, "node_modules/sucrase/node_modules/commander": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/supabase": { - "version": "1.204.3", - "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.204.3.tgz", - "integrity": "sha512-uO09eyAw7TZAX/7wPeieQBWrl4QAJ0WLF+HTkFy35GWBmQULP5nkJR93LcuhSyooYiqwEUKlChEF/PGAEmTCKw==", + "version": "1.207.9", + "resolved": "https://registry.npmjs.org/supabase/-/supabase-1.207.9.tgz", + "integrity": "sha512-BJPwsAd2UBIpQawcQV3/xKHEZ8YrrkHYpgibxCZbG+RuxuhTtkHG7zR4I3LylIIEwcKp3hmDKu/hO1m2NT5RXA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13332,6 +15098,8 @@ }, "node_modules/supabase/node_modules/agent-base": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, "license": "MIT", "dependencies": { @@ -13343,6 +15111,8 @@ }, "node_modules/supabase/node_modules/chownr": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -13351,6 +15121,8 @@ }, "node_modules/supabase/node_modules/https-proxy-agent": { "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, "license": "MIT", "dependencies": { @@ -13363,6 +15135,8 @@ }, "node_modules/supabase/node_modules/minizlib": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dev": true, "license": "MIT", "dependencies": { @@ -13375,6 +15149,8 @@ }, "node_modules/supabase/node_modules/mkdirp": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "license": "MIT", "bin": { @@ -13389,6 +15165,8 @@ }, "node_modules/supabase/node_modules/node-fetch": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dev": true, "license": "MIT", "dependencies": { @@ -13406,6 +15184,8 @@ }, "node_modules/supabase/node_modules/rimraf": { "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "license": "ISC", "dependencies": { @@ -13420,6 +15200,8 @@ }, "node_modules/supabase/node_modules/tar": { "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { @@ -13436,6 +15218,8 @@ }, "node_modules/supabase/node_modules/yallist": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -13444,6 +15228,8 @@ }, "node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -13455,6 +15241,8 @@ }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -13505,6 +15293,8 @@ }, "node_modules/swr": { "version": "2.2.5", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.5.tgz", + "integrity": "sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==", "license": "MIT", "dependencies": { "client-only": "^0.0.1", @@ -13516,10 +15306,14 @@ }, "node_modules/swrev": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/swrev/-/swrev-4.0.0.tgz", + "integrity": "sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA==", "license": "MIT" }, "node_modules/swrv": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/swrv/-/swrv-1.0.4.tgz", + "integrity": "sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g==", "license": "Apache-2.0", "peerDependencies": { "vue": ">=3.2.26 < 4" @@ -13570,6 +15364,8 @@ }, "node_modules/tailwindcss-animate": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" @@ -13582,6 +15378,8 @@ }, "node_modules/tapable": { "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "license": "MIT", "engines": { @@ -13590,6 +15388,8 @@ }, "node_modules/tar": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "license": "ISC", "dependencies": { "chownr": "^2.0.0", @@ -13605,6 +15405,8 @@ }, "node_modules/tar-fs": { "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", "license": "MIT", "dependencies": { "pump": "^3.0.0", @@ -13617,6 +15419,8 @@ }, "node_modules/tar-stream": { "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "license": "MIT", "dependencies": { "b4a": "^1.6.4", @@ -13626,6 +15430,8 @@ }, "node_modules/tar/node_modules/fs-minipass": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "license": "ISC", "dependencies": { "minipass": "^3.0.0" @@ -13636,6 +15442,8 @@ }, "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -13646,6 +15454,8 @@ }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "license": "ISC", "engines": { "node": ">=8" @@ -13653,6 +15463,8 @@ }, "node_modules/tdigest": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", "license": "MIT", "dependencies": { "bintrees": "1.0.2" @@ -13728,11 +15540,15 @@ }, "node_modules/text-table": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "license": "MIT" }, "node_modules/thenify": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -13740,6 +15556,8 @@ }, "node_modules/thenify-all": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -13750,6 +15568,8 @@ }, "node_modules/thread-stream": { "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", "license": "MIT", "dependencies": { "real-require": "^0.2.0" @@ -13757,6 +15577,8 @@ }, "node_modules/throttle-debounce": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", "license": "MIT", "engines": { "node": ">=10" @@ -13764,6 +15586,8 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -13774,6 +15598,8 @@ }, "node_modules/toad-cache": { "version": "3.7.0", + "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", "license": "MIT", "engines": { "node": ">=12" @@ -13781,14 +15607,20 @@ }, "node_modules/toggle-selection": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", "license": "MIT" }, "node_modules/tr46": { "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, "node_modules/trim-lines": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", "funding": { "type": "github", @@ -13797,6 +15629,8 @@ }, "node_modules/trough": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", "funding": { "type": "github", @@ -13805,6 +15639,8 @@ }, "node_modules/ts-api-utils": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "license": "MIT", "engines": { @@ -13816,14 +15652,20 @@ }, "node_modules/ts-easing": { "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==", "license": "Unlicense" }, "node_modules/ts-interface-checker": { "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, "node_modules/tsconfig-paths": { "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", "dependencies": { @@ -13839,6 +15681,8 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -13849,6 +15693,8 @@ }, "node_modules/type-check": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -13860,6 +15706,8 @@ }, "node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -13871,6 +15719,8 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13884,6 +15734,8 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, "license": "MIT", "dependencies": { @@ -13902,6 +15754,8 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "license": "MIT", "dependencies": { @@ -13921,6 +15775,8 @@ }, "node_modules/typed-array-length": { "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "license": "MIT", "dependencies": { @@ -13952,6 +15808,8 @@ }, "node_modules/unbox-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "license": "MIT", "dependencies": { @@ -13970,6 +15828,8 @@ }, "node_modules/unified": { "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -13987,6 +15847,8 @@ }, "node_modules/unique-filename": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "license": "ISC", "dependencies": { "unique-slug": "^4.0.0" @@ -13997,6 +15859,8 @@ }, "node_modules/unique-slug": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" @@ -14007,6 +15871,8 @@ }, "node_modules/unist-util-find-after": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14019,6 +15885,8 @@ }, "node_modules/unist-util-is": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -14030,6 +15898,8 @@ }, "node_modules/unist-util-position": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -14041,6 +15911,8 @@ }, "node_modules/unist-util-remove-position": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14053,6 +15925,8 @@ }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -14064,6 +15938,8 @@ }, "node_modules/unist-util-visit": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14077,6 +15953,8 @@ }, "node_modules/unist-util-visit-parents": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14118,6 +15996,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -14132,6 +16012,8 @@ }, "node_modules/use-callback-ref": { "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -14151,6 +16033,8 @@ }, "node_modules/use-sidecar": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", "license": "MIT", "dependencies": { "detect-node-es": "^1.1.0", @@ -14171,6 +16055,8 @@ }, "node_modules/use-sync-external-store": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" @@ -14178,6 +16064,8 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/uuid": { @@ -14206,6 +16094,8 @@ }, "node_modules/vfile-location": { "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14218,6 +16108,8 @@ }, "node_modules/vfile-message": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -14264,6 +16156,8 @@ }, "node_modules/web-namespaces": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", "license": "MIT", "funding": { "type": "github", @@ -14272,6 +16166,8 @@ }, "node_modules/web-streams-polyfill": { "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "dev": true, "license": "MIT", "engines": { @@ -14280,6 +16176,8 @@ }, "node_modules/webidl-conversions": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, "node_modules/webpack": { @@ -14365,6 +16263,8 @@ }, "node_modules/whatwg-url": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -14373,6 +16273,8 @@ }, "node_modules/which": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -14386,6 +16288,8 @@ }, "node_modules/which-boxed-primitive": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, "license": "MIT", "dependencies": { @@ -14443,6 +16347,8 @@ }, "node_modules/which-typed-array": { "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "license": "MIT", "dependencies": { @@ -14461,6 +16367,8 @@ }, "node_modules/wide-align": { "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "license": "ISC", "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" @@ -14468,10 +16376,14 @@ }, "node_modules/wide-align/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/wide-align/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -14484,6 +16396,8 @@ }, "node_modules/word-wrap": { "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -14492,6 +16406,8 @@ }, "node_modules/wrap-ansi": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -14508,6 +16424,8 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -14523,10 +16441,14 @@ }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -14549,6 +16471,8 @@ }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "license": "MIT", "engines": { "node": ">=12" @@ -14559,6 +16483,8 @@ }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -14572,6 +16498,8 @@ }, "node_modules/wrappy": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/write-file-atomic": { @@ -14590,6 +16518,8 @@ }, "node_modules/ws": { "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -14609,6 +16539,8 @@ }, "node_modules/xtend": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "license": "MIT", "engines": { "node": ">=0.4" @@ -14616,6 +16548,8 @@ }, "node_modules/yallist": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, "node_modules/yaml": { @@ -14647,6 +16581,8 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { @@ -14707,6 +16643,8 @@ }, "node_modules/zwitch": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", "license": "MIT", "funding": { "type": "github", diff --git a/package.json b/package.json index 256d059f..13df9187 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,6 @@ }, "workspaces": ["apps/*"], "devDependencies": { - "supabase": "^1.204.3" + "supabase": "^1.207.9" } } diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index bb0e4041..0958281d 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -52,6 +52,7 @@ create table deployments ( status deployment_status not null default 'in_progress', deployed_database_id bigint references deployed_databases(id), events jsonb not null default '[]'::jsonb, + user_id uuid not null references auth.users(id) default auth.uid(), created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); @@ -111,39 +112,33 @@ alter table deployments enable row level security; -- RLS policies for deployments create policy "Users can read their own deployments" on deployments for select - using (auth.uid() = ( - select dpi.user_id - from deployed_databases dd - join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id - where dd.id = deployments.deployed_database_id - )); + using (auth.uid() = user_id); create policy "Users can create their own deployments" on deployments for insert - with check (auth.uid() = ( - select dpi.user_id - from deployed_databases dd - join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id - where dd.id = deployments.deployed_database_id - )); + with check (auth.uid() = user_id); create policy "Users can update their own deployments" on deployments for update - using (auth.uid() = ( - select dpi.user_id - from deployed_databases dd - join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id - where dd.id = deployments.deployed_database_id - )); + using (auth.uid() = user_id) + with check ( + auth.uid() = user_id + and ( + deployed_database_id is null + or + exists ( + select 1 + from deployed_databases dd + join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id + where dd.id = deployed_database_id + and dpi.user_id = auth.uid() + ) + ) + ); create policy "Users can delete their own deployments" on deployments for delete - using (auth.uid() = ( - select dpi.user_id - from deployed_databases dd - join deployment_provider_integrations dpi on dd.deployment_provider_integration_id = dpi.id - where dd.id = deployments.deployed_database_id - )); + using (auth.uid() = user_id); create or replace function insert_secret(secret text, name text) returns uuid From 7a8e0ad13266892f173ec270df57616e43dca6de Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 23 Oct 2024 12:26:38 +0200 Subject: [PATCH 14/59] populate .env.example --- apps/deploy-worker/.env.example | 5 +++++ apps/postgres-new/.env.example | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 apps/deploy-worker/.env.example diff --git a/apps/deploy-worker/.env.example b/apps/deploy-worker/.env.example new file mode 100644 index 00000000..eb14de85 --- /dev/null +++ b/apps/deploy-worker/.env.example @@ -0,0 +1,5 @@ +SUPABASE_ANON_KEY="" +SUPABASE_OAUTH_CLIENT_ID="" +SUPABASE_OAUTH_SECRET="" +SUPABASE_SERVICE_ROLE_KEY="" +SUPABASE_URL="" \ No newline at end of file diff --git a/apps/postgres-new/.env.example b/apps/postgres-new/.env.example index b8560b13..3a4b74fb 100644 --- a/apps/postgres-new/.env.example +++ b/apps/postgres-new/.env.example @@ -1,6 +1,8 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY="" NEXT_PUBLIC_SUPABASE_URL="" NEXT_PUBLIC_BROWSER_PROXY_DOMAIN="" +NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN="" +NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID="" OPENAI_API_KEY="" # Optional @@ -11,6 +13,9 @@ OPENAI_API_KEY="" KV_REST_API_URL="http://localhost:8080" KV_REST_API_TOKEN="local_token" +SUPABASE_OAUTH_SECRET="" +SUPABASE_SERVICE_ROLE_KEY="" + NEXT_PUBLIC_LEGACY_DOMAIN=https://postgres.new NEXT_PUBLIC_CURRENT_DOMAIN=https://database.build REDIRECT_LEGACY_DOMAIN=false From dd85d7794b6c850540650a93e0f1366ee7da4538 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 23 Oct 2024 17:24:48 +0200 Subject: [PATCH 15/59] add debug logs --- apps/deploy-worker/fly.toml | 22 +++++-------------- .../app/api/oauth/supabase/callback/route.ts | 18 +++++++++++++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/apps/deploy-worker/fly.toml b/apps/deploy-worker/fly.toml index e23f6c12..0b6cc8b8 100644 --- a/apps/deploy-worker/fly.toml +++ b/apps/deploy-worker/fly.toml @@ -1,21 +1,11 @@ primary_region = 'iad' -[[services]] -internal_port = 5432 -protocol = "tcp" -[[services.ports]] -handlers = ["proxy_proto"] -port = 5432 - -[[services]] -internal_port = 443 -protocol = "tcp" -[[services.ports]] -port = 443 - -[[restart]] -policy = "always" -retries = 10 +[http_service] +internal_port = 4000 +force_https = true +auto_stop_machines = "suspend" +auto_start_machines = true +min_machines_running = 0 [[vm]] memory = '512mb' diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index 97e13fe2..85f601eb 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -33,7 +33,7 @@ export async function GET(req: NextRequest) { } const now = Date.now() - + console.log('getting tokens') // get tokens const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { method: 'POST', @@ -48,6 +48,7 @@ export async function GET(req: NextRequest) { redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', }), }) + console.log('got tokens') const tokens = (await tokensResponse.json()) as { access_token: string @@ -57,6 +58,7 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } + console.log('getting organization') // get org const [org] = (await fetch('https://api.supabase.com/v1/organizations', { method: 'GET', @@ -68,9 +70,11 @@ export async function GET(req: NextRequest) { id: string name: string }[] + console.log('got organization') const adminClient = createAdminClient() + console.log('storing refresh token') // store the tokens as secrets const { data: refreshTokenSecretId, error: refreshTokenSecretError } = await adminClient.rpc( 'insert_secret', @@ -83,6 +87,8 @@ export async function GET(req: NextRequest) { if (refreshTokenSecretError) { return new Response('Failed to store refresh token as secret', { status: 500 }) } + console.log('stored refresh token') + console.log('storing access token') const { data: accessTokenSecretId, error: accessTokenSecretError } = await adminClient.rpc( 'insert_secret', { @@ -94,7 +100,9 @@ export async function GET(req: NextRequest) { if (accessTokenSecretError) { return new Response('Failed to store access token as secret', { status: 500 }) } + console.log('stored access token') + console.log('getting deployment provider') // store the credentials and relevant metadata const { data: deploymentProvider, error: deploymentProviderError } = await supabase .from('deployment_providers') @@ -105,7 +113,9 @@ export async function GET(req: NextRequest) { if (deploymentProviderError) { return new Response('Failed to get deployment provider', { status: 500 }) } + console.log('got deployment provider') + console.log('creating integration') const integration = await supabase .from('deployment_provider_integrations') .insert({ @@ -125,10 +135,14 @@ export async function GET(req: NextRequest) { if (integration.error) { return new Response('Failed to create integration', { status: 500 }) } - + console.log('created integration') const params = new URLSearchParams({ integration: integration.data.id.toString(), }) + console.log( + 'redirecting to', + new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url).toString() + ) return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) } From dd9db8fad4a67c5d4c98070bfa3aa288b002b7ea Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 23 Oct 2024 17:36:50 +0200 Subject: [PATCH 16/59] remove logs --- .../app/api/oauth/supabase/callback/route.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index 85f601eb..ddbb5d84 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -33,7 +33,7 @@ export async function GET(req: NextRequest) { } const now = Date.now() - console.log('getting tokens') + // get tokens const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { method: 'POST', @@ -48,7 +48,6 @@ export async function GET(req: NextRequest) { redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', }), }) - console.log('got tokens') const tokens = (await tokensResponse.json()) as { access_token: string @@ -58,7 +57,6 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } - console.log('getting organization') // get org const [org] = (await fetch('https://api.supabase.com/v1/organizations', { method: 'GET', @@ -70,11 +68,9 @@ export async function GET(req: NextRequest) { id: string name: string }[] - console.log('got organization') const adminClient = createAdminClient() - console.log('storing refresh token') // store the tokens as secrets const { data: refreshTokenSecretId, error: refreshTokenSecretError } = await adminClient.rpc( 'insert_secret', @@ -87,8 +83,7 @@ export async function GET(req: NextRequest) { if (refreshTokenSecretError) { return new Response('Failed to store refresh token as secret', { status: 500 }) } - console.log('stored refresh token') - console.log('storing access token') + const { data: accessTokenSecretId, error: accessTokenSecretError } = await adminClient.rpc( 'insert_secret', { @@ -100,9 +95,7 @@ export async function GET(req: NextRequest) { if (accessTokenSecretError) { return new Response('Failed to store access token as secret', { status: 500 }) } - console.log('stored access token') - console.log('getting deployment provider') // store the credentials and relevant metadata const { data: deploymentProvider, error: deploymentProviderError } = await supabase .from('deployment_providers') @@ -113,9 +106,7 @@ export async function GET(req: NextRequest) { if (deploymentProviderError) { return new Response('Failed to get deployment provider', { status: 500 }) } - console.log('got deployment provider') - console.log('creating integration') const integration = await supabase .from('deployment_provider_integrations') .insert({ @@ -135,14 +126,10 @@ export async function GET(req: NextRequest) { if (integration.error) { return new Response('Failed to create integration', { status: 500 }) } - console.log('created integration') + const params = new URLSearchParams({ integration: integration.data.id.toString(), }) - console.log( - 'redirecting to', - new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url).toString() - ) return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) } From 8f429251ddf65f3db606286169157e6d75b2cc55 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 23 Oct 2024 18:32:26 +0200 Subject: [PATCH 17/59] add TODOs --- apps/deploy-worker/src/supabase/wait-for-health.ts | 4 +++- apps/postgres-new/app/api/oauth/supabase/callback/route.ts | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index 9aaa903b..1200b93a 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -33,7 +33,8 @@ export async function waitForProjectToBeHealthy( if (project.status === 'ACTIVE_HEALTHY') { return } - + // TODO: investigate why this error is being thrown sometimes in less than MAX_POLLING_TIME + // Could it be Fly.io suspending the machine which would impact Date.now()? if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { throw new DeployError(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`, { cause: { @@ -101,6 +102,7 @@ export async function waitForDatabaseToBeHealthy( return } + // TODO: investigate why this error is being thrown sometimes in less than MAX_POLLING_TIME if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { throw new DeployError( `Database did not become healthy within ${MAX_POLLING_TIME} minutes`, diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index ddbb5d84..2c6b3a93 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -71,6 +71,9 @@ export async function GET(req: NextRequest) { const adminClient = createAdminClient() + // TODO: check if secret already exists first as the secret is tied to an org, multiple users from the same org could + // be using the same token. Or scope the secret to the user id instead? Or don't give a name to the secret? + // store the tokens as secrets const { data: refreshTokenSecretId, error: refreshTokenSecretError } = await adminClient.rpc( 'insert_secret', From a51f164921f5ca3d6a0d1b40074ef022cf1b6784 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 24 Oct 2024 09:33:18 +0200 Subject: [PATCH 18/59] enhance UX --- apps/postgres-new/components/sidebar.tsx | 64 +++++++++---------- .../deployed-databases-query.ts | 3 - apps/postgres-new/lib/util.ts | 19 ++++++ 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 26508619..4ed799e2 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -15,6 +15,7 @@ import { RadioIcon, Trash2, Upload, + Loader2, } from 'lucide-react' import Link from 'next/link' import { useParams, useRouter } from 'next/navigation' @@ -28,7 +29,7 @@ import { useDatabasesQuery } from '~/data/databases/databases-query' import { useDeployWaitlistCreateMutation } from '~/data/deploy-waitlist/deploy-waitlist-create-mutation' import { useIsOnDeployWaitlistQuery } from '~/data/deploy-waitlist/deploy-waitlist-query' import { Database as LocalDatabase } from '~/lib/db' -import { downloadFile, titleToKebabCase } from '~/lib/util' +import { downloadFile, getDeployUrl, getOauthUrl, titleToKebabCase } from '~/lib/util' import { cn } from '~/lib/utils' import { useApp } from './app-provider' import { CodeBlock } from './code-block' @@ -64,10 +65,13 @@ export default function Sidebar() { } = useApp() let { id: currentDatabaseId } = useParams<{ id: string }>() const router = useRouter() - const { data: localDatabases, isLoading: isLoadingDatabases } = useDatabasesQuery() - const { data: deployedDatabases } = useDeployedDatabasesQuery() + const { data: localDatabases, isLoading: isLoadingLocalDatabases } = useDatabasesQuery() + const { data: deployedDatabases, isLoading: isLoadingDeployedDatabases } = + useDeployedDatabasesQuery() const [showSidebar, setShowSidebar] = useState(true) + const isLoadingDatabases = isLoadingLocalDatabases && isLoadingDeployedDatabases + const databases = localDatabases?.map((db) => ({ ...db, isDeployed: @@ -326,6 +330,8 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { const [isRedeployAlertDialogOpen, setIsRedeployAlertDialogOpen] = useState(false) const [deployUrl, setDeployUrl] = useState(null) + const [isDeploying, setIsDeploying] = useState(false) + return ( <> { e.preventDefault() + setIsDeploying(true) const supabase = createClient() - const { data: provider, error: providerError } = await supabase - .from('deployment_providers') - .select('id') - .eq('name', 'Supabase') - .single() - - if (providerError) { - console.error(providerError) - return - } // check existing integration, we currently assume a single integration per user and provider // later we will allow for multiple integrations per provider with different scopes const { data: integration, error: integrationError } = await supabase .from('deployment_provider_integrations') - .select('id') - .eq('deployment_provider_id', provider.id) - .eq('user_id', user!.id) + .select('id, deployment_providers!inner(name)') + .eq('deployment_providers.name', 'Supabase') .maybeSingle() if (integrationError) { @@ -540,25 +536,15 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { } if (!integration) { - const params = new URLSearchParams({ - client_id: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, - redirect_uri: `${window.location.origin}/api/oauth/supabase/callback`, - response_type: 'code', - state: JSON.stringify({ - databaseId: database.id, - }), - }) - window.location.href = - 'https://api.supabase.com/v1/oauth/authorize' + '?' + params.toString() + router.push(getOauthUrl({ databaseId: database.id })) return } - const params = new URLSearchParams({ - integration: integration.id.toString(), + const deployUrl = getDeployUrl({ + databaseId: database.id, + integrationId: integration.id, }) - const deployUrl = `/deploy/${database.id}?${params.toString()}` - setDeployUrl(deployUrl) if (database.isDeployed) { @@ -569,11 +555,19 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { }} disabled={user === undefined} > - + {isDeploying ? ( + + ) : ( + + )} {database.isDeployed ? 'Redeploy' : 'Deploy'} , 'queryKey' | 'queryFn'> = {} ) => { - const { user } = useApp() - console.log('user', user) return useQuery({ ...options, queryKey: getDeployedDatabasesQueryKey(), diff --git a/apps/postgres-new/lib/util.ts b/apps/postgres-new/lib/util.ts index 25e5d471..c2ac6b58 100644 --- a/apps/postgres-new/lib/util.ts +++ b/apps/postgres-new/lib/util.ts @@ -119,3 +119,22 @@ export function titleToKebabCase(str: string): string { export function stripSuffix(value: string, suffix: string): string { return value.endsWith(suffix) ? value.slice(0, -suffix.length) : value } + +export function getDeployUrl(params: { databaseId: string; integrationId: number }) { + const deployParams = new URLSearchParams({ + integration: params.integrationId.toString(), + }) + return `/deploy/${params.databaseId}?${deployParams.toString()}` +} + +export function getOauthUrl(params: { databaseId: string }) { + const oauthParams = new URLSearchParams({ + client_id: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, + redirect_uri: `${window.location.origin}/api/oauth/supabase/callback`, + response_type: 'code', + state: JSON.stringify({ + databaseId: params.databaseId, + }), + }) + return `https://api.supabase.com/v1/oauth/authorize?${oauthParams.toString()}` +} From 7bb913b585dc93a11a5c081c4381f630a20fb7a8 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 24 Oct 2024 10:14:48 +0200 Subject: [PATCH 19/59] parallelize what can be --- .../app/api/oauth/supabase/callback/route.ts | 80 ++++++++++--------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index 2c6b3a93..4c989f44 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -5,14 +5,14 @@ import { NextRequest, NextResponse } from 'next/server' export async function GET(req: NextRequest) { const supabase = createClient() - const { data, error } = await supabase.auth.getUser() + const getUserResponse = await supabase.auth.getUser() // We have middleware, so this should never happen (used for type narrowing) - if (error) { + if (getUserResponse.error) { return new Response('Unauthorized', { status: 401 }) } - const { user } = data + const { user } = getUserResponse.data const code = req.nextUrl.searchParams.get('code') as string | null @@ -49,6 +49,10 @@ export async function GET(req: NextRequest) { }), }) + if (!tokensResponse.ok) { + return new Response('Failed to get tokens', { status: 500 }) + } + const tokens = (await tokensResponse.json()) as { access_token: string refresh_token: string @@ -57,81 +61,85 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } - // get org - const [org] = (await fetch('https://api.supabase.com/v1/organizations', { + const organizationsResponse = await fetch('https://api.supabase.com/v1/organizations', { method: 'GET', headers: { Accept: 'application/json', Authorization: `Bearer ${tokens.access_token}`, }, - }).then((res) => res.json())) as { + }) + + if (!organizationsResponse.ok) { + return new Response('Failed to get organizations', { status: 500 }) + } + + const [organization] = (await organizationsResponse.json()) as { id: string name: string }[] - const adminClient = createAdminClient() + if (!organization) { + return new Response('Organization not found', { status: 404 }) + } - // TODO: check if secret already exists first as the secret is tied to an org, multiple users from the same org could - // be using the same token. Or scope the secret to the user id instead? Or don't give a name to the secret? + const adminClient = createAdminClient() // store the tokens as secrets - const { data: refreshTokenSecretId, error: refreshTokenSecretError } = await adminClient.rpc( - 'insert_secret', - { - name: `supabase_oauth_refresh_token_${org.id}`, - secret: tokens.refresh_token, - } - ) - - if (refreshTokenSecretError) { + const createRefreshTokenSecret = adminClient.rpc('insert_secret', { + name: `supabase_oauth_refresh_token_${organization.id}_${user.id}`, + secret: tokens.refresh_token, + }) + const createAccessTokenSecret = adminClient.rpc('insert_secret', { + name: `supabase_oauth_access_token_${organization.id}_${user.id}`, + secret: tokens.access_token, + }) + + const [createRefreshTokenSecretResponse, createAccessTokenSecretResponse] = await Promise.all([ + createRefreshTokenSecret, + createAccessTokenSecret, + ]) + + if (createRefreshTokenSecretResponse.error) { return new Response('Failed to store refresh token as secret', { status: 500 }) } - const { data: accessTokenSecretId, error: accessTokenSecretError } = await adminClient.rpc( - 'insert_secret', - { - name: `supabase_oauth_access_token_${org.id}`, - secret: tokens.access_token, - } - ) - - if (accessTokenSecretError) { + if (createAccessTokenSecretResponse.error) { return new Response('Failed to store access token as secret', { status: 500 }) } // store the credentials and relevant metadata - const { data: deploymentProvider, error: deploymentProviderError } = await supabase + const getDeploymentProviderResponse = await supabase .from('deployment_providers') .select('id') .eq('name', 'Supabase') .single() - if (deploymentProviderError) { + if (getDeploymentProviderResponse.error) { return new Response('Failed to get deployment provider', { status: 500 }) } - const integration = await supabase + const createIntegrationResponse = await supabase .from('deployment_provider_integrations') .insert({ - deployment_provider_id: deploymentProvider.id, + deployment_provider_id: getDeploymentProviderResponse.data.id, credentials: { - accessToken: accessTokenSecretId, + accessToken: createAccessTokenSecretResponse.data, expiresAt: new Date(now + tokens.expires_in * 1000).toISOString(), - refreshToken: refreshTokenSecretId, + refreshToken: createRefreshTokenSecretResponse.data, }, scope: { - organizationId: org.id, + organizationId: organization.id, }, }) .select('id') .single() - if (integration.error) { + if (createIntegrationResponse.error) { return new Response('Failed to create integration', { status: 500 }) } const params = new URLSearchParams({ - integration: integration.data.id.toString(), + integration: createIntegrationResponse.data.id.toString(), }) return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) From d17a40d0b13caadd334f6c80d7cb7316e4e51780 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 24 Oct 2024 11:01:47 +0200 Subject: [PATCH 20/59] logs --- .../app/api/oauth/supabase/callback/route.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index 4c989f44..937f8ef9 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -5,7 +5,9 @@ import { NextRequest, NextResponse } from 'next/server' export async function GET(req: NextRequest) { const supabase = createClient() + console.time('get user') const getUserResponse = await supabase.auth.getUser() + console.timeEnd('get user') // We have middleware, so this should never happen (used for type narrowing) if (getUserResponse.error) { @@ -34,6 +36,7 @@ export async function GET(req: NextRequest) { const now = Date.now() + console.time('get tokens') // get tokens const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { method: 'POST', @@ -48,6 +51,7 @@ export async function GET(req: NextRequest) { redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', }), }) + console.timeEnd('get tokens') if (!tokensResponse.ok) { return new Response('Failed to get tokens', { status: 500 }) @@ -61,6 +65,7 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } + console.time('get organizations') const organizationsResponse = await fetch('https://api.supabase.com/v1/organizations', { method: 'GET', headers: { @@ -68,6 +73,7 @@ export async function GET(req: NextRequest) { Authorization: `Bearer ${tokens.access_token}`, }, }) + console.timeEnd('get organizations') if (!organizationsResponse.ok) { return new Response('Failed to get organizations', { status: 500 }) @@ -94,10 +100,12 @@ export async function GET(req: NextRequest) { secret: tokens.access_token, }) + console.time('create secrets') const [createRefreshTokenSecretResponse, createAccessTokenSecretResponse] = await Promise.all([ createRefreshTokenSecret, createAccessTokenSecret, ]) + console.timeEnd('create secrets') if (createRefreshTokenSecretResponse.error) { return new Response('Failed to store refresh token as secret', { status: 500 }) @@ -107,17 +115,20 @@ export async function GET(req: NextRequest) { return new Response('Failed to store access token as secret', { status: 500 }) } + console.time('get deployment provider') // store the credentials and relevant metadata const getDeploymentProviderResponse = await supabase .from('deployment_providers') .select('id') .eq('name', 'Supabase') .single() + console.timeEnd('get deployment provider') if (getDeploymentProviderResponse.error) { return new Response('Failed to get deployment provider', { status: 500 }) } + console.time('create integration') const createIntegrationResponse = await supabase .from('deployment_provider_integrations') .insert({ @@ -133,6 +144,7 @@ export async function GET(req: NextRequest) { }) .select('id') .single() + console.timeEnd('create integration') if (createIntegrationResponse.error) { return new Response('Failed to create integration', { status: 500 }) From 8740da8dd404ac3f5838d9a848a84a66f34be6ca Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 24 Oct 2024 11:04:07 +0200 Subject: [PATCH 21/59] whole callback log --- apps/postgres-new/app/api/oauth/supabase/callback/route.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index 937f8ef9..ffccaaed 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -3,6 +3,7 @@ import { createClient as createAdminClient } from '~/utils/supabase/admin' import { NextRequest, NextResponse } from 'next/server' export async function GET(req: NextRequest) { + console.time('oauth callback') const supabase = createClient() console.time('get user') @@ -154,5 +155,7 @@ export async function GET(req: NextRequest) { integration: createIntegrationResponse.data.id.toString(), }) + console.timeEnd('oauth callback') + return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) } From cdbf4316f8d0d40d2893d0afed57215b927ff8bf Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 14:17:13 +0200 Subject: [PATCH 22/59] fail if project exists on Supabase --- .../src/supabase/create-deployed-database.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index 6dffe54e..cf70cd92 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -45,6 +45,23 @@ export async function createDeployedDatabase( const databasePassword = generatePassword() + const projectName = `database-build-${params.databaseId}` + + // check if the project already exists on Supabase + const { data: projects, error: getProjectsError } = await managementApiClient.GET('/v1/projects') + + if (getProjectsError) { + throw new DeployError('Failed to get projects from Supabase', { cause: getProjectsError }) + } + + const project = projects.find((p) => p.name === projectName) + + if (project) { + throw new DeployError(`A project with this name ${projectName} already exists on Supabase`, { + cause: project, + }) + } + // create a new project on Supabase using the Management API const { data: createdProject, error: createdProjectError } = await managementApiClient.POST( '/v1/projects', From 84981028b732a91b6e77ed002c6e95d622a9ca95 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 14:17:23 +0200 Subject: [PATCH 23/59] don't rely on the date for the health loop --- .../src/supabase/wait-for-health.ts | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index 1200b93a..decb08a3 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -11,10 +11,11 @@ export async function waitForProjectToBeHealthy( ) { const MAX_POLLING_TIME = 2 // 2 minutes const POLLING_INTERVAL = 5 * 1000 // 5 seconds in milliseconds + const MAX_ATTEMPTS = (MAX_POLLING_TIME * 60 * 1000) / POLLING_INTERVAL - const startTime = Date.now() + let attempts = 0 - while (true) { + while (attempts < MAX_ATTEMPTS) { try { const { data: project, error } = await ctx.managementApiClient.GET('/v1/projects/{ref}', { params: { @@ -33,21 +34,15 @@ export async function waitForProjectToBeHealthy( if (project.status === 'ACTIVE_HEALTHY') { return } - // TODO: investigate why this error is being thrown sometimes in less than MAX_POLLING_TIME - // Could it be Fly.io suspending the machine which would impact Date.now()? - if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { - throw new DeployError(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`, { - cause: { - status: project.status, - }, - }) - } + attempts += 1 await setTimeout(POLLING_INTERVAL) } catch (error) { throw error } } + + throw new DeployError(`Project did not become healthy within ${MAX_POLLING_TIME} minutes`) } /** @@ -59,10 +54,11 @@ export async function waitForDatabaseToBeHealthy( ) { const MAX_POLLING_TIME = 2 // 2 minutes const POLLING_INTERVAL = 5 * 1000 // 5 seconds in milliseconds + const MAX_ATTEMPTS = (MAX_POLLING_TIME * 60 * 1000) / POLLING_INTERVAL - const startTime = Date.now() + let attempts = 0 - while (true) { + while (attempts < MAX_ATTEMPTS) { try { const { data: servicesHealth, error } = await ctx.managementApiClient.GET( '/v1/projects/{ref}/health', @@ -102,22 +98,12 @@ export async function waitForDatabaseToBeHealthy( return } - // TODO: investigate why this error is being thrown sometimes in less than MAX_POLLING_TIME - if (Date.now() - startTime > MAX_POLLING_TIME * 60 * 1000) { - throw new DeployError( - `Database did not become healthy within ${MAX_POLLING_TIME} minutes`, - { - cause: { - status: databaseService.status, - error: databaseService.error, - }, - } - ) - } - + attempts += 1 await setTimeout(POLLING_INTERVAL) } catch (error) { throw error } } + + throw new DeployError(`Database did not become healthy within ${MAX_POLLING_TIME} minutes`) } From 0c1aabad318182943b7983e2cdf1d6fcadd9a60f Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 15:32:37 +0200 Subject: [PATCH 24/59] make waiting for deployment more fun with a background animation --- .../app/deploy/[databaseId]/page.tsx | 37 +++--- .../components/particles-background.tsx | 120 ++++++++++++++++++ apps/postgres-new/components/ui/dialog.tsx | 57 +++------ 3 files changed, 163 insertions(+), 51 deletions(-) create mode 100644 apps/postgres-new/components/particles-background.tsx diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index 4207ac86..daedee6f 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -7,6 +7,7 @@ import { useApp } from '~/components/app-provider' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' import { createClient } from '~/utils/supabase/client' import { Loader2 } from 'lucide-react' +import { ParticlesBackground } from '~/components/particles-background' export default function Page() { const params = useParams<{ databaseId: string }>() @@ -88,22 +89,28 @@ export default function Page() { }, [deploy]) return ( - - - - Deploying your database -
- -
-
- -
-

Your database is being deployed. This process typically takes a few minutes.

-

Please keep this page open to ensure successful deployment.

+ + + + + Deploying your database +
+ +
+
+ +
+

Your database is being deployed. This process typically takes a few minutes.

+

Please keep this page open to ensure successful deployment.

+
-
-
-
+ +
+ ) } diff --git a/apps/postgres-new/components/particles-background.tsx b/apps/postgres-new/components/particles-background.tsx new file mode 100644 index 00000000..d03264df --- /dev/null +++ b/apps/postgres-new/components/particles-background.tsx @@ -0,0 +1,120 @@ +'use client' + +import React, { useRef, useEffect, ReactNode, useState } from 'react' + +interface Particle { + x: number + y: number + size: number + speed: number + opacity: number +} + +interface ParticlesBackgroundProps { + children?: ReactNode +} + +export function ParticlesBackground({ children }: ParticlesBackgroundProps) { + const canvasRef = useRef(null) + const [prefersReducedMotion, setPrefersReducedMotion] = useState(false) + + useEffect(() => { + const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)') + setPrefersReducedMotion(mediaQuery.matches) + + const handleChange = (e: MediaQueryListEvent) => { + setPrefersReducedMotion(e.matches) + } + + mediaQuery.addEventListener('change', handleChange) + return () => mediaQuery.removeEventListener('change', handleChange) + }, []) + + useEffect(() => { + const canvas = canvasRef.current + if (!canvas) return + + const ctx = canvas.getContext('2d') + if (!ctx) return + + let animationFrameId: number + let particles: Particle[] = [] + + const COLOR = '#FFFFFF' + const MIN_SIZE = 3 + const MAX_SIZE = 8 + + const resizeCanvas = () => { + canvas.width = window.innerWidth + canvas.height = window.innerHeight + } + + const createParticles = () => { + const particleCount = Math.floor((canvas.width * canvas.height) / 10000) + particles = [] + for (let i = 0; i < particleCount; i++) { + particles.push({ + x: Math.random() * canvas.width, + y: Math.random() * canvas.height, + size: Math.random() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE, + speed: Math.random() * 0.5 + 0.1, + opacity: Math.random() * 0.8 + 0.2, + }) + } + } + + const drawParticles = () => { + ctx.clearRect(0, 0, canvas.width, canvas.height) + + particles.forEach((particle) => { + ctx.fillStyle = `${COLOR}${Math.floor(particle.opacity * 255) + .toString(16) + .padStart(2, '0')}` + ctx.fillRect(particle.x, particle.y, particle.size, particle.size) + + if (!prefersReducedMotion) { + particle.y -= particle.speed + if (particle.y + particle.size < 0) { + particle.y = canvas.height + particle.x = Math.random() * canvas.width + particle.opacity = Math.random() * 0.8 + 0.2 + } + } + }) + } + + const animate = () => { + drawParticles() + if (!prefersReducedMotion) { + animationFrameId = requestAnimationFrame(animate) + } + } + + resizeCanvas() + createParticles() + animate() + + window.addEventListener('resize', () => { + resizeCanvas() + createParticles() + drawParticles() + }) + + return () => { + cancelAnimationFrame(animationFrameId) + window.removeEventListener('resize', resizeCanvas) + } + }, [prefersReducedMotion]) + + return ( +
+ + {children} +
+ ) +} diff --git a/apps/postgres-new/components/ui/dialog.tsx b/apps/postgres-new/components/ui/dialog.tsx index 25754da0..1c69c0c1 100644 --- a/apps/postgres-new/components/ui/dialog.tsx +++ b/apps/postgres-new/components/ui/dialog.tsx @@ -1,10 +1,10 @@ -"use client" +'use client' -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { X } from "lucide-react" +import * as React from 'react' +import * as DialogPrimitive from '@radix-ui/react-dialog' +import { X } from 'lucide-react' -import { cn } from "~/lib/utils" +import { cn } from '~/lib/utils' const Dialog = DialogPrimitive.Root @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef< , - React.ComponentPropsWithoutRef & { showCloseButton?: boolean } ->(({ className, children, showCloseButton = true, ...props }, ref) => ( + React.ComponentPropsWithoutRef & { + showCloseButton?: boolean + overlay?: boolean + } +>(({ className, children, showCloseButton = true, overlay = true, ...props }, ref) => ( - + {overlay && } ) => ( -
+const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
) -DialogHeader.displayName = "DialogHeader" +DialogHeader.displayName = 'DialogHeader' -const DialogFooter = ({ - className, - ...props -}: React.HTMLAttributes) => ( +const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => (
) -DialogFooter.displayName = "DialogFooter" +DialogFooter.displayName = 'DialogFooter' const DialogTitle = React.forwardRef< React.ElementRef, @@ -89,10 +77,7 @@ const DialogTitle = React.forwardRef< >(({ className, ...props }, ref) => ( )) @@ -104,7 +89,7 @@ const DialogDescription = React.forwardRef< >(({ className, ...props }, ref) => ( )) From c36382c7786d9a0d72e503a55fb76ae3bf89a1d7 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 17:19:31 +0200 Subject: [PATCH 25/59] improvements --- .../src/supabase/create-deployed-database.ts | 8 +- apps/deploy-worker/src/supabase/deploy.ts | 25 +++- .../src/supabase/get-database-url.ts | 31 ++++- apps/deploy-worker/src/supabase/types.ts | 8 +- .../src/supabase/wait-for-health.ts | 4 +- .../components/deploy-success-dialog.tsx | 5 +- apps/postgres-new/components/sidebar.tsx | 129 ++++++++++-------- .../postgres-new/components/supabase-icon.tsx | 53 +++++++ 8 files changed, 198 insertions(+), 65 deletions(-) create mode 100644 apps/postgres-new/components/supabase-icon.tsx diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index cf70cd92..dd71c420 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -128,10 +128,16 @@ export async function createDeployedDatabase( name: createdProject.name, region: createdProject.region, createdAt: createdProject.created_at, + databasePasswordSecretId: databasePasswordSecret.data, database: { + host: createdProject.database!.host, + name: 'postgres', + port: 5432, + user: 'postgres', + }, + pooler: { host: primaryDatabase.db_host, name: primaryDatabase.db_name, - password: databasePasswordSecret.data, // use session mode for prepared statements port: 5432, user: primaryDatabase.db_user, diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index f7bc0a5b..fe3c7cf0 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -3,7 +3,7 @@ import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' import { createDeployedDatabase } from './create-deployed-database.ts' -import { getDatabaseUrl } from './get-database-url.ts' +import { getDatabaseUrl, getPoolerUrl } from './get-database-url.ts' import { DeployError } from '../error.ts' const exec = promisify(execSync) @@ -75,8 +75,28 @@ export async function deploy( project, }) + const excludedSchemas = [ + '_realtime', + 'auth', + 'cron', + 'extensions', + 'graphql', + 'graphql_public', + 'net', + 'pgbouncer', + 'pgsodium', + 'pgsodium_masks', + 'realtime', + 'storage', + 'supabase_functions', + 'supabase_migrations', + 'vault', + ] + .map((schema) => `--exclude-schema=${schema}`) + .join(' ') + // use pg_dump and pg_restore to transfer the data from the local database to the remote database - const command = `pg_dump "${params.localDatabaseUrl}" -Fc | pg_restore -d "${databaseUrl}" --clean --if-exists` + const command = `pg_dump "${params.localDatabaseUrl}" -Fc ${excludedSchemas} | pg_restore -d "${databaseUrl}" --clean --if-exists` try { await exec(command) @@ -100,6 +120,7 @@ export async function deploy( name: project.name, url: `https://supabase.com/dashboard/project/${project.id}`, databaseUrl: await getDatabaseUrl({ project, hidePassword: isRedeploy }), + poolerUrl: await getPoolerUrl({ project, hidePassword: isRedeploy }), isRedeploy, } } catch (error) { diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/apps/deploy-worker/src/supabase/get-database-url.ts index fd447267..32dc0aee 100644 --- a/apps/deploy-worker/src/supabase/get-database-url.ts +++ b/apps/deploy-worker/src/supabase/get-database-url.ts @@ -3,7 +3,7 @@ import { supabaseAdmin } from './client.ts' import type { SupabaseProviderMetadata } from './types.ts' /** - * Get the database url for a given Supabase project. + * Get the direct database url for a given Supabase project. */ export async function getDatabaseUrl(params: { project: SupabaseProviderMetadata['project'] @@ -12,7 +12,7 @@ export async function getDatabaseUrl(params: { let password = '[YOUR-PASSWORD]' if (!params.hidePassword) { const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { - secret_id: params.project.database.password, + secret_id: params.project.databasePasswordSecretId, }) if (databasePasswordSecret.error) { @@ -28,3 +28,30 @@ export async function getDatabaseUrl(params: { return `postgresql://${database.user}:${password}@${database.host}:${database.port}/${database.name}` } + +/** + * Get the pooler url for a given Supabase project. + */ +export async function getPoolerUrl(params: { + project: SupabaseProviderMetadata['project'] + hidePassword?: boolean +}) { + let password = '[YOUR-PASSWORD]' + if (!params.hidePassword) { + const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { + secret_id: params.project.databasePasswordSecretId, + }) + + if (databasePasswordSecret.error) { + throw new DeployError('Cannot read database password secret', { + cause: databasePasswordSecret.error, + }) + } + + password = databasePasswordSecret.data + } + + const { pooler } = params.project + + return `postgresql://${pooler.user}:${password}@${pooler.host}:${pooler.port}/${pooler.name}` +} diff --git a/apps/deploy-worker/src/supabase/types.ts b/apps/deploy-worker/src/supabase/types.ts index 11fc93f0..6dd5ca4f 100644 --- a/apps/deploy-worker/src/supabase/types.ts +++ b/apps/deploy-worker/src/supabase/types.ts @@ -20,10 +20,16 @@ export type SupabaseProviderMetadata = { name: Project['name'] region: Project['region'] createdAt: Project['created_at'] + databasePasswordSecretId: string database: { + host: NonNullable['host'] + name: string + port: number + user: string + } + pooler: { host: Database['db_host'] name: Database['db_name'] - password: string port: number user: Database['db_user'] } diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index decb08a3..4eb11aa0 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -9,8 +9,8 @@ export async function waitForProjectToBeHealthy( ctx: { managementApiClient: ManagementApiClient }, params: { project: Project } ) { - const MAX_POLLING_TIME = 2 // 2 minutes - const POLLING_INTERVAL = 5 * 1000 // 5 seconds in milliseconds + const MAX_POLLING_TIME = 3 // minutes + const POLLING_INTERVAL = 5 * 1000 // seconds in milliseconds const MAX_ATTEMPTS = (MAX_POLLING_TIME * 60 * 1000) / POLLING_INTERVAL let attempts = 0 diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index 8dc6051b..c30adfd2 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -12,6 +12,7 @@ export function DeploySuccessDialog() { name: string url: string databaseUrl: string + poolerUrl: string isRedeploy: boolean } | null>(null) const [open, setOpen] = useState(false) @@ -40,7 +41,8 @@ export function DeploySuccessDialog() {

- Your database has been {deployText} to the Supabase project:{' '} + Your database has been {deployText} to the Supabase project: +

+ {project.isRedeploy ? null : ( diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 4ed799e2..ebc66450 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -39,7 +39,11 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, + DropdownMenuPortal, DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, DropdownMenuTrigger, } from './ui/dropdown-menu' import { TooltipPortal } from '@radix-ui/react-tooltip' @@ -47,6 +51,7 @@ import { LiveShareIcon } from './live-share-icon' import { createClient } from '~/utils/supabase/client' import { RedeployAlertDialog } from './redeploy-alert-dialog' import { useDeployedDatabasesQuery } from '~/data/deployed-databases/deployed-databases-query' +import { SupabaseIcon } from './supabase-icon' type Database = LocalDatabase & { isDeployed: boolean @@ -474,7 +479,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { /> ) : ( -

+
{ @@ -515,61 +520,73 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { Download - { - e.preventDefault() - setIsDeploying(true) - const supabase = createClient() - - // check existing integration, we currently assume a single integration per user and provider - // later we will allow for multiple integrations per provider with different scopes - const { data: integration, error: integrationError } = await supabase - .from('deployment_provider_integrations') - .select('id, deployment_providers!inner(name)') - .eq('deployment_providers.name', 'Supabase') - .maybeSingle() - - if (integrationError) { - console.error(integrationError) - return - } - - if (!integration) { - router.push(getOauthUrl({ databaseId: database.id })) - return - } - - const deployUrl = getDeployUrl({ - databaseId: database.id, - integrationId: integration.id, - }) - - setDeployUrl(deployUrl) - - if (database.isDeployed) { - setIsRedeployAlertDialogOpen(true) - } else { - router.push(deployUrl) - } - }} - disabled={user === undefined} - > - {isDeploying ? ( - - ) : ( - - )} - {database.isDeployed ? 'Redeploy' : 'Deploy'} - + + + {isDeploying ? ( + + ) : ( + + )} + Deploy + + + + { + e.preventDefault() + setIsDeploying(true) + const supabase = createClient() + + // check existing integration, we currently assume a single integration per user and provider + // later we will allow for multiple integrations per provider with different scopes + const { data: integration, error: integrationError } = await supabase + .from('deployment_provider_integrations') + .select('id, deployment_providers!inner(name)') + .eq('deployment_providers.name', 'Supabase') + .maybeSingle() + + if (integrationError) { + console.error(integrationError) + return + } + + if (!integration) { + router.push(getOauthUrl({ databaseId: database.id })) + return + } + + const deployUrl = getDeployUrl({ + databaseId: database.id, + integrationId: integration.id, + }) + + setDeployUrl(deployUrl) + + if (database.isDeployed) { + setIsRedeployAlertDialogOpen(true) + } else { + router.push(deployUrl) + } + }} + > + + Supabase + + + + { + const aspectRatio = 113 / 109 + const width = props.size ?? 16 + const height = Math.round(width * aspectRatio) + + return ( + + + + + + + + + + + + + + + + ) +} From c0ce41e45e6ecb65a9a55b020ba7d19308497c04 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 17:35:48 +0200 Subject: [PATCH 26/59] fixes --- .../src/supabase/create-deployed-database.ts | 13 ++++++++----- apps/deploy-worker/src/supabase/wait-for-health.ts | 2 +- apps/postgres-new/components/ui/dropdown-menu.tsx | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index dd71c420..063701f9 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -54,11 +54,11 @@ export async function createDeployedDatabase( throw new DeployError('Failed to get projects from Supabase', { cause: getProjectsError }) } - const project = projects.find((p) => p.name === projectName) + const existingProject = projects.find((p) => p.name === projectName) - if (project) { + if (existingProject) { throw new DeployError(`A project with this name ${projectName} already exists on Supabase`, { - cause: project, + cause: existingProject, }) } @@ -81,7 +81,10 @@ export async function createDeployedDatabase( }) } - await waitForProjectToBeHealthy({ managementApiClient }, { project: createdProject }) + const project = await waitForProjectToBeHealthy( + { managementApiClient }, + { project: createdProject } + ) await waitForDatabaseToBeHealthy({ managementApiClient }, { project: createdProject }) @@ -130,7 +133,7 @@ export async function createDeployedDatabase( createdAt: createdProject.created_at, databasePasswordSecretId: databasePasswordSecret.data, database: { - host: createdProject.database!.host, + host: project.database!.host, name: 'postgres', port: 5432, user: 'postgres', diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index 4eb11aa0..702950cd 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -32,7 +32,7 @@ export async function waitForProjectToBeHealthy( } if (project.status === 'ACTIVE_HEALTHY') { - return + return project } attempts += 1 diff --git a/apps/postgres-new/components/ui/dropdown-menu.tsx b/apps/postgres-new/components/ui/dropdown-menu.tsx index ff52c617..26e06923 100644 --- a/apps/postgres-new/components/ui/dropdown-menu.tsx +++ b/apps/postgres-new/components/ui/dropdown-menu.tsx @@ -27,7 +27,7 @@ const DropdownMenuSubTrigger = React.forwardRef< Date: Fri, 25 Oct 2024 18:41:13 +0200 Subject: [PATCH 27/59] fix chevron right color --- apps/postgres-new/components/sidebar.tsx | 1 + apps/postgres-new/components/ui/dropdown-menu.tsx | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index ebc66450..0978c44b 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -524,6 +524,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { {isDeploying ? ( , React.ComponentPropsWithoutRef & { inset?: boolean + chevronRightClassName?: string } ->(({ className, inset, children, ...props }, ref) => ( +>(({ className, inset, children, chevronRightClassName, ...props }, ref) => ( {children} - + )) DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName From 94feb4e33bf9bf289216989db699f1315413a550 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 25 Oct 2024 18:43:11 +0200 Subject: [PATCH 28/59] UI fixes --- apps/postgres-new/components/redeploy-alert-dialog.tsx | 9 ++++++++- apps/postgres-new/components/sidebar.tsx | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/postgres-new/components/redeploy-alert-dialog.tsx b/apps/postgres-new/components/redeploy-alert-dialog.tsx index 375549d5..9d0fe6ee 100644 --- a/apps/postgres-new/components/redeploy-alert-dialog.tsx +++ b/apps/postgres-new/components/redeploy-alert-dialog.tsx @@ -13,6 +13,7 @@ type RedeployAlertDialogProps = { isOpen: boolean onOpenChange: (open: boolean) => void onConfirm: () => void + onCancel: () => void } export function RedeployAlertDialog(props: RedeployAlertDialogProps) { @@ -27,7 +28,13 @@ export function RedeployAlertDialog(props: RedeployAlertDialogProps) { - Cancel + { + props.onCancel() + }} + > + Cancel + { props.onConfirm() diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 0978c44b..c99c6abb 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -345,6 +345,9 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { onConfirm={() => { router.push(deployUrl!) }} + onCancel={() => { + setIsDeploying(false) + }} /> Date: Tue, 29 Oct 2024 16:46:01 +0100 Subject: [PATCH 29/59] remove _realtime --- apps/deploy-worker/src/supabase/deploy.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index fe3c7cf0..8233179d 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -76,7 +76,6 @@ export async function deploy( }) const excludedSchemas = [ - '_realtime', 'auth', 'cron', 'extensions', From faf504a40fc7e99feb2bc69cd82a997661efd68c Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 31 Oct 2024 11:45:02 +0100 Subject: [PATCH 30/59] simplify secrets --- apps/deploy-worker/package.json | 4 +- apps/deploy-worker/src/error.ts | 10 ++ apps/deploy-worker/src/index.ts | 7 +- .../src/supabase/create-deployed-database.ts | 56 ++++---- .../src/supabase/database-types.ts | 9 +- apps/deploy-worker/src/supabase/deploy.ts | 79 +++++++++-- .../src/supabase/get-access-token.ts | 89 +++++------- .../src/supabase/get-database-url.ts | 44 ++---- .../src/supabase/management-api.ts | 0 .../src/supabase/management-api/client.ts | 20 ++- .../src/supabase/management-api/types.ts | 105 ++++++++++++++ .../src/supabase/revoke-integration.ts | 34 +++++ apps/deploy-worker/src/supabase/types.ts | 1 - .../src/supabase/wait-for-health.ts | 6 +- .../app/api/oauth/supabase/callback/route.ts | 132 ++++++++++-------- .../app/deploy/[databaseId]/page.tsx | 22 ++- .../components/deploy-success-dialog.tsx | 21 +-- apps/postgres-new/components/sidebar.tsx | 3 +- apps/postgres-new/utils/supabase/db-types.ts | 9 +- package-lock.json | 24 ++-- .../migrations/20241003131953_deployment.sql | 3 +- 21 files changed, 447 insertions(+), 231 deletions(-) delete mode 100644 apps/deploy-worker/src/supabase/management-api.ts create mode 100644 apps/deploy-worker/src/supabase/revoke-integration.ts diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json index 806658c0..217dbd06 100644 --- a/apps/deploy-worker/package.json +++ b/apps/deploy-worker/package.json @@ -15,14 +15,14 @@ "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", - "openapi-fetch": "^0.12.2", + "openapi-fetch": "^0.13.0", "zod": "^3.23.8" }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/debug": "^4.1.12", "@types/node": "^22.5.4", - "openapi-typescript": "^7.4.1", + "openapi-typescript": "^7.4.2", "typescript": "^5.5.4" } } diff --git a/apps/deploy-worker/src/error.ts b/apps/deploy-worker/src/error.ts index 557c5ed7..0b097db9 100644 --- a/apps/deploy-worker/src/error.ts +++ b/apps/deploy-worker/src/error.ts @@ -3,3 +3,13 @@ export class DeployError extends Error { super(message, options) } } + +export class IntegrationRevokedError extends Error { + constructor(options?: ErrorOptions) { + super( + 'Your Supabase integration has been revoked. Please retry to restore your integration.', + options + ) + this.name = 'IntegrationRevokedError' + } +} diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index 8af571b4..14cd0970 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -6,7 +6,8 @@ import { zValidator } from '@hono/zod-validator' import { createClient } from './supabase/client.ts' import { HTTPException } from 'hono/http-exception' import { deploy } from './supabase/deploy.ts' -import { DeployError } from './error.ts' +import { DeployError, IntegrationRevokedError } from './error.ts' +import { revokeIntegration } from './supabase/revoke-integration.ts' const app = new Hono() @@ -50,6 +51,10 @@ app.post( if (error instanceof DeployError) { throw new HTTPException(500, { message: error.message }) } + if (error instanceof IntegrationRevokedError) { + await revokeIntegration({ supabase }, { integrationId }) + throw new HTTPException(406, { message: error.message }) + } throw new HTTPException(500, { message: 'Internal server error' }) } } diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index 063701f9..9aeeb0c7 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -1,9 +1,8 @@ import { DeployError } from '../error.ts' -import { supabaseAdmin } from './client.ts' import { generatePassword } from './generate-password.ts' import { getAccessToken } from './get-access-token.ts' import { createManagementApiClient } from './management-api/client.ts' -import type { Credentials, SupabaseClient, SupabaseProviderMetadata } from './types.ts' +import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.ts' /** @@ -28,18 +27,16 @@ export async function createDeployedDatabase( throw new DeployError('Cannot find integration', { cause: integration.error }) } - // first we need to create a new project on Supabase using the Management API - const credentials = integration.data.credentials as Credentials + // It should be impossible to reach this state + if (!integration.data.credentials) { + throw new DeployError('The integration was revoked') + } - const accessToken = await getAccessToken( - { - supabase: ctx.supabase, - }, - { - integrationId: integration.data.id, - credentials, - } - ) + // first we need to create a new project on Supabase using the Management API + const accessToken = await getAccessToken({ + integrationId: integration.data.id, + credentialsSecretId: integration.data.credentials, + }) const managementApiClient = createManagementApiClient(accessToken) @@ -48,10 +45,17 @@ export async function createDeployedDatabase( const projectName = `database-build-${params.databaseId}` // check if the project already exists on Supabase - const { data: projects, error: getProjectsError } = await managementApiClient.GET('/v1/projects') + const { + data: projects, + error: getProjectsError, + response, + } = await managementApiClient.GET('/v1/projects') if (getProjectsError) { - throw new DeployError('Failed to get projects from Supabase', { cause: getProjectsError }) + console.log(response) + throw new DeployError('Failed to get projects from Supabase', { + cause: getProjectsError, + }) } const existingProject = projects.find((p) => p.name === projectName) @@ -106,24 +110,12 @@ export async function createDeployedDatabase( }) } - const primaryDatabase = pooler.find((db) => db.database_type === 'PRIMARY') + const primaryDatabase = pooler!.find((db) => db.database_type === 'PRIMARY') if (!primaryDatabase) { throw new DeployError('Primary database not found') } - // store the database password as a secret - const databasePasswordSecret = await supabaseAdmin.rpc('insert_secret', { - name: `supabase_database_password_${params.databaseId}`, - secret: databasePassword, - }) - - if (databasePasswordSecret.error) { - throw new DeployError('Cannot store database password as secret', { - cause: databasePasswordSecret.error, - }) - } - const metadata: SupabaseProviderMetadata = { project: { id: createdProject.id, @@ -131,9 +123,8 @@ export async function createDeployedDatabase( name: createdProject.name, region: createdProject.region, createdAt: createdProject.created_at, - databasePasswordSecretId: databasePasswordSecret.data, database: { - host: project.database!.host, + host: project!.database!.host, name: 'postgres', port: 5432, user: 'postgres', @@ -162,5 +153,8 @@ export async function createDeployedDatabase( throw new DeployError('Cannot create deployed database', { cause: deployedDatabase.error }) } - return deployedDatabase.data + return { + deployedDatabase: deployedDatabase.data, + databasePassword, + } } diff --git a/apps/deploy-worker/src/supabase/database-types.ts b/apps/deploy-worker/src/supabase/database-types.ts index 1ecc9693..f57a5e9c 100644 --- a/apps/deploy-worker/src/supabase/database-types.ts +++ b/apps/deploy-worker/src/supabase/database-types.ts @@ -90,27 +90,30 @@ export type Database = { deployment_provider_integrations: { Row: { created_at: string - credentials: Json + credentials: string | null deployment_provider_id: number | null id: number + revoked_at: string | null scope: Json updated_at: string user_id: string } Insert: { created_at?: string - credentials: Json + credentials?: string | null deployment_provider_id?: number | null id?: never + revoked_at?: string | null scope?: Json updated_at?: string user_id?: string } Update: { created_at?: string - credentials?: Json + credentials?: string | null deployment_provider_id?: number | null id?: never + revoked_at?: string | null scope?: Json updated_at?: string user_id?: string diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index 8233179d..8fe4733d 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -1,10 +1,12 @@ -import { supabaseAdmin, type createClient } from './client.ts' import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' import { createDeployedDatabase } from './create-deployed-database.ts' import { getDatabaseUrl, getPoolerUrl } from './get-database-url.ts' -import { DeployError } from '../error.ts' +import { DeployError, IntegrationRevokedError } from '../error.ts' +import { generatePassword } from './generate-password.ts' +import { getAccessToken } from './get-access-token.ts' +import { createManagementApiClient } from './management-api/client.ts' const exec = promisify(execSync) /** @@ -15,6 +17,32 @@ export async function deploy( ctx: { supabase: SupabaseClient }, params: { databaseId: string; integrationId: number; localDatabaseUrl: string } ) { + // check if the integration is still active + const integration = await ctx.supabase + .from('deployment_provider_integrations') + .select('*') + .eq('id', params.integrationId) + .single() + + if (integration.error) { + throw new DeployError('Integration not found', { cause: integration.error }) + } + + if (integration.data.revoked_at) { + throw new IntegrationRevokedError() + } + + const accessToken = await getAccessToken({ + integrationId: params.integrationId, + // the integration isn't revoked, so it must have credentials + credentialsSecretId: integration.data.credentials!, + }) + + const managementApiClient = createManagementApiClient(accessToken) + + // this is just to check if the integration is still active, an IntegrationRevokedError will be thrown if not + await managementApiClient.GET('/v1/organizations') + const { data: deployment, error: createDeploymentError } = await ctx.supabase .from('deployments') .insert({ @@ -31,8 +59,6 @@ export async function deploy( throw new DeployError('Cannot create deployment', { cause: createDeploymentError }) } - let isRedeploy = false - try { // check if the database was already deployed const deployedDatabase = await ctx.supabase @@ -46,13 +72,16 @@ export async function deploy( throw new DeployError('Cannot find deployed database', { cause: deployedDatabase.error }) } + let databasePassword: string | undefined + if (!deployedDatabase.data) { - deployedDatabase.data = await createDeployedDatabase( + const createdDeployedDatabase = await createDeployedDatabase( { supabase: ctx.supabase }, { databaseId: params.databaseId, integrationId: params.integrationId } ) - } else { - isRedeploy = true + + deployedDatabase.data = createdDeployedDatabase.deployedDatabase + databasePassword = createdDeployedDatabase.databasePassword } const { error: linkDeploymentError } = await ctx.supabase @@ -70,9 +99,23 @@ export async function deploy( const project = (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project - // get the database url - const databaseUrl = await getDatabaseUrl({ + // create temporary credentials to restore the Supabase database + const remoteDatabaseUser = `db-build-${params.databaseId}` + const remoteDatabasePassword = generatePassword() + await managementApiClient.POST('/v1/projects/{ref}/database/query', { + body: { + query: `create user ${remoteDatabaseUser} with password '${remoteDatabasePassword}' in role postgres;`, + }, + params: { + path: { + ref: project.id, + }, + }, + }) + const remoteDatabaseUrl = getDatabaseUrl({ project, + databaseUser: remoteDatabaseUser, + databasePassword: remoteDatabasePassword, }) const excludedSchemas = [ @@ -95,7 +138,7 @@ export async function deploy( .join(' ') // use pg_dump and pg_restore to transfer the data from the local database to the remote database - const command = `pg_dump "${params.localDatabaseUrl}" -Fc ${excludedSchemas} | pg_restore -d "${databaseUrl}" --clean --if-exists` + const command = `pg_dump "${params.localDatabaseUrl}" -Fc ${excludedSchemas} -Z 0 | pg_restore -d "${remoteDatabaseUrl}" --clean --if-exists` try { await exec(command) @@ -106,6 +149,16 @@ export async function deploy( cause: error, } ) + } finally { + // delete the temporary credentials + await managementApiClient.POST('/v1/projects/{ref}/database/query', { + body: { + query: `drop user ${remoteDatabaseUser};`, + }, + params: { + path: { ref: project.id }, + }, + }) } await ctx.supabase @@ -118,9 +171,9 @@ export async function deploy( return { name: project.name, url: `https://supabase.com/dashboard/project/${project.id}`, - databaseUrl: await getDatabaseUrl({ project, hidePassword: isRedeploy }), - poolerUrl: await getPoolerUrl({ project, hidePassword: isRedeploy }), - isRedeploy, + databasePassword, + databaseUrl: getDatabaseUrl({ project, databasePassword }), + poolerUrl: getPoolerUrl({ project, databasePassword }), } } catch (error) { await ctx.supabase diff --git a/apps/deploy-worker/src/supabase/get-access-token.ts b/apps/deploy-worker/src/supabase/get-access-token.ts index a64bb593..de9aa10a 100644 --- a/apps/deploy-worker/src/supabase/get-access-token.ts +++ b/apps/deploy-worker/src/supabase/get-access-token.ts @@ -1,27 +1,28 @@ -import { DeployError } from '../error.ts' +import { DeployError, IntegrationRevokedError } from '../error.ts' import { supabaseAdmin } from './client.ts' -import type { Credentials, SupabaseClient } from './types.ts' +import type { Credentials } from './types.ts' /** * Get the access token for a given Supabase integration. */ -export async function getAccessToken( - ctx: { supabase: SupabaseClient }, - params: { - integrationId: number - credentials: Credentials +export async function getAccessToken(params: { + integrationId: number + credentialsSecretId: string +}): Promise { + const credentialsSecret = await supabaseAdmin.rpc('read_secret', { + secret_id: params.credentialsSecretId, + }) + + if (credentialsSecret.error) { + throw new DeployError('Failed to read credentials secret', { cause: credentialsSecret.error }) } -): Promise { - // if the token expires in less than 1 hour, refresh it - if (new Date(params.credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { - const refreshToken = await supabaseAdmin.rpc('read_secret', { - secret_id: params.credentials.refreshToken, - }) - if (refreshToken.error) { - throw new DeployError('Failed to read refresh token', { cause: refreshToken.error }) - } + const credentials = JSON.parse(credentialsSecret.data) as Credentials + + let accessToken = credentials.accessToken + // if the token expires in less than 1 hour, refresh it + if (new Date(credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { const now = Date.now() const newCredentialsResponse = await fetch('https://api.supabase.com/v1/oauth/token', { @@ -33,11 +34,15 @@ export async function getAccessToken( }, body: new URLSearchParams({ grant_type: 'refresh_token', - refresh_token: params.credentials.refreshToken, + refresh_token: credentials.refreshToken, }), }) if (!newCredentialsResponse.ok) { + if (newCredentialsResponse.status === 406) { + throw new IntegrationRevokedError() + } + throw new DeployError('Failed to fetch new credentials', { cause: { status: newCredentialsResponse.status, @@ -52,49 +57,25 @@ export async function getAccessToken( expires_in: number } - const expiresAt = new Date(now + newCredentials.expires_in * 1000) - - const updateRefreshToken = await supabaseAdmin.rpc('update_secret', { - secret_id: params.credentials.refreshToken, - new_secret: newCredentials.refresh_token, - }) + accessToken = newCredentials.access_token - if (updateRefreshToken.error) { - throw new DeployError('Failed to update refresh token', { cause: updateRefreshToken.error }) - } + const expiresAt = new Date(now + newCredentials.expires_in * 1000) - const updateAccessToken = await supabaseAdmin.rpc('update_secret', { - secret_id: params.credentials.accessToken, - new_secret: newCredentials.access_token, + const updateCredentialsSecret = await supabaseAdmin.rpc('update_secret', { + secret_id: params.credentialsSecretId, + new_secret: JSON.stringify({ + accessToken: newCredentials.access_token, + expiresAt: expiresAt.toISOString(), + refreshToken: newCredentials.refresh_token, + }), }) - if (updateAccessToken.error) { - throw new DeployError('Failed to update access token', { cause: updateAccessToken.error }) - } - - const updateIntegration = await ctx.supabase - .from('deployment_provider_integrations') - .update({ - credentials: { - accessToken: params.credentials.accessToken, - expiresAt: expiresAt.toISOString(), - refreshToken: params.credentials.refreshToken, - }, + if (updateCredentialsSecret.error) { + throw new DeployError('Failed to update credentials secret', { + cause: updateCredentialsSecret.error, }) - .eq('id', params.integrationId) - - if (updateIntegration.error) { - throw new DeployError('Failed to update integration', { cause: updateIntegration.error }) } } - const accessToken = await supabaseAdmin.rpc('read_secret', { - secret_id: params.credentials.accessToken, - }) - - if (accessToken.error) { - throw new DeployError('Failed to read access token', { cause: accessToken.error }) - } - - return accessToken.data + return accessToken } diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/apps/deploy-worker/src/supabase/get-database-url.ts index 32dc0aee..25e1ace8 100644 --- a/apps/deploy-worker/src/supabase/get-database-url.ts +++ b/apps/deploy-worker/src/supabase/get-database-url.ts @@ -1,55 +1,29 @@ -import { DeployError } from '../error.ts' -import { supabaseAdmin } from './client.ts' import type { SupabaseProviderMetadata } from './types.ts' /** * Get the direct database url for a given Supabase project. */ -export async function getDatabaseUrl(params: { +export function getDatabaseUrl(params: { project: SupabaseProviderMetadata['project'] - hidePassword?: boolean + databaseUser?: string + databasePassword?: string }) { - let password = '[YOUR-PASSWORD]' - if (!params.hidePassword) { - const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { - secret_id: params.project.databasePasswordSecretId, - }) - - if (databasePasswordSecret.error) { - throw new DeployError('Cannot read database password secret', { - cause: databasePasswordSecret.error, - }) - } - - password = databasePasswordSecret.data - } + const user = params.databaseUser ?? params.project.database.user + const password = params.databasePassword ?? '[YOUR-PASSWORD]' const { database } = params.project - return `postgresql://${database.user}:${password}@${database.host}:${database.port}/${database.name}` + return `postgresql://${user}:${password}@${database.host}:${database.port}/${database.name}` } /** * Get the pooler url for a given Supabase project. */ -export async function getPoolerUrl(params: { +export function getPoolerUrl(params: { project: SupabaseProviderMetadata['project'] - hidePassword?: boolean + databasePassword?: string }) { - let password = '[YOUR-PASSWORD]' - if (!params.hidePassword) { - const databasePasswordSecret = await supabaseAdmin.rpc('read_secret', { - secret_id: params.project.databasePasswordSecretId, - }) - - if (databasePasswordSecret.error) { - throw new DeployError('Cannot read database password secret', { - cause: databasePasswordSecret.error, - }) - } - - password = databasePasswordSecret.data - } + const password = params.databasePassword ?? '[YOUR-PASSWORD]' const { pooler } = params.project diff --git a/apps/deploy-worker/src/supabase/management-api.ts b/apps/deploy-worker/src/supabase/management-api.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/deploy-worker/src/supabase/management-api/client.ts b/apps/deploy-worker/src/supabase/management-api/client.ts index c43e62c0..bcbed483 100644 --- a/apps/deploy-worker/src/supabase/management-api/client.ts +++ b/apps/deploy-worker/src/supabase/management-api/client.ts @@ -1,11 +1,25 @@ -import createClient from 'openapi-fetch' +import createClient, { type Middleware } from 'openapi-fetch' import type { paths } from './types.ts' +import { IntegrationRevokedError } from '../../error.ts' -export const createManagementApiClient = (accessToken: string) => - createClient({ +const integrationRevokedMiddleware: Middleware = { + async onResponse({ response }) { + if (response.status === 406) { + throw new IntegrationRevokedError() + } + }, +} + +export function createManagementApiClient(accessToken: string) { + const client = createClient({ baseUrl: 'https://api.supabase.com/', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, }, }) + + client.use(integrationRevokedMiddleware) + + return client +} diff --git a/apps/deploy-worker/src/supabase/management-api/types.ts b/apps/deploy-worker/src/supabase/management-api/types.ts index 42e6310b..5652b310 100644 --- a/apps/deploy-worker/src/supabase/management-api/types.ts +++ b/apps/deploy-worker/src/supabase/management-api/types.ts @@ -671,6 +671,24 @@ export interface paths { patch?: never; trace?: never; }; + "/v1/projects/{ref}/config/storage": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** Gets project's storage config */ + get: operations["v1-get-storage-config"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** Updates project's storage config */ + patch: operations["v1-update-storage-config"]; + trace?: never; + }; "/v1/projects/{ref}/config/database/postgres": { parameters: { query?: never; @@ -1051,6 +1069,7 @@ export interface components { message: string; }; BranchResetResponse: { + workflow_run_id: string; message: string; }; V1DatabaseResponse: { @@ -1432,6 +1451,20 @@ export interface components { status: "COMING_UP" | "ACTIVE_HEALTHY" | "UNHEALTHY"; error?: string; }; + StorageFeatureImageTransformation: { + enabled: boolean; + }; + StorageFeatures: { + imageTransformation: components["schemas"]["StorageFeatureImageTransformation"]; + }; + StorageConfigResponse: { + fileSizeLimit: number; + features: components["schemas"]["StorageFeatures"]; + }; + UpdateStorageConfigBody: { + fileSizeLimit?: number; + features?: components["schemas"]["StorageFeatures"]; + }; PostgresConfigResponse: { effective_cache_size?: string; logical_decoding_work_mem?: string; @@ -3737,6 +3770,78 @@ export interface operations { }; }; }; + "v1-get-storage-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StorageConfigResponse"]; + }; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to retrieve project's storage config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; + "v1-update-storage-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Project ref */ + ref: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["UpdateStorageConfigBody"]; + }; + }; + responses: { + 200: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + 403: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Failed to update project's storage config */ + 500: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + }; + }; "v1-get-postgres-config": { parameters: { query?: never; diff --git a/apps/deploy-worker/src/supabase/revoke-integration.ts b/apps/deploy-worker/src/supabase/revoke-integration.ts new file mode 100644 index 00000000..8efcc740 --- /dev/null +++ b/apps/deploy-worker/src/supabase/revoke-integration.ts @@ -0,0 +1,34 @@ +import type { SupabaseClient } from './types.ts' +import { supabaseAdmin } from './client.ts' + +export async function revokeIntegration( + ctx: { supabase: SupabaseClient }, + params: { integrationId: number } +) { + const integration = await ctx.supabase + .from('deployment_provider_integrations') + .select('*') + .eq('id', params.integrationId) + .single() + + if (integration.error) { + throw new Error('Integration not found') + } + + const updatedIntegration = await ctx.supabase + .from('deployment_provider_integrations') + .update({ revoked_at: 'now', credentials: null }) + .eq('id', params.integrationId) + + if (updatedIntegration.error) { + throw new Error('Failed to revoke integration') + } + + const deleteSecret = await supabaseAdmin.rpc('delete_secret', { + secret_id: integration.data.credentials!, + }) + + if (deleteSecret.error) { + throw new Error('Failed to delete the integration credentials') + } +} diff --git a/apps/deploy-worker/src/supabase/types.ts b/apps/deploy-worker/src/supabase/types.ts index 6dd5ca4f..a8ec23e6 100644 --- a/apps/deploy-worker/src/supabase/types.ts +++ b/apps/deploy-worker/src/supabase/types.ts @@ -20,7 +20,6 @@ export type SupabaseProviderMetadata = { name: Project['name'] region: Project['region'] createdAt: Project['created_at'] - databasePasswordSecretId: string database: { host: NonNullable['host'] name: string diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/apps/deploy-worker/src/supabase/wait-for-health.ts index 702950cd..3eba8d27 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/apps/deploy-worker/src/supabase/wait-for-health.ts @@ -31,7 +31,7 @@ export async function waitForProjectToBeHealthy( }) } - if (project.status === 'ACTIVE_HEALTHY') { + if (project!.status === 'ACTIVE_HEALTHY') { return project } @@ -80,8 +80,8 @@ export async function waitForDatabaseToBeHealthy( }) } - const databaseService = servicesHealth.find((service) => service.name === 'db') - const poolerService = servicesHealth.find((service) => service.name === 'pooler') + const databaseService = servicesHealth!.find((service) => service.name === 'db') + const poolerService = servicesHealth!.find((service) => service.name === 'pooler') if (!databaseService) { throw new DeployError('Database service not found on Supabase for health check') diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index ffccaaed..d617176a 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -2,13 +2,20 @@ import { createClient } from '~/utils/supabase/server' import { createClient as createAdminClient } from '~/utils/supabase/admin' import { NextRequest, NextResponse } from 'next/server' +type Credentials = { + refreshToken: string + accessToken: string + expiresAt: string +} + +/** + * This route is used to handle the callback from Supabase OAuth App integration. + * It will exchange the oauth code for tokens and create or update a deployment integration against the given provider. + */ export async function GET(req: NextRequest) { - console.time('oauth callback') const supabase = createClient() - console.time('get user') const getUserResponse = await supabase.auth.getUser() - console.timeEnd('get user') // We have middleware, so this should never happen (used for type narrowing) if (getUserResponse.error) { @@ -37,7 +44,6 @@ export async function GET(req: NextRequest) { const now = Date.now() - console.time('get tokens') // get tokens const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { method: 'POST', @@ -52,7 +58,6 @@ export async function GET(req: NextRequest) { redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', }), }) - console.timeEnd('get tokens') if (!tokensResponse.ok) { return new Response('Failed to get tokens', { status: 500 }) @@ -66,7 +71,6 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } - console.time('get organizations') const organizationsResponse = await fetch('https://api.supabase.com/v1/organizations', { method: 'GET', headers: { @@ -74,7 +78,6 @@ export async function GET(req: NextRequest) { Authorization: `Bearer ${tokens.access_token}`, }, }) - console.timeEnd('get organizations') if (!organizationsResponse.ok) { return new Response('Failed to get organizations', { status: 500 }) @@ -89,73 +92,88 @@ export async function GET(req: NextRequest) { return new Response('Organization not found', { status: 404 }) } - const adminClient = createAdminClient() - - // store the tokens as secrets - const createRefreshTokenSecret = adminClient.rpc('insert_secret', { - name: `supabase_oauth_refresh_token_${organization.id}_${user.id}`, - secret: tokens.refresh_token, - }) - const createAccessTokenSecret = adminClient.rpc('insert_secret', { - name: `supabase_oauth_access_token_${organization.id}_${user.id}`, - secret: tokens.access_token, - }) - - console.time('create secrets') - const [createRefreshTokenSecretResponse, createAccessTokenSecretResponse] = await Promise.all([ - createRefreshTokenSecret, - createAccessTokenSecret, - ]) - console.timeEnd('create secrets') - - if (createRefreshTokenSecretResponse.error) { - return new Response('Failed to store refresh token as secret', { status: 500 }) - } - - if (createAccessTokenSecretResponse.error) { - return new Response('Failed to store access token as secret', { status: 500 }) - } - - console.time('get deployment provider') // store the credentials and relevant metadata const getDeploymentProviderResponse = await supabase .from('deployment_providers') .select('id') .eq('name', 'Supabase') .single() - console.timeEnd('get deployment provider') if (getDeploymentProviderResponse.error) { return new Response('Failed to get deployment provider', { status: 500 }) } - console.time('create integration') - const createIntegrationResponse = await supabase + // check if an existing revoked integration exists with the same organization id + const getRevokedIntegrationsResponse = await supabase .from('deployment_provider_integrations') - .insert({ - deployment_provider_id: getDeploymentProviderResponse.data.id, - credentials: { - accessToken: createAccessTokenSecretResponse.data, - expiresAt: new Date(now + tokens.expires_in * 1000).toISOString(), - refreshToken: createRefreshTokenSecretResponse.data, - }, - scope: { - organizationId: organization.id, - }, - }) - .select('id') - .single() - console.timeEnd('create integration') + .select('id,scope') + .eq('deployment_provider_id', getDeploymentProviderResponse.data.id) + .not('revoked_at', 'is', null) - if (createIntegrationResponse.error) { - return new Response('Failed to create integration', { status: 500 }) + if (getRevokedIntegrationsResponse.error) { + return new Response('Failed to get revoked integrations', { status: 500 }) } - const params = new URLSearchParams({ - integration: createIntegrationResponse.data.id.toString(), + const revokedIntegration = getRevokedIntegrationsResponse.data.find( + (ri) => (ri.scope as { organizationId: string }).organizationId === organization.id + ) + + const adminClient = createAdminClient() + + // store the tokens as secret + const credentialsSecret = await adminClient.rpc('insert_secret', { + name: `oauth_credentials_supabase_${organization.id}_${user.id}`, + secret: JSON.stringify({ + accessToken: tokens.access_token, + expiresAt: new Date(now + tokens.expires_in * 1000).toISOString(), + refreshToken: tokens.refresh_token, + }), }) - console.timeEnd('oauth callback') + if (credentialsSecret.error) { + return new Response('Failed to store the integration credentials as secret', { status: 500 }) + } + + let integrationId: number + + // if an existing revoked integration exists, update the tokens and cancel the revokation + if (revokedIntegration) { + const updateIntegrationResponse = await supabase + .from('deployment_provider_integrations') + .update({ + credentials: credentialsSecret.data, + revoked_at: null, + }) + .eq('id', revokedIntegration.id) + + if (updateIntegrationResponse.error) { + return new Response('Failed to update integration', { status: 500 }) + } + + integrationId = revokedIntegration.id + } else { + const createIntegrationResponse = await supabase + .from('deployment_provider_integrations') + .insert({ + deployment_provider_id: getDeploymentProviderResponse.data.id, + credentials: credentialsSecret.data, + scope: { + organizationId: organization.id, + }, + }) + .select('id') + .single() + + if (createIntegrationResponse.error) { + return new Response('Failed to create integration', { status: 500 }) + } + + integrationId = createIntegrationResponse.data.id + } + + const params = new URLSearchParams({ + integration: integrationId.toString(), + }) return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) } diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index daedee6f..e2f3b442 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -8,6 +8,14 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/u import { createClient } from '~/utils/supabase/client' import { Loader2 } from 'lucide-react' import { ParticlesBackground } from '~/components/particles-background' +import { getOauthUrl } from '~/lib/util' + +class IntegrationRevokedError extends Error { + constructor() { + super('The integration is no longer active. Please re-authorize the integration.') + this.name = 'IntegrationRevokedError' + } +} export default function Page() { const params = useParams<{ databaseId: string }>() @@ -46,15 +54,20 @@ export default function Page() { }) if (!response.ok) { - throw new Error(await response.text()) + if (response.status === 406) { + throw new IntegrationRevokedError() + } else { + throw new Error(await response.text()) + } } return (await response.json()) as { project: { name: string url: string + databasePassword: string | undefined databaseUrl: string - isRedeploy: boolean + poolerUrl: string } } }, @@ -70,6 +83,11 @@ export default function Page() { router.push(url.toString()) }, onError(error) { + if (error instanceof IntegrationRevokedError) { + router.push(getOauthUrl({ databaseId: params.databaseId })) + return + } + const searchParams = new URLSearchParams({ event: 'deploy.failure', error: error.message, diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index c30adfd2..0beddf44 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -11,9 +11,9 @@ export function DeploySuccessDialog() { const [project, setProject] = useState<{ name: string url: string + databasePassword: string | undefined databaseUrl: string poolerUrl: string - isRedeploy: boolean } | null>(null) const [open, setOpen] = useState(false) useEffect(() => { @@ -30,7 +30,7 @@ export function DeploySuccessDialog() { return null } - const deployText = project.isRedeploy ? 'redeployed' : 'deployed' + const deployText = project.databasePassword ? 'deployed' : 'redeployed' return ( @@ -55,13 +55,16 @@ export function DeploySuccessDialog() {

- {project.isRedeploy ? null : ( - - {/* eslint-disable-next-line react/no-unescaped-entities */} - Important: Please save your database password securely as it won't be displayed - again. - - )} + {project.databasePassword ? ( + <> + + + {/* eslint-disable-next-line react/no-unescaped-entities */} + Important: Please save your database password securely as it won't be displayed + again. + + + ) : null}

diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index c99c6abb..a883a0f1 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -553,12 +553,13 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { setIsDeploying(true) const supabase = createClient() - // check existing integration, we currently assume a single integration per user and provider + // check existing integration, we currently assume a single active integration per user and provider // later we will allow for multiple integrations per provider with different scopes const { data: integration, error: integrationError } = await supabase .from('deployment_provider_integrations') .select('id, deployment_providers!inner(name)') .eq('deployment_providers.name', 'Supabase') + .is('revoked_at', null) .maybeSingle() if (integrationError) { diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts index 1ecc9693..f57a5e9c 100644 --- a/apps/postgres-new/utils/supabase/db-types.ts +++ b/apps/postgres-new/utils/supabase/db-types.ts @@ -90,27 +90,30 @@ export type Database = { deployment_provider_integrations: { Row: { created_at: string - credentials: Json + credentials: string | null deployment_provider_id: number | null id: number + revoked_at: string | null scope: Json updated_at: string user_id: string } Insert: { created_at?: string - credentials: Json + credentials?: string | null deployment_provider_id?: number | null id?: never + revoked_at?: string | null scope?: Json updated_at?: string user_id?: string } Update: { created_at?: string - credentials?: Json + credentials?: string | null deployment_provider_id?: number | null id?: never + revoked_at?: string | null scope?: Json updated_at?: string user_id?: string diff --git a/package-lock.json b/package-lock.json index ba43df1e..28243adf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -89,14 +89,14 @@ "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", - "openapi-fetch": "^0.12.2", + "openapi-fetch": "^0.13.0", "zod": "^3.23.8" }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", "@types/debug": "^4.1.12", "@types/node": "^22.5.4", - "openapi-typescript": "^7.4.1", + "openapi-typescript": "^7.4.2", "typescript": "^5.5.4" } }, @@ -12073,12 +12073,12 @@ "license": "Apache-2.0" }, "node_modules/openapi-fetch": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.12.2.tgz", - "integrity": "sha512-ctMQ4LkkSWfIDUMuf1SYuPMsQ7ePcWAkYaMPW1lCDdk4WlV3Vulq1zoyGrwnFVvrBs5t7OOqNF+EKa8SAaovEA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.13.0.tgz", + "integrity": "sha512-6Nlf/BDbtyHwHdNrLPUiyt4CZMzL3ZyAt55yWH8W7+Z+8aYWnvca4uZHQHXViy8KcnCMqAhLM/bifh2Yjjkf6w==", "license": "MIT", "dependencies": { - "openapi-typescript-helpers": "^0.0.13" + "openapi-typescript-helpers": "^0.0.15" } }, "node_modules/openapi-types": { @@ -12088,9 +12088,9 @@ "license": "MIT" }, "node_modules/openapi-typescript": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.4.1.tgz", - "integrity": "sha512-HrRoWveViADezHCNgQqZmPKmQ74q7nuH/yg9ursFucZaYQNUqsX38fE/V2sKBHVM+pws4tAHpuh/ext2UJ/AoQ==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.4.2.tgz", + "integrity": "sha512-SvhmSTItcEAdDUcz+wzrcg6OENpMRkHqqY2hZB01FT+NOfgLcZ1B1ML6vcQrnipONHtG9AQELiKHgGTjpNGjiQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12109,9 +12109,9 @@ } }, "node_modules/openapi-typescript-helpers": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.13.tgz", - "integrity": "sha512-z44WK2e7ygW3aUtAtiurfEACohf/Qt9g6BsejmIYgEoY4REHeRzgFJmO3ium0libsuzPc145I+8lE9aiiZrQvQ==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz", + "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==", "license": "MIT" }, "node_modules/openapi-typescript/node_modules/supports-color": { diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index 0958281d..86a7c890 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -20,7 +20,8 @@ create table deployment_provider_integrations ( user_id uuid not null references auth.users(id) default auth.uid(), deployment_provider_id bigint references deployment_providers(id), scope jsonb not null default '{}'::jsonb, - credentials jsonb not null, + credentials uuid references vault.secrets(id) on delete set null, + revoked_at timestamptz, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique(user_id, deployment_provider_id, scope) From 52810101d9c45646723c533ade38ff04fdb097ee Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 31 Oct 2024 15:22:49 +0100 Subject: [PATCH 31/59] use quotes dammit --- apps/deploy-worker/src/supabase/deploy.ts | 38 +++++++++++++------ .../src/supabase/get-database-url.ts | 6 ++- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index 8fe4733d..f06eb479 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -100,11 +100,11 @@ export async function deploy( const project = (deployedDatabase.data.provider_metadata as SupabaseProviderMetadata).project // create temporary credentials to restore the Supabase database - const remoteDatabaseUser = `db-build-${params.databaseId}` + const remoteDatabaseUser = `db_build_${generatePassword()}` const remoteDatabasePassword = generatePassword() - await managementApiClient.POST('/v1/projects/{ref}/database/query', { + const createUserResponse = await managementApiClient.POST('/v1/projects/{ref}/database/query', { body: { - query: `create user ${remoteDatabaseUser} with password '${remoteDatabasePassword}' in role postgres;`, + query: `create user "${remoteDatabaseUser}" with password '${remoteDatabasePassword}' in role postgres`, }, params: { path: { @@ -112,6 +112,13 @@ export async function deploy( }, }, }) + + if (createUserResponse.error) { + throw new DeployError('Cannot create temporary role for deployment', { + cause: createUserResponse.error, + }) + } + const remoteDatabaseUrl = getDatabaseUrl({ project, databaseUser: remoteDatabaseUser, @@ -151,14 +158,23 @@ export async function deploy( ) } finally { // delete the temporary credentials - await managementApiClient.POST('/v1/projects/{ref}/database/query', { - body: { - query: `drop user ${remoteDatabaseUser};`, - }, - params: { - path: { ref: project.id }, - }, - }) + const deleteUserResponse = await managementApiClient.POST( + '/v1/projects/{ref}/database/query', + { + body: { + query: `drop user "${remoteDatabaseUser}";`, + }, + params: { + path: { ref: project.id }, + }, + } + ) + + if (deleteUserResponse.error) { + throw new DeployError('Cannot delete temporary role for deployment', { + cause: deleteUserResponse.error, + }) + } } await ctx.supabase diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/apps/deploy-worker/src/supabase/get-database-url.ts index 25e1ace8..8adc6328 100644 --- a/apps/deploy-worker/src/supabase/get-database-url.ts +++ b/apps/deploy-worker/src/supabase/get-database-url.ts @@ -21,11 +21,15 @@ export function getDatabaseUrl(params: { */ export function getPoolerUrl(params: { project: SupabaseProviderMetadata['project'] + databaseUser?: string databasePassword?: string }) { + const user = params.databaseUser + ? params.project.pooler.user.replace('postgres', params.databaseUser) + : params.project.pooler.user const password = params.databasePassword ?? '[YOUR-PASSWORD]' const { pooler } = params.project - return `postgresql://${pooler.user}:${password}@${pooler.host}:${pooler.port}/${pooler.name}` + return `postgresql://${user}:${password}@${pooler.host}:${pooler.port}/${pooler.name}` } From d7cdcecebc680735e3557141f4ea5d26d5d84e50 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 31 Oct 2024 15:44:49 +0100 Subject: [PATCH 32/59] ip infos --- .../components/copyable-field.tsx | 4 +-- .../components/deploy-success-dialog.tsx | 30 ++++++++++++---- apps/postgres-new/components/ui/badge.tsx | 36 +++++++++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 apps/postgres-new/components/ui/badge.tsx diff --git a/apps/postgres-new/components/copyable-field.tsx b/apps/postgres-new/components/copyable-field.tsx index 1deb03e0..f801a21e 100644 --- a/apps/postgres-new/components/copyable-field.tsx +++ b/apps/postgres-new/components/copyable-field.tsx @@ -1,10 +1,10 @@ import { CopyIcon } from 'lucide-react' -import { useState } from 'react' +import { type ReactNode, useState } from 'react' import { Button } from '~/components/ui/button' import { Input } from '~/components/ui/input' import { Label } from '~/components/ui/label' -export function CopyableField(props: { label?: string; value: string; disableCopy?: boolean }) { +export function CopyableField(props: { label?: ReactNode; value: string; disableCopy?: boolean }) { return (
{props.label && } diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index 0beddf44..7b1a5f96 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation' import { CopyableField } from './copyable-field' import Link from 'next/link' import { useEffect, useState } from 'react' +import { Badge } from './ui/badge' export function DeploySuccessDialog() { const router = useRouter() @@ -39,10 +40,9 @@ export function DeploySuccessDialog() { Database {deployText}
-
+

- Your database has been {deployText} to the Supabase project: -
+ Database {deployText} to the Supabase project{' '}

-

- - +

+ + Database Connection URL IPv6 + + } + value={project.databaseUrl} + /> + + Pooler Connection URL{' '} + + IPv4 + IPv6 + + + } + value={project.poolerUrl} + /> {project.databasePassword ? ( <> diff --git a/apps/postgres-new/components/ui/badge.tsx b/apps/postgres-new/components/ui/badge.tsx new file mode 100644 index 00000000..9b213de3 --- /dev/null +++ b/apps/postgres-new/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "~/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +

+ ) +} + +export { Badge, badgeVariants } From 8c5f14c3a509bb22178bb3c9f7802cd4c2fbf397 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 31 Oct 2024 15:55:04 +0100 Subject: [PATCH 33/59] change wording --- .../components/deploy-success-dialog.tsx | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index 7b1a5f96..64021980 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -42,7 +42,7 @@ export function DeploySuccessDialog() {

- Database {deployText} to the Supabase project{' '} + Database {deployText} to your Supabase project{' '} - Database Connection URL IPv6 + Database Connection URL{' '} + + IPv6 + } value={project.databaseUrl} @@ -66,8 +69,12 @@ export function DeploySuccessDialog() { <> Pooler Connection URL{' '} - IPv4 - IPv6 + + IPv4 + + + IPv6 + } @@ -76,13 +83,27 @@ export function DeploySuccessDialog() { {project.databasePassword ? ( <> - + {/* eslint-disable-next-line react/no-unescaped-entities */} - Important: Please save your database password securely as it won't be displayed - again. + Please{' '} + + save your database password securely + {' '} + as it won't be displayed again. ) : null} + + You can change your password and learn more about your connection strings in your{' '} + + database settings + +

From 50fa9ab29c540db6114920517dcd254288815d90 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Thu, 31 Oct 2024 16:43:59 +0100 Subject: [PATCH 34/59] fix delete secret --- supabase/migrations/20241003131953_deployment.sql | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index 86a7c890..ffe27468 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -190,15 +190,23 @@ end; $$; create function delete_secret(secret_id uuid) -returns text +returns bigint language plpgsql security definer set search_path = public as $$ +declare + deleted_count bigint; begin if current_setting('role') != 'service_role' then raise exception 'authentication required'; end if; - return delete from vault.decrypted_secrets where id = secret_id; + with deleted as ( + delete from vault.secrets where id = secret_id + returning * + ) + select count(*) into deleted_count from deleted; + + return deleted_count; end; $$; From 9c593ec01360ddc45e53f9c60196c7abb6a49e79 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 1 Nov 2024 08:52:30 +0100 Subject: [PATCH 35/59] fix lint --- apps/postgres-new/components/deploy-success-dialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy-success-dialog.tsx index 64021980..e9192d8d 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy-success-dialog.tsx @@ -84,11 +84,11 @@ export function DeploySuccessDialog() { <> - {/* eslint-disable-next-line react/no-unescaped-entities */} Please{' '} save your database password securely {' '} + {/* eslint-disable-next-line react/no-unescaped-entities */} as it won't be displayed again. From 0fdf79ac1a0840294b6d811e3ce1e4ec96d959b9 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 30 Oct 2024 15:46:37 -0600 Subject: [PATCH 36/59] wip: deploy dialogs --- apps/deploy-worker/.env.example | 5 +- .../src/supabase/create-deployed-database.ts | 4 +- apps/deploy-worker/src/supabase/deploy.ts | 2 +- .../src/supabase/get-access-token.ts | 27 ++-- .../src/supabase/management-api/client.ts | 2 +- apps/deploy-worker/src/supabase/types.ts | 3 + apps/postgres-new/.env.example | 1 + apps/postgres-new/app/(main)/db/[id]/page.tsx | 4 +- .../app/api/oauth/supabase/callback/route.ts | 48 +++--- .../components/deploy/deploy-dialog.tsx | 25 +++ .../{ => deploy}/deploy-failure-dialog.tsx | 2 +- .../{ => deploy}/deploy-success-dialog.tsx | 13 +- .../components/deploy/integration-dialog.tsx | 32 ++++ .../{ => deploy}/redeploy-alert-dialog.tsx | 0 apps/postgres-new/components/sidebar.tsx | 147 ++++++------------ .../data/integrations/integration-query.ts | 38 +++++ apps/postgres-new/lib/util.ts | 2 +- 17 files changed, 207 insertions(+), 148 deletions(-) create mode 100644 apps/postgres-new/components/deploy/deploy-dialog.tsx rename apps/postgres-new/components/{ => deploy}/deploy-failure-dialog.tsx (97%) rename apps/postgres-new/components/{ => deploy}/deploy-success-dialog.tsx (92%) create mode 100644 apps/postgres-new/components/deploy/integration-dialog.tsx rename apps/postgres-new/components/{ => deploy}/redeploy-alert-dialog.tsx (100%) create mode 100644 apps/postgres-new/data/integrations/integration-query.ts diff --git a/apps/deploy-worker/.env.example b/apps/deploy-worker/.env.example index eb14de85..04ae599e 100644 --- a/apps/deploy-worker/.env.example +++ b/apps/deploy-worker/.env.example @@ -2,4 +2,7 @@ SUPABASE_ANON_KEY="" SUPABASE_OAUTH_CLIENT_ID="" SUPABASE_OAUTH_SECRET="" SUPABASE_SERVICE_ROLE_KEY="" -SUPABASE_URL="" \ No newline at end of file +SUPABASE_URL="" +SUPABASE_PLATFORM_URL="https://supabase.com" +SUPABASE_PLATFORM_API_URL="https://api.supabase.com" +SUPABASE_PLATFORM_DEPLOY_REGION="us-east-1" diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/apps/deploy-worker/src/supabase/create-deployed-database.ts index 9aeeb0c7..7c460c29 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/apps/deploy-worker/src/supabase/create-deployed-database.ts @@ -2,7 +2,7 @@ import { DeployError } from '../error.ts' import { generatePassword } from './generate-password.ts' import { getAccessToken } from './get-access-token.ts' import { createManagementApiClient } from './management-api/client.ts' -import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' +import type { Region, SupabaseClient, SupabaseProviderMetadata } from './types.ts' import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.ts' /** @@ -74,7 +74,7 @@ export async function createDeployedDatabase( db_pass: databasePassword, name: `database-build-${params.databaseId}`, organization_id: (integration.data.scope as { organizationId: string }).organizationId, - region: 'us-east-1', + region: process.env.SUPABASE_PLATFORM_DEPLOY_REGION as Region, }, } ) diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/apps/deploy-worker/src/supabase/deploy.ts index f06eb479..144547fb 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/supabase/deploy.ts @@ -186,7 +186,7 @@ export async function deploy( return { name: project.name, - url: `https://supabase.com/dashboard/project/${project.id}`, + url: `${process.env.SUPABASE_PLATFORM_URL}/dashboard/project/${project.id}`, databasePassword, databaseUrl: getDatabaseUrl({ project, databasePassword }), poolerUrl: getPoolerUrl({ project, databasePassword }), diff --git a/apps/deploy-worker/src/supabase/get-access-token.ts b/apps/deploy-worker/src/supabase/get-access-token.ts index de9aa10a..a96e6acc 100644 --- a/apps/deploy-worker/src/supabase/get-access-token.ts +++ b/apps/deploy-worker/src/supabase/get-access-token.ts @@ -25,18 +25,21 @@ export async function getAccessToken(params: { if (new Date(credentials.expiresAt) < new Date(Date.now() + 1 * 60 * 60 * 1000)) { const now = Date.now() - const newCredentialsResponse = await fetch('https://api.supabase.com/v1/oauth/token', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', - Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, - }, - body: new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: credentials.refreshToken, - }), - }) + const newCredentialsResponse = await fetch( + `${process.env.SUPABASE_PLATFORM_API_URL}/v1/oauth/token`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: credentials.refreshToken, + }), + } + ) if (!newCredentialsResponse.ok) { if (newCredentialsResponse.status === 406) { diff --git a/apps/deploy-worker/src/supabase/management-api/client.ts b/apps/deploy-worker/src/supabase/management-api/client.ts index bcbed483..a05935ff 100644 --- a/apps/deploy-worker/src/supabase/management-api/client.ts +++ b/apps/deploy-worker/src/supabase/management-api/client.ts @@ -12,7 +12,7 @@ const integrationRevokedMiddleware: Middleware = { export function createManagementApiClient(accessToken: string) { const client = createClient({ - baseUrl: 'https://api.supabase.com/', + baseUrl: process.env.SUPABASE_PLATFORM_API_URL, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, diff --git a/apps/deploy-worker/src/supabase/types.ts b/apps/deploy-worker/src/supabase/types.ts index a8ec23e6..28b6a316 100644 --- a/apps/deploy-worker/src/supabase/types.ts +++ b/apps/deploy-worker/src/supabase/types.ts @@ -13,6 +13,9 @@ type Database = Unpacked< paths['/v1/projects/{ref}/config/database/pooler']['get']['responses']['200']['content']['application/json'] > +export type Region = + paths['/v1/projects']['post']['requestBody']['content']['application/json']['region'] + export type SupabaseProviderMetadata = { project: { id: Project['id'] diff --git a/apps/postgres-new/.env.example b/apps/postgres-new/.env.example index 3a4b74fb..011123b1 100644 --- a/apps/postgres-new/.env.example +++ b/apps/postgres-new/.env.example @@ -3,6 +3,7 @@ NEXT_PUBLIC_SUPABASE_URL="" NEXT_PUBLIC_BROWSER_PROXY_DOMAIN="" NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN="" NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID="" +NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL=https://api.supabase.com OPENAI_API_KEY="" # Optional diff --git a/apps/postgres-new/app/(main)/db/[id]/page.tsx b/apps/postgres-new/app/(main)/db/[id]/page.tsx index 64fce78b..ca174576 100644 --- a/apps/postgres-new/app/(main)/db/[id]/page.tsx +++ b/apps/postgres-new/app/(main)/db/[id]/page.tsx @@ -3,8 +3,8 @@ import { useRouter } from 'next/navigation' import { useEffect } from 'react' import { useApp } from '~/components/app-provider' -import { DeployFailureDialog } from '~/components/deploy-failure-dialog' -import { DeploySuccessDialog } from '~/components/deploy-success-dialog' +import { DeployFailureDialog } from '~/components/deploy/deploy-failure-dialog' +import { DeploySuccessDialog } from '~/components/deploy/deploy-success-dialog' import Workspace from '~/components/workspace' export default function Page({ params }: { params: { id: string } }) { diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts index d617176a..89915a2f 100644 --- a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts +++ b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts @@ -45,19 +45,22 @@ export async function GET(req: NextRequest) { const now = Date.now() // get tokens - const tokensResponse = await fetch('https://api.supabase.com/v1/oauth/token', { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Accept: 'application/json', - Authorization: `Basic ${btoa(`${process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, - }, - body: new URLSearchParams({ - grant_type: 'authorization_code', - code, - redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', - }), - }) + const tokensResponse = await fetch( + `${process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL}/v1/oauth/token`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Accept: 'application/json', + Authorization: `Basic ${btoa(`${process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + code, + redirect_uri: req.nextUrl.origin + '/api/oauth/supabase/callback', + }), + } + ) if (!tokensResponse.ok) { return new Response('Failed to get tokens', { status: 500 }) @@ -71,13 +74,18 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } - const organizationsResponse = await fetch('https://api.supabase.com/v1/organizations', { - method: 'GET', - headers: { - Accept: 'application/json', - Authorization: `Bearer ${tokens.access_token}`, - }, - }) + console.log({ tokens }) + + const organizationsResponse = await fetch( + `${process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL}/v1/organizations`, + { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${tokens.access_token}`, + }, + } + ) if (!organizationsResponse.ok) { return new Response('Failed to get organizations', { status: 500 }) diff --git a/apps/postgres-new/components/deploy/deploy-dialog.tsx b/apps/postgres-new/components/deploy/deploy-dialog.tsx new file mode 100644 index 00000000..98318e38 --- /dev/null +++ b/apps/postgres-new/components/deploy/deploy-dialog.tsx @@ -0,0 +1,25 @@ +'use client' + +import { DialogProps } from '@radix-ui/react-dialog' +import { Button } from '~/components/ui/button' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' + +export type DeployDialogProps = DialogProps & { + onConfirm?: () => void +} + +export function DeployDialog({ onConfirm, ...props }: DeployDialogProps) { + return ( + + + + Deploy to Supabase +
+ +
+ +
+ +
+ ) +} diff --git a/apps/postgres-new/components/deploy-failure-dialog.tsx b/apps/postgres-new/components/deploy/deploy-failure-dialog.tsx similarity index 97% rename from apps/postgres-new/components/deploy-failure-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-failure-dialog.tsx index 4bbb6683..3ea9c531 100644 --- a/apps/postgres-new/components/deploy-failure-dialog.tsx +++ b/apps/postgres-new/components/deploy/deploy-failure-dialog.tsx @@ -1,6 +1,6 @@ 'use client' -import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' +import { Dialog, DialogContent, DialogTitle, DialogHeader } from '~/components/ui/dialog' import { useRouter } from 'next/navigation' import { useEffect, useState } from 'react' diff --git a/apps/postgres-new/components/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy/deploy-success-dialog.tsx similarity index 92% rename from apps/postgres-new/components/deploy-success-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-success-dialog.tsx index e9192d8d..d9bf46ce 100644 --- a/apps/postgres-new/components/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy/deploy-success-dialog.tsx @@ -1,11 +1,11 @@ 'use client' -import { Dialog, DialogContent, DialogTitle, DialogHeader } from './ui/dialog' -import { useRouter } from 'next/navigation' -import { CopyableField } from './copyable-field' import Link from 'next/link' +import { useRouter } from 'next/navigation' import { useEffect, useState } from 'react' -import { Badge } from './ui/badge' +import { CopyableField } from '~/components/copyable-field' +import { Badge } from '~/components/ui/badge' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' export function DeploySuccessDialog() { const router = useRouter() @@ -84,12 +84,12 @@ export function DeploySuccessDialog() { <> + {/* eslint-disable-next-line react/no-unescaped-entities */} Please{' '} save your database password securely {' '} - {/* eslint-disable-next-line react/no-unescaped-entities */} - as it won't be displayed again. + as it won't be displayed again. ) : null} @@ -103,6 +103,7 @@ export function DeploySuccessDialog() { > database settings + .

diff --git a/apps/postgres-new/components/deploy/integration-dialog.tsx b/apps/postgres-new/components/deploy/integration-dialog.tsx new file mode 100644 index 00000000..f4395f1d --- /dev/null +++ b/apps/postgres-new/components/deploy/integration-dialog.tsx @@ -0,0 +1,32 @@ +'use client' + +import { DialogProps } from '@radix-ui/react-dialog' +import { Button } from '~/components/ui/button' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' + +export type IntegrationDialogProps = DialogProps & { + onConfirm?: () => void +} + +export function IntegrationDialog({ onConfirm, ...props }: IntegrationDialogProps) { + return ( + + + + Connect Supabase +
+ +
+

+ To deploy your database, you need to connect your Supabase account. If you don't + already have a Supabase account, you can create one for free. +

+

+ Click Connect to connect your account. +

+ +
+ +
+ ) +} diff --git a/apps/postgres-new/components/redeploy-alert-dialog.tsx b/apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx similarity index 100% rename from apps/postgres-new/components/redeploy-alert-dialog.tsx rename to apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index a883a0f1..0072f71a 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -1,5 +1,6 @@ 'use client' +import { TooltipPortal } from '@radix-ui/react-tooltip' import { AnimatePresence, m } from 'framer-motion' import { ArrowLeftToLine, @@ -7,6 +8,7 @@ import { Database as DbIcon, Download, Loader, + Loader2, LogOut, MoreVertical, PackagePlus, @@ -15,7 +17,6 @@ import { RadioIcon, Trash2, Upload, - Loader2, } from 'lucide-react' import Link from 'next/link' import { useParams, useRouter } from 'next/navigation' @@ -26,14 +27,18 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '~/components/ui/tooltip import { useDatabaseDeleteMutation } from '~/data/databases/database-delete-mutation' import { useDatabaseUpdateMutation } from '~/data/databases/database-update-mutation' import { useDatabasesQuery } from '~/data/databases/databases-query' -import { useDeployWaitlistCreateMutation } from '~/data/deploy-waitlist/deploy-waitlist-create-mutation' -import { useIsOnDeployWaitlistQuery } from '~/data/deploy-waitlist/deploy-waitlist-query' +import { useDeployedDatabasesQuery } from '~/data/deployed-databases/deployed-databases-query' +import { useIntegrationQuery } from '~/data/integrations/integration-query' import { Database as LocalDatabase } from '~/lib/db' import { downloadFile, getDeployUrl, getOauthUrl, titleToKebabCase } from '~/lib/util' import { cn } from '~/lib/utils' import { useApp } from './app-provider' -import { CodeBlock } from './code-block' +import { DeployDialog } from './deploy/deploy-dialog' +import { IntegrationDialog } from './deploy/integration-dialog' +import { RedeployAlertDialog } from './deploy/redeploy-alert-dialog' +import { LiveShareIcon } from './live-share-icon' import SignInButton from './sign-in-button' +import { SupabaseIcon } from './supabase-icon' import ThemeDropdown from './theme-dropdown' import { DropdownMenu, @@ -46,12 +51,6 @@ import { DropdownMenuSubTrigger, DropdownMenuTrigger, } from './ui/dropdown-menu' -import { TooltipPortal } from '@radix-ui/react-tooltip' -import { LiveShareIcon } from './live-share-icon' -import { createClient } from '~/utils/supabase/client' -import { RedeployAlertDialog } from './redeploy-alert-dialog' -import { useDeployedDatabasesQuery } from '~/data/deployed-databases/deployed-databases-query' -import { SupabaseIcon } from './supabase-icon' type Database = LocalDatabase & { isDeployed: boolean @@ -325,13 +324,12 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { const [isPopoverOpen, setIsPopoverOpen] = useState(false) const { mutateAsync: deleteDatabase } = useDatabaseDeleteMutation() const { mutateAsync: updateDatabase } = useDatabaseUpdateMutation() + const { data: supabaseIntegration } = useIntegrationQuery('Supabase') const [isRenaming, setIsRenaming] = useState(false) - const [isDeployDialogOpen, setIsDeployDialogOpen] = useState(false) - - const { data: isOnDeployWaitlist } = useIsOnDeployWaitlistQuery() - const { mutateAsync: joinDeployWaitlist } = useDeployWaitlistCreateMutation() + const [isIntegrationDialogOpen, setIsIntegrationDialogOpen] = useState(false) + const [isDeployDialogOpen, setIsDeployDialogOpen] = useState(false) const [isRedeployAlertDialogOpen, setIsRedeployAlertDialogOpen] = useState(false) const [deployUrl, setDeployUrl] = useState(null) @@ -339,6 +337,35 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { return ( <> + { + setIsIntegrationDialogOpen(open) + }} + onConfirm={() => { + router.push(getOauthUrl({ databaseId: database.id })) + }} + /> + { + setIsDeployDialogOpen(open) + }} + onConfirm={() => { + if (!supabaseIntegration) { + setIsDeployDialogOpen(false) + setIsIntegrationDialogOpen(true) + return + } + + const deployUrl = getDeployUrl({ + databaseId: database.id, + integrationId: supabaseIntegration.id, + }) + + router.push(deployUrl) + }} + /> - { - setIsDeployDialogOpen(open) - }} - > - - - Deployments are in Private Alpha -
- -

What are deployments?

-

- Deploy your database to a serverless PGlite instance so that it can be accessed outside - the browser using any Postgres client: -

- - {`psql "postgres://postgres:@/postgres"`} - -
- - {!isOnDeployWaitlist ? ( - - ) : ( - -

🎉 You're on the waitlist!

-

We'll send you an email when you have access to deploy.

-
- )} -
-
- -
{isDeploying ? ( @@ -548,41 +522,12 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { { + onSelect={async (e) => { e.preventDefault() - setIsDeploying(true) - const supabase = createClient() - - // check existing integration, we currently assume a single active integration per user and provider - // later we will allow for multiple integrations per provider with different scopes - const { data: integration, error: integrationError } = await supabase - .from('deployment_provider_integrations') - .select('id, deployment_providers!inner(name)') - .eq('deployment_providers.name', 'Supabase') - .is('revoked_at', null) - .maybeSingle() - - if (integrationError) { - console.error(integrationError) - return - } - - if (!integration) { - router.push(getOauthUrl({ databaseId: database.id })) - return - } - - const deployUrl = getDeployUrl({ - databaseId: database.id, - integrationId: integration.id, - }) - - setDeployUrl(deployUrl) - - if (database.isDeployed) { - setIsRedeployAlertDialogOpen(true) + if (!supabaseIntegration) { + setIsIntegrationDialogOpen(true) } else { - router.push(deployUrl) + setIsDeployDialogOpen(true) } }} > diff --git a/apps/postgres-new/data/integrations/integration-query.ts b/apps/postgres-new/data/integrations/integration-query.ts new file mode 100644 index 00000000..e500f750 --- /dev/null +++ b/apps/postgres-new/data/integrations/integration-query.ts @@ -0,0 +1,38 @@ +import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { Database } from '~/utils/supabase/db-types' +import { createClient } from '~/utils/supabase/client' + +export type Integration = { + id: number + deployment_providers: { + name: string + } +} + +export const useIntegrationQuery = ( + name: string, + options: Omit, 'queryKey' | 'queryFn'> = {} +) => { + return useQuery({ + ...options, + queryKey: getIntegrationQueryKey(name), + queryFn: async () => { + const supabase = createClient() + + const { data, error } = await supabase + .from('deployment_provider_integrations') + .select('id, deployment_providers!inner(name)') + .eq('deployment_providers.name', name) + .is('revoked_at', null) + .single() + + if (error) { + throw error + } + + return data + }, + }) +} + +export const getIntegrationQueryKey = (name: string) => ['integration', name] diff --git a/apps/postgres-new/lib/util.ts b/apps/postgres-new/lib/util.ts index c2ac6b58..e7403d30 100644 --- a/apps/postgres-new/lib/util.ts +++ b/apps/postgres-new/lib/util.ts @@ -136,5 +136,5 @@ export function getOauthUrl(params: { databaseId: string }) { databaseId: params.databaseId, }), }) - return `https://api.supabase.com/v1/oauth/authorize?${oauthParams.toString()}` + return `${process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL}/v1/oauth/authorize?${oauthParams.toString()}` } From 9f7f6d62cba17880a06296286a20c7eb2800c9aa Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Thu, 7 Nov 2024 14:58:11 -0700 Subject: [PATCH 37/59] feat: more cautious redeploy dialog --- .../deploy/redeploy-alert-dialog.tsx | 49 ----------- .../components/deploy/redeploy-dialog.tsx | 83 +++++++++++++++++++ apps/postgres-new/components/sidebar.tsx | 15 ++-- 3 files changed, 92 insertions(+), 55 deletions(-) delete mode 100644 apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx create mode 100644 apps/postgres-new/components/deploy/redeploy-dialog.tsx diff --git a/apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx b/apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx deleted file mode 100644 index 9d0fe6ee..00000000 --- a/apps/postgres-new/components/deploy/redeploy-alert-dialog.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from '~/components/ui/alert-dialog' - -type RedeployAlertDialogProps = { - isOpen: boolean - onOpenChange: (open: boolean) => void - onConfirm: () => void - onCancel: () => void -} - -export function RedeployAlertDialog(props: RedeployAlertDialogProps) { - return ( - - - - Redeploy database? - - Redeploying the database will overwrite the existing deployed database with the latest - version. - - - - { - props.onCancel() - }} - > - Cancel - - { - props.onConfirm() - }} - > - Redeploy - - - - - ) -} diff --git a/apps/postgres-new/components/deploy/redeploy-dialog.tsx b/apps/postgres-new/components/deploy/redeploy-dialog.tsx new file mode 100644 index 00000000..bfb9943f --- /dev/null +++ b/apps/postgres-new/components/deploy/redeploy-dialog.tsx @@ -0,0 +1,83 @@ +import { TriangleAlert } from 'lucide-react' +import { useState } from 'react' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '~/components/ui/dialog' +import { Input } from '~/components/ui/input' +import { Database } from '~/lib/db' +import { Button } from '../ui/button' + +export type RedeployDialogProps = { + database: Database + isOpen: boolean + onOpenChange: (open: boolean) => void + onConfirm: () => void + onCancel: () => void +} + +export function RedeployDialog({ + database, + isOpen, + onOpenChange, + onConfirm, + onCancel, +}: RedeployDialogProps) { + const [confirmedValue, setConfirmedValue] = useState('') + return ( + + + + Confirm redeploy of {database.name} + +
+ + This action cannot be undone. +
+

+ Redeploying will completely overwrite the existing deployed database with the latest + version of your browser database. Existing schema and data in the deployed database + will be lost. +

+
+
+

+ Type {database.name} to confirm. +

+ setConfirmedValue(e.target.value)} + /> +
+ + + + + + + +
+ ) +} diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx index 0072f71a..49e0aa2d 100644 --- a/apps/postgres-new/components/sidebar.tsx +++ b/apps/postgres-new/components/sidebar.tsx @@ -35,7 +35,7 @@ import { cn } from '~/lib/utils' import { useApp } from './app-provider' import { DeployDialog } from './deploy/deploy-dialog' import { IntegrationDialog } from './deploy/integration-dialog' -import { RedeployAlertDialog } from './deploy/redeploy-alert-dialog' +import { RedeployDialog } from './deploy/redeploy-dialog' import { LiveShareIcon } from './live-share-icon' import SignInButton from './sign-in-button' import { SupabaseIcon } from './supabase-icon' @@ -330,7 +330,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { const [isIntegrationDialogOpen, setIsIntegrationDialogOpen] = useState(false) const [isDeployDialogOpen, setIsDeployDialogOpen] = useState(false) - const [isRedeployAlertDialogOpen, setIsRedeployAlertDialogOpen] = useState(false) + const [isRedeployDialogOpen, setIsRedeployDialogOpen] = useState(false) const [deployUrl, setDeployUrl] = useState(null) const [isDeploying, setIsDeploying] = useState(false) @@ -366,9 +366,10 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { router.push(deployUrl) }} /> - { router.push(deployUrl!) }} @@ -526,8 +527,10 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { e.preventDefault() if (!supabaseIntegration) { setIsIntegrationDialogOpen(true) - } else { + } else if (!database.isDeployed) { setIsDeployDialogOpen(true) + } else { + setIsRedeployDialogOpen(true) } }} > From 74b22f1707925a1d7c82029bf5d1269eae9ca480 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Thu, 7 Nov 2024 15:01:41 -0700 Subject: [PATCH 38/59] feat: turborepo with deploy package --- .gitignore | 1 + README.md | 59 +- apps/browser-proxy/README.md | 14 +- apps/deploy-worker/README.md | 13 +- apps/deploy-worker/package.json | 9 +- apps/deploy-worker/src/debug.ts | 3 - apps/deploy-worker/src/index.ts | 14 +- apps/deploy-worker/tsconfig.json | 1 - apps/{postgres-new => web}/.env.example | 4 +- apps/{postgres-new => web}/README.md | 37 +- .../app/(main)/db/[id]/page.tsx | 0 .../app/(main)/layout.tsx | 0 .../{postgres-new => web}/app/(main)/page.tsx | 0 .../app/api/chat/route.ts | 0 .../app/api/oauth/supabase/callback/route.ts | 0 .../api/oauth/supabase/organizations/route.ts | 6 + apps/{postgres-new => web}/app/apple-icon.png | Bin .../app/deploy/[databaseId]/page.tsx | 0 .../{postgres-new => web}/app/export/page.tsx | 0 apps/{postgres-new => web}/app/favicon.ico | Bin apps/{postgres-new => web}/app/globals.css | 0 apps/{postgres-new => web}/app/icon.svg | 0 .../{postgres-new => web}/app/import/page.tsx | 0 apps/{postgres-new => web}/app/layout.tsx | 0 .../app/opengraph-image.png | Bin .../assets/github-icon.tsx | 0 apps/{postgres-new => web}/components.json | 0 .../ai-icon-animation-style.module.css | 0 .../ai-icon-animation/ai-icon-animation.tsx | 0 .../components/ai-icon-animation/index.tsx | 0 .../components/app-provider.tsx | 0 .../components/chat-message.tsx | 0 .../{postgres-new => web}/components/chat.tsx | 0 .../components/code-accordion.tsx | 0 .../components/code-block.tsx | 0 .../components/copyable-field.tsx | 0 .../components/deploy/deploy-dialog.tsx | 0 .../deploy/deploy-failure-dialog.tsx | 0 .../deploy/deploy-success-dialog.tsx | 0 .../components/deploy/integration-dialog.tsx | 0 .../components/deploy/redeploy-dialog.tsx | 0 .../components/framer-features.ts | 0 apps/{postgres-new => web}/components/ide.tsx | 0 .../components/layout.tsx | 0 .../components/live-share-icon.tsx | 0 .../components/markdown-accordion.tsx | 0 .../components/particles-background.tsx | 0 .../components/providers.tsx | 0 .../components/schema/graph.tsx | 0 .../components/schema/legend.tsx | 0 .../components/schema/table-graph.tsx | 0 .../components/schema/table-node.tsx | 0 .../components/sidebar.tsx | 0 .../components/sign-in-button.tsx | 0 .../components/supabase-icon.tsx | 0 .../components/theme-dropdown.tsx | 0 .../components/theme-provider.tsx | 0 .../components/tools/conversation-rename.tsx | 0 .../components/tools/csv-export.tsx | 0 .../components/tools/csv-import.tsx | 0 .../components/tools/csv-request.tsx | 0 .../components/tools/executed-sql.tsx | 0 .../components/tools/generated-chart.tsx | 0 .../components/tools/generated-embedding.tsx | 0 .../components/tools/index.tsx | 0 .../components/ui/accordion.tsx | 0 .../components/ui/alert-dialog.tsx | 0 .../components/ui/badge.tsx | 0 .../components/ui/button.tsx | 0 .../components/ui/dialog.tsx | 0 .../components/ui/dropdown-menu.tsx | 0 .../components/ui/input.tsx | 0 .../components/ui/label.tsx | 0 .../components/ui/popover.tsx | 0 .../components/ui/progress.tsx | 0 .../components/ui/skeleton.tsx | 0 .../components/ui/tabs.tsx | 0 .../components/ui/tooltip.tsx | 0 .../components/workspace.tsx | 0 .../config/default-colors.js | 0 .../config/tailwind.config.js | 0 .../{postgres-new => web}/config/ui.config.js | 0 .../databases/database-create-mutation.ts | 0 .../databases/database-delete-mutation.ts | 0 .../data/databases/database-query.ts | 0 .../databases/database-update-mutation.ts | 0 .../data/databases/databases-query.ts | 0 .../deploy-waitlist-create-mutation.ts | 0 .../deploy-waitlist/deploy-waitlist-query.ts | 0 .../deployed-databases-query.ts | 0 .../data/integrations/integration-query.ts | 0 .../data/messages/message-create-mutation.ts | 0 .../data/messages/messages-query.ts | 0 .../data/tables/tables-query.ts | 0 apps/{postgres-new => web}/docker-compose.yml | 0 apps/{postgres-new => web}/global.d.ts | 0 apps/{postgres-new => web}/lib/db/index.ts | 0 apps/{postgres-new => web}/lib/db/worker.ts | 0 apps/{postgres-new => web}/lib/embed/index.ts | 0 .../{postgres-new => web}/lib/embed/worker.ts | 0 apps/{postgres-new => web}/lib/files.ts | 0 apps/{postgres-new => web}/lib/hooks.ts | 0 apps/{postgres-new => web}/lib/indexed-db.ts | 0 .../{postgres-new => web}/lib/pg-wire-util.ts | 0 apps/{postgres-new => web}/lib/schema.ts | 0 .../lib/smooth-scroller.ts | 0 apps/{postgres-new => web}/lib/sql-util.ts | 0 apps/{postgres-new => web}/lib/streams.ts | 0 apps/{postgres-new => web}/lib/tools.ts | 0 .../lib/use-breakpoint.ts | 0 apps/{postgres-new => web}/lib/util.ts | 0 apps/{postgres-new => web}/lib/utils.ts | 0 .../lib/websocket-protocol.ts | 0 apps/{postgres-new => web}/middleware.ts | 0 apps/{postgres-new => web}/next.config.mjs | 0 apps/{postgres-new => web}/package.json | 4 +- .../polyfills/readable-stream.ts | 0 apps/{postgres-new => web}/postcss.config.mjs | 0 .../public/fonts/custom/CustomFont-Black.woff | Bin .../fonts/custom/CustomFont-Black.woff2 | Bin .../fonts/custom/CustomFont-BlackItalic.woff | Bin .../fonts/custom/CustomFont-BlackItalic.woff2 | Bin .../public/fonts/custom/CustomFont-Bold.woff | Bin .../public/fonts/custom/CustomFont-Bold.woff2 | Bin .../fonts/custom/CustomFont-BoldItalic.woff | Bin .../fonts/custom/CustomFont-BoldItalic.woff2 | Bin .../public/fonts/custom/CustomFont-Book.woff | Bin .../public/fonts/custom/CustomFont-Book.woff2 | Bin .../fonts/custom/CustomFont-BookItalic.woff | Bin .../fonts/custom/CustomFont-BookItalic.woff2 | Bin .../fonts/custom/CustomFont-Medium.woff | Bin .../fonts/custom/CustomFont-Medium.woff2 | Bin .../source-code-pro/SourceCodePro-Regular.eot | Bin .../source-code-pro/SourceCodePro-Regular.svg | 0 .../source-code-pro/SourceCodePro-Regular.ttf | Bin .../SourceCodePro-Regular.woff | Bin .../SourceCodePro-Regular.woff2 | Bin apps/{postgres-new => web}/tailwind.config.ts | 0 apps/{postgres-new => web}/tsconfig.json | 0 .../types/highlightjs-curl.d.ts | 0 .../utils/supabase/admin.ts | 0 .../utils/supabase/client.ts | 0 .../utils/supabase/db-types.ts | 0 .../utils/supabase/middleware.ts | 0 .../utils/supabase/server.ts | 0 package-lock.json | 1391 ++++++++++++++++- package.json | 9 +- packages/deploy/package.json | 30 + .../deploy}/src/error.ts | 0 packages/deploy/src/index.ts | 1 + .../deploy}/src/supabase/client.ts | 2 +- .../src/supabase/create-deployed-database.ts | 12 +- .../deploy}/src/supabase/database-types.ts | 0 .../deploy}/src/supabase/deploy.ts | 14 +- .../deploy}/src/supabase/generate-password.ts | 0 .../deploy}/src/supabase/get-access-token.ts | 6 +- .../deploy}/src/supabase/get-database-url.ts | 2 +- packages/deploy/src/supabase/index.ts | 8 + .../src/supabase/management-api/client.ts | 4 +- .../src/supabase/management-api/types.ts | 0 .../src/supabase/revoke-integration.ts | 4 +- .../deploy}/src/supabase/types.ts | 6 +- .../deploy}/src/supabase/wait-for-health.ts | 4 +- packages/deploy/tsconfig.json | 8 + packages/deploy/tsup.config.ts | 13 + turbo.json | 23 + 166 files changed, 1543 insertions(+), 159 deletions(-) delete mode 100644 apps/deploy-worker/src/debug.ts rename apps/{postgres-new => web}/.env.example (85%) rename apps/{postgres-new => web}/README.md (65%) rename apps/{postgres-new => web}/app/(main)/db/[id]/page.tsx (100%) rename apps/{postgres-new => web}/app/(main)/layout.tsx (100%) rename apps/{postgres-new => web}/app/(main)/page.tsx (100%) rename apps/{postgres-new => web}/app/api/chat/route.ts (100%) rename apps/{postgres-new => web}/app/api/oauth/supabase/callback/route.ts (100%) create mode 100644 apps/web/app/api/oauth/supabase/organizations/route.ts rename apps/{postgres-new => web}/app/apple-icon.png (100%) rename apps/{postgres-new => web}/app/deploy/[databaseId]/page.tsx (100%) rename apps/{postgres-new => web}/app/export/page.tsx (100%) rename apps/{postgres-new => web}/app/favicon.ico (100%) rename apps/{postgres-new => web}/app/globals.css (100%) rename apps/{postgres-new => web}/app/icon.svg (100%) rename apps/{postgres-new => web}/app/import/page.tsx (100%) rename apps/{postgres-new => web}/app/layout.tsx (100%) rename apps/{postgres-new => web}/app/opengraph-image.png (100%) rename apps/{postgres-new => web}/assets/github-icon.tsx (100%) rename apps/{postgres-new => web}/components.json (100%) rename apps/{postgres-new => web}/components/ai-icon-animation/ai-icon-animation-style.module.css (100%) rename apps/{postgres-new => web}/components/ai-icon-animation/ai-icon-animation.tsx (100%) rename apps/{postgres-new => web}/components/ai-icon-animation/index.tsx (100%) rename apps/{postgres-new => web}/components/app-provider.tsx (100%) rename apps/{postgres-new => web}/components/chat-message.tsx (100%) rename apps/{postgres-new => web}/components/chat.tsx (100%) rename apps/{postgres-new => web}/components/code-accordion.tsx (100%) rename apps/{postgres-new => web}/components/code-block.tsx (100%) rename apps/{postgres-new => web}/components/copyable-field.tsx (100%) rename apps/{postgres-new => web}/components/deploy/deploy-dialog.tsx (100%) rename apps/{postgres-new => web}/components/deploy/deploy-failure-dialog.tsx (100%) rename apps/{postgres-new => web}/components/deploy/deploy-success-dialog.tsx (100%) rename apps/{postgres-new => web}/components/deploy/integration-dialog.tsx (100%) rename apps/{postgres-new => web}/components/deploy/redeploy-dialog.tsx (100%) rename apps/{postgres-new => web}/components/framer-features.ts (100%) rename apps/{postgres-new => web}/components/ide.tsx (100%) rename apps/{postgres-new => web}/components/layout.tsx (100%) rename apps/{postgres-new => web}/components/live-share-icon.tsx (100%) rename apps/{postgres-new => web}/components/markdown-accordion.tsx (100%) rename apps/{postgres-new => web}/components/particles-background.tsx (100%) rename apps/{postgres-new => web}/components/providers.tsx (100%) rename apps/{postgres-new => web}/components/schema/graph.tsx (100%) rename apps/{postgres-new => web}/components/schema/legend.tsx (100%) rename apps/{postgres-new => web}/components/schema/table-graph.tsx (100%) rename apps/{postgres-new => web}/components/schema/table-node.tsx (100%) rename apps/{postgres-new => web}/components/sidebar.tsx (100%) rename apps/{postgres-new => web}/components/sign-in-button.tsx (100%) rename apps/{postgres-new => web}/components/supabase-icon.tsx (100%) rename apps/{postgres-new => web}/components/theme-dropdown.tsx (100%) rename apps/{postgres-new => web}/components/theme-provider.tsx (100%) rename apps/{postgres-new => web}/components/tools/conversation-rename.tsx (100%) rename apps/{postgres-new => web}/components/tools/csv-export.tsx (100%) rename apps/{postgres-new => web}/components/tools/csv-import.tsx (100%) rename apps/{postgres-new => web}/components/tools/csv-request.tsx (100%) rename apps/{postgres-new => web}/components/tools/executed-sql.tsx (100%) rename apps/{postgres-new => web}/components/tools/generated-chart.tsx (100%) rename apps/{postgres-new => web}/components/tools/generated-embedding.tsx (100%) rename apps/{postgres-new => web}/components/tools/index.tsx (100%) rename apps/{postgres-new => web}/components/ui/accordion.tsx (100%) rename apps/{postgres-new => web}/components/ui/alert-dialog.tsx (100%) rename apps/{postgres-new => web}/components/ui/badge.tsx (100%) rename apps/{postgres-new => web}/components/ui/button.tsx (100%) rename apps/{postgres-new => web}/components/ui/dialog.tsx (100%) rename apps/{postgres-new => web}/components/ui/dropdown-menu.tsx (100%) rename apps/{postgres-new => web}/components/ui/input.tsx (100%) rename apps/{postgres-new => web}/components/ui/label.tsx (100%) rename apps/{postgres-new => web}/components/ui/popover.tsx (100%) rename apps/{postgres-new => web}/components/ui/progress.tsx (100%) rename apps/{postgres-new => web}/components/ui/skeleton.tsx (100%) rename apps/{postgres-new => web}/components/ui/tabs.tsx (100%) rename apps/{postgres-new => web}/components/ui/tooltip.tsx (100%) rename apps/{postgres-new => web}/components/workspace.tsx (100%) rename apps/{postgres-new => web}/config/default-colors.js (100%) rename apps/{postgres-new => web}/config/tailwind.config.js (100%) rename apps/{postgres-new => web}/config/ui.config.js (100%) rename apps/{postgres-new => web}/data/databases/database-create-mutation.ts (100%) rename apps/{postgres-new => web}/data/databases/database-delete-mutation.ts (100%) rename apps/{postgres-new => web}/data/databases/database-query.ts (100%) rename apps/{postgres-new => web}/data/databases/database-update-mutation.ts (100%) rename apps/{postgres-new => web}/data/databases/databases-query.ts (100%) rename apps/{postgres-new => web}/data/deploy-waitlist/deploy-waitlist-create-mutation.ts (100%) rename apps/{postgres-new => web}/data/deploy-waitlist/deploy-waitlist-query.ts (100%) rename apps/{postgres-new => web}/data/deployed-databases/deployed-databases-query.ts (100%) rename apps/{postgres-new => web}/data/integrations/integration-query.ts (100%) rename apps/{postgres-new => web}/data/messages/message-create-mutation.ts (100%) rename apps/{postgres-new => web}/data/messages/messages-query.ts (100%) rename apps/{postgres-new => web}/data/tables/tables-query.ts (100%) rename apps/{postgres-new => web}/docker-compose.yml (100%) rename apps/{postgres-new => web}/global.d.ts (100%) rename apps/{postgres-new => web}/lib/db/index.ts (100%) rename apps/{postgres-new => web}/lib/db/worker.ts (100%) rename apps/{postgres-new => web}/lib/embed/index.ts (100%) rename apps/{postgres-new => web}/lib/embed/worker.ts (100%) rename apps/{postgres-new => web}/lib/files.ts (100%) rename apps/{postgres-new => web}/lib/hooks.ts (100%) rename apps/{postgres-new => web}/lib/indexed-db.ts (100%) rename apps/{postgres-new => web}/lib/pg-wire-util.ts (100%) rename apps/{postgres-new => web}/lib/schema.ts (100%) rename apps/{postgres-new => web}/lib/smooth-scroller.ts (100%) rename apps/{postgres-new => web}/lib/sql-util.ts (100%) rename apps/{postgres-new => web}/lib/streams.ts (100%) rename apps/{postgres-new => web}/lib/tools.ts (100%) rename apps/{postgres-new => web}/lib/use-breakpoint.ts (100%) rename apps/{postgres-new => web}/lib/util.ts (100%) rename apps/{postgres-new => web}/lib/utils.ts (100%) rename apps/{postgres-new => web}/lib/websocket-protocol.ts (100%) rename apps/{postgres-new => web}/middleware.ts (100%) rename apps/{postgres-new => web}/next.config.mjs (100%) rename apps/{postgres-new => web}/package.json (96%) rename apps/{postgres-new => web}/polyfills/readable-stream.ts (100%) rename apps/{postgres-new => web}/postcss.config.mjs (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Black.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Black.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BlackItalic.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BlackItalic.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Bold.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Bold.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BoldItalic.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BoldItalic.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Book.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Book.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BookItalic.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-BookItalic.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Medium.woff (100%) rename apps/{postgres-new => web}/public/fonts/custom/CustomFont-Medium.woff2 (100%) rename apps/{postgres-new => web}/public/fonts/source-code-pro/SourceCodePro-Regular.eot (100%) rename apps/{postgres-new => web}/public/fonts/source-code-pro/SourceCodePro-Regular.svg (100%) rename apps/{postgres-new => web}/public/fonts/source-code-pro/SourceCodePro-Regular.ttf (100%) rename apps/{postgres-new => web}/public/fonts/source-code-pro/SourceCodePro-Regular.woff (100%) rename apps/{postgres-new => web}/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 (100%) rename apps/{postgres-new => web}/tailwind.config.ts (100%) rename apps/{postgres-new => web}/tsconfig.json (100%) rename apps/{postgres-new => web}/types/highlightjs-curl.d.ts (100%) rename apps/{postgres-new => web}/utils/supabase/admin.ts (100%) rename apps/{postgres-new => web}/utils/supabase/client.ts (100%) rename apps/{postgres-new => web}/utils/supabase/db-types.ts (100%) rename apps/{postgres-new => web}/utils/supabase/middleware.ts (100%) rename apps/{postgres-new => web}/utils/supabase/server.ts (100%) create mode 100644 packages/deploy/package.json rename {apps/deploy-worker => packages/deploy}/src/error.ts (100%) create mode 100644 packages/deploy/src/index.ts rename {apps/deploy-worker => packages/deploy}/src/supabase/client.ts (86%) rename {apps/deploy-worker => packages/deploy}/src/supabase/create-deployed-database.ts (95%) rename {apps/deploy-worker => packages/deploy}/src/supabase/database-types.ts (100%) rename {apps/deploy-worker => packages/deploy}/src/supabase/deploy.ts (96%) rename {apps/deploy-worker => packages/deploy}/src/supabase/generate-password.ts (100%) rename {apps/deploy-worker => packages/deploy}/src/supabase/get-access-token.ts (94%) rename {apps/deploy-worker => packages/deploy}/src/supabase/get-database-url.ts (94%) create mode 100644 packages/deploy/src/supabase/index.ts rename {apps/deploy-worker => packages/deploy}/src/supabase/management-api/client.ts (85%) rename {apps/deploy-worker => packages/deploy}/src/supabase/management-api/types.ts (100%) rename {apps/deploy-worker => packages/deploy}/src/supabase/revoke-integration.ts (90%) rename {apps/deploy-worker => packages/deploy}/src/supabase/types.ts (91%) rename {apps/deploy-worker => packages/deploy}/src/supabase/wait-for-health.ts (96%) create mode 100644 packages/deploy/tsconfig.json create mode 100644 packages/deploy/tsup.config.ts create mode 100644 turbo.json diff --git a/.gitignore b/.gitignore index 67333569..9cafba4f 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ tls/ dist/ .env +.turbo diff --git a/README.md b/README.md index f3dcf2ce..0934b4fe 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,63 @@ How is this possible? [PGlite](https://pglite.dev/), a WASM version of Postgres This is a monorepo split into the following projects: -- [Frontend (Next.js)](./apps/postgres-new/): This contains the primary web app built with Next.js -- [Backend (pg-gateway)](./apps/db-service/): This serves S3-backed PGlite databases over the PG wire protocol using [pg-gateway](https://github.com/supabase-community/pg-gateway) +- [Web](./apps/web/): The primary web app built with Next.js +- [Browser proxy](./apps/browser-proxy/): Proxies Postgres TCP connections back to the browser using [pg-gateway](https://github.com/supabase-community/pg-gateway) and Web Sockets +- [Deploy worker](./apps/deploy-worker/): Deploys in-browser databases to database platforms (currently Supabase is supported) + +### Setup + +From the monorepo root: + +1. Install dependencies + + ```shell + npm i + ``` + +2. Start local Supabase stack: + ```shell + npx supabase start + ``` +3. Store local Supabase URL/anon key in `./apps/web/.env.local`: + ```shell + npx supabase status -o env \ + --override-name api.url=NEXT_PUBLIC_SUPABASE_URL \ + --override-name auth.anon_key=NEXT_PUBLIC_SUPABASE_ANON_KEY | + grep NEXT_PUBLIC >> ./apps/web/.env.local + ``` +4. Create an [OpenAI API key](https://platform.openai.com/api-keys) and save to `./apps/web/.env.local`: + ```shell + echo 'OPENAI_API_KEY=""' >> ./apps/web/.env.local + ``` +5. Store local KV (Redis) vars. Use these exact values: + + ```shell + echo 'KV_REST_API_URL="http://localhost:8080"' >> ./apps/web/.env.local + echo 'KV_REST_API_TOKEN="local_token"' >> ./apps/web/.env.local + ``` + +6. Start local Redis containers (used for rate limiting). Serves an API on port 8080: + + ```shell + docker compose -f ./apps/web/docker-compose.yml up -d + ``` + +7. Fill in the remaining variables for each app as seen in: + + - `./apps/web/.env.example` + - `./apps/browser-proxy/.env.example` + - `./apps/deploy-worker/.env.example` + +### Development + +From the monorepo root: + +```shell +npm run dev +``` + +_**Important:** This command uses `turbo` under the hood which understands the relationship between dependencies in the monorepo and automatically builds them accordingly (ie. `./packages/*`). If you by-pass `turbo`, you will have to manually build each `./packages/*` before each `./app/*` can use them._ ## Why rename postgres.new? diff --git a/apps/browser-proxy/README.md b/apps/browser-proxy/README.md index 1b6f4e9e..0d0abc2f 100644 --- a/apps/browser-proxy/README.md +++ b/apps/browser-proxy/README.md @@ -8,17 +8,9 @@ It is using a WebSocket server and a TCP server to make the communication betwee Copy the `.env.example` file to `.env` and set the correct environment variables. -Install dependencies: +Run the dev server from the monorepo root. See [Development](../../README.md#development). -```sh -npm install -``` - -Start the proxy in development mode: - -```sh -npm run dev -``` +The browser proxy will be listening on ports `5432` (Postgres TCP) and `443` (Web Sockets). ## Deployment @@ -30,4 +22,4 @@ Deploy the app: ```sh fly deploy --app database-build-browser-proxy -``` \ No newline at end of file +``` diff --git a/apps/deploy-worker/README.md b/apps/deploy-worker/README.md index e12b31db..0a3b325a 100644 --- a/apps/deploy-worker/README.md +++ b/apps/deploy-worker/README.md @@ -1,8 +1,7 @@ -``` -npm install -npm run dev -``` +## Development -``` -open http://localhost:3000 -``` +Copy the `.env.example` file to `.env` and set the correct environment variables. + +Run the dev server from the monorepo root. See [Development](../../README.md#development). + +The deploy worker will be listening on port `4000` (HTTP). diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json index 217dbd06..5c3d064b 100644 --- a/apps/deploy-worker/package.json +++ b/apps/deploy-worker/package.json @@ -3,16 +3,16 @@ "type": "module", "scripts": { "start": "node --env-file=.env --experimental-strip-types src/index.ts", - "dev": "node --watch --env-file=.env --experimental-strip-types src/index.ts", + "dev": "npm run start", "type-check": "tsc", - "generate:database-types": "npx supabase gen types --lang=typescript --local > src/supabase/database-types.ts", - "generate:management-api-types": "npx openapi-typescript https://api.supabase.com/api/v1-json -o ./src/supabase/management-api/types.ts" + "generate:database-types": "npx supabase gen types --lang=typescript --local > ./supabase/database-types.ts", + "generate:management-api-types": "npx openapi-typescript https://api.supabase.com/api/v1-json -o ./supabase/management-api/types.ts" }, "dependencies": { + "@database.build/deploy": "*", "@hono/node-server": "^1.13.2", "@hono/zod-validator": "^0.4.1", "@supabase/supabase-js": "^2.45.4", - "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", "openapi-fetch": "^0.13.0", @@ -20,7 +20,6 @@ }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", - "@types/debug": "^4.1.12", "@types/node": "^22.5.4", "openapi-typescript": "^7.4.2", "typescript": "^5.5.4" diff --git a/apps/deploy-worker/src/debug.ts b/apps/deploy-worker/src/debug.ts deleted file mode 100644 index e03388ac..00000000 --- a/apps/deploy-worker/src/debug.ts +++ /dev/null @@ -1,3 +0,0 @@ -import createDebug from 'debug' - -export const debug = createDebug('deploy-worker') diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index 14cd0970..5825da6e 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -1,13 +1,13 @@ +import { DeployError, IntegrationRevokedError } from '@database.build/deploy' +import { createClient } from '@database.build/deploy/supabase' +import { deploy } from '@database.build/deploy/supabase' +import { revokeIntegration } from '@database.build/deploy/supabase' import { serve } from '@hono/node-server' +import { zValidator } from '@hono/zod-validator' import { Hono } from 'hono' import { cors } from 'hono/cors' -import { z } from 'zod' -import { zValidator } from '@hono/zod-validator' -import { createClient } from './supabase/client.ts' import { HTTPException } from 'hono/http-exception' -import { deploy } from './supabase/deploy.ts' -import { DeployError, IntegrationRevokedError } from './error.ts' -import { revokeIntegration } from './supabase/revoke-integration.ts' +import { z } from 'zod' const app = new Hono() @@ -60,6 +60,8 @@ app.post( } ) +app.get('') + const port = 4000 console.log(`Server is running on port ${port}`) diff --git a/apps/deploy-worker/tsconfig.json b/apps/deploy-worker/tsconfig.json index c7e60e1c..42cf8fb4 100644 --- a/apps/deploy-worker/tsconfig.json +++ b/apps/deploy-worker/tsconfig.json @@ -3,7 +3,6 @@ "include": ["src/**/*.ts"], "compilerOptions": { "noEmit": true, - "allowImportingTsExtensions": true, "outDir": "dist" } } diff --git a/apps/postgres-new/.env.example b/apps/web/.env.example similarity index 85% rename from apps/postgres-new/.env.example rename to apps/web/.env.example index 011123b1..2ff8a91e 100644 --- a/apps/postgres-new/.env.example +++ b/apps/web/.env.example @@ -1,7 +1,7 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY="" NEXT_PUBLIC_SUPABASE_URL="" -NEXT_PUBLIC_BROWSER_PROXY_DOMAIN="" -NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN="" +NEXT_PUBLIC_BROWSER_PROXY_DOMAIN="browser.dev.db.build" +NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN="http://localhost:4000" NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID="" NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL=https://api.supabase.com diff --git a/apps/postgres-new/README.md b/apps/web/README.md similarity index 65% rename from apps/postgres-new/README.md rename to apps/web/README.md index 233348aa..b6880c63 100644 --- a/apps/postgres-new/README.md +++ b/apps/web/README.md @@ -13,7 +13,6 @@ Both databases are stored locally in the browser via IndexedDB. This means that Every PGlite instance runs in a Web Worker so that the main thread is not blocked. - ## AI The AI component is powered by OpenAI's GPT-4o model by default. The project uses [Vercel's AI SDK](https://sdk.vercel.ai/docs/introduction) to simplify message streams and tool calls. @@ -27,7 +26,6 @@ In addition to the required `OPENAI_API_KEY`, the following environment variable **NOTE**: The current prompts and tools are designed around the GPT-4o model. If you choose to use a different model, expect different behavior and results. Additionally, ensure that the model you select supports tool (function) call capabilities. - ## Authentication Because LLMs cost money, a lightweight auth wall exists to prevent abuse. It is currently only used to validate that the user has a legitimate GitHub account, but in the future it could be used to save private/public databases to the cloud. @@ -36,37 +34,4 @@ Authentication and users are managed by a [Supabase](https://supabase.com/) data ## Development -From this directory (`./apps/postgres-new`): - -1. Install dependencies: - ```shell - npm i - ``` -2. Start local Supabase stack: - ```shell - npx supabase start - ``` -3. Store local Supabase URL/anon key in `.env.local`: - ```shell - npx supabase status -o env \ - --override-name api.url=NEXT_PUBLIC_SUPABASE_URL \ - --override-name auth.anon_key=NEXT_PUBLIC_SUPABASE_ANON_KEY | - grep NEXT_PUBLIC >> .env.local - ``` -4. Create an [OpenAI API key](https://platform.openai.com/api-keys) and save to `.env.local`: - ```shell - echo 'OPENAI_API_KEY=""' >> .env.local - ``` -5. Start local Redis containers (used for rate limiting). Serves an API on port 8080: - ```shell - docker compose up -d - ``` -6. Store local KV (Redis) vars. Use these exact values: - ```shell - echo 'KV_REST_API_URL="http://localhost:8080"' >> .env.local - echo 'KV_REST_API_TOKEN="local_token"' >> .env.local - ``` -7. Start Next.js development server: - ```shell - npm run dev - ``` +The Next.js server should run from the monorepo root. See [Development](../../README.md#development). diff --git a/apps/postgres-new/app/(main)/db/[id]/page.tsx b/apps/web/app/(main)/db/[id]/page.tsx similarity index 100% rename from apps/postgres-new/app/(main)/db/[id]/page.tsx rename to apps/web/app/(main)/db/[id]/page.tsx diff --git a/apps/postgres-new/app/(main)/layout.tsx b/apps/web/app/(main)/layout.tsx similarity index 100% rename from apps/postgres-new/app/(main)/layout.tsx rename to apps/web/app/(main)/layout.tsx diff --git a/apps/postgres-new/app/(main)/page.tsx b/apps/web/app/(main)/page.tsx similarity index 100% rename from apps/postgres-new/app/(main)/page.tsx rename to apps/web/app/(main)/page.tsx diff --git a/apps/postgres-new/app/api/chat/route.ts b/apps/web/app/api/chat/route.ts similarity index 100% rename from apps/postgres-new/app/api/chat/route.ts rename to apps/web/app/api/chat/route.ts diff --git a/apps/postgres-new/app/api/oauth/supabase/callback/route.ts b/apps/web/app/api/oauth/supabase/callback/route.ts similarity index 100% rename from apps/postgres-new/app/api/oauth/supabase/callback/route.ts rename to apps/web/app/api/oauth/supabase/callback/route.ts diff --git a/apps/web/app/api/oauth/supabase/organizations/route.ts b/apps/web/app/api/oauth/supabase/organizations/route.ts new file mode 100644 index 00000000..e23c4487 --- /dev/null +++ b/apps/web/app/api/oauth/supabase/organizations/route.ts @@ -0,0 +1,6 @@ +import { NextRequest } from 'next/server' +import { createClient } from '~/utils/supabase/server' + +export async function GET(req: NextRequest) { + const supabase = createClient() +} diff --git a/apps/postgres-new/app/apple-icon.png b/apps/web/app/apple-icon.png similarity index 100% rename from apps/postgres-new/app/apple-icon.png rename to apps/web/app/apple-icon.png diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/web/app/deploy/[databaseId]/page.tsx similarity index 100% rename from apps/postgres-new/app/deploy/[databaseId]/page.tsx rename to apps/web/app/deploy/[databaseId]/page.tsx diff --git a/apps/postgres-new/app/export/page.tsx b/apps/web/app/export/page.tsx similarity index 100% rename from apps/postgres-new/app/export/page.tsx rename to apps/web/app/export/page.tsx diff --git a/apps/postgres-new/app/favicon.ico b/apps/web/app/favicon.ico similarity index 100% rename from apps/postgres-new/app/favicon.ico rename to apps/web/app/favicon.ico diff --git a/apps/postgres-new/app/globals.css b/apps/web/app/globals.css similarity index 100% rename from apps/postgres-new/app/globals.css rename to apps/web/app/globals.css diff --git a/apps/postgres-new/app/icon.svg b/apps/web/app/icon.svg similarity index 100% rename from apps/postgres-new/app/icon.svg rename to apps/web/app/icon.svg diff --git a/apps/postgres-new/app/import/page.tsx b/apps/web/app/import/page.tsx similarity index 100% rename from apps/postgres-new/app/import/page.tsx rename to apps/web/app/import/page.tsx diff --git a/apps/postgres-new/app/layout.tsx b/apps/web/app/layout.tsx similarity index 100% rename from apps/postgres-new/app/layout.tsx rename to apps/web/app/layout.tsx diff --git a/apps/postgres-new/app/opengraph-image.png b/apps/web/app/opengraph-image.png similarity index 100% rename from apps/postgres-new/app/opengraph-image.png rename to apps/web/app/opengraph-image.png diff --git a/apps/postgres-new/assets/github-icon.tsx b/apps/web/assets/github-icon.tsx similarity index 100% rename from apps/postgres-new/assets/github-icon.tsx rename to apps/web/assets/github-icon.tsx diff --git a/apps/postgres-new/components.json b/apps/web/components.json similarity index 100% rename from apps/postgres-new/components.json rename to apps/web/components.json diff --git a/apps/postgres-new/components/ai-icon-animation/ai-icon-animation-style.module.css b/apps/web/components/ai-icon-animation/ai-icon-animation-style.module.css similarity index 100% rename from apps/postgres-new/components/ai-icon-animation/ai-icon-animation-style.module.css rename to apps/web/components/ai-icon-animation/ai-icon-animation-style.module.css diff --git a/apps/postgres-new/components/ai-icon-animation/ai-icon-animation.tsx b/apps/web/components/ai-icon-animation/ai-icon-animation.tsx similarity index 100% rename from apps/postgres-new/components/ai-icon-animation/ai-icon-animation.tsx rename to apps/web/components/ai-icon-animation/ai-icon-animation.tsx diff --git a/apps/postgres-new/components/ai-icon-animation/index.tsx b/apps/web/components/ai-icon-animation/index.tsx similarity index 100% rename from apps/postgres-new/components/ai-icon-animation/index.tsx rename to apps/web/components/ai-icon-animation/index.tsx diff --git a/apps/postgres-new/components/app-provider.tsx b/apps/web/components/app-provider.tsx similarity index 100% rename from apps/postgres-new/components/app-provider.tsx rename to apps/web/components/app-provider.tsx diff --git a/apps/postgres-new/components/chat-message.tsx b/apps/web/components/chat-message.tsx similarity index 100% rename from apps/postgres-new/components/chat-message.tsx rename to apps/web/components/chat-message.tsx diff --git a/apps/postgres-new/components/chat.tsx b/apps/web/components/chat.tsx similarity index 100% rename from apps/postgres-new/components/chat.tsx rename to apps/web/components/chat.tsx diff --git a/apps/postgres-new/components/code-accordion.tsx b/apps/web/components/code-accordion.tsx similarity index 100% rename from apps/postgres-new/components/code-accordion.tsx rename to apps/web/components/code-accordion.tsx diff --git a/apps/postgres-new/components/code-block.tsx b/apps/web/components/code-block.tsx similarity index 100% rename from apps/postgres-new/components/code-block.tsx rename to apps/web/components/code-block.tsx diff --git a/apps/postgres-new/components/copyable-field.tsx b/apps/web/components/copyable-field.tsx similarity index 100% rename from apps/postgres-new/components/copyable-field.tsx rename to apps/web/components/copyable-field.tsx diff --git a/apps/postgres-new/components/deploy/deploy-dialog.tsx b/apps/web/components/deploy/deploy-dialog.tsx similarity index 100% rename from apps/postgres-new/components/deploy/deploy-dialog.tsx rename to apps/web/components/deploy/deploy-dialog.tsx diff --git a/apps/postgres-new/components/deploy/deploy-failure-dialog.tsx b/apps/web/components/deploy/deploy-failure-dialog.tsx similarity index 100% rename from apps/postgres-new/components/deploy/deploy-failure-dialog.tsx rename to apps/web/components/deploy/deploy-failure-dialog.tsx diff --git a/apps/postgres-new/components/deploy/deploy-success-dialog.tsx b/apps/web/components/deploy/deploy-success-dialog.tsx similarity index 100% rename from apps/postgres-new/components/deploy/deploy-success-dialog.tsx rename to apps/web/components/deploy/deploy-success-dialog.tsx diff --git a/apps/postgres-new/components/deploy/integration-dialog.tsx b/apps/web/components/deploy/integration-dialog.tsx similarity index 100% rename from apps/postgres-new/components/deploy/integration-dialog.tsx rename to apps/web/components/deploy/integration-dialog.tsx diff --git a/apps/postgres-new/components/deploy/redeploy-dialog.tsx b/apps/web/components/deploy/redeploy-dialog.tsx similarity index 100% rename from apps/postgres-new/components/deploy/redeploy-dialog.tsx rename to apps/web/components/deploy/redeploy-dialog.tsx diff --git a/apps/postgres-new/components/framer-features.ts b/apps/web/components/framer-features.ts similarity index 100% rename from apps/postgres-new/components/framer-features.ts rename to apps/web/components/framer-features.ts diff --git a/apps/postgres-new/components/ide.tsx b/apps/web/components/ide.tsx similarity index 100% rename from apps/postgres-new/components/ide.tsx rename to apps/web/components/ide.tsx diff --git a/apps/postgres-new/components/layout.tsx b/apps/web/components/layout.tsx similarity index 100% rename from apps/postgres-new/components/layout.tsx rename to apps/web/components/layout.tsx diff --git a/apps/postgres-new/components/live-share-icon.tsx b/apps/web/components/live-share-icon.tsx similarity index 100% rename from apps/postgres-new/components/live-share-icon.tsx rename to apps/web/components/live-share-icon.tsx diff --git a/apps/postgres-new/components/markdown-accordion.tsx b/apps/web/components/markdown-accordion.tsx similarity index 100% rename from apps/postgres-new/components/markdown-accordion.tsx rename to apps/web/components/markdown-accordion.tsx diff --git a/apps/postgres-new/components/particles-background.tsx b/apps/web/components/particles-background.tsx similarity index 100% rename from apps/postgres-new/components/particles-background.tsx rename to apps/web/components/particles-background.tsx diff --git a/apps/postgres-new/components/providers.tsx b/apps/web/components/providers.tsx similarity index 100% rename from apps/postgres-new/components/providers.tsx rename to apps/web/components/providers.tsx diff --git a/apps/postgres-new/components/schema/graph.tsx b/apps/web/components/schema/graph.tsx similarity index 100% rename from apps/postgres-new/components/schema/graph.tsx rename to apps/web/components/schema/graph.tsx diff --git a/apps/postgres-new/components/schema/legend.tsx b/apps/web/components/schema/legend.tsx similarity index 100% rename from apps/postgres-new/components/schema/legend.tsx rename to apps/web/components/schema/legend.tsx diff --git a/apps/postgres-new/components/schema/table-graph.tsx b/apps/web/components/schema/table-graph.tsx similarity index 100% rename from apps/postgres-new/components/schema/table-graph.tsx rename to apps/web/components/schema/table-graph.tsx diff --git a/apps/postgres-new/components/schema/table-node.tsx b/apps/web/components/schema/table-node.tsx similarity index 100% rename from apps/postgres-new/components/schema/table-node.tsx rename to apps/web/components/schema/table-node.tsx diff --git a/apps/postgres-new/components/sidebar.tsx b/apps/web/components/sidebar.tsx similarity index 100% rename from apps/postgres-new/components/sidebar.tsx rename to apps/web/components/sidebar.tsx diff --git a/apps/postgres-new/components/sign-in-button.tsx b/apps/web/components/sign-in-button.tsx similarity index 100% rename from apps/postgres-new/components/sign-in-button.tsx rename to apps/web/components/sign-in-button.tsx diff --git a/apps/postgres-new/components/supabase-icon.tsx b/apps/web/components/supabase-icon.tsx similarity index 100% rename from apps/postgres-new/components/supabase-icon.tsx rename to apps/web/components/supabase-icon.tsx diff --git a/apps/postgres-new/components/theme-dropdown.tsx b/apps/web/components/theme-dropdown.tsx similarity index 100% rename from apps/postgres-new/components/theme-dropdown.tsx rename to apps/web/components/theme-dropdown.tsx diff --git a/apps/postgres-new/components/theme-provider.tsx b/apps/web/components/theme-provider.tsx similarity index 100% rename from apps/postgres-new/components/theme-provider.tsx rename to apps/web/components/theme-provider.tsx diff --git a/apps/postgres-new/components/tools/conversation-rename.tsx b/apps/web/components/tools/conversation-rename.tsx similarity index 100% rename from apps/postgres-new/components/tools/conversation-rename.tsx rename to apps/web/components/tools/conversation-rename.tsx diff --git a/apps/postgres-new/components/tools/csv-export.tsx b/apps/web/components/tools/csv-export.tsx similarity index 100% rename from apps/postgres-new/components/tools/csv-export.tsx rename to apps/web/components/tools/csv-export.tsx diff --git a/apps/postgres-new/components/tools/csv-import.tsx b/apps/web/components/tools/csv-import.tsx similarity index 100% rename from apps/postgres-new/components/tools/csv-import.tsx rename to apps/web/components/tools/csv-import.tsx diff --git a/apps/postgres-new/components/tools/csv-request.tsx b/apps/web/components/tools/csv-request.tsx similarity index 100% rename from apps/postgres-new/components/tools/csv-request.tsx rename to apps/web/components/tools/csv-request.tsx diff --git a/apps/postgres-new/components/tools/executed-sql.tsx b/apps/web/components/tools/executed-sql.tsx similarity index 100% rename from apps/postgres-new/components/tools/executed-sql.tsx rename to apps/web/components/tools/executed-sql.tsx diff --git a/apps/postgres-new/components/tools/generated-chart.tsx b/apps/web/components/tools/generated-chart.tsx similarity index 100% rename from apps/postgres-new/components/tools/generated-chart.tsx rename to apps/web/components/tools/generated-chart.tsx diff --git a/apps/postgres-new/components/tools/generated-embedding.tsx b/apps/web/components/tools/generated-embedding.tsx similarity index 100% rename from apps/postgres-new/components/tools/generated-embedding.tsx rename to apps/web/components/tools/generated-embedding.tsx diff --git a/apps/postgres-new/components/tools/index.tsx b/apps/web/components/tools/index.tsx similarity index 100% rename from apps/postgres-new/components/tools/index.tsx rename to apps/web/components/tools/index.tsx diff --git a/apps/postgres-new/components/ui/accordion.tsx b/apps/web/components/ui/accordion.tsx similarity index 100% rename from apps/postgres-new/components/ui/accordion.tsx rename to apps/web/components/ui/accordion.tsx diff --git a/apps/postgres-new/components/ui/alert-dialog.tsx b/apps/web/components/ui/alert-dialog.tsx similarity index 100% rename from apps/postgres-new/components/ui/alert-dialog.tsx rename to apps/web/components/ui/alert-dialog.tsx diff --git a/apps/postgres-new/components/ui/badge.tsx b/apps/web/components/ui/badge.tsx similarity index 100% rename from apps/postgres-new/components/ui/badge.tsx rename to apps/web/components/ui/badge.tsx diff --git a/apps/postgres-new/components/ui/button.tsx b/apps/web/components/ui/button.tsx similarity index 100% rename from apps/postgres-new/components/ui/button.tsx rename to apps/web/components/ui/button.tsx diff --git a/apps/postgres-new/components/ui/dialog.tsx b/apps/web/components/ui/dialog.tsx similarity index 100% rename from apps/postgres-new/components/ui/dialog.tsx rename to apps/web/components/ui/dialog.tsx diff --git a/apps/postgres-new/components/ui/dropdown-menu.tsx b/apps/web/components/ui/dropdown-menu.tsx similarity index 100% rename from apps/postgres-new/components/ui/dropdown-menu.tsx rename to apps/web/components/ui/dropdown-menu.tsx diff --git a/apps/postgres-new/components/ui/input.tsx b/apps/web/components/ui/input.tsx similarity index 100% rename from apps/postgres-new/components/ui/input.tsx rename to apps/web/components/ui/input.tsx diff --git a/apps/postgres-new/components/ui/label.tsx b/apps/web/components/ui/label.tsx similarity index 100% rename from apps/postgres-new/components/ui/label.tsx rename to apps/web/components/ui/label.tsx diff --git a/apps/postgres-new/components/ui/popover.tsx b/apps/web/components/ui/popover.tsx similarity index 100% rename from apps/postgres-new/components/ui/popover.tsx rename to apps/web/components/ui/popover.tsx diff --git a/apps/postgres-new/components/ui/progress.tsx b/apps/web/components/ui/progress.tsx similarity index 100% rename from apps/postgres-new/components/ui/progress.tsx rename to apps/web/components/ui/progress.tsx diff --git a/apps/postgres-new/components/ui/skeleton.tsx b/apps/web/components/ui/skeleton.tsx similarity index 100% rename from apps/postgres-new/components/ui/skeleton.tsx rename to apps/web/components/ui/skeleton.tsx diff --git a/apps/postgres-new/components/ui/tabs.tsx b/apps/web/components/ui/tabs.tsx similarity index 100% rename from apps/postgres-new/components/ui/tabs.tsx rename to apps/web/components/ui/tabs.tsx diff --git a/apps/postgres-new/components/ui/tooltip.tsx b/apps/web/components/ui/tooltip.tsx similarity index 100% rename from apps/postgres-new/components/ui/tooltip.tsx rename to apps/web/components/ui/tooltip.tsx diff --git a/apps/postgres-new/components/workspace.tsx b/apps/web/components/workspace.tsx similarity index 100% rename from apps/postgres-new/components/workspace.tsx rename to apps/web/components/workspace.tsx diff --git a/apps/postgres-new/config/default-colors.js b/apps/web/config/default-colors.js similarity index 100% rename from apps/postgres-new/config/default-colors.js rename to apps/web/config/default-colors.js diff --git a/apps/postgres-new/config/tailwind.config.js b/apps/web/config/tailwind.config.js similarity index 100% rename from apps/postgres-new/config/tailwind.config.js rename to apps/web/config/tailwind.config.js diff --git a/apps/postgres-new/config/ui.config.js b/apps/web/config/ui.config.js similarity index 100% rename from apps/postgres-new/config/ui.config.js rename to apps/web/config/ui.config.js diff --git a/apps/postgres-new/data/databases/database-create-mutation.ts b/apps/web/data/databases/database-create-mutation.ts similarity index 100% rename from apps/postgres-new/data/databases/database-create-mutation.ts rename to apps/web/data/databases/database-create-mutation.ts diff --git a/apps/postgres-new/data/databases/database-delete-mutation.ts b/apps/web/data/databases/database-delete-mutation.ts similarity index 100% rename from apps/postgres-new/data/databases/database-delete-mutation.ts rename to apps/web/data/databases/database-delete-mutation.ts diff --git a/apps/postgres-new/data/databases/database-query.ts b/apps/web/data/databases/database-query.ts similarity index 100% rename from apps/postgres-new/data/databases/database-query.ts rename to apps/web/data/databases/database-query.ts diff --git a/apps/postgres-new/data/databases/database-update-mutation.ts b/apps/web/data/databases/database-update-mutation.ts similarity index 100% rename from apps/postgres-new/data/databases/database-update-mutation.ts rename to apps/web/data/databases/database-update-mutation.ts diff --git a/apps/postgres-new/data/databases/databases-query.ts b/apps/web/data/databases/databases-query.ts similarity index 100% rename from apps/postgres-new/data/databases/databases-query.ts rename to apps/web/data/databases/databases-query.ts diff --git a/apps/postgres-new/data/deploy-waitlist/deploy-waitlist-create-mutation.ts b/apps/web/data/deploy-waitlist/deploy-waitlist-create-mutation.ts similarity index 100% rename from apps/postgres-new/data/deploy-waitlist/deploy-waitlist-create-mutation.ts rename to apps/web/data/deploy-waitlist/deploy-waitlist-create-mutation.ts diff --git a/apps/postgres-new/data/deploy-waitlist/deploy-waitlist-query.ts b/apps/web/data/deploy-waitlist/deploy-waitlist-query.ts similarity index 100% rename from apps/postgres-new/data/deploy-waitlist/deploy-waitlist-query.ts rename to apps/web/data/deploy-waitlist/deploy-waitlist-query.ts diff --git a/apps/postgres-new/data/deployed-databases/deployed-databases-query.ts b/apps/web/data/deployed-databases/deployed-databases-query.ts similarity index 100% rename from apps/postgres-new/data/deployed-databases/deployed-databases-query.ts rename to apps/web/data/deployed-databases/deployed-databases-query.ts diff --git a/apps/postgres-new/data/integrations/integration-query.ts b/apps/web/data/integrations/integration-query.ts similarity index 100% rename from apps/postgres-new/data/integrations/integration-query.ts rename to apps/web/data/integrations/integration-query.ts diff --git a/apps/postgres-new/data/messages/message-create-mutation.ts b/apps/web/data/messages/message-create-mutation.ts similarity index 100% rename from apps/postgres-new/data/messages/message-create-mutation.ts rename to apps/web/data/messages/message-create-mutation.ts diff --git a/apps/postgres-new/data/messages/messages-query.ts b/apps/web/data/messages/messages-query.ts similarity index 100% rename from apps/postgres-new/data/messages/messages-query.ts rename to apps/web/data/messages/messages-query.ts diff --git a/apps/postgres-new/data/tables/tables-query.ts b/apps/web/data/tables/tables-query.ts similarity index 100% rename from apps/postgres-new/data/tables/tables-query.ts rename to apps/web/data/tables/tables-query.ts diff --git a/apps/postgres-new/docker-compose.yml b/apps/web/docker-compose.yml similarity index 100% rename from apps/postgres-new/docker-compose.yml rename to apps/web/docker-compose.yml diff --git a/apps/postgres-new/global.d.ts b/apps/web/global.d.ts similarity index 100% rename from apps/postgres-new/global.d.ts rename to apps/web/global.d.ts diff --git a/apps/postgres-new/lib/db/index.ts b/apps/web/lib/db/index.ts similarity index 100% rename from apps/postgres-new/lib/db/index.ts rename to apps/web/lib/db/index.ts diff --git a/apps/postgres-new/lib/db/worker.ts b/apps/web/lib/db/worker.ts similarity index 100% rename from apps/postgres-new/lib/db/worker.ts rename to apps/web/lib/db/worker.ts diff --git a/apps/postgres-new/lib/embed/index.ts b/apps/web/lib/embed/index.ts similarity index 100% rename from apps/postgres-new/lib/embed/index.ts rename to apps/web/lib/embed/index.ts diff --git a/apps/postgres-new/lib/embed/worker.ts b/apps/web/lib/embed/worker.ts similarity index 100% rename from apps/postgres-new/lib/embed/worker.ts rename to apps/web/lib/embed/worker.ts diff --git a/apps/postgres-new/lib/files.ts b/apps/web/lib/files.ts similarity index 100% rename from apps/postgres-new/lib/files.ts rename to apps/web/lib/files.ts diff --git a/apps/postgres-new/lib/hooks.ts b/apps/web/lib/hooks.ts similarity index 100% rename from apps/postgres-new/lib/hooks.ts rename to apps/web/lib/hooks.ts diff --git a/apps/postgres-new/lib/indexed-db.ts b/apps/web/lib/indexed-db.ts similarity index 100% rename from apps/postgres-new/lib/indexed-db.ts rename to apps/web/lib/indexed-db.ts diff --git a/apps/postgres-new/lib/pg-wire-util.ts b/apps/web/lib/pg-wire-util.ts similarity index 100% rename from apps/postgres-new/lib/pg-wire-util.ts rename to apps/web/lib/pg-wire-util.ts diff --git a/apps/postgres-new/lib/schema.ts b/apps/web/lib/schema.ts similarity index 100% rename from apps/postgres-new/lib/schema.ts rename to apps/web/lib/schema.ts diff --git a/apps/postgres-new/lib/smooth-scroller.ts b/apps/web/lib/smooth-scroller.ts similarity index 100% rename from apps/postgres-new/lib/smooth-scroller.ts rename to apps/web/lib/smooth-scroller.ts diff --git a/apps/postgres-new/lib/sql-util.ts b/apps/web/lib/sql-util.ts similarity index 100% rename from apps/postgres-new/lib/sql-util.ts rename to apps/web/lib/sql-util.ts diff --git a/apps/postgres-new/lib/streams.ts b/apps/web/lib/streams.ts similarity index 100% rename from apps/postgres-new/lib/streams.ts rename to apps/web/lib/streams.ts diff --git a/apps/postgres-new/lib/tools.ts b/apps/web/lib/tools.ts similarity index 100% rename from apps/postgres-new/lib/tools.ts rename to apps/web/lib/tools.ts diff --git a/apps/postgres-new/lib/use-breakpoint.ts b/apps/web/lib/use-breakpoint.ts similarity index 100% rename from apps/postgres-new/lib/use-breakpoint.ts rename to apps/web/lib/use-breakpoint.ts diff --git a/apps/postgres-new/lib/util.ts b/apps/web/lib/util.ts similarity index 100% rename from apps/postgres-new/lib/util.ts rename to apps/web/lib/util.ts diff --git a/apps/postgres-new/lib/utils.ts b/apps/web/lib/utils.ts similarity index 100% rename from apps/postgres-new/lib/utils.ts rename to apps/web/lib/utils.ts diff --git a/apps/postgres-new/lib/websocket-protocol.ts b/apps/web/lib/websocket-protocol.ts similarity index 100% rename from apps/postgres-new/lib/websocket-protocol.ts rename to apps/web/lib/websocket-protocol.ts diff --git a/apps/postgres-new/middleware.ts b/apps/web/middleware.ts similarity index 100% rename from apps/postgres-new/middleware.ts rename to apps/web/middleware.ts diff --git a/apps/postgres-new/next.config.mjs b/apps/web/next.config.mjs similarity index 100% rename from apps/postgres-new/next.config.mjs rename to apps/web/next.config.mjs diff --git a/apps/postgres-new/package.json b/apps/web/package.json similarity index 96% rename from apps/postgres-new/package.json rename to apps/web/package.json index 409dad61..20206334 100644 --- a/apps/postgres-new/package.json +++ b/apps/web/package.json @@ -1,5 +1,5 @@ { - "name": "postgres-new", + "name": "@database.build/web", "version": "0.0.0", "private": true, "scripts": { @@ -7,11 +7,13 @@ "build": "next build", "start": "next start", "lint": "next lint", + "check-types": "tsc --noEmit", "generate:database-types": "supabase gen types --lang=typescript --local > utils/supabase/db-types.ts" }, "dependencies": { "@ai-sdk/openai": "^0.0.21", "@dagrejs/dagre": "^1.1.2", + "@database.build/deploy": "*", "@electric-sql/pglite": "^0.2.9", "@gregnr/postgres-meta": "^0.82.0-dev.2", "@monaco-editor/react": "^4.6.0", diff --git a/apps/postgres-new/polyfills/readable-stream.ts b/apps/web/polyfills/readable-stream.ts similarity index 100% rename from apps/postgres-new/polyfills/readable-stream.ts rename to apps/web/polyfills/readable-stream.ts diff --git a/apps/postgres-new/postcss.config.mjs b/apps/web/postcss.config.mjs similarity index 100% rename from apps/postgres-new/postcss.config.mjs rename to apps/web/postcss.config.mjs diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Black.woff b/apps/web/public/fonts/custom/CustomFont-Black.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Black.woff rename to apps/web/public/fonts/custom/CustomFont-Black.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Black.woff2 b/apps/web/public/fonts/custom/CustomFont-Black.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Black.woff2 rename to apps/web/public/fonts/custom/CustomFont-Black.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff b/apps/web/public/fonts/custom/CustomFont-BlackItalic.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff rename to apps/web/public/fonts/custom/CustomFont-BlackItalic.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff2 b/apps/web/public/fonts/custom/CustomFont-BlackItalic.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff2 rename to apps/web/public/fonts/custom/CustomFont-BlackItalic.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff b/apps/web/public/fonts/custom/CustomFont-Bold.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff rename to apps/web/public/fonts/custom/CustomFont-Bold.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff2 b/apps/web/public/fonts/custom/CustomFont-Bold.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff2 rename to apps/web/public/fonts/custom/CustomFont-Bold.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff b/apps/web/public/fonts/custom/CustomFont-BoldItalic.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff rename to apps/web/public/fonts/custom/CustomFont-BoldItalic.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff2 b/apps/web/public/fonts/custom/CustomFont-BoldItalic.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff2 rename to apps/web/public/fonts/custom/CustomFont-BoldItalic.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Book.woff b/apps/web/public/fonts/custom/CustomFont-Book.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Book.woff rename to apps/web/public/fonts/custom/CustomFont-Book.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Book.woff2 b/apps/web/public/fonts/custom/CustomFont-Book.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Book.woff2 rename to apps/web/public/fonts/custom/CustomFont-Book.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff b/apps/web/public/fonts/custom/CustomFont-BookItalic.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff rename to apps/web/public/fonts/custom/CustomFont-BookItalic.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff2 b/apps/web/public/fonts/custom/CustomFont-BookItalic.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff2 rename to apps/web/public/fonts/custom/CustomFont-BookItalic.woff2 diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff b/apps/web/public/fonts/custom/CustomFont-Medium.woff similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff rename to apps/web/public/fonts/custom/CustomFont-Medium.woff diff --git a/apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff2 b/apps/web/public/fonts/custom/CustomFont-Medium.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff2 rename to apps/web/public/fonts/custom/CustomFont-Medium.woff2 diff --git a/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.eot b/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.eot similarity index 100% rename from apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.eot rename to apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.eot diff --git a/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.svg b/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.svg similarity index 100% rename from apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.svg rename to apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.svg diff --git a/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.ttf b/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.ttf similarity index 100% rename from apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.ttf rename to apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.ttf diff --git a/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff b/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff similarity index 100% rename from apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff rename to apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff diff --git a/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 b/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 similarity index 100% rename from apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 rename to apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 diff --git a/apps/postgres-new/tailwind.config.ts b/apps/web/tailwind.config.ts similarity index 100% rename from apps/postgres-new/tailwind.config.ts rename to apps/web/tailwind.config.ts diff --git a/apps/postgres-new/tsconfig.json b/apps/web/tsconfig.json similarity index 100% rename from apps/postgres-new/tsconfig.json rename to apps/web/tsconfig.json diff --git a/apps/postgres-new/types/highlightjs-curl.d.ts b/apps/web/types/highlightjs-curl.d.ts similarity index 100% rename from apps/postgres-new/types/highlightjs-curl.d.ts rename to apps/web/types/highlightjs-curl.d.ts diff --git a/apps/postgres-new/utils/supabase/admin.ts b/apps/web/utils/supabase/admin.ts similarity index 100% rename from apps/postgres-new/utils/supabase/admin.ts rename to apps/web/utils/supabase/admin.ts diff --git a/apps/postgres-new/utils/supabase/client.ts b/apps/web/utils/supabase/client.ts similarity index 100% rename from apps/postgres-new/utils/supabase/client.ts rename to apps/web/utils/supabase/client.ts diff --git a/apps/postgres-new/utils/supabase/db-types.ts b/apps/web/utils/supabase/db-types.ts similarity index 100% rename from apps/postgres-new/utils/supabase/db-types.ts rename to apps/web/utils/supabase/db-types.ts diff --git a/apps/postgres-new/utils/supabase/middleware.ts b/apps/web/utils/supabase/middleware.ts similarity index 100% rename from apps/postgres-new/utils/supabase/middleware.ts rename to apps/web/utils/supabase/middleware.ts diff --git a/apps/postgres-new/utils/supabase/server.ts b/apps/web/utils/supabase/server.ts similarity index 100% rename from apps/postgres-new/utils/supabase/server.ts rename to apps/web/utils/supabase/server.ts diff --git a/package-lock.json b/package-lock.json index 28243adf..901acfe5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,17 @@ { - "name": "postgres-new", + "name": "@database.build/root", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "@database.build/root", "workspaces": [ - "apps/*" + "apps/*", + "packages/*" ], "devDependencies": { - "supabase": "^1.207.9" + "supabase": "^1.207.9", + "turbo": "^2.2.3" } }, "apps/browser-proxy": { @@ -83,10 +86,10 @@ "apps/deploy-worker": { "name": "@database.build/deploy-worker", "dependencies": { + "@database.build/deploy": "*", "@hono/node-server": "^1.13.2", "@hono/zod-validator": "^0.4.1", "@supabase/supabase-js": "^2.45.4", - "debug": "^4.3.7", "hono": "^4.6.5", "neverthrow": "^8.0.0", "openapi-fetch": "^0.13.0", @@ -94,7 +97,6 @@ }, "devDependencies": { "@total-typescript/tsconfig": "^1.0.4", - "@types/debug": "^4.1.12", "@types/node": "^22.5.4", "openapi-typescript": "^7.4.2", "typescript": "^5.5.4" @@ -119,6 +121,7 @@ }, "apps/postgres-new": { "version": "0.0.0", + "extraneous": true, "dependencies": { "@ai-sdk/openai": "^0.0.21", "@dagrejs/dagre": "^1.1.2", @@ -203,14 +206,97 @@ "webpack": "^5.95.0" } }, - "apps/postgres-new/node_modules/@electric-sql/pglite": { - "version": "0.2.9", - "license": "Apache-2.0" + "apps/web": { + "name": "@database.build/web", + "version": "0.0.0", + "dependencies": { + "@ai-sdk/openai": "^0.0.21", + "@dagrejs/dagre": "^1.1.2", + "@electric-sql/pglite": "^0.2.9", + "@gregnr/postgres-meta": "^0.82.0-dev.2", + "@monaco-editor/react": "^4.6.0", + "@radix-ui/react-accordion": "^1.2.0", + "@radix-ui/react-alert-dialog": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dropdown-menu": "^2.1.1", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.1", + "@radix-ui/react-progress": "^1.1.0", + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-tabs": "^1.1.0", + "@radix-ui/react-tooltip": "^1.1.2", + "@std/tar": "npm:@jsr/std__tar@^0.1.2", + "@supabase/postgres-meta": "^0.81.2", + "@supabase/ssr": "^0.4.0", + "@supabase/supabase-js": "^2.45.0", + "@tanstack/react-query": "^5.45.0", + "@upstash/ratelimit": "^2.0.1", + "@vercel/kv": "^2.0.0", + "@xenova/transformers": "^2.17.2", + "ai": "^3.2.8", + "async-mutex": "^0.5.0", + "chart.js": "^4.4.3", + "chartjs-adapter-date-fns": "^3.0.0", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "comlink": "^4.4.1", + "common-tags": "^1.8.2", + "date-fns": "^3.6.0", + "framer-motion": "^11.2.10", + "highlightjs-curl": "^1.3.0", + "katex": "^0.16.10", + "libpg-query": "npm:@gregnr/libpg-query@15.2.0-rc.deparse.3", + "lodash": "^4.17.21", + "lucide-react": "^0.426.0", + "monaco-editor": "^0.49.0", + "nanoid": "^5.0.7", + "next": "14.2.3", + "next-themes": "^0.3.0", + "react": "^18", + "react-chartjs-2": "^5.2.0", + "react-dom": "^18", + "react-error-boundary": "^4.0.13", + "react-markdown": "^9.0.1", + "react-syntax-highlighter": "^15.5.0", + "react-use": "^17.5.1", + "reactflow": "^11.11.3", + "rehype-katex": "^7.0.0", + "remark-gfm": "^4.0.0", + "remark-math": "^6.0.0", + "sql-formatter": "^15.3.1", + "tailwind-merge": "^2.4.0", + "tailwindcss-animate": "^1.0.7", + "web-streams-polyfill": "^4.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@mertasan/tailwindcss-variables": "^2.7.0", + "@radix-ui/colors": "^3.0.0", + "@tailwindcss/forms": "^0.5.7", + "@tailwindcss/typography": "^0.5.14", + "@types/common-tags": "^1.8.4", + "@types/lodash": "^4.17.7", + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "@types/react-syntax-highlighter": "^15.5.13", + "@types/wicg-file-system-access": "^2023.10.5", + "autoprefixer": "^10.4.19", + "deepmerge": "^4.3.1", + "eslint": "^8", + "eslint-config-next": "14.2.3", + "mini-svg-data-uri": "^1.4.4", + "postcss": "^8", + "tailwindcss": "^3.4.6", + "tailwindcss-radix": "^3.0.3", + "typescript": "^5.5.2", + "webpack": "^5.95.0" + } }, - "apps/postgres-new/node_modules/nanoid": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", - "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "apps/web/node_modules/nanoid": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", + "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", "funding": [ { "type": "github", @@ -225,7 +311,7 @@ "node": "^18 || >=20" } }, - "apps/postgres-new/node_modules/web-streams-polyfill": { + "apps/web/node_modules/web-streams-polyfill": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0.tgz", "integrity": "sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==", @@ -1475,35 +1561,457 @@ "node": ">=6.9.0" } }, - "node_modules/@dagrejs/dagre": { - "version": "1.1.3", + "node_modules/@dagrejs/dagre": { + "version": "1.1.3", + "license": "MIT", + "dependencies": { + "@dagrejs/graphlib": "2.2.2" + } + }, + "node_modules/@dagrejs/graphlib": { + "version": "2.2.2", + "license": "MIT", + "engines": { + "node": ">17.0.0" + } + }, + "node_modules/@database.build/browser-proxy": { + "resolved": "apps/browser-proxy", + "link": true + }, + "node_modules/@database.build/deploy": { + "resolved": "packages/deploy", + "link": true + }, + "node_modules/@database.build/deploy-worker": { + "resolved": "apps/deploy-worker", + "link": true + }, + "node_modules/@database.build/web": { + "resolved": "apps/web", + "link": true + }, + "node_modules/@electric-sql/pglite": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.2.12.tgz", + "integrity": "sha512-J/X42ujcoFEbOkgRyoNqZB5qcqrnJRWVlwpH3fKYoJkTz49N91uAK/rDSSG/85WRas9nC9mdV4FnMTxnQWE/rw==", + "license": "Apache-2.0" + }, + "node_modules/@emnapi/runtime": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.43.1.tgz", + "integrity": "sha512-Q5sMc4Z4gsD4tlmlyFu+MpNAwpR7Gv2errDhVJ+SOhNjWcx8UTqy+hswb8L31RfC8jBvDgcnT87l3xI2w08rAg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@dagrejs/graphlib": "2.2.2" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@dagrejs/graphlib": { - "version": "2.2.2", + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "cpu": [ + "ia32" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">17.0.0" + "node": ">=18" } }, - "node_modules/@database.build/browser-proxy": { - "resolved": "apps/browser-proxy", - "link": true - }, - "node_modules/@database.build/deploy-worker": { - "resolved": "apps/deploy-worker", - "link": true - }, - "node_modules/@emnapi/runtime": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.43.1.tgz", - "integrity": "sha512-Q5sMc4Z4gsD4tlmlyFu+MpNAwpR7Gv2errDhVJ+SOhNjWcx8UTqy+hswb8L31RfC8jBvDgcnT87l3xI2w08rAg==", + "node_modules/@esbuild/win32-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.4.0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -3490,6 +3998,257 @@ "node": ">=10" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", + "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", + "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", + "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", + "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", + "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", + "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", + "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", + "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", + "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", + "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", + "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", + "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", + "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", + "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", + "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", + "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", + "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", + "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.3", "dev": true, @@ -4101,14 +4860,18 @@ } }, "node_modules/@supabase/auth-js": { - "version": "2.65.0", + "version": "2.65.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.65.1.tgz", + "integrity": "sha512-IA7i2Xq2SWNCNMKxwmPlHafBQda0qtnFr8QnyyBr+KaSxoXXqEzFCnQ1dGTy6bsZjVBgXu++o3qrDypTspaAPw==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/functions-js": { - "version": "2.4.1", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.3.tgz", + "integrity": "sha512-sOLXy+mWRyu4LLv1onYydq+10mNRQ4rzqQxNhbrKLTLTcdcmS9hbWif0bGz/NavmiQfPs4ZcmQJp4WqOXlR4AQ==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" @@ -4156,14 +4919,18 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "1.16.1", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.16.3.tgz", + "integrity": "sha512-HI6dsbW68AKlOPofUjDTaosiDBCtW4XAm0D18pPwxoW3zKOE2Ru13Z69Wuys9fd6iTpfDViNco5sgrtnP0666A==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/realtime-js": { - "version": "2.10.2", + "version": "2.10.7", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.10.7.tgz", + "integrity": "sha512-OLI0hiSAqQSqRpGMTUwoIWo51eUivSYlaNBgxsXZE7PSoWh12wPRdVt0psUMaUzEonSB85K21wGc7W5jHnT6uA==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14", @@ -4186,22 +4953,26 @@ } }, "node_modules/@supabase/storage-js": { - "version": "2.7.0", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.7.1.tgz", + "integrity": "sha512-asYHcyDR1fKqrMpytAS1zjyEfvxuOIp1CIXX7ji4lHHcJKqyk+sLl/Vxgm4sN6u8zvuUtae9e4kDxQP2qrwWBA==", "license": "MIT", "dependencies": { "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/supabase-js": { - "version": "2.45.4", + "version": "2.46.1", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.46.1.tgz", + "integrity": "sha512-HiBpd8stf7M6+tlr+/82L8b2QmCjAD8ex9YdSAKU+whB/SHXXJdus1dGlqiH9Umy9ePUuxaYmVkGd9BcvBnNvg==", "license": "MIT", "dependencies": { - "@supabase/auth-js": "2.65.0", - "@supabase/functions-js": "2.4.1", + "@supabase/auth-js": "2.65.1", + "@supabase/functions-js": "2.4.3", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.16.1", - "@supabase/realtime-js": "2.10.2", - "@supabase/storage-js": "2.7.0" + "@supabase/postgrest-js": "1.16.3", + "@supabase/realtime-js": "2.10.7", + "@supabase/storage-js": "2.7.1" } }, "node_modules/@swc/counter": { @@ -4567,7 +5338,9 @@ "license": "MIT" }, "node_modules/@types/estree": { - "version": "1.0.5", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -4701,9 +5474,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", + "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -6043,6 +6816,22 @@ "dev": true, "license": "MIT" }, + "node_modules/bundle-require": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.0.0.tgz", + "integrity": "sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -6054,6 +6843,16 @@ "node": ">=10.16.0" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cacache": { "version": "18.0.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", @@ -6459,6 +7258,16 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -7241,6 +8050,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" + } + }, "node_modules/escalade": { "version": "3.1.2", "dev": true, @@ -9802,6 +10651,16 @@ "jiti": "bin/jiti.js" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", @@ -10068,6 +10927,16 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -10133,6 +11002,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -12833,7 +13709,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -13154,10 +14032,6 @@ "node": ">=0.10.0" } }, - "node_modules/postgres-new": { - "resolved": "apps/postgres-new", - "link": true - }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -14166,6 +15040,44 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", + "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.4", + "@rollup/rollup-android-arm64": "4.24.4", + "@rollup/rollup-darwin-arm64": "4.24.4", + "@rollup/rollup-darwin-x64": "4.24.4", + "@rollup/rollup-freebsd-arm64": "4.24.4", + "@rollup/rollup-freebsd-x64": "4.24.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", + "@rollup/rollup-linux-arm-musleabihf": "4.24.4", + "@rollup/rollup-linux-arm64-gnu": "4.24.4", + "@rollup/rollup-linux-arm64-musl": "4.24.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", + "@rollup/rollup-linux-riscv64-gnu": "4.24.4", + "@rollup/rollup-linux-s390x-gnu": "4.24.4", + "@rollup/rollup-linux-x64-gnu": "4.24.4", + "@rollup/rollup-linux-x64-musl": "4.24.4", + "@rollup/rollup-win32-arm64-msvc": "4.24.4", + "@rollup/rollup-win32-ia32-msvc": "4.24.4", + "@rollup/rollup-win32-x64-msvc": "4.24.4", + "fsevents": "~2.3.2" + } + }, "node_modules/rtl-css-js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", @@ -15584,6 +16496,55 @@ "node": ">=10" } }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15617,6 +16578,16 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -15679,6 +16650,196 @@ "version": "2.6.3", "license": "0BSD" }, + "node_modules/tsup": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.3.5.tgz", + "integrity": "sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-require": "^5.0.0", + "cac": "^6.7.14", + "chokidar": "^4.0.1", + "consola": "^3.2.3", + "debug": "^4.3.7", + "esbuild": "^0.24.0", + "joycon": "^3.1.1", + "picocolors": "^1.1.1", + "postcss-load-config": "^6.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.24.0", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.35.0", + "tinyexec": "^0.3.1", + "tinyglobby": "^0.2.9", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tsup/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/tsup/node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/tsup/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsup/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tsup/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/tsup/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -15691,6 +16852,108 @@ "node": "*" } }, + "node_modules/turbo": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.2.3.tgz", + "integrity": "sha512-5lDvSqIxCYJ/BAd6rQGK/AzFRhBkbu4JHVMLmGh/hCb7U3CqSnr5Tjwfy9vc+/5wG2DJ6wttgAaA7MoCgvBKZQ==", + "dev": true, + "license": "MIT", + "bin": { + "turbo": "bin/turbo" + }, + "optionalDependencies": { + "turbo-darwin-64": "2.2.3", + "turbo-darwin-arm64": "2.2.3", + "turbo-linux-64": "2.2.3", + "turbo-linux-arm64": "2.2.3", + "turbo-windows-64": "2.2.3", + "turbo-windows-arm64": "2.2.3" + } + }, + "node_modules/turbo-darwin-64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.2.3.tgz", + "integrity": "sha512-Rcm10CuMKQGcdIBS3R/9PMeuYnv6beYIHqfZFeKWVYEWH69sauj4INs83zKMTUiZJ3/hWGZ4jet9AOwhsssLyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-darwin-arm64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.2.3.tgz", + "integrity": "sha512-+EIMHkuLFqUdJYsA3roj66t9+9IciCajgj+DVek+QezEdOJKcRxlvDOS2BUaeN8kEzVSsNiAGnoysFWYw4K0HA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-linux-64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.2.3.tgz", + "integrity": "sha512-UBhJCYnqtaeOBQLmLo8BAisWbc9v9daL9G8upLR+XGj6vuN/Nz6qUAhverN4Pyej1g4Nt1BhROnj6GLOPYyqxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-linux-arm64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.2.3.tgz", + "integrity": "sha512-hJYT9dN06XCQ3jBka/EWvvAETnHRs3xuO/rb5bESmDfG+d9yQjeTMlhRXKrr4eyIMt6cLDt1LBfyi+6CQ+VAwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-windows-64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.2.3.tgz", + "integrity": "sha512-NPrjacrZypMBF31b4HE4ROg4P3nhMBPHKS5WTpMwf7wydZ8uvdEHpESVNMOtqhlp857zbnKYgP+yJF30H3N2dQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/turbo-windows-arm64": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.2.3.tgz", + "integrity": "sha512-fnNrYBCqn6zgKPKLHu4sOkihBI/+0oYFr075duRxqUZ+1aLWTAGfHZLgjVeLh3zR37CVzuerGIPWAEkNhkWEIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -15795,7 +17058,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -16650,6 +17915,22 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } + }, + "packages/deploy": { + "name": "@database.build/deploy", + "version": "0.0.0", + "dependencies": { + "@supabase/supabase-js": "^2.46.1", + "neverthrow": "^8.0.0", + "openapi-fetch": "^0.13.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@total-typescript/tsconfig": "^1.0.4", + "openapi-typescript": "^7.4.2", + "tsup": "^8.3.5", + "typescript": "^5.6.3" + } } } } diff --git a/package.json b/package.json index 13df9187..9c29e366 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,13 @@ { + "name": "@database.build/root", "private": true, + "packageManager": "npm@10.8.3", "scripts": { - "dev": "npm run dev --workspace postgres-new" + "dev": "turbo watch dev" }, - "workspaces": ["apps/*"], + "workspaces": ["apps/*", "packages/*"], "devDependencies": { - "supabase": "^1.207.9" + "supabase": "^1.207.9", + "turbo": "^2.2.3" } } diff --git a/packages/deploy/package.json b/packages/deploy/package.json new file mode 100644 index 00000000..18a288a5 --- /dev/null +++ b/packages/deploy/package.json @@ -0,0 +1,30 @@ +{ + "name": "@database.build/deploy", + "version": "0.0.0", + "description": "Database deployment utilities", + "private": true, + "type": "module", + "exports": { + ".": "./dist/index.js", + "./supabase": "./dist/supabase/index.js" + }, + "scripts": { + "type-check": "tsc", + "build": "tsup", + "clean": "rm -rf dist", + "generate:database-types": "supabase gen types --lang=typescript --local > src/supabase/database-types.ts", + "generate:management-api-types": "openapi-typescript https://api.supabase.com/api/v1-json -o ./src/supabase/management-api/types.ts" + }, + "dependencies": { + "@supabase/supabase-js": "^2.46.1", + "neverthrow": "^8.0.0", + "openapi-fetch": "^0.13.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@total-typescript/tsconfig": "^1.0.4", + "openapi-typescript": "^7.4.2", + "tsup": "^8.3.5", + "typescript": "^5.6.3" + } +} diff --git a/apps/deploy-worker/src/error.ts b/packages/deploy/src/error.ts similarity index 100% rename from apps/deploy-worker/src/error.ts rename to packages/deploy/src/error.ts diff --git a/packages/deploy/src/index.ts b/packages/deploy/src/index.ts new file mode 100644 index 00000000..81762939 --- /dev/null +++ b/packages/deploy/src/index.ts @@ -0,0 +1 @@ +export * from './error.js' diff --git a/apps/deploy-worker/src/supabase/client.ts b/packages/deploy/src/supabase/client.ts similarity index 86% rename from apps/deploy-worker/src/supabase/client.ts rename to packages/deploy/src/supabase/client.ts index bdd8fc0c..bc023075 100644 --- a/apps/deploy-worker/src/supabase/client.ts +++ b/packages/deploy/src/supabase/client.ts @@ -1,5 +1,5 @@ import { createClient as createSupabaseClient } from '@supabase/supabase-js' -import type { Database } from './database-types.ts' +import type { Database } from './database-types.js' export const supabaseAdmin = createSupabaseClient( process.env.SUPABASE_URL!, diff --git a/apps/deploy-worker/src/supabase/create-deployed-database.ts b/packages/deploy/src/supabase/create-deployed-database.ts similarity index 95% rename from apps/deploy-worker/src/supabase/create-deployed-database.ts rename to packages/deploy/src/supabase/create-deployed-database.ts index 7c460c29..cf6cea53 100644 --- a/apps/deploy-worker/src/supabase/create-deployed-database.ts +++ b/packages/deploy/src/supabase/create-deployed-database.ts @@ -1,9 +1,9 @@ -import { DeployError } from '../error.ts' -import { generatePassword } from './generate-password.ts' -import { getAccessToken } from './get-access-token.ts' -import { createManagementApiClient } from './management-api/client.ts' -import type { Region, SupabaseClient, SupabaseProviderMetadata } from './types.ts' -import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.ts' +import { DeployError } from '../error.js' +import { generatePassword } from './generate-password.js' +import { getAccessToken } from './get-access-token.js' +import { createManagementApiClient } from './management-api/client.js' +import type { Region, SupabaseClient, SupabaseProviderMetadata } from './types.js' +import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.js' /** * Create a new project on Supabase and store the relevant metadata in the database. diff --git a/apps/deploy-worker/src/supabase/database-types.ts b/packages/deploy/src/supabase/database-types.ts similarity index 100% rename from apps/deploy-worker/src/supabase/database-types.ts rename to packages/deploy/src/supabase/database-types.ts diff --git a/apps/deploy-worker/src/supabase/deploy.ts b/packages/deploy/src/supabase/deploy.ts similarity index 96% rename from apps/deploy-worker/src/supabase/deploy.ts rename to packages/deploy/src/supabase/deploy.ts index 144547fb..7b684097 100644 --- a/apps/deploy-worker/src/supabase/deploy.ts +++ b/packages/deploy/src/supabase/deploy.ts @@ -1,12 +1,12 @@ -import type { SupabaseClient, SupabaseProviderMetadata } from './types.ts' +import type { SupabaseClient, SupabaseProviderMetadata } from './types.js' import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' -import { createDeployedDatabase } from './create-deployed-database.ts' -import { getDatabaseUrl, getPoolerUrl } from './get-database-url.ts' -import { DeployError, IntegrationRevokedError } from '../error.ts' -import { generatePassword } from './generate-password.ts' -import { getAccessToken } from './get-access-token.ts' -import { createManagementApiClient } from './management-api/client.ts' +import { createDeployedDatabase } from './create-deployed-database.js' +import { getDatabaseUrl, getPoolerUrl } from './get-database-url.js' +import { DeployError, IntegrationRevokedError } from '../error.js' +import { generatePassword } from './generate-password.js' +import { getAccessToken } from './get-access-token.js' +import { createManagementApiClient } from './management-api/client.js' const exec = promisify(execSync) /** diff --git a/apps/deploy-worker/src/supabase/generate-password.ts b/packages/deploy/src/supabase/generate-password.ts similarity index 100% rename from apps/deploy-worker/src/supabase/generate-password.ts rename to packages/deploy/src/supabase/generate-password.ts diff --git a/apps/deploy-worker/src/supabase/get-access-token.ts b/packages/deploy/src/supabase/get-access-token.ts similarity index 94% rename from apps/deploy-worker/src/supabase/get-access-token.ts rename to packages/deploy/src/supabase/get-access-token.ts index a96e6acc..0ae4238e 100644 --- a/apps/deploy-worker/src/supabase/get-access-token.ts +++ b/packages/deploy/src/supabase/get-access-token.ts @@ -1,6 +1,6 @@ -import { DeployError, IntegrationRevokedError } from '../error.ts' -import { supabaseAdmin } from './client.ts' -import type { Credentials } from './types.ts' +import { DeployError, IntegrationRevokedError } from '../error.js' +import { supabaseAdmin } from './client.js' +import type { Credentials } from './types.js' /** * Get the access token for a given Supabase integration. diff --git a/apps/deploy-worker/src/supabase/get-database-url.ts b/packages/deploy/src/supabase/get-database-url.ts similarity index 94% rename from apps/deploy-worker/src/supabase/get-database-url.ts rename to packages/deploy/src/supabase/get-database-url.ts index 8adc6328..c82d5f2a 100644 --- a/apps/deploy-worker/src/supabase/get-database-url.ts +++ b/packages/deploy/src/supabase/get-database-url.ts @@ -1,4 +1,4 @@ -import type { SupabaseProviderMetadata } from './types.ts' +import type { SupabaseProviderMetadata } from './types.js' /** * Get the direct database url for a given Supabase project. diff --git a/packages/deploy/src/supabase/index.ts b/packages/deploy/src/supabase/index.ts new file mode 100644 index 00000000..75e6cbcd --- /dev/null +++ b/packages/deploy/src/supabase/index.ts @@ -0,0 +1,8 @@ +export * from './client.js' +export * from './create-deployed-database.js' +export * from './deploy.js' +export * from './generate-password.js' +export * from './get-access-token.js' +export * from './get-database-url.js' +export * from './revoke-integration.js' +export * from './wait-for-health.js' diff --git a/apps/deploy-worker/src/supabase/management-api/client.ts b/packages/deploy/src/supabase/management-api/client.ts similarity index 85% rename from apps/deploy-worker/src/supabase/management-api/client.ts rename to packages/deploy/src/supabase/management-api/client.ts index a05935ff..907fa22f 100644 --- a/apps/deploy-worker/src/supabase/management-api/client.ts +++ b/packages/deploy/src/supabase/management-api/client.ts @@ -1,6 +1,6 @@ import createClient, { type Middleware } from 'openapi-fetch' -import type { paths } from './types.ts' -import { IntegrationRevokedError } from '../../error.ts' +import type { paths } from './types.js' +import { IntegrationRevokedError } from '../../error.js' const integrationRevokedMiddleware: Middleware = { async onResponse({ response }) { diff --git a/apps/deploy-worker/src/supabase/management-api/types.ts b/packages/deploy/src/supabase/management-api/types.ts similarity index 100% rename from apps/deploy-worker/src/supabase/management-api/types.ts rename to packages/deploy/src/supabase/management-api/types.ts diff --git a/apps/deploy-worker/src/supabase/revoke-integration.ts b/packages/deploy/src/supabase/revoke-integration.ts similarity index 90% rename from apps/deploy-worker/src/supabase/revoke-integration.ts rename to packages/deploy/src/supabase/revoke-integration.ts index 8efcc740..85e4aed7 100644 --- a/apps/deploy-worker/src/supabase/revoke-integration.ts +++ b/packages/deploy/src/supabase/revoke-integration.ts @@ -1,5 +1,5 @@ -import type { SupabaseClient } from './types.ts' -import { supabaseAdmin } from './client.ts' +import type { SupabaseClient } from './types.js' +import { supabaseAdmin } from './client.js' export async function revokeIntegration( ctx: { supabase: SupabaseClient }, diff --git a/apps/deploy-worker/src/supabase/types.ts b/packages/deploy/src/supabase/types.ts similarity index 91% rename from apps/deploy-worker/src/supabase/types.ts rename to packages/deploy/src/supabase/types.ts index 28b6a316..ecb5cc60 100644 --- a/apps/deploy-worker/src/supabase/types.ts +++ b/packages/deploy/src/supabase/types.ts @@ -1,6 +1,6 @@ -import type { createClient } from './client.ts' -import type { createManagementApiClient } from './management-api/client.ts' -import type { paths } from './management-api/types.ts' +import type { createClient } from './client.js' +import type { createManagementApiClient } from './management-api/client.js' +import type { paths } from './management-api/types.js' export type Credentials = { expiresAt: string; refreshToken: string; accessToken: string } diff --git a/apps/deploy-worker/src/supabase/wait-for-health.ts b/packages/deploy/src/supabase/wait-for-health.ts similarity index 96% rename from apps/deploy-worker/src/supabase/wait-for-health.ts rename to packages/deploy/src/supabase/wait-for-health.ts index 3eba8d27..05a9ff45 100644 --- a/apps/deploy-worker/src/supabase/wait-for-health.ts +++ b/packages/deploy/src/supabase/wait-for-health.ts @@ -1,5 +1,5 @@ -import { DeployError } from '../error.ts' -import type { ManagementApiClient, Project } from './types.ts' +import { DeployError } from '../error.js' +import type { ManagementApiClient, Project } from './types.js' import { setTimeout } from 'timers/promises' /** diff --git a/packages/deploy/tsconfig.json b/packages/deploy/tsconfig.json new file mode 100644 index 00000000..42cf8fb4 --- /dev/null +++ b/packages/deploy/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@total-typescript/tsconfig/tsc/no-dom/app", + "include": ["src/**/*.ts"], + "compilerOptions": { + "noEmit": true, + "outDir": "dist" + } +} diff --git a/packages/deploy/tsup.config.ts b/packages/deploy/tsup.config.ts new file mode 100644 index 00000000..5fc0fc1f --- /dev/null +++ b/packages/deploy/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'tsup' + +export default defineConfig([ + { + entry: ['src/index.ts', 'src/supabase/index.ts'], + format: ['cjs', 'esm'], + outDir: 'dist', + sourcemap: true, + dts: true, + minify: true, + splitting: true, + }, +]) diff --git a/turbo.json b/turbo.json new file mode 100644 index 00000000..9cf68258 --- /dev/null +++ b/turbo.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://turbo.build/schema.json", + "tasks": { + "@database.build/deploy#build": { + "dependsOn": ["^build"], + "cache": false + }, + "@database.build/deploy-worker#dev": { + "dependsOn": ["^build"], + "interruptible": true, + "persistent": true, + "cache": false + }, + "dev": { + "dependsOn": ["^build"], + "cache": false, + "persistent": true + }, + "type-check": { + "dependsOn": ["^type-check"] + } + } +} From aba7af748dba49241917f3bd8902593b501d6094 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Fri, 8 Nov 2024 15:45:27 -0700 Subject: [PATCH 39/59] chore(turbo): fix watch mode --- package-lock.json | 57 ++++++++++++++++++++++++----------------------- package.json | 5 +++-- turbo.json | 15 ++++++++----- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index 901acfe5..5ed14e9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ ], "devDependencies": { "supabase": "^1.207.9", - "turbo": "^2.2.3" + "turbo": "^2.2.4-canary.9" } }, "apps/browser-proxy": { @@ -212,6 +212,7 @@ "dependencies": { "@ai-sdk/openai": "^0.0.21", "@dagrejs/dagre": "^1.1.2", + "@database.build/deploy": "*", "@electric-sql/pglite": "^0.2.9", "@gregnr/postgres-meta": "^0.82.0-dev.2", "@monaco-editor/react": "^4.6.0", @@ -16853,27 +16854,27 @@ } }, "node_modules/turbo": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.2.3.tgz", - "integrity": "sha512-5lDvSqIxCYJ/BAd6rQGK/AzFRhBkbu4JHVMLmGh/hCb7U3CqSnr5Tjwfy9vc+/5wG2DJ6wttgAaA7MoCgvBKZQ==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.2.4-canary.9.tgz", + "integrity": "sha512-nuLYPHCT3Tu9fQvyDseXEAaVlZp6OZF1gotVSi3JHcxsj5JxAlV8Lg5feLfpMjLb9DRMkUuBrjK9CJPk2BkC7Q==", "dev": true, "license": "MIT", "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "2.2.3", - "turbo-darwin-arm64": "2.2.3", - "turbo-linux-64": "2.2.3", - "turbo-linux-arm64": "2.2.3", - "turbo-windows-64": "2.2.3", - "turbo-windows-arm64": "2.2.3" + "turbo-darwin-64": "2.2.4-canary.9", + "turbo-darwin-arm64": "2.2.4-canary.9", + "turbo-linux-64": "2.2.4-canary.9", + "turbo-linux-arm64": "2.2.4-canary.9", + "turbo-windows-64": "2.2.4-canary.9", + "turbo-windows-arm64": "2.2.4-canary.9" } }, "node_modules/turbo-darwin-64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.2.3.tgz", - "integrity": "sha512-Rcm10CuMKQGcdIBS3R/9PMeuYnv6beYIHqfZFeKWVYEWH69sauj4INs83zKMTUiZJ3/hWGZ4jet9AOwhsssLyg==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.2.4-canary.9.tgz", + "integrity": "sha512-oD5eqe5DlzjOXxO2KdNcib19LB0qhX04UVZpY/dcNKAjFUb46nKgRD/2aLBOdn+g7a7KKmMHvwA4KU0PkBcUCQ==", "cpu": [ "x64" ], @@ -16885,9 +16886,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.2.3.tgz", - "integrity": "sha512-+EIMHkuLFqUdJYsA3roj66t9+9IciCajgj+DVek+QezEdOJKcRxlvDOS2BUaeN8kEzVSsNiAGnoysFWYw4K0HA==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.2.4-canary.9.tgz", + "integrity": "sha512-NPe6T3cVUoYrZJN3uws3EupaFZsLIEDrFDzOor6neEFVjqSV/BSR3GuGcCCrf83Zjf1QqcTf3UWmInoKm1mtog==", "cpu": [ "arm64" ], @@ -16899,9 +16900,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.2.3.tgz", - "integrity": "sha512-UBhJCYnqtaeOBQLmLo8BAisWbc9v9daL9G8upLR+XGj6vuN/Nz6qUAhverN4Pyej1g4Nt1BhROnj6GLOPYyqxQ==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.2.4-canary.9.tgz", + "integrity": "sha512-gHFvhblgm8DymUseeqK3ADudbbb8BHpWN/jsiJlZQbrzWGQDkg7PFrExedOy1EZz31ZJ13pZZ87oAjafsCui/Q==", "cpu": [ "x64" ], @@ -16913,9 +16914,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.2.3.tgz", - "integrity": "sha512-hJYT9dN06XCQ3jBka/EWvvAETnHRs3xuO/rb5bESmDfG+d9yQjeTMlhRXKrr4eyIMt6cLDt1LBfyi+6CQ+VAwQ==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.2.4-canary.9.tgz", + "integrity": "sha512-0nInXz9nvQr7AF/Xl2t7+xQqI4jA6Hi5JWMRuDTQ9EmO785jJz9He1MnP59aJrrVG0GWNgYKZJj5AzAnYZw4cA==", "cpu": [ "arm64" ], @@ -16927,9 +16928,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.2.3.tgz", - "integrity": "sha512-NPrjacrZypMBF31b4HE4ROg4P3nhMBPHKS5WTpMwf7wydZ8uvdEHpESVNMOtqhlp857zbnKYgP+yJF30H3N2dQ==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.2.4-canary.9.tgz", + "integrity": "sha512-C8rfMvxTfMWzbZUwRRnj8v825jR+Z+0fMM5NAfZEx4qsjJqgfT/yGCCOjYxX6AxLi2rJT5HMpayjfDN1otnFBg==", "cpu": [ "x64" ], @@ -16941,9 +16942,9 @@ ] }, "node_modules/turbo-windows-arm64": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.2.3.tgz", - "integrity": "sha512-fnNrYBCqn6zgKPKLHu4sOkihBI/+0oYFr075duRxqUZ+1aLWTAGfHZLgjVeLh3zR37CVzuerGIPWAEkNhkWEIw==", + "version": "2.2.4-canary.9", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.2.4-canary.9.tgz", + "integrity": "sha512-86FhIPL51ZsTOcL21GduRI91nVtSQTVsPnJjeD1IAhhewwcvn3R8xMH0ndI/1DvHq566QUj73AIp/M5mnwwIKw==", "cpu": [ "arm64" ], diff --git a/package.json b/package.json index 9c29e366..b2026b63 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,12 @@ "private": true, "packageManager": "npm@10.8.3", "scripts": { - "dev": "turbo watch dev" + "dev": "turbo watch dev", + "build": "turbo run build" }, "workspaces": ["apps/*", "packages/*"], "devDependencies": { "supabase": "^1.207.9", - "turbo": "^2.2.3" + "turbo": "^2.2.4-canary.9" } } diff --git a/turbo.json b/turbo.json index 9cf68258..75ef8ad4 100644 --- a/turbo.json +++ b/turbo.json @@ -1,20 +1,23 @@ { - "$schema": "https://turbo.build/schema.json", + "$schema": "https://turbo.build/schema.v2.json", + "ui": "stream", "tasks": { "@database.build/deploy#build": { "dependsOn": ["^build"], - "cache": false + "outputs": ["dist/**"], + "cache": true }, "@database.build/deploy-worker#dev": { "dependsOn": ["^build"], - "interruptible": true, "persistent": true, + "interruptible": true, "cache": false }, - "dev": { + "@database.build/web#dev": { "dependsOn": ["^build"], - "cache": false, - "persistent": true + "outputs": [".next/**", "!.next/cache/**"], + "persistent": true, + "cache": true }, "type-check": { "dependsOn": ["^type-check"] From 50b5255dcba3e58683248435d02751eb3a224538 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Fri, 8 Nov 2024 15:57:48 -0700 Subject: [PATCH 40/59] feat: integration details --- .../deploy-worker/src}/deploy.ts | 41 ++++-- apps/deploy-worker/src/index.ts | 42 +++++- apps/deploy-worker/tsconfig.json | 1 + apps/web/.env.example | 1 + .../api/integrations/[id]/details/route.ts | 129 ++++++++++++++++++ .../app/api/oauth/supabase/callback/route.ts | 23 +--- .../api/oauth/supabase/organizations/route.ts | 6 - apps/web/components/deploy/deploy-dialog.tsx | 102 ++++++++++++-- .../web/components/deploy/redeploy-dialog.tsx | 6 +- apps/web/components/sidebar.tsx | 35 ++--- .../deployed-databases-query.ts | 22 ++- .../data/integrations/integration-query.ts | 50 ++++--- .../data/merged-databases/merged-databases.ts | 33 +++++ apps/web/utils/supabase/db-types.ts | 9 +- apps/web/utils/supabase/server.ts | 8 ++ packages/deploy/src/supabase/client.ts | 11 -- .../src/supabase/create-deployed-database.ts | 26 +++- .../deploy/src/supabase/database-types.ts | 9 +- .../deploy/src/supabase/get-access-token.ts | 25 ++-- packages/deploy/src/supabase/index.ts | 7 +- .../src/supabase/management-api/client.ts | 8 +- .../deploy/src/supabase/revoke-integration.ts | 8 +- packages/deploy/src/supabase/types.ts | 16 ++- .../deploy/src/supabase/wait-for-health.ts | 5 +- .../migrations/20241003131953_deployment.sql | 26 ++++ 25 files changed, 507 insertions(+), 142 deletions(-) rename {packages/deploy/src/supabase => apps/deploy-worker/src}/deploy.ts (86%) create mode 100644 apps/web/app/api/integrations/[id]/details/route.ts delete mode 100644 apps/web/app/api/oauth/supabase/organizations/route.ts create mode 100644 apps/web/data/merged-databases/merged-databases.ts delete mode 100644 packages/deploy/src/supabase/client.ts diff --git a/packages/deploy/src/supabase/deploy.ts b/apps/deploy-worker/src/deploy.ts similarity index 86% rename from packages/deploy/src/supabase/deploy.ts rename to apps/deploy-worker/src/deploy.ts index 7b684097..af253f86 100644 --- a/packages/deploy/src/supabase/deploy.ts +++ b/apps/deploy-worker/src/deploy.ts @@ -1,12 +1,18 @@ -import type { SupabaseClient, SupabaseProviderMetadata } from './types.js' import { exec as execSync } from 'node:child_process' import { promisify } from 'node:util' -import { createDeployedDatabase } from './create-deployed-database.js' -import { getDatabaseUrl, getPoolerUrl } from './get-database-url.js' -import { DeployError, IntegrationRevokedError } from '../error.js' -import { generatePassword } from './generate-password.js' -import { getAccessToken } from './get-access-token.js' -import { createManagementApiClient } from './management-api/client.js' +import { DeployError, IntegrationRevokedError } from '@database.build/deploy' +import { + getAccessToken, + createManagementApiClient, + createDeployedDatabase, + generatePassword, + getDatabaseUrl, + getPoolerUrl, + type SupabaseClient, + type SupabaseDeploymentConfig, + type SupabasePlatformConfig, + type SupabaseProviderMetadata, +} from '@database.build/deploy/supabase' const exec = promisify(execSync) /** @@ -14,7 +20,12 @@ const exec = promisify(execSync) * If the database was already deployed, it will overwrite the existing database data */ export async function deploy( - ctx: { supabase: SupabaseClient }, + ctx: { + supabase: SupabaseClient + supabaseAdmin: SupabaseClient + supabasePlatformConfig: SupabasePlatformConfig + supabaseDeploymentConfig: SupabaseDeploymentConfig + }, params: { databaseId: string; integrationId: number; localDatabaseUrl: string } ) { // check if the integration is still active @@ -32,13 +43,13 @@ export async function deploy( throw new IntegrationRevokedError() } - const accessToken = await getAccessToken({ + const accessToken = await getAccessToken(ctx, { integrationId: params.integrationId, // the integration isn't revoked, so it must have credentials credentialsSecretId: integration.data.credentials!, }) - const managementApiClient = createManagementApiClient(accessToken) + const managementApiClient = createManagementApiClient(ctx, accessToken) // this is just to check if the integration is still active, an IntegrationRevokedError will be thrown if not await managementApiClient.GET('/v1/organizations') @@ -75,10 +86,10 @@ export async function deploy( let databasePassword: string | undefined if (!deployedDatabase.data) { - const createdDeployedDatabase = await createDeployedDatabase( - { supabase: ctx.supabase }, - { databaseId: params.databaseId, integrationId: params.integrationId } - ) + const createdDeployedDatabase = await createDeployedDatabase(ctx, { + databaseId: params.databaseId, + integrationId: params.integrationId, + }) deployedDatabase.data = createdDeployedDatabase.deployedDatabase databasePassword = createdDeployedDatabase.databasePassword @@ -186,7 +197,7 @@ export async function deploy( return { name: project.name, - url: `${process.env.SUPABASE_PLATFORM_URL}/dashboard/project/${project.id}`, + url: `${ctx.supabasePlatformConfig.url}/dashboard/project/${project.id}`, databasePassword, databaseUrl: getDatabaseUrl({ project, databasePassword }), poolerUrl: getPoolerUrl({ project, databasePassword }), diff --git a/apps/deploy-worker/src/index.ts b/apps/deploy-worker/src/index.ts index 5825da6e..04af8fc2 100644 --- a/apps/deploy-worker/src/index.ts +++ b/apps/deploy-worker/src/index.ts @@ -1,13 +1,30 @@ import { DeployError, IntegrationRevokedError } from '@database.build/deploy' -import { createClient } from '@database.build/deploy/supabase' -import { deploy } from '@database.build/deploy/supabase' +import { + type Database, + type Region, + type SupabaseDeploymentConfig, + type SupabasePlatformConfig, +} from '@database.build/deploy/supabase' import { revokeIntegration } from '@database.build/deploy/supabase' import { serve } from '@hono/node-server' import { zValidator } from '@hono/zod-validator' +import { createClient } from '@supabase/supabase-js' import { Hono } from 'hono' import { cors } from 'hono/cors' import { HTTPException } from 'hono/http-exception' import { z } from 'zod' +import { deploy } from './deploy.ts' + +const supabasePlatformConfig: SupabasePlatformConfig = { + url: process.env.SUPABASE_PLATFORM_URL!, + apiUrl: process.env.SUPABASE_PLATFORM_API_URL!, + oauthClientId: process.env.SUPABASE_OAUTH_CLIENT_ID!, + oauthSecret: process.env.SUPABASE_OAUTH_SECRET!, +} + +const supabaseDeploymentConfig: SupabaseDeploymentConfig = { + region: process.env.SUPABASE_PLATFORM_DEPLOY_REGION! as Region, +} const app = new Hono() @@ -32,7 +49,15 @@ app.post( throw new HTTPException(401, { message: 'Unauthorized' }) } - const supabase = createClient() + const supabaseAdmin = createClient( + process.env.SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! + ) + + const supabase = createClient( + process.env.SUPABASE_URL!, + process.env.SUPABASE_ANON_KEY! + ) const { error } = await supabase.auth.setSession({ access_token: accessToken, @@ -43,8 +68,15 @@ app.post( throw new HTTPException(401, { message: 'Unauthorized' }) } + const ctx = { + supabase, + supabaseAdmin, + supabasePlatformConfig, + supabaseDeploymentConfig, + } + try { - const project = await deploy({ supabase }, { databaseId, integrationId, localDatabaseUrl }) + const project = await deploy(ctx, { databaseId, integrationId, localDatabaseUrl }) return c.json({ project }) } catch (error: unknown) { console.error(error) @@ -52,7 +84,7 @@ app.post( throw new HTTPException(500, { message: error.message }) } if (error instanceof IntegrationRevokedError) { - await revokeIntegration({ supabase }, { integrationId }) + await revokeIntegration(ctx, { integrationId }) throw new HTTPException(406, { message: error.message }) } throw new HTTPException(500, { message: 'Internal server error' }) diff --git a/apps/deploy-worker/tsconfig.json b/apps/deploy-worker/tsconfig.json index 42cf8fb4..0963b32c 100644 --- a/apps/deploy-worker/tsconfig.json +++ b/apps/deploy-worker/tsconfig.json @@ -2,6 +2,7 @@ "extends": "@total-typescript/tsconfig/tsc/no-dom/app", "include": ["src/**/*.ts"], "compilerOptions": { + "allowImportingTsExtensions": true, "noEmit": true, "outDir": "dist" } diff --git a/apps/web/.env.example b/apps/web/.env.example index 2ff8a91e..2c724409 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -3,6 +3,7 @@ NEXT_PUBLIC_SUPABASE_URL="" NEXT_PUBLIC_BROWSER_PROXY_DOMAIN="browser.dev.db.build" NEXT_PUBLIC_DEPLOY_WORKER_DOMAIN="http://localhost:4000" NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID="" +NEXT_PUBLIC_SUPABASE_PLATFORM_URL=https://supabase.com NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL=https://api.supabase.com OPENAI_API_KEY="" diff --git a/apps/web/app/api/integrations/[id]/details/route.ts b/apps/web/app/api/integrations/[id]/details/route.ts new file mode 100644 index 00000000..998ed4de --- /dev/null +++ b/apps/web/app/api/integrations/[id]/details/route.ts @@ -0,0 +1,129 @@ +import { IntegrationRevokedError } from '@database.build/deploy' +import { + createManagementApiClient, + getAccessToken, + revokeIntegration, + SupabasePlatformConfig, +} from '@database.build/deploy/supabase' +import { createAdminClient, createClient } from '~/utils/supabase/server' + +export type IntegrationDetails = { + id: number + provider: { + id: number + name: string + } + organization: { + id: string + name: string + } +} + +const supabasePlatformConfig: SupabasePlatformConfig = { + url: process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_URL!, + apiUrl: process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL!, + oauthClientId: process.env.NEXT_PUBLIC_SUPABASE_OAUTH_CLIENT_ID!, + oauthSecret: process.env.SUPABASE_OAUTH_SECRET!, +} + +/** + * Gets the details of an integration by querying the Supabase + * management API. Details include the organization ID and name + * that the integration is scoped to. + */ +export async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) { + const { id } = await params + const supabase = createClient() + const supabaseAdmin = createAdminClient() + + const ctx = { + supabase, + supabaseAdmin, + supabasePlatformConfig, + } + + const integrationId = parseInt(id, 10) + + try { + const { data: integration, error: getIntegrationError } = await supabase + .from('deployment_provider_integrations') + .select('*, provider:deployment_providers!inner(id, name)') + .eq('id', integrationId) + .single() + + if (getIntegrationError) { + throw new Error('Integration not found', { cause: getIntegrationError }) + } + + if (integration.revoked_at) { + throw new IntegrationRevokedError() + } + + const credentialsSecretId = integration.credentials + + if (!credentialsSecretId) { + throw new Error('Integration has no credentials') + } + + if (!integration.scope) { + throw new Error('Integration has no scope') + } + + if ( + typeof integration.scope !== 'object' || + !('organizationId' in integration.scope) || + typeof integration.scope.organizationId !== 'string' + ) { + throw new Error('Integration scope is invalid') + } + + const accessToken = await getAccessToken(ctx, { + integrationId: integration.id, + credentialsSecretId, + }) + + const managementApiClient = createManagementApiClient(ctx, accessToken) + + const { data: organization, error: getOrgError } = await managementApiClient.GET( + `/v1/organizations/{slug}`, + { + params: { + path: { + slug: integration.scope.organizationId, + }, + }, + } + ) + + if (getOrgError) { + throw new Error('Failed to retrieve organization', { cause: getOrgError }) + } + + const integrationDetails: IntegrationDetails = { + id: integration.id, + provider: { + id: integration.provider.id, + name: integration.provider.name, + }, + organization: { + id: organization.id, + name: organization.name, + }, + } + + return Response.json(integrationDetails) + } catch (error: unknown) { + console.error(error) + + if (error instanceof IntegrationRevokedError) { + await revokeIntegration(ctx, { integrationId }) + return Response.json({ message: error.message }, { status: 406 }) + } + + if (error instanceof Error) { + return Response.json({ message: error.message }, { status: 400 }) + } + + return Response.json({ message: 'Internal server error' }, { status: 500 }) + } +} diff --git a/apps/web/app/api/oauth/supabase/callback/route.ts b/apps/web/app/api/oauth/supabase/callback/route.ts index 89915a2f..a3da84fd 100644 --- a/apps/web/app/api/oauth/supabase/callback/route.ts +++ b/apps/web/app/api/oauth/supabase/callback/route.ts @@ -74,8 +74,6 @@ export async function GET(req: NextRequest) { token_type: 'Bearer' } - console.log({ tokens }) - const organizationsResponse = await fetch( `${process.env.NEXT_PUBLIC_SUPABASE_PLATFORM_API_URL}/v1/organizations`, { @@ -128,9 +126,11 @@ export async function GET(req: NextRequest) { const adminClient = createAdminClient() + const secretName = `oauth_credentials_supabase_${organization.id}_${user.id}` + // store the tokens as secret - const credentialsSecret = await adminClient.rpc('insert_secret', { - name: `oauth_credentials_supabase_${organization.id}_${user.id}`, + const credentialsSecret = await adminClient.rpc('upsert_secret', { + name: secretName, secret: JSON.stringify({ accessToken: tokens.access_token, expiresAt: new Date(now + tokens.expires_in * 1000).toISOString(), @@ -139,12 +139,11 @@ export async function GET(req: NextRequest) { }) if (credentialsSecret.error) { + console.error(credentialsSecret.error) return new Response('Failed to store the integration credentials as secret', { status: 500 }) } - let integrationId: number - - // if an existing revoked integration exists, update the tokens and cancel the revokation + // if an existing revoked integration exists, update the tokens and cancel the revocation if (revokedIntegration) { const updateIntegrationResponse = await supabase .from('deployment_provider_integrations') @@ -157,8 +156,6 @@ export async function GET(req: NextRequest) { if (updateIntegrationResponse.error) { return new Response('Failed to update integration', { status: 500 }) } - - integrationId = revokedIntegration.id } else { const createIntegrationResponse = await supabase .from('deployment_provider_integrations') @@ -175,13 +172,7 @@ export async function GET(req: NextRequest) { if (createIntegrationResponse.error) { return new Response('Failed to create integration', { status: 500 }) } - - integrationId = createIntegrationResponse.data.id } - const params = new URLSearchParams({ - integration: integrationId.toString(), - }) - - return NextResponse.redirect(new URL(`/deploy/${state.databaseId}?${params.toString()}`, req.url)) + return NextResponse.redirect(new URL(`/db/${state.databaseId}?deploy=Supabase`, req.url)) } diff --git a/apps/web/app/api/oauth/supabase/organizations/route.ts b/apps/web/app/api/oauth/supabase/organizations/route.ts deleted file mode 100644 index e23c4487..00000000 --- a/apps/web/app/api/oauth/supabase/organizations/route.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { NextRequest } from 'next/server' -import { createClient } from '~/utils/supabase/server' - -export async function GET(req: NextRequest) { - const supabase = createClient() -} diff --git a/apps/web/components/deploy/deploy-dialog.tsx b/apps/web/components/deploy/deploy-dialog.tsx index 98318e38..a495e8e1 100644 --- a/apps/web/components/deploy/deploy-dialog.tsx +++ b/apps/web/components/deploy/deploy-dialog.tsx @@ -1,25 +1,111 @@ 'use client' -import { DialogProps } from '@radix-ui/react-dialog' +import { generateProjectName } from '@database.build/deploy/supabase' +import { PropsWithChildren } from 'react' import { Button } from '~/components/ui/button' -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, +} from '~/components/ui/dialog' +import { useIntegrationQuery } from '~/data/integrations/integration-query' +import { SupabaseIcon } from '../supabase-icon' -export type DeployDialogProps = DialogProps & { - onConfirm?: () => void +export type DeployDialogProps = { + databaseId: string + open: boolean + onOpenChange: (open: boolean) => void + onConfirm: () => void + onCancel: () => void } -export function DeployDialog({ onConfirm, ...props }: DeployDialogProps) { +export function DeployDialog({ + databaseId, + open, + onOpenChange, + onConfirm, + onCancel, +}: DeployDialogProps) { + const { data: integration } = useIntegrationQuery('Supabase') + return ( - + - Deploy to Supabase + + + Deploy to Supabase +
- + {!integration ? ( +

Loading...

+ ) : ( +
+ You are about to deploy your in-browser database to Supabase. This will create a new + Supabase project under your linked organization. + + Would you like to deploy this database? +
+ )}
+ + + +
) } + +type DeployCardProps = { + organization: { id: string; name: string } + projectName: string +} + +function DeployCard({ organization, projectName }: DeployCardProps) { + return ( +
+ + + {organization.name} + {' '} + ({organization.id}) + +
+ {projectName} +
+ ) +} + +type DeployCardRowProps = PropsWithChildren<{ + label: string +}> + +function DeployCardRow({ label, children }: DeployCardRowProps) { + return ( +
+
{label}
+
+
{children}
+
+ ) +} diff --git a/apps/web/components/deploy/redeploy-dialog.tsx b/apps/web/components/deploy/redeploy-dialog.tsx index bfb9943f..bd207a49 100644 --- a/apps/web/components/deploy/redeploy-dialog.tsx +++ b/apps/web/components/deploy/redeploy-dialog.tsx @@ -14,7 +14,7 @@ import { Button } from '../ui/button' export type RedeployDialogProps = { database: Database - isOpen: boolean + open: boolean onOpenChange: (open: boolean) => void onConfirm: () => void onCancel: () => void @@ -22,14 +22,14 @@ export type RedeployDialogProps = { export function RedeployDialog({ database, - isOpen, + open, onOpenChange, onConfirm, onCancel, }: RedeployDialogProps) { const [confirmedValue, setConfirmedValue] = useState('') return ( - + Confirm redeploy of {database.name} diff --git a/apps/web/components/sidebar.tsx b/apps/web/components/sidebar.tsx index 49e0aa2d..1e4f7754 100644 --- a/apps/web/components/sidebar.tsx +++ b/apps/web/components/sidebar.tsx @@ -26,10 +26,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/u import { Tooltip, TooltipContent, TooltipTrigger } from '~/components/ui/tooltip' import { useDatabaseDeleteMutation } from '~/data/databases/database-delete-mutation' import { useDatabaseUpdateMutation } from '~/data/databases/database-update-mutation' -import { useDatabasesQuery } from '~/data/databases/databases-query' -import { useDeployedDatabasesQuery } from '~/data/deployed-databases/deployed-databases-query' import { useIntegrationQuery } from '~/data/integrations/integration-query' -import { Database as LocalDatabase } from '~/lib/db' +import { MergedDatabase, useMergedDatabases } from '~/data/merged-databases/merged-databases' import { downloadFile, getDeployUrl, getOauthUrl, titleToKebabCase } from '~/lib/util' import { cn } from '~/lib/utils' import { useApp } from './app-provider' @@ -52,10 +50,6 @@ import { DropdownMenuTrigger, } from './ui/dropdown-menu' -type Database = LocalDatabase & { - isDeployed: boolean -} - export default function Sidebar() { const { user, @@ -69,18 +63,9 @@ export default function Sidebar() { } = useApp() let { id: currentDatabaseId } = useParams<{ id: string }>() const router = useRouter() - const { data: localDatabases, isLoading: isLoadingLocalDatabases } = useDatabasesQuery() - const { data: deployedDatabases, isLoading: isLoadingDeployedDatabases } = - useDeployedDatabasesQuery() const [showSidebar, setShowSidebar] = useState(true) - const isLoadingDatabases = isLoadingLocalDatabases && isLoadingDeployedDatabases - - const databases = localDatabases?.map((db) => ({ - ...db, - isDeployed: - deployedDatabases?.some((deployedDb) => deployedDb.local_database_id === db.id) ?? false, - })) + const { data: databases, isLoading: isLoadingDatabases } = useMergedDatabases() return ( <> @@ -314,7 +299,7 @@ export default function Sidebar() { } type DatabaseMenuItemProps = { - database: Database + database: MergedDatabase isActive: boolean } @@ -347,6 +332,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { }} /> { setIsDeployDialogOpen(open) @@ -365,10 +351,13 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { router.push(deployUrl) }} + onCancel={() => { + setIsDeploying(false) + }} /> { router.push(deployUrl!) @@ -527,10 +516,12 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { e.preventDefault() if (!supabaseIntegration) { setIsIntegrationDialogOpen(true) - } else if (!database.isDeployed) { - setIsDeployDialogOpen(true) - } else { + } else if ( + database.deployments.some((d) => d.provider_name === 'Supabase') + ) { setIsRedeployDialogOpen(true) + } else { + setIsDeployDialogOpen(true) } }} > diff --git a/apps/web/data/deployed-databases/deployed-databases-query.ts b/apps/web/data/deployed-databases/deployed-databases-query.ts index 17e8f6b3..1d7649d3 100644 --- a/apps/web/data/deployed-databases/deployed-databases-query.ts +++ b/apps/web/data/deployed-databases/deployed-databases-query.ts @@ -1,8 +1,22 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' -import { Database } from '~/utils/supabase/db-types' import { createClient } from '~/utils/supabase/client' -type DeployedDatabase = Database['public']['Tables']['deployed_databases']['Row'] +export type DeployedDatabase = Awaited>[number] + +async function getDeployedDatabases() { + const supabase = createClient() + const { data, error } = await supabase + .from('deployed_databases') + .select( + '*, ...deployment_provider_integrations!inner(...deployment_providers!inner(provider_name:name))' + ) + + if (error) { + throw error + } + + return data +} export const useDeployedDatabasesQuery = ( options: Omit, 'queryKey' | 'queryFn'> = {} @@ -11,9 +25,7 @@ export const useDeployedDatabasesQuery = ( ...options, queryKey: getDeployedDatabasesQueryKey(), queryFn: async () => { - const supabase = createClient() - const deployedDatabases = await supabase.from('deployed_databases').select() - return deployedDatabases.data ?? [] + return await getDeployedDatabases() }, }) } diff --git a/apps/web/data/integrations/integration-query.ts b/apps/web/data/integrations/integration-query.ts index e500f750..e018ccc6 100644 --- a/apps/web/data/integrations/integration-query.ts +++ b/apps/web/data/integrations/integration-query.ts @@ -1,36 +1,44 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' -import { Database } from '~/utils/supabase/db-types' +import { IntegrationDetails } from '~/app/api/integrations/[id]/details/route' import { createClient } from '~/utils/supabase/client' -export type Integration = { - id: number - deployment_providers: { - name: string +async function getIntegrationDetails(id: number): Promise { + const response = await fetch(`/api/integrations/${id}/details`) + + if (!response.ok) { + throw new Error('Failed to fetch integration details') } + + return await response.json() +} + +async function getIntegration(name: string) { + const supabase = createClient() + + const { data, error } = await supabase + .from('deployment_provider_integrations') + .select('id, deployment_providers!inner()') + .eq('deployment_providers.name', name) + .is('revoked_at', null) + .single() + + if (error) { + throw error + } + + return data } export const useIntegrationQuery = ( name: string, - options: Omit, 'queryKey' | 'queryFn'> = {} + options: Omit, 'queryKey' | 'queryFn'> = {} ) => { - return useQuery({ + return useQuery({ ...options, queryKey: getIntegrationQueryKey(name), queryFn: async () => { - const supabase = createClient() - - const { data, error } = await supabase - .from('deployment_provider_integrations') - .select('id, deployment_providers!inner(name)') - .eq('deployment_providers.name', name) - .is('revoked_at', null) - .single() - - if (error) { - throw error - } - - return data + const { id } = await getIntegration(name) + return await getIntegrationDetails(id) }, }) } diff --git a/apps/web/data/merged-databases/merged-databases.ts b/apps/web/data/merged-databases/merged-databases.ts new file mode 100644 index 00000000..c069a0cb --- /dev/null +++ b/apps/web/data/merged-databases/merged-databases.ts @@ -0,0 +1,33 @@ +import { Database } from '~/lib/db' +import { useDatabasesQuery } from '../databases/databases-query' +import { + DeployedDatabase, + useDeployedDatabasesQuery, +} from '../deployed-databases/deployed-databases-query' + +export type MergedDatabase = Database & { + deployments: DeployedDatabase[] +} + +/** + * Merges local databases with deployed databases. + */ +export function useMergedDatabases() { + const { data: localDatabases, isLoading: isLoadingLocalDatabases } = useDatabasesQuery() + const { data: deployedDatabases, isLoading: isLoadingDeployedDatabases } = + useDeployedDatabasesQuery() + + const isLoading = isLoadingLocalDatabases && isLoadingDeployedDatabases + + if (!localDatabases) { + return { data: undefined, isLoading } + } + + const databases = localDatabases.map((db) => ({ + ...db, + deployments: + deployedDatabases?.filter((deployedDb) => deployedDb.local_database_id === db.id) ?? [], + })) + + return { data: databases, isLoading } +} diff --git a/apps/web/utils/supabase/db-types.ts b/apps/web/utils/supabase/db-types.ts index f57a5e9c..454cfbd9 100644 --- a/apps/web/utils/supabase/db-types.ts +++ b/apps/web/utils/supabase/db-types.ts @@ -199,7 +199,7 @@ export type Database = { Args: { secret_id: string } - Returns: string + Returns: number } insert_secret: { Args: { @@ -229,6 +229,13 @@ export type Database = { } Returns: string } + upsert_secret: { + Args: { + secret: string + name: string + } + Returns: string + } } Enums: { deployment_status: "in_progress" | "success" | "failed" diff --git a/apps/web/utils/supabase/server.ts b/apps/web/utils/supabase/server.ts index fe6aabfb..bcdbada7 100644 --- a/apps/web/utils/supabase/server.ts +++ b/apps/web/utils/supabase/server.ts @@ -1,6 +1,7 @@ import { createServerClient } from '@supabase/ssr' import { cookies } from 'next/headers' import { Database } from './db-types' +import { createClient as createSupabaseClient } from '@supabase/supabase-js' export function createClient() { const cookieStore = cookies() @@ -28,3 +29,10 @@ export function createClient() { } ) } + +export function createAdminClient() { + return createSupabaseClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_KEY! + ) +} diff --git a/packages/deploy/src/supabase/client.ts b/packages/deploy/src/supabase/client.ts deleted file mode 100644 index bc023075..00000000 --- a/packages/deploy/src/supabase/client.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createClient as createSupabaseClient } from '@supabase/supabase-js' -import type { Database } from './database-types.js' - -export const supabaseAdmin = createSupabaseClient( - process.env.SUPABASE_URL!, - process.env.SUPABASE_SERVICE_ROLE_KEY! -) - -export function createClient() { - return createSupabaseClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!) -} diff --git a/packages/deploy/src/supabase/create-deployed-database.ts b/packages/deploy/src/supabase/create-deployed-database.ts index cf6cea53..cbc03566 100644 --- a/packages/deploy/src/supabase/create-deployed-database.ts +++ b/packages/deploy/src/supabase/create-deployed-database.ts @@ -2,15 +2,30 @@ import { DeployError } from '../error.js' import { generatePassword } from './generate-password.js' import { getAccessToken } from './get-access-token.js' import { createManagementApiClient } from './management-api/client.js' -import type { Region, SupabaseClient, SupabaseProviderMetadata } from './types.js' +import type { + SupabaseClient, + SupabaseDeploymentConfig, + SupabasePlatformConfig, + SupabaseProviderMetadata, +} from './types.js' import { waitForDatabaseToBeHealthy, waitForProjectToBeHealthy } from './wait-for-health.js' +/** + * Generate a project name for a deployed database. + */ +export function generateProjectName(databaseId: string) { + return `database-build-${databaseId}` +} + /** * Create a new project on Supabase and store the relevant metadata in the database. */ export async function createDeployedDatabase( ctx: { supabase: SupabaseClient + supabaseAdmin: SupabaseClient + supabasePlatformConfig: SupabasePlatformConfig + supabaseDeploymentConfig: SupabaseDeploymentConfig }, params: { databaseId: string @@ -33,16 +48,16 @@ export async function createDeployedDatabase( } // first we need to create a new project on Supabase using the Management API - const accessToken = await getAccessToken({ + const accessToken = await getAccessToken(ctx, { integrationId: integration.data.id, credentialsSecretId: integration.data.credentials, }) - const managementApiClient = createManagementApiClient(accessToken) + const managementApiClient = createManagementApiClient(ctx, accessToken) const databasePassword = generatePassword() - const projectName = `database-build-${params.databaseId}` + const projectName = generateProjectName(params.databaseId) // check if the project already exists on Supabase const { @@ -52,7 +67,6 @@ export async function createDeployedDatabase( } = await managementApiClient.GET('/v1/projects') if (getProjectsError) { - console.log(response) throw new DeployError('Failed to get projects from Supabase', { cause: getProjectsError, }) @@ -74,7 +88,7 @@ export async function createDeployedDatabase( db_pass: databasePassword, name: `database-build-${params.databaseId}`, organization_id: (integration.data.scope as { organizationId: string }).organizationId, - region: process.env.SUPABASE_PLATFORM_DEPLOY_REGION as Region, + region: ctx.supabaseDeploymentConfig.region, }, } ) diff --git a/packages/deploy/src/supabase/database-types.ts b/packages/deploy/src/supabase/database-types.ts index f57a5e9c..454cfbd9 100644 --- a/packages/deploy/src/supabase/database-types.ts +++ b/packages/deploy/src/supabase/database-types.ts @@ -199,7 +199,7 @@ export type Database = { Args: { secret_id: string } - Returns: string + Returns: number } insert_secret: { Args: { @@ -229,6 +229,13 @@ export type Database = { } Returns: string } + upsert_secret: { + Args: { + secret: string + name: string + } + Returns: string + } } Enums: { deployment_status: "in_progress" | "success" | "failed" diff --git a/packages/deploy/src/supabase/get-access-token.ts b/packages/deploy/src/supabase/get-access-token.ts index 0ae4238e..01c3e6ab 100644 --- a/packages/deploy/src/supabase/get-access-token.ts +++ b/packages/deploy/src/supabase/get-access-token.ts @@ -1,15 +1,20 @@ import { DeployError, IntegrationRevokedError } from '../error.js' -import { supabaseAdmin } from './client.js' -import type { Credentials } from './types.js' +import type { Credentials, SupabaseClient, SupabasePlatformConfig } from './types.js' /** * Get the access token for a given Supabase integration. */ -export async function getAccessToken(params: { - integrationId: number - credentialsSecretId: string -}): Promise { - const credentialsSecret = await supabaseAdmin.rpc('read_secret', { +export async function getAccessToken( + ctx: { + supabaseAdmin: SupabaseClient + supabasePlatformConfig: SupabasePlatformConfig + }, + params: { + integrationId: number + credentialsSecretId: string + } +): Promise { + const credentialsSecret = await ctx.supabaseAdmin.rpc('read_secret', { secret_id: params.credentialsSecretId, }) @@ -26,13 +31,13 @@ export async function getAccessToken(params: { const now = Date.now() const newCredentialsResponse = await fetch( - `${process.env.SUPABASE_PLATFORM_API_URL}/v1/oauth/token`, + `${ctx.supabasePlatformConfig.apiUrl}/v1/oauth/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json', - Authorization: `Basic ${btoa(`${process.env.SUPABASE_OAUTH_CLIENT_ID}:${process.env.SUPABASE_OAUTH_SECRET}`)}`, + Authorization: `Basic ${btoa(`${ctx.supabasePlatformConfig.oauthClientId}:${ctx.supabasePlatformConfig.oauthSecret}`)}`, }, body: new URLSearchParams({ grant_type: 'refresh_token', @@ -64,7 +69,7 @@ export async function getAccessToken(params: { const expiresAt = new Date(now + newCredentials.expires_in * 1000) - const updateCredentialsSecret = await supabaseAdmin.rpc('update_secret', { + const updateCredentialsSecret = await ctx.supabaseAdmin.rpc('update_secret', { secret_id: params.credentialsSecretId, new_secret: JSON.stringify({ accessToken: newCredentials.access_token, diff --git a/packages/deploy/src/supabase/index.ts b/packages/deploy/src/supabase/index.ts index 75e6cbcd..dfd97f8e 100644 --- a/packages/deploy/src/supabase/index.ts +++ b/packages/deploy/src/supabase/index.ts @@ -1,8 +1,11 @@ -export * from './client.js' export * from './create-deployed-database.js' -export * from './deploy.js' export * from './generate-password.js' export * from './get-access-token.js' export * from './get-database-url.js' export * from './revoke-integration.js' export * from './wait-for-health.js' +export * from './database-types.js' +export * from './types.js' + +export * from './management-api/client.js' +export * from './management-api/types.js' diff --git a/packages/deploy/src/supabase/management-api/client.ts b/packages/deploy/src/supabase/management-api/client.ts index 907fa22f..904f12e8 100644 --- a/packages/deploy/src/supabase/management-api/client.ts +++ b/packages/deploy/src/supabase/management-api/client.ts @@ -1,6 +1,7 @@ import createClient, { type Middleware } from 'openapi-fetch' import type { paths } from './types.js' import { IntegrationRevokedError } from '../../error.js' +import type { SupabasePlatformConfig } from '../types.js' const integrationRevokedMiddleware: Middleware = { async onResponse({ response }) { @@ -10,9 +11,12 @@ const integrationRevokedMiddleware: Middleware = { }, } -export function createManagementApiClient(accessToken: string) { +export function createManagementApiClient( + ctx: { supabasePlatformConfig: SupabasePlatformConfig }, + accessToken: string +) { const client = createClient({ - baseUrl: process.env.SUPABASE_PLATFORM_API_URL, + baseUrl: ctx.supabasePlatformConfig.apiUrl, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, diff --git a/packages/deploy/src/supabase/revoke-integration.ts b/packages/deploy/src/supabase/revoke-integration.ts index 85e4aed7..fc23faf2 100644 --- a/packages/deploy/src/supabase/revoke-integration.ts +++ b/packages/deploy/src/supabase/revoke-integration.ts @@ -1,8 +1,10 @@ import type { SupabaseClient } from './types.js' -import { supabaseAdmin } from './client.js' export async function revokeIntegration( - ctx: { supabase: SupabaseClient }, + ctx: { + supabase: SupabaseClient + supabaseAdmin: SupabaseClient + }, params: { integrationId: number } ) { const integration = await ctx.supabase @@ -24,7 +26,7 @@ export async function revokeIntegration( throw new Error('Failed to revoke integration') } - const deleteSecret = await supabaseAdmin.rpc('delete_secret', { + const deleteSecret = await ctx.supabaseAdmin.rpc('delete_secret', { secret_id: integration.data.credentials!, }) diff --git a/packages/deploy/src/supabase/types.ts b/packages/deploy/src/supabase/types.ts index ecb5cc60..9ad11ab3 100644 --- a/packages/deploy/src/supabase/types.ts +++ b/packages/deploy/src/supabase/types.ts @@ -1,4 +1,5 @@ -import type { createClient } from './client.js' +import { SupabaseClient as SupabaseClientGeneric } from '@supabase/supabase-js' +import type { Database as SupabaseDatabase } from './database-types.js' import type { createManagementApiClient } from './management-api/client.js' import type { paths } from './management-api/types.js' @@ -38,6 +39,17 @@ export type SupabaseProviderMetadata = { } } -export type SupabaseClient = Awaited> +export type SupabaseClient = SupabaseClientGeneric export type ManagementApiClient = Awaited> + +export type SupabasePlatformConfig = { + url: string + apiUrl: string + oauthClientId: string + oauthSecret: string +} + +export type SupabaseDeploymentConfig = { + region: Region +} diff --git a/packages/deploy/src/supabase/wait-for-health.ts b/packages/deploy/src/supabase/wait-for-health.ts index 05a9ff45..65fdde71 100644 --- a/packages/deploy/src/supabase/wait-for-health.ts +++ b/packages/deploy/src/supabase/wait-for-health.ts @@ -1,6 +1,5 @@ import { DeployError } from '../error.js' import type { ManagementApiClient, Project } from './types.js' -import { setTimeout } from 'timers/promises' /** * Wait for a Supabase project to be ready. @@ -36,7 +35,7 @@ export async function waitForProjectToBeHealthy( } attempts += 1 - await setTimeout(POLLING_INTERVAL) + await new Promise((r) => setTimeout(r, POLLING_INTERVAL)) } catch (error) { throw error } @@ -99,7 +98,7 @@ export async function waitForDatabaseToBeHealthy( } attempts += 1 - await setTimeout(POLLING_INTERVAL) + await new Promise((r) => setTimeout(r, POLLING_INTERVAL)) } catch (error) { throw error } diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index ffe27468..74f3a829 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -156,6 +156,32 @@ begin end; $$; +create or replace function upsert_secret(secret text, name text) +returns uuid +language plpgsql +security definer +set search_path = public +as $$ +declare + secret_id uuid; +begin + if current_setting('role') != 'service_role' then + raise exception 'authentication required'; + end if; + + -- check if the secret already exists and store the id + select id into secret_id from vault.decrypted_secrets where vault.decrypted_secrets.name = upsert_secret.name; + + if secret_id is not null then + -- If the secret exists, update it + return vault.update_secret(secret_id, secret); + else + -- If the secret does not exist, create it + return vault.create_secret(secret, name); + end if; +end; +$$; + create or replace function update_secret(secret_id uuid, new_secret text) returns text language plpgsql From 56ba442959aaa6f4a778505ffd4af0e243bc9a49 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Thu, 14 Nov 2024 16:52:05 -0700 Subject: [PATCH 41/59] chore: browser-proxy turbo task --- turbo.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/turbo.json b/turbo.json index 75ef8ad4..fdff56c9 100644 --- a/turbo.json +++ b/turbo.json @@ -13,6 +13,12 @@ "interruptible": true, "cache": false }, + "@database.build/browser-proxy#dev": { + "dependsOn": ["^build"], + "persistent": true, + "interruptible": true, + "cache": false + }, "@database.build/web#dev": { "dependsOn": ["^build"], "outputs": [".next/**", "!.next/cache/**"], From 9b93665d4388befc5a3b99eb275ce59e5a6744bc Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Thu, 14 Nov 2024 16:52:53 -0700 Subject: [PATCH 42/59] fix: lock pg 16 client in deploy worker dockerfile --- apps/deploy-worker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/deploy-worker/Dockerfile b/apps/deploy-worker/Dockerfile index b269878a..e7bee1e4 100644 --- a/apps/deploy-worker/Dockerfile +++ b/apps/deploy-worker/Dockerfile @@ -1,6 +1,6 @@ FROM node:22-alpine -RUN apk add --no-cache postgresql-client +RUN apk add --no-cache postgresql16-client WORKDIR /app From 1d035af5bf1331e0ae847873c2f1dd1739f9bee8 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Fri, 15 Nov 2024 10:37:03 +0100 Subject: [PATCH 43/59] dismiss security advisor notification by enabling RLS on deployment_providers --- .../20241115093122_enable_rls_deployment_providers.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 supabase/migrations/20241115093122_enable_rls_deployment_providers.sql diff --git a/supabase/migrations/20241115093122_enable_rls_deployment_providers.sql b/supabase/migrations/20241115093122_enable_rls_deployment_providers.sql new file mode 100644 index 00000000..68b7cd77 --- /dev/null +++ b/supabase/migrations/20241115093122_enable_rls_deployment_providers.sql @@ -0,0 +1,8 @@ +-- Enable RLS on deployment_providers to dismiss security warnings +alter table deployment_providers enable row level security; + +-- RLS allow all policy for deployment_providers +create policy "Allow all operations on deployment_providers" + on deployment_providers + for all + using (true); From f653fe198194b0ce6ff8e702134f808327549e8a Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 14:26:57 -0700 Subject: [PATCH 44/59] feat(deploy): guided deployment flow --- apps/web/app/(main)/db/[id]/page.tsx | 10 +- .../app/api/oauth/supabase/callback/route.ts | 8 +- apps/web/components/deploy/deploy-dialog.tsx | 17 +-- .../deploy/deploy-failure-dialog.tsx | 41 +++--- .../components/deploy/deploy-info-dialog.tsx | 95 +++++++++++++ apps/web/components/deploy/deploy-info.tsx | 95 +++++++++++++ .../deploy/deploy-success-dialog.tsx | 106 ++------------ .../web/components/deploy/redeploy-dialog.tsx | 17 +-- apps/web/components/sidebar.tsx | 131 +++++++++++++++--- .../deployed-databases-query.ts | 2 +- .../data/integrations/integration-query.ts | 1 + .../data/merged-databases/merged-databases.ts | 5 +- apps/web/lib/hooks.ts | 19 +++ apps/web/utils/supabase/db-types.ts | 28 +++- .../deploy/src/supabase/database-types.ts | 28 +++- .../migrations/20241003131953_deployment.sql | 18 +++ 16 files changed, 444 insertions(+), 177 deletions(-) create mode 100644 apps/web/components/deploy/deploy-info-dialog.tsx create mode 100644 apps/web/components/deploy/deploy-info.tsx diff --git a/apps/web/app/(main)/db/[id]/page.tsx b/apps/web/app/(main)/db/[id]/page.tsx index ca174576..371dd132 100644 --- a/apps/web/app/(main)/db/[id]/page.tsx +++ b/apps/web/app/(main)/db/[id]/page.tsx @@ -3,8 +3,6 @@ import { useRouter } from 'next/navigation' import { useEffect } from 'react' import { useApp } from '~/components/app-provider' -import { DeployFailureDialog } from '~/components/deploy/deploy-failure-dialog' -import { DeploySuccessDialog } from '~/components/deploy/deploy-success-dialog' import Workspace from '~/components/workspace' export default function Page({ params }: { params: { id: string } }) { @@ -28,11 +26,5 @@ export default function Page({ params }: { params: { id: string } }) { run() }, [dbManager, databaseId, router]) - return ( - <> - - - - - ) + return } diff --git a/apps/web/app/api/oauth/supabase/callback/route.ts b/apps/web/app/api/oauth/supabase/callback/route.ts index a3da84fd..7a538ffc 100644 --- a/apps/web/app/api/oauth/supabase/callback/route.ts +++ b/apps/web/app/api/oauth/supabase/callback/route.ts @@ -1,6 +1,6 @@ -import { createClient } from '~/utils/supabase/server' -import { createClient as createAdminClient } from '~/utils/supabase/admin' import { NextRequest, NextResponse } from 'next/server' +import { createClient as createAdminClient } from '~/utils/supabase/admin' +import { createClient } from '~/utils/supabase/server' type Credentials = { refreshToken: string @@ -174,5 +174,7 @@ export async function GET(req: NextRequest) { } } - return NextResponse.redirect(new URL(`/db/${state.databaseId}?deploy=Supabase`, req.url)) + return NextResponse.redirect( + new URL(`/db/${state.databaseId}?event=deploy.start&provider=Supabase`, req.url) + ) } diff --git a/apps/web/components/deploy/deploy-dialog.tsx b/apps/web/components/deploy/deploy-dialog.tsx index a495e8e1..3a8f2fd6 100644 --- a/apps/web/components/deploy/deploy-dialog.tsx +++ b/apps/web/components/deploy/deploy-dialog.tsx @@ -1,6 +1,7 @@ 'use client' import { generateProjectName } from '@database.build/deploy/supabase' +import { Loader } from 'lucide-react' import { PropsWithChildren } from 'react' import { Button } from '~/components/ui/button' import { @@ -18,16 +19,9 @@ export type DeployDialogProps = { open: boolean onOpenChange: (open: boolean) => void onConfirm: () => void - onCancel: () => void } -export function DeployDialog({ - databaseId, - open, - onOpenChange, - onConfirm, - onCancel, -}: DeployDialogProps) { +export function DeployDialog({ databaseId, open, onOpenChange, onConfirm }: DeployDialogProps) { const { data: integration } = useIntegrationQuery('Supabase') return ( @@ -42,7 +36,11 @@ export function DeployDialog({
{!integration ? ( -

Loading...

+ ) : (
You are about to deploy your in-browser database to Supabase. This will create a new @@ -59,7 +57,6 @@ export function DeployDialog({ +
+ + + +
+ ) +} diff --git a/apps/web/components/deploy/deploy-info.tsx b/apps/web/components/deploy/deploy-info.tsx new file mode 100644 index 00000000..ce4b4671 --- /dev/null +++ b/apps/web/components/deploy/deploy-info.tsx @@ -0,0 +1,95 @@ +import { format } from 'date-fns' +import Link from 'next/link' +import { CopyableField } from '~/components/copyable-field' +import { Badge } from '~/components/ui/badge' + +export type SupabaseDeploymentInfo = { + name: string + url: string + databasePassword?: string + databaseUrl: string + poolerUrl: string + createdAt?: Date +} + +export type DeployInfoProps = { + info: SupabaseDeploymentInfo + isRedeploy?: boolean +} + +export function SupabaseDeployInfo({ info, isRedeploy = false }: DeployInfoProps) { + const deployText = isRedeploy ? 'redeployed' : 'deployed' + + return ( +
+

+ Your in-browser database was {deployText} to the Supabase project{' '} + + {info.name} + + {info.createdAt + ? ` at ${format(info.createdAt, 'h:mm a')} on ${format(info.createdAt, 'MMMM d, yyyy')}` + : ''} + . +

+

+ + Database Connection URL{' '} + + IPv6 + + + } + value={info.databaseUrl} + /> + + Pooler Connection URL{' '} + + + IPv4 + + + IPv6 + + + + } + value={info.poolerUrl} + /> + {info.databasePassword && ( + <> + + + Please{' '} + + save your database password securely + {' '} + as it won't be displayed again. + + + )} + + You can change your password and learn more about your connection strings in your{' '} + + database settings + + . + +

+
+ ) +} diff --git a/apps/web/components/deploy/deploy-success-dialog.tsx b/apps/web/components/deploy/deploy-success-dialog.tsx index d9bf46ce..74afdeb1 100644 --- a/apps/web/components/deploy/deploy-success-dialog.tsx +++ b/apps/web/components/deploy/deploy-success-dialog.tsx @@ -1,111 +1,27 @@ 'use client' -import Link from 'next/link' -import { useRouter } from 'next/navigation' -import { useEffect, useState } from 'react' -import { CopyableField } from '~/components/copyable-field' -import { Badge } from '~/components/ui/badge' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' +import { SupabaseDeployInfo, SupabaseDeploymentInfo } from './deploy-info' -export function DeploySuccessDialog() { - const router = useRouter() - const [project, setProject] = useState<{ - name: string - url: string - databasePassword: string | undefined - databaseUrl: string - poolerUrl: string - } | null>(null) - const [open, setOpen] = useState(false) - useEffect(() => { - const searchParams = new URLSearchParams(window.location.search) - - if (searchParams.get('event') === 'deploy.success') { - setProject(JSON.parse(searchParams.get('project')!)) - setOpen(true) - router.replace(window.location.pathname) - } - }, [router]) - - if (!project) { - return null - } +export type DeploySuccessDialogProps = { + open: boolean + onOpenChange: (open: boolean) => void + deployInfo: SupabaseDeploymentInfo +} - const deployText = project.databasePassword ? 'deployed' : 'redeployed' +export function DeploySuccessDialog({ open, onOpenChange, deployInfo }: DeploySuccessDialogProps) { + const isRedeploy = !deployInfo.databasePassword + const deployText = isRedeploy ? 'redeployed' : 'deployed' return ( - + Database {deployText}
-

- Database {deployText} to your Supabase project{' '} - - {project.name} - -

-

- - Database Connection URL{' '} - - IPv6 - - - } - value={project.databaseUrl} - /> - - Pooler Connection URL{' '} - - - IPv4 - - - IPv6 - - - - } - value={project.poolerUrl} - /> - {project.databasePassword ? ( - <> - - - {/* eslint-disable-next-line react/no-unescaped-entities */} - Please{' '} - - save your database password securely - {' '} - as it won't be displayed again. - - - ) : null} - - You can change your password and learn more about your connection strings in your{' '} - - database settings - - . - -

+
diff --git a/apps/web/components/deploy/redeploy-dialog.tsx b/apps/web/components/deploy/redeploy-dialog.tsx index bd207a49..a84c9ae3 100644 --- a/apps/web/components/deploy/redeploy-dialog.tsx +++ b/apps/web/components/deploy/redeploy-dialog.tsx @@ -1,3 +1,5 @@ +'use client' + import { TriangleAlert } from 'lucide-react' import { useState } from 'react' import { @@ -9,25 +11,19 @@ import { DialogTitle, } from '~/components/ui/dialog' import { Input } from '~/components/ui/input' -import { Database } from '~/lib/db' +import { MergedDatabase } from '~/data/merged-databases/merged-databases' import { Button } from '../ui/button' export type RedeployDialogProps = { - database: Database + database: MergedDatabase open: boolean onOpenChange: (open: boolean) => void onConfirm: () => void - onCancel: () => void } -export function RedeployDialog({ - database, - open, - onOpenChange, - onConfirm, - onCancel, -}: RedeployDialogProps) { +export function RedeployDialog({ database, open, onOpenChange, onConfirm }: RedeployDialogProps) { const [confirmedValue, setConfirmedValue] = useState('') + return ( @@ -62,7 +58,6 @@ export function RedeployDialog({ variant="secondary" onClick={() => { onOpenChange(false) - onCancel() }} > Cancel diff --git a/apps/web/components/sidebar.tsx b/apps/web/components/sidebar.tsx index 1e4f7754..b1d42534 100644 --- a/apps/web/components/sidebar.tsx +++ b/apps/web/components/sidebar.tsx @@ -20,7 +20,9 @@ import { } from 'lucide-react' import Link from 'next/link' import { useParams, useRouter } from 'next/navigation' -import { useState } from 'react' +import { useCallback, useState } from 'react' +import { DeployFailureDialog } from '~/components/deploy/deploy-failure-dialog' +import { DeploySuccessDialog } from '~/components/deploy/deploy-success-dialog' import { Button } from '~/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' import { Tooltip, TooltipContent, TooltipTrigger } from '~/components/ui/tooltip' @@ -28,10 +30,13 @@ import { useDatabaseDeleteMutation } from '~/data/databases/database-delete-muta import { useDatabaseUpdateMutation } from '~/data/databases/database-update-mutation' import { useIntegrationQuery } from '~/data/integrations/integration-query' import { MergedDatabase, useMergedDatabases } from '~/data/merged-databases/merged-databases' +import { useQueryEvent } from '~/lib/hooks' import { downloadFile, getDeployUrl, getOauthUrl, titleToKebabCase } from '~/lib/util' import { cn } from '~/lib/utils' import { useApp } from './app-provider' import { DeployDialog } from './deploy/deploy-dialog' +import { SupabaseDeploymentInfo } from './deploy/deploy-info' +import { DeployInfoDialog } from './deploy/deploy-info-dialog' import { IntegrationDialog } from './deploy/integration-dialog' import { RedeployDialog } from './deploy/redeploy-dialog' import { LiveShareIcon } from './live-share-icon' @@ -309,16 +314,79 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { const [isPopoverOpen, setIsPopoverOpen] = useState(false) const { mutateAsync: deleteDatabase } = useDatabaseDeleteMutation() const { mutateAsync: updateDatabase } = useDatabaseUpdateMutation() - const { data: supabaseIntegration } = useIntegrationQuery('Supabase') + const { data: supabaseIntegration, isLoading: isLoadingSupabaseIntegration } = + useIntegrationQuery('Supabase') const [isRenaming, setIsRenaming] = useState(false) const [isIntegrationDialogOpen, setIsIntegrationDialogOpen] = useState(false) const [isDeployDialogOpen, setIsDeployDialogOpen] = useState(false) + const [isDeployInfoDialogOpen, setIsDeployInfoDialogOpen] = useState(false) const [isRedeployDialogOpen, setIsRedeployDialogOpen] = useState(false) - const [deployUrl, setDeployUrl] = useState(null) + const [isDeploySuccessDialogOpen, setIsDeploySuccessDialogOpen] = useState(false) + const [isDeployFailureDialogOpen, setIsDeployFailureDialogOpen] = useState(false) - const [isDeploying, setIsDeploying] = useState(false) + const [deployInfo, setDeployInfo] = useState() + const [deployError, setDeployError] = useState() + + const isDeploying = isIntegrationDialogOpen || isDeployDialogOpen || isRedeployDialogOpen + const supabaseDeployment = database.deployments.find((d) => d.provider_name === 'Supabase') + + /** + * Starts the deploy flow. + * - If the user has not connected to Supabase, open the integration dialog. + * - If the user has already deployed to Supabase, open the redeploy dialog. + * - Otherwise, open the deploy dialog. + */ + const startDeployFlow = useCallback(() => { + setIsIntegrationDialogOpen(false) + setIsDeployDialogOpen(false) + setIsDeployInfoDialogOpen(false) + setIsRedeployDialogOpen(false) + setIsDeploySuccessDialogOpen(false) + setIsDeployFailureDialogOpen(false) + + if (!isLoadingSupabaseIntegration && !supabaseIntegration) { + setIsIntegrationDialogOpen(true) + } else if (supabaseDeployment) { + setIsDeployInfoDialogOpen(true) + } else { + setIsDeployDialogOpen(true) + } + }, [supabaseDeployment, supabaseIntegration, isLoadingSupabaseIntegration]) + + useQueryEvent('deploy.start', (params) => { + if (!isActive) { + return + } + const provider = params.get('provider')?.toLowerCase() + if (provider === 'supabase') { + startDeployFlow() + } + }) + + useQueryEvent('deploy.success', (params) => { + if (!isActive) { + return + } + const deployInfoJson = params.get('project') + const deployInfo = deployInfoJson ? JSON.parse(deployInfoJson) : undefined + if (deployInfo) { + setDeployInfo(deployInfo) + setIsDeploySuccessDialogOpen(true) + } + }) + + useQueryEvent('deploy.failure', (params) => { + if (!isActive) { + return + } + const errorMessage = params.get('error') + if (errorMessage) { + setDeployError(errorMessage) + setIsDeployFailureDialogOpen(true) + } + }) return ( <> @@ -339,8 +407,7 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { }} onConfirm={() => { if (!supabaseIntegration) { - setIsDeployDialogOpen(false) - setIsIntegrationDialogOpen(true) + startDeployFlow() return } @@ -351,21 +418,49 @@ function DatabaseMenuItem({ database, isActive }: DatabaseMenuItemProps) { router.push(deployUrl) }} - onCancel={() => { - setIsDeploying(false) - }} /> + {supabaseDeployment && ( + { + setIsRedeployDialogOpen(true) + }} + /> + )} { - router.push(deployUrl!) - }} - onCancel={() => { - setIsDeploying(false) + if (!supabaseIntegration) { + startDeployFlow() + return + } + + const deployUrl = getDeployUrl({ + databaseId: database.id, + integrationId: supabaseIntegration.id, + }) + + router.push(deployUrl) }} /> + {deployInfo && ( + + )} + {deployError && ( + + )} { e.preventDefault() - if (!supabaseIntegration) { - setIsIntegrationDialogOpen(true) - } else if ( - database.deployments.some((d) => d.provider_name === 'Supabase') - ) { - setIsRedeployDialogOpen(true) - } else { - setIsDeployDialogOpen(true) - } + startDeployFlow() }} > diff --git a/apps/web/data/deployed-databases/deployed-databases-query.ts b/apps/web/data/deployed-databases/deployed-databases-query.ts index 1d7649d3..ee5f635f 100644 --- a/apps/web/data/deployed-databases/deployed-databases-query.ts +++ b/apps/web/data/deployed-databases/deployed-databases-query.ts @@ -6,7 +6,7 @@ export type DeployedDatabase = Awaited>[ async function getDeployedDatabases() { const supabase = createClient() const { data, error } = await supabase - .from('deployed_databases') + .from('latest_deployed_databases') .select( '*, ...deployment_provider_integrations!inner(...deployment_providers!inner(provider_name:name))' ) diff --git a/apps/web/data/integrations/integration-query.ts b/apps/web/data/integrations/integration-query.ts index e018ccc6..8d5a05db 100644 --- a/apps/web/data/integrations/integration-query.ts +++ b/apps/web/data/integrations/integration-query.ts @@ -40,6 +40,7 @@ export const useIntegrationQuery = ( const { id } = await getIntegration(name) return await getIntegrationDetails(id) }, + retry: false, }) } diff --git a/apps/web/data/merged-databases/merged-databases.ts b/apps/web/data/merged-databases/merged-databases.ts index c069a0cb..4b43a2cc 100644 --- a/apps/web/data/merged-databases/merged-databases.ts +++ b/apps/web/data/merged-databases/merged-databases.ts @@ -5,12 +5,15 @@ import { useDeployedDatabasesQuery, } from '../deployed-databases/deployed-databases-query' +/** + * A local database with remote deployment information. + */ export type MergedDatabase = Database & { deployments: DeployedDatabase[] } /** - * Merges local databases with deployed databases. + * Merges local databases with remote deployed databases. */ export function useMergedDatabases() { const { data: localDatabases, isLoading: isLoadingLocalDatabases } = useDatabasesQuery() diff --git a/apps/web/lib/hooks.ts b/apps/web/lib/hooks.ts index 38737b45..4168836d 100644 --- a/apps/web/lib/hooks.ts +++ b/apps/web/lib/hooks.ts @@ -3,6 +3,7 @@ import { generateId } from 'ai' import { Chart } from 'chart.js' import { codeBlock } from 'common-tags' +import { useRouter, useSearchParams } from 'next/navigation' import { cloneElement, isValidElement, @@ -572,3 +573,21 @@ export function useFollowMouse({ return { ref } } + +/** + * Use a query parameter event to trigger a callback. + * + * Automatically removes query params from the URL. + */ +export function useQueryEvent(event: string, callback: (params: URLSearchParams) => void) { + const router = useRouter() + const params = useSearchParams() + + useEffect(() => { + if (params.get('event') === event) { + router.replace(window.location.pathname) + callback(params) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [router, params]) +} diff --git a/apps/web/utils/supabase/db-types.ts b/apps/web/utils/supabase/db-types.ts index 454cfbd9..f3c701ab 100644 --- a/apps/web/utils/supabase/db-types.ts +++ b/apps/web/utils/supabase/db-types.ts @@ -188,11 +188,37 @@ export type Database = { referencedRelation: "deployed_databases" referencedColumns: ["id"] }, + { + foreignKeyName: "deployments_deployed_database_id_fkey" + columns: ["deployed_database_id"] + isOneToOne: false + referencedRelation: "latest_deployed_databases" + referencedColumns: ["id"] + }, ] } } Views: { - [_ in never]: never + latest_deployed_databases: { + Row: { + created_at: string | null + deployment_provider_integration_id: number | null + id: number | null + last_deployment_at: string | null + local_database_id: string | null + provider_metadata: Json | null + updated_at: string | null + } + Relationships: [ + { + foreignKeyName: "deployed_databases_deployment_provider_integration_id_fkey" + columns: ["deployment_provider_integration_id"] + isOneToOne: false + referencedRelation: "deployment_provider_integrations" + referencedColumns: ["id"] + }, + ] + } } Functions: { delete_secret: { diff --git a/packages/deploy/src/supabase/database-types.ts b/packages/deploy/src/supabase/database-types.ts index 454cfbd9..f3c701ab 100644 --- a/packages/deploy/src/supabase/database-types.ts +++ b/packages/deploy/src/supabase/database-types.ts @@ -188,11 +188,37 @@ export type Database = { referencedRelation: "deployed_databases" referencedColumns: ["id"] }, + { + foreignKeyName: "deployments_deployed_database_id_fkey" + columns: ["deployed_database_id"] + isOneToOne: false + referencedRelation: "latest_deployed_databases" + referencedColumns: ["id"] + }, ] } } Views: { - [_ in never]: never + latest_deployed_databases: { + Row: { + created_at: string | null + deployment_provider_integration_id: number | null + id: number | null + last_deployment_at: string | null + local_database_id: string | null + provider_metadata: Json | null + updated_at: string | null + } + Relationships: [ + { + foreignKeyName: "deployed_databases_deployment_provider_integration_id_fkey" + columns: ["deployment_provider_integration_id"] + isOneToOne: false + referencedRelation: "deployment_provider_integrations" + referencedColumns: ["id"] + }, + ] + } } Functions: { delete_secret: { diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index 74f3a829..b2d33272 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -65,6 +65,24 @@ where status = 'in_progress'; create trigger deployments_updated_at before update on deployments for each row execute procedure moddatetime (updated_at); +-- view for getting deployed databases with their last deployment date +create view latest_deployed_databases as +select + deployed_databases.*, + d.created_at as last_deployment_at +from + deployed_databases +left join ( + select + deployed_database_id, + max(created_at) as created_at + from + deployments + group by + deployed_database_id +) d + on d.deployed_database_id = deployed_databases.id; + -- Enable RLS on deployment_provider_integrations alter table deployment_provider_integrations enable row level security; From ded6c3b02206b11539dbc83b9b2d38a5454e130f Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 14:27:10 -0700 Subject: [PATCH 45/59] chore: update turbo --- package-lock.json | 154 +++++++++++++--------------------------------- package.json | 2 +- 2 files changed, 44 insertions(+), 112 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ed14e9e..d0760c7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ ], "devDependencies": { "supabase": "^1.207.9", - "turbo": "^2.2.4-canary.9" + "turbo": "^2.3.0" } }, "apps/browser-proxy": { @@ -120,90 +120,18 @@ "license": "MIT" }, "apps/postgres-new": { - "version": "0.0.0", - "extraneous": true, "dependencies": { - "@ai-sdk/openai": "^0.0.21", - "@dagrejs/dagre": "^1.1.2", - "@electric-sql/pglite": "^0.2.9", - "@gregnr/postgres-meta": "^0.82.0-dev.2", - "@monaco-editor/react": "^4.6.0", - "@radix-ui/react-accordion": "^1.2.0", - "@radix-ui/react-alert-dialog": "^1.1.2", - "@radix-ui/react-dialog": "^1.1.1", - "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-popover": "^1.1.1", - "@radix-ui/react-progress": "^1.1.0", - "@radix-ui/react-slot": "^1.1.0", - "@radix-ui/react-tabs": "^1.1.0", - "@radix-ui/react-tooltip": "^1.1.2", - "@std/tar": "npm:@jsr/std__tar@^0.1.2", - "@supabase/postgres-meta": "^0.81.2", - "@supabase/ssr": "^0.4.0", - "@supabase/supabase-js": "^2.45.0", - "@tanstack/react-query": "^5.45.0", - "@upstash/ratelimit": "^2.0.1", - "@vercel/kv": "^2.0.0", - "@xenova/transformers": "^2.17.2", - "ai": "^3.2.8", - "async-mutex": "^0.5.0", - "chart.js": "^4.4.3", - "chartjs-adapter-date-fns": "^3.0.0", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "comlink": "^4.4.1", - "common-tags": "^1.8.2", - "date-fns": "^3.6.0", - "framer-motion": "^11.2.10", - "highlightjs-curl": "^1.3.0", - "katex": "^0.16.10", - "libpg-query": "npm:@gregnr/libpg-query@15.2.0-rc.deparse.3", - "lodash": "^4.17.21", - "lucide-react": "^0.426.0", - "monaco-editor": "^0.49.0", - "nanoid": "^5.0.7", - "next": "14.2.3", - "next-themes": "^0.3.0", - "react": "^18", - "react-chartjs-2": "^5.2.0", - "react-dom": "^18", - "react-error-boundary": "^4.0.13", - "react-markdown": "^9.0.1", - "react-syntax-highlighter": "^15.5.0", - "react-use": "^17.5.1", - "reactflow": "^11.11.3", - "rehype-katex": "^7.0.0", - "remark-gfm": "^4.0.0", - "remark-math": "^6.0.0", - "sql-formatter": "^15.3.1", - "tailwind-merge": "^2.4.0", - "tailwindcss-animate": "^1.0.7", - "web-streams-polyfill": "^4.0.0", - "zod": "^3.23.8" - }, - "devDependencies": { - "@mertasan/tailwindcss-variables": "^2.7.0", - "@radix-ui/colors": "^3.0.0", - "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.14", - "@types/common-tags": "^1.8.4", - "@types/lodash": "^4.17.7", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "@types/react-syntax-highlighter": "^15.5.13", - "@types/wicg-file-system-access": "^2023.10.5", - "autoprefixer": "^10.4.19", - "deepmerge": "^4.3.1", - "eslint": "^8", - "eslint-config-next": "14.2.3", - "mini-svg-data-uri": "^1.4.4", - "postcss": "^8", - "tailwindcss": "^3.4.6", - "tailwindcss-radix": "^3.0.3", - "typescript": "^5.5.2", - "webpack": "^5.95.0" + "date-fns": "^4.1.0" + } + }, + "apps/postgres-new/node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, "apps/web": { @@ -14033,6 +13961,10 @@ "node": ">=0.10.0" } }, + "node_modules/postgres-new": { + "resolved": "apps/postgres-new", + "link": true + }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -16854,27 +16786,27 @@ } }, "node_modules/turbo": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.2.4-canary.9.tgz", - "integrity": "sha512-nuLYPHCT3Tu9fQvyDseXEAaVlZp6OZF1gotVSi3JHcxsj5JxAlV8Lg5feLfpMjLb9DRMkUuBrjK9CJPk2BkC7Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.3.0.tgz", + "integrity": "sha512-/uOq5o2jwRPyaUDnwBpOR5k9mQq4c3wziBgWNWttiYQPmbhDtrKYPRBxTvA2WpgQwRIbt8UM612RMN8n/TvmHA==", "dev": true, "license": "MIT", "bin": { "turbo": "bin/turbo" }, "optionalDependencies": { - "turbo-darwin-64": "2.2.4-canary.9", - "turbo-darwin-arm64": "2.2.4-canary.9", - "turbo-linux-64": "2.2.4-canary.9", - "turbo-linux-arm64": "2.2.4-canary.9", - "turbo-windows-64": "2.2.4-canary.9", - "turbo-windows-arm64": "2.2.4-canary.9" + "turbo-darwin-64": "2.3.0", + "turbo-darwin-arm64": "2.3.0", + "turbo-linux-64": "2.3.0", + "turbo-linux-arm64": "2.3.0", + "turbo-windows-64": "2.3.0", + "turbo-windows-arm64": "2.3.0" } }, "node_modules/turbo-darwin-64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.2.4-canary.9.tgz", - "integrity": "sha512-oD5eqe5DlzjOXxO2KdNcib19LB0qhX04UVZpY/dcNKAjFUb46nKgRD/2aLBOdn+g7a7KKmMHvwA4KU0PkBcUCQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.3.0.tgz", + "integrity": "sha512-pji+D49PhFItyQjf2QVoLZw2d3oRGo8gJgKyOiRzvip78Rzie74quA8XNwSg/DuzM7xx6gJ3p2/LylTTlgZXxQ==", "cpu": [ "x64" ], @@ -16886,9 +16818,9 @@ ] }, "node_modules/turbo-darwin-arm64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.2.4-canary.9.tgz", - "integrity": "sha512-NPe6T3cVUoYrZJN3uws3EupaFZsLIEDrFDzOor6neEFVjqSV/BSR3GuGcCCrf83Zjf1QqcTf3UWmInoKm1mtog==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.3.0.tgz", + "integrity": "sha512-AJrGIL9BO41mwDF/IBHsNGwvtdyB911vp8f5mbNo1wG66gWTvOBg7WCtYQBvCo11XTenTfXPRSsAb7w3WAZb6w==", "cpu": [ "arm64" ], @@ -16900,9 +16832,9 @@ ] }, "node_modules/turbo-linux-64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.2.4-canary.9.tgz", - "integrity": "sha512-gHFvhblgm8DymUseeqK3ADudbbb8BHpWN/jsiJlZQbrzWGQDkg7PFrExedOy1EZz31ZJ13pZZ87oAjafsCui/Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.3.0.tgz", + "integrity": "sha512-jZqW6vc2sPJT3M/3ZmV1Cg4ecQVPqsbHncG/RnogHpBu783KCSXIndgxvUQNm9qfgBYbZDBnP1md63O4UTElhw==", "cpu": [ "x64" ], @@ -16914,9 +16846,9 @@ ] }, "node_modules/turbo-linux-arm64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.2.4-canary.9.tgz", - "integrity": "sha512-0nInXz9nvQr7AF/Xl2t7+xQqI4jA6Hi5JWMRuDTQ9EmO785jJz9He1MnP59aJrrVG0GWNgYKZJj5AzAnYZw4cA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.3.0.tgz", + "integrity": "sha512-HUbDLJlvd/hxuyCNO0BmEWYQj0TugRMvSQeG8vHJH+Lq8qOgDAe7J0K73bFNbZejZQxW3C3XEiZFB3pnpO78+A==", "cpu": [ "arm64" ], @@ -16928,9 +16860,9 @@ ] }, "node_modules/turbo-windows-64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.2.4-canary.9.tgz", - "integrity": "sha512-C8rfMvxTfMWzbZUwRRnj8v825jR+Z+0fMM5NAfZEx4qsjJqgfT/yGCCOjYxX6AxLi2rJT5HMpayjfDN1otnFBg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.3.0.tgz", + "integrity": "sha512-c5rxrGNTYDWX9QeMzWLFE9frOXnKjHGEvQMp1SfldDlbZYsloX9UKs31TzUThzfTgTiz8NYuShaXJ2UvTMnV/g==", "cpu": [ "x64" ], @@ -16942,9 +16874,9 @@ ] }, "node_modules/turbo-windows-arm64": { - "version": "2.2.4-canary.9", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.2.4-canary.9.tgz", - "integrity": "sha512-86FhIPL51ZsTOcL21GduRI91nVtSQTVsPnJjeD1IAhhewwcvn3R8xMH0ndI/1DvHq566QUj73AIp/M5mnwwIKw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.3.0.tgz", + "integrity": "sha512-7qfUuYhfIVb1AZgs89DxhXK+zZez6O2ocmixEQ4hXZK7ytnBt5vaz2zGNJJKFNYIL5HX1C3tuHolnpNgDNCUIg==", "cpu": [ "arm64" ], diff --git a/package.json b/package.json index b2026b63..387076be 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,6 @@ "workspaces": ["apps/*", "packages/*"], "devDependencies": { "supabase": "^1.207.9", - "turbo": "^2.2.4-canary.9" + "turbo": "^2.3.0" } } From 2c9ed90280fa747b9a29b9113c6938da60b996b9 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 14:37:19 -0700 Subject: [PATCH 46/59] chore: temp rename subproject back to postgres-new --- apps/{web => postgres-new}/.env.example | 0 apps/{web => postgres-new}/README.md | 0 .../app/(main)/db/[id]/page.tsx | 0 .../app/(main)/layout.tsx | 0 .../{web => postgres-new}/app/(main)/page.tsx | 0 .../app/api/chat/route.ts | 0 .../api/integrations/[id]/details/route.ts | 0 .../app/api/oauth/supabase/callback/route.ts | 0 apps/{web => postgres-new}/app/apple-icon.png | Bin .../app/deploy/[databaseId]/page.tsx | 0 .../{web => postgres-new}/app/export/page.tsx | 0 apps/{web => postgres-new}/app/favicon.ico | Bin apps/{web => postgres-new}/app/globals.css | 0 apps/{web => postgres-new}/app/icon.svg | 0 .../{web => postgres-new}/app/import/page.tsx | 0 apps/{web => postgres-new}/app/layout.tsx | 0 .../app/opengraph-image.png | Bin .../assets/github-icon.tsx | 0 apps/{web => postgres-new}/components.json | 0 .../ai-icon-animation-style.module.css | 0 .../ai-icon-animation/ai-icon-animation.tsx | 0 .../components/ai-icon-animation/index.tsx | 0 .../components/app-provider.tsx | 0 .../components/chat-message.tsx | 0 .../{web => postgres-new}/components/chat.tsx | 0 .../components/code-accordion.tsx | 0 .../components/code-block.tsx | 0 .../components/copyable-field.tsx | 0 .../components/deploy/deploy-dialog.tsx | 0 .../deploy/deploy-failure-dialog.tsx | 0 .../components/deploy/deploy-info-dialog.tsx | 0 .../components/deploy/deploy-info.tsx | 0 .../deploy/deploy-success-dialog.tsx | 0 .../components/deploy/integration-dialog.tsx | 0 .../components/deploy/redeploy-dialog.tsx | 0 .../components/framer-features.ts | 0 apps/{web => postgres-new}/components/ide.tsx | 0 .../components/layout.tsx | 0 .../components/live-share-icon.tsx | 0 .../components/markdown-accordion.tsx | 0 .../components/particles-background.tsx | 0 .../components/providers.tsx | 0 .../components/schema/graph.tsx | 0 .../components/schema/legend.tsx | 0 .../components/schema/table-graph.tsx | 0 .../components/schema/table-node.tsx | 0 .../components/sidebar.tsx | 0 .../components/sign-in-button.tsx | 0 .../components/supabase-icon.tsx | 0 .../components/theme-dropdown.tsx | 0 .../components/theme-provider.tsx | 0 .../components/tools/conversation-rename.tsx | 0 .../components/tools/csv-export.tsx | 0 .../components/tools/csv-import.tsx | 0 .../components/tools/csv-request.tsx | 0 .../components/tools/executed-sql.tsx | 0 .../components/tools/generated-chart.tsx | 0 .../components/tools/generated-embedding.tsx | 0 .../components/tools/index.tsx | 0 .../components/ui/accordion.tsx | 0 .../components/ui/alert-dialog.tsx | 0 .../components/ui/badge.tsx | 0 .../components/ui/button.tsx | 0 .../components/ui/dialog.tsx | 0 .../components/ui/dropdown-menu.tsx | 0 .../components/ui/input.tsx | 0 .../components/ui/label.tsx | 0 .../components/ui/popover.tsx | 0 .../components/ui/progress.tsx | 0 .../components/ui/skeleton.tsx | 0 .../components/ui/tabs.tsx | 0 .../components/ui/tooltip.tsx | 0 .../components/workspace.tsx | 0 .../config/default-colors.js | 0 .../config/tailwind.config.js | 0 .../{web => postgres-new}/config/ui.config.js | 0 .../databases/database-create-mutation.ts | 0 .../databases/database-delete-mutation.ts | 0 .../data/databases/database-query.ts | 0 .../databases/database-update-mutation.ts | 0 .../data/databases/databases-query.ts | 0 .../deploy-waitlist-create-mutation.ts | 0 .../deploy-waitlist/deploy-waitlist-query.ts | 0 .../deployed-databases-query.ts | 0 .../data/integrations/integration-query.ts | 0 .../data/merged-databases/merged-databases.ts | 0 .../data/messages/message-create-mutation.ts | 0 .../data/messages/messages-query.ts | 0 .../data/tables/tables-query.ts | 0 apps/{web => postgres-new}/docker-compose.yml | 0 apps/{web => postgres-new}/global.d.ts | 0 apps/{web => postgres-new}/lib/db/index.ts | 0 apps/{web => postgres-new}/lib/db/worker.ts | 0 apps/{web => postgres-new}/lib/embed/index.ts | 0 .../{web => postgres-new}/lib/embed/worker.ts | 0 apps/{web => postgres-new}/lib/files.ts | 0 apps/{web => postgres-new}/lib/hooks.ts | 0 apps/{web => postgres-new}/lib/indexed-db.ts | 0 .../{web => postgres-new}/lib/pg-wire-util.ts | 0 apps/{web => postgres-new}/lib/schema.ts | 0 .../lib/smooth-scroller.ts | 0 apps/{web => postgres-new}/lib/sql-util.ts | 0 apps/{web => postgres-new}/lib/streams.ts | 0 apps/{web => postgres-new}/lib/tools.ts | 0 .../lib/use-breakpoint.ts | 0 apps/{web => postgres-new}/lib/util.ts | 0 apps/{web => postgres-new}/lib/utils.ts | 0 .../lib/websocket-protocol.ts | 0 apps/{web => postgres-new}/middleware.ts | 0 apps/{web => postgres-new}/next.config.mjs | 0 apps/{web => postgres-new}/package.json | 0 .../polyfills/readable-stream.ts | 0 apps/{web => postgres-new}/postcss.config.mjs | 0 .../public/fonts/custom/CustomFont-Black.woff | Bin .../fonts/custom/CustomFont-Black.woff2 | Bin .../fonts/custom/CustomFont-BlackItalic.woff | Bin .../fonts/custom/CustomFont-BlackItalic.woff2 | Bin .../public/fonts/custom/CustomFont-Bold.woff | Bin .../public/fonts/custom/CustomFont-Bold.woff2 | Bin .../fonts/custom/CustomFont-BoldItalic.woff | Bin .../fonts/custom/CustomFont-BoldItalic.woff2 | Bin .../public/fonts/custom/CustomFont-Book.woff | Bin .../public/fonts/custom/CustomFont-Book.woff2 | Bin .../fonts/custom/CustomFont-BookItalic.woff | Bin .../fonts/custom/CustomFont-BookItalic.woff2 | Bin .../fonts/custom/CustomFont-Medium.woff | Bin .../fonts/custom/CustomFont-Medium.woff2 | Bin .../source-code-pro/SourceCodePro-Regular.eot | Bin .../source-code-pro/SourceCodePro-Regular.svg | 0 .../source-code-pro/SourceCodePro-Regular.ttf | Bin .../SourceCodePro-Regular.woff | Bin .../SourceCodePro-Regular.woff2 | Bin apps/{web => postgres-new}/tailwind.config.ts | 0 apps/{web => postgres-new}/tsconfig.json | 0 .../types/highlightjs-curl.d.ts | 0 .../utils/supabase/admin.ts | 0 .../utils/supabase/client.ts | 0 .../utils/supabase/db-types.ts | 0 .../utils/supabase/middleware.ts | 0 .../utils/supabase/server.ts | 0 package-lock.json | 48 +++++------------- 141 files changed, 14 insertions(+), 34 deletions(-) rename apps/{web => postgres-new}/.env.example (100%) rename apps/{web => postgres-new}/README.md (100%) rename apps/{web => postgres-new}/app/(main)/db/[id]/page.tsx (100%) rename apps/{web => postgres-new}/app/(main)/layout.tsx (100%) rename apps/{web => postgres-new}/app/(main)/page.tsx (100%) rename apps/{web => postgres-new}/app/api/chat/route.ts (100%) rename apps/{web => postgres-new}/app/api/integrations/[id]/details/route.ts (100%) rename apps/{web => postgres-new}/app/api/oauth/supabase/callback/route.ts (100%) rename apps/{web => postgres-new}/app/apple-icon.png (100%) rename apps/{web => postgres-new}/app/deploy/[databaseId]/page.tsx (100%) rename apps/{web => postgres-new}/app/export/page.tsx (100%) rename apps/{web => postgres-new}/app/favicon.ico (100%) rename apps/{web => postgres-new}/app/globals.css (100%) rename apps/{web => postgres-new}/app/icon.svg (100%) rename apps/{web => postgres-new}/app/import/page.tsx (100%) rename apps/{web => postgres-new}/app/layout.tsx (100%) rename apps/{web => postgres-new}/app/opengraph-image.png (100%) rename apps/{web => postgres-new}/assets/github-icon.tsx (100%) rename apps/{web => postgres-new}/components.json (100%) rename apps/{web => postgres-new}/components/ai-icon-animation/ai-icon-animation-style.module.css (100%) rename apps/{web => postgres-new}/components/ai-icon-animation/ai-icon-animation.tsx (100%) rename apps/{web => postgres-new}/components/ai-icon-animation/index.tsx (100%) rename apps/{web => postgres-new}/components/app-provider.tsx (100%) rename apps/{web => postgres-new}/components/chat-message.tsx (100%) rename apps/{web => postgres-new}/components/chat.tsx (100%) rename apps/{web => postgres-new}/components/code-accordion.tsx (100%) rename apps/{web => postgres-new}/components/code-block.tsx (100%) rename apps/{web => postgres-new}/components/copyable-field.tsx (100%) rename apps/{web => postgres-new}/components/deploy/deploy-dialog.tsx (100%) rename apps/{web => postgres-new}/components/deploy/deploy-failure-dialog.tsx (100%) rename apps/{web => postgres-new}/components/deploy/deploy-info-dialog.tsx (100%) rename apps/{web => postgres-new}/components/deploy/deploy-info.tsx (100%) rename apps/{web => postgres-new}/components/deploy/deploy-success-dialog.tsx (100%) rename apps/{web => postgres-new}/components/deploy/integration-dialog.tsx (100%) rename apps/{web => postgres-new}/components/deploy/redeploy-dialog.tsx (100%) rename apps/{web => postgres-new}/components/framer-features.ts (100%) rename apps/{web => postgres-new}/components/ide.tsx (100%) rename apps/{web => postgres-new}/components/layout.tsx (100%) rename apps/{web => postgres-new}/components/live-share-icon.tsx (100%) rename apps/{web => postgres-new}/components/markdown-accordion.tsx (100%) rename apps/{web => postgres-new}/components/particles-background.tsx (100%) rename apps/{web => postgres-new}/components/providers.tsx (100%) rename apps/{web => postgres-new}/components/schema/graph.tsx (100%) rename apps/{web => postgres-new}/components/schema/legend.tsx (100%) rename apps/{web => postgres-new}/components/schema/table-graph.tsx (100%) rename apps/{web => postgres-new}/components/schema/table-node.tsx (100%) rename apps/{web => postgres-new}/components/sidebar.tsx (100%) rename apps/{web => postgres-new}/components/sign-in-button.tsx (100%) rename apps/{web => postgres-new}/components/supabase-icon.tsx (100%) rename apps/{web => postgres-new}/components/theme-dropdown.tsx (100%) rename apps/{web => postgres-new}/components/theme-provider.tsx (100%) rename apps/{web => postgres-new}/components/tools/conversation-rename.tsx (100%) rename apps/{web => postgres-new}/components/tools/csv-export.tsx (100%) rename apps/{web => postgres-new}/components/tools/csv-import.tsx (100%) rename apps/{web => postgres-new}/components/tools/csv-request.tsx (100%) rename apps/{web => postgres-new}/components/tools/executed-sql.tsx (100%) rename apps/{web => postgres-new}/components/tools/generated-chart.tsx (100%) rename apps/{web => postgres-new}/components/tools/generated-embedding.tsx (100%) rename apps/{web => postgres-new}/components/tools/index.tsx (100%) rename apps/{web => postgres-new}/components/ui/accordion.tsx (100%) rename apps/{web => postgres-new}/components/ui/alert-dialog.tsx (100%) rename apps/{web => postgres-new}/components/ui/badge.tsx (100%) rename apps/{web => postgres-new}/components/ui/button.tsx (100%) rename apps/{web => postgres-new}/components/ui/dialog.tsx (100%) rename apps/{web => postgres-new}/components/ui/dropdown-menu.tsx (100%) rename apps/{web => postgres-new}/components/ui/input.tsx (100%) rename apps/{web => postgres-new}/components/ui/label.tsx (100%) rename apps/{web => postgres-new}/components/ui/popover.tsx (100%) rename apps/{web => postgres-new}/components/ui/progress.tsx (100%) rename apps/{web => postgres-new}/components/ui/skeleton.tsx (100%) rename apps/{web => postgres-new}/components/ui/tabs.tsx (100%) rename apps/{web => postgres-new}/components/ui/tooltip.tsx (100%) rename apps/{web => postgres-new}/components/workspace.tsx (100%) rename apps/{web => postgres-new}/config/default-colors.js (100%) rename apps/{web => postgres-new}/config/tailwind.config.js (100%) rename apps/{web => postgres-new}/config/ui.config.js (100%) rename apps/{web => postgres-new}/data/databases/database-create-mutation.ts (100%) rename apps/{web => postgres-new}/data/databases/database-delete-mutation.ts (100%) rename apps/{web => postgres-new}/data/databases/database-query.ts (100%) rename apps/{web => postgres-new}/data/databases/database-update-mutation.ts (100%) rename apps/{web => postgres-new}/data/databases/databases-query.ts (100%) rename apps/{web => postgres-new}/data/deploy-waitlist/deploy-waitlist-create-mutation.ts (100%) rename apps/{web => postgres-new}/data/deploy-waitlist/deploy-waitlist-query.ts (100%) rename apps/{web => postgres-new}/data/deployed-databases/deployed-databases-query.ts (100%) rename apps/{web => postgres-new}/data/integrations/integration-query.ts (100%) rename apps/{web => postgres-new}/data/merged-databases/merged-databases.ts (100%) rename apps/{web => postgres-new}/data/messages/message-create-mutation.ts (100%) rename apps/{web => postgres-new}/data/messages/messages-query.ts (100%) rename apps/{web => postgres-new}/data/tables/tables-query.ts (100%) rename apps/{web => postgres-new}/docker-compose.yml (100%) rename apps/{web => postgres-new}/global.d.ts (100%) rename apps/{web => postgres-new}/lib/db/index.ts (100%) rename apps/{web => postgres-new}/lib/db/worker.ts (100%) rename apps/{web => postgres-new}/lib/embed/index.ts (100%) rename apps/{web => postgres-new}/lib/embed/worker.ts (100%) rename apps/{web => postgres-new}/lib/files.ts (100%) rename apps/{web => postgres-new}/lib/hooks.ts (100%) rename apps/{web => postgres-new}/lib/indexed-db.ts (100%) rename apps/{web => postgres-new}/lib/pg-wire-util.ts (100%) rename apps/{web => postgres-new}/lib/schema.ts (100%) rename apps/{web => postgres-new}/lib/smooth-scroller.ts (100%) rename apps/{web => postgres-new}/lib/sql-util.ts (100%) rename apps/{web => postgres-new}/lib/streams.ts (100%) rename apps/{web => postgres-new}/lib/tools.ts (100%) rename apps/{web => postgres-new}/lib/use-breakpoint.ts (100%) rename apps/{web => postgres-new}/lib/util.ts (100%) rename apps/{web => postgres-new}/lib/utils.ts (100%) rename apps/{web => postgres-new}/lib/websocket-protocol.ts (100%) rename apps/{web => postgres-new}/middleware.ts (100%) rename apps/{web => postgres-new}/next.config.mjs (100%) rename apps/{web => postgres-new}/package.json (100%) rename apps/{web => postgres-new}/polyfills/readable-stream.ts (100%) rename apps/{web => postgres-new}/postcss.config.mjs (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Black.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Black.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BlackItalic.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BlackItalic.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Bold.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Bold.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BoldItalic.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BoldItalic.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Book.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Book.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BookItalic.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-BookItalic.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Medium.woff (100%) rename apps/{web => postgres-new}/public/fonts/custom/CustomFont-Medium.woff2 (100%) rename apps/{web => postgres-new}/public/fonts/source-code-pro/SourceCodePro-Regular.eot (100%) rename apps/{web => postgres-new}/public/fonts/source-code-pro/SourceCodePro-Regular.svg (100%) rename apps/{web => postgres-new}/public/fonts/source-code-pro/SourceCodePro-Regular.ttf (100%) rename apps/{web => postgres-new}/public/fonts/source-code-pro/SourceCodePro-Regular.woff (100%) rename apps/{web => postgres-new}/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 (100%) rename apps/{web => postgres-new}/tailwind.config.ts (100%) rename apps/{web => postgres-new}/tsconfig.json (100%) rename apps/{web => postgres-new}/types/highlightjs-curl.d.ts (100%) rename apps/{web => postgres-new}/utils/supabase/admin.ts (100%) rename apps/{web => postgres-new}/utils/supabase/client.ts (100%) rename apps/{web => postgres-new}/utils/supabase/db-types.ts (100%) rename apps/{web => postgres-new}/utils/supabase/middleware.ts (100%) rename apps/{web => postgres-new}/utils/supabase/server.ts (100%) diff --git a/apps/web/.env.example b/apps/postgres-new/.env.example similarity index 100% rename from apps/web/.env.example rename to apps/postgres-new/.env.example diff --git a/apps/web/README.md b/apps/postgres-new/README.md similarity index 100% rename from apps/web/README.md rename to apps/postgres-new/README.md diff --git a/apps/web/app/(main)/db/[id]/page.tsx b/apps/postgres-new/app/(main)/db/[id]/page.tsx similarity index 100% rename from apps/web/app/(main)/db/[id]/page.tsx rename to apps/postgres-new/app/(main)/db/[id]/page.tsx diff --git a/apps/web/app/(main)/layout.tsx b/apps/postgres-new/app/(main)/layout.tsx similarity index 100% rename from apps/web/app/(main)/layout.tsx rename to apps/postgres-new/app/(main)/layout.tsx diff --git a/apps/web/app/(main)/page.tsx b/apps/postgres-new/app/(main)/page.tsx similarity index 100% rename from apps/web/app/(main)/page.tsx rename to apps/postgres-new/app/(main)/page.tsx diff --git a/apps/web/app/api/chat/route.ts b/apps/postgres-new/app/api/chat/route.ts similarity index 100% rename from apps/web/app/api/chat/route.ts rename to apps/postgres-new/app/api/chat/route.ts diff --git a/apps/web/app/api/integrations/[id]/details/route.ts b/apps/postgres-new/app/api/integrations/[id]/details/route.ts similarity index 100% rename from apps/web/app/api/integrations/[id]/details/route.ts rename to apps/postgres-new/app/api/integrations/[id]/details/route.ts diff --git a/apps/web/app/api/oauth/supabase/callback/route.ts b/apps/postgres-new/app/api/oauth/supabase/callback/route.ts similarity index 100% rename from apps/web/app/api/oauth/supabase/callback/route.ts rename to apps/postgres-new/app/api/oauth/supabase/callback/route.ts diff --git a/apps/web/app/apple-icon.png b/apps/postgres-new/app/apple-icon.png similarity index 100% rename from apps/web/app/apple-icon.png rename to apps/postgres-new/app/apple-icon.png diff --git a/apps/web/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx similarity index 100% rename from apps/web/app/deploy/[databaseId]/page.tsx rename to apps/postgres-new/app/deploy/[databaseId]/page.tsx diff --git a/apps/web/app/export/page.tsx b/apps/postgres-new/app/export/page.tsx similarity index 100% rename from apps/web/app/export/page.tsx rename to apps/postgres-new/app/export/page.tsx diff --git a/apps/web/app/favicon.ico b/apps/postgres-new/app/favicon.ico similarity index 100% rename from apps/web/app/favicon.ico rename to apps/postgres-new/app/favicon.ico diff --git a/apps/web/app/globals.css b/apps/postgres-new/app/globals.css similarity index 100% rename from apps/web/app/globals.css rename to apps/postgres-new/app/globals.css diff --git a/apps/web/app/icon.svg b/apps/postgres-new/app/icon.svg similarity index 100% rename from apps/web/app/icon.svg rename to apps/postgres-new/app/icon.svg diff --git a/apps/web/app/import/page.tsx b/apps/postgres-new/app/import/page.tsx similarity index 100% rename from apps/web/app/import/page.tsx rename to apps/postgres-new/app/import/page.tsx diff --git a/apps/web/app/layout.tsx b/apps/postgres-new/app/layout.tsx similarity index 100% rename from apps/web/app/layout.tsx rename to apps/postgres-new/app/layout.tsx diff --git a/apps/web/app/opengraph-image.png b/apps/postgres-new/app/opengraph-image.png similarity index 100% rename from apps/web/app/opengraph-image.png rename to apps/postgres-new/app/opengraph-image.png diff --git a/apps/web/assets/github-icon.tsx b/apps/postgres-new/assets/github-icon.tsx similarity index 100% rename from apps/web/assets/github-icon.tsx rename to apps/postgres-new/assets/github-icon.tsx diff --git a/apps/web/components.json b/apps/postgres-new/components.json similarity index 100% rename from apps/web/components.json rename to apps/postgres-new/components.json diff --git a/apps/web/components/ai-icon-animation/ai-icon-animation-style.module.css b/apps/postgres-new/components/ai-icon-animation/ai-icon-animation-style.module.css similarity index 100% rename from apps/web/components/ai-icon-animation/ai-icon-animation-style.module.css rename to apps/postgres-new/components/ai-icon-animation/ai-icon-animation-style.module.css diff --git a/apps/web/components/ai-icon-animation/ai-icon-animation.tsx b/apps/postgres-new/components/ai-icon-animation/ai-icon-animation.tsx similarity index 100% rename from apps/web/components/ai-icon-animation/ai-icon-animation.tsx rename to apps/postgres-new/components/ai-icon-animation/ai-icon-animation.tsx diff --git a/apps/web/components/ai-icon-animation/index.tsx b/apps/postgres-new/components/ai-icon-animation/index.tsx similarity index 100% rename from apps/web/components/ai-icon-animation/index.tsx rename to apps/postgres-new/components/ai-icon-animation/index.tsx diff --git a/apps/web/components/app-provider.tsx b/apps/postgres-new/components/app-provider.tsx similarity index 100% rename from apps/web/components/app-provider.tsx rename to apps/postgres-new/components/app-provider.tsx diff --git a/apps/web/components/chat-message.tsx b/apps/postgres-new/components/chat-message.tsx similarity index 100% rename from apps/web/components/chat-message.tsx rename to apps/postgres-new/components/chat-message.tsx diff --git a/apps/web/components/chat.tsx b/apps/postgres-new/components/chat.tsx similarity index 100% rename from apps/web/components/chat.tsx rename to apps/postgres-new/components/chat.tsx diff --git a/apps/web/components/code-accordion.tsx b/apps/postgres-new/components/code-accordion.tsx similarity index 100% rename from apps/web/components/code-accordion.tsx rename to apps/postgres-new/components/code-accordion.tsx diff --git a/apps/web/components/code-block.tsx b/apps/postgres-new/components/code-block.tsx similarity index 100% rename from apps/web/components/code-block.tsx rename to apps/postgres-new/components/code-block.tsx diff --git a/apps/web/components/copyable-field.tsx b/apps/postgres-new/components/copyable-field.tsx similarity index 100% rename from apps/web/components/copyable-field.tsx rename to apps/postgres-new/components/copyable-field.tsx diff --git a/apps/web/components/deploy/deploy-dialog.tsx b/apps/postgres-new/components/deploy/deploy-dialog.tsx similarity index 100% rename from apps/web/components/deploy/deploy-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-dialog.tsx diff --git a/apps/web/components/deploy/deploy-failure-dialog.tsx b/apps/postgres-new/components/deploy/deploy-failure-dialog.tsx similarity index 100% rename from apps/web/components/deploy/deploy-failure-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-failure-dialog.tsx diff --git a/apps/web/components/deploy/deploy-info-dialog.tsx b/apps/postgres-new/components/deploy/deploy-info-dialog.tsx similarity index 100% rename from apps/web/components/deploy/deploy-info-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-info-dialog.tsx diff --git a/apps/web/components/deploy/deploy-info.tsx b/apps/postgres-new/components/deploy/deploy-info.tsx similarity index 100% rename from apps/web/components/deploy/deploy-info.tsx rename to apps/postgres-new/components/deploy/deploy-info.tsx diff --git a/apps/web/components/deploy/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy/deploy-success-dialog.tsx similarity index 100% rename from apps/web/components/deploy/deploy-success-dialog.tsx rename to apps/postgres-new/components/deploy/deploy-success-dialog.tsx diff --git a/apps/web/components/deploy/integration-dialog.tsx b/apps/postgres-new/components/deploy/integration-dialog.tsx similarity index 100% rename from apps/web/components/deploy/integration-dialog.tsx rename to apps/postgres-new/components/deploy/integration-dialog.tsx diff --git a/apps/web/components/deploy/redeploy-dialog.tsx b/apps/postgres-new/components/deploy/redeploy-dialog.tsx similarity index 100% rename from apps/web/components/deploy/redeploy-dialog.tsx rename to apps/postgres-new/components/deploy/redeploy-dialog.tsx diff --git a/apps/web/components/framer-features.ts b/apps/postgres-new/components/framer-features.ts similarity index 100% rename from apps/web/components/framer-features.ts rename to apps/postgres-new/components/framer-features.ts diff --git a/apps/web/components/ide.tsx b/apps/postgres-new/components/ide.tsx similarity index 100% rename from apps/web/components/ide.tsx rename to apps/postgres-new/components/ide.tsx diff --git a/apps/web/components/layout.tsx b/apps/postgres-new/components/layout.tsx similarity index 100% rename from apps/web/components/layout.tsx rename to apps/postgres-new/components/layout.tsx diff --git a/apps/web/components/live-share-icon.tsx b/apps/postgres-new/components/live-share-icon.tsx similarity index 100% rename from apps/web/components/live-share-icon.tsx rename to apps/postgres-new/components/live-share-icon.tsx diff --git a/apps/web/components/markdown-accordion.tsx b/apps/postgres-new/components/markdown-accordion.tsx similarity index 100% rename from apps/web/components/markdown-accordion.tsx rename to apps/postgres-new/components/markdown-accordion.tsx diff --git a/apps/web/components/particles-background.tsx b/apps/postgres-new/components/particles-background.tsx similarity index 100% rename from apps/web/components/particles-background.tsx rename to apps/postgres-new/components/particles-background.tsx diff --git a/apps/web/components/providers.tsx b/apps/postgres-new/components/providers.tsx similarity index 100% rename from apps/web/components/providers.tsx rename to apps/postgres-new/components/providers.tsx diff --git a/apps/web/components/schema/graph.tsx b/apps/postgres-new/components/schema/graph.tsx similarity index 100% rename from apps/web/components/schema/graph.tsx rename to apps/postgres-new/components/schema/graph.tsx diff --git a/apps/web/components/schema/legend.tsx b/apps/postgres-new/components/schema/legend.tsx similarity index 100% rename from apps/web/components/schema/legend.tsx rename to apps/postgres-new/components/schema/legend.tsx diff --git a/apps/web/components/schema/table-graph.tsx b/apps/postgres-new/components/schema/table-graph.tsx similarity index 100% rename from apps/web/components/schema/table-graph.tsx rename to apps/postgres-new/components/schema/table-graph.tsx diff --git a/apps/web/components/schema/table-node.tsx b/apps/postgres-new/components/schema/table-node.tsx similarity index 100% rename from apps/web/components/schema/table-node.tsx rename to apps/postgres-new/components/schema/table-node.tsx diff --git a/apps/web/components/sidebar.tsx b/apps/postgres-new/components/sidebar.tsx similarity index 100% rename from apps/web/components/sidebar.tsx rename to apps/postgres-new/components/sidebar.tsx diff --git a/apps/web/components/sign-in-button.tsx b/apps/postgres-new/components/sign-in-button.tsx similarity index 100% rename from apps/web/components/sign-in-button.tsx rename to apps/postgres-new/components/sign-in-button.tsx diff --git a/apps/web/components/supabase-icon.tsx b/apps/postgres-new/components/supabase-icon.tsx similarity index 100% rename from apps/web/components/supabase-icon.tsx rename to apps/postgres-new/components/supabase-icon.tsx diff --git a/apps/web/components/theme-dropdown.tsx b/apps/postgres-new/components/theme-dropdown.tsx similarity index 100% rename from apps/web/components/theme-dropdown.tsx rename to apps/postgres-new/components/theme-dropdown.tsx diff --git a/apps/web/components/theme-provider.tsx b/apps/postgres-new/components/theme-provider.tsx similarity index 100% rename from apps/web/components/theme-provider.tsx rename to apps/postgres-new/components/theme-provider.tsx diff --git a/apps/web/components/tools/conversation-rename.tsx b/apps/postgres-new/components/tools/conversation-rename.tsx similarity index 100% rename from apps/web/components/tools/conversation-rename.tsx rename to apps/postgres-new/components/tools/conversation-rename.tsx diff --git a/apps/web/components/tools/csv-export.tsx b/apps/postgres-new/components/tools/csv-export.tsx similarity index 100% rename from apps/web/components/tools/csv-export.tsx rename to apps/postgres-new/components/tools/csv-export.tsx diff --git a/apps/web/components/tools/csv-import.tsx b/apps/postgres-new/components/tools/csv-import.tsx similarity index 100% rename from apps/web/components/tools/csv-import.tsx rename to apps/postgres-new/components/tools/csv-import.tsx diff --git a/apps/web/components/tools/csv-request.tsx b/apps/postgres-new/components/tools/csv-request.tsx similarity index 100% rename from apps/web/components/tools/csv-request.tsx rename to apps/postgres-new/components/tools/csv-request.tsx diff --git a/apps/web/components/tools/executed-sql.tsx b/apps/postgres-new/components/tools/executed-sql.tsx similarity index 100% rename from apps/web/components/tools/executed-sql.tsx rename to apps/postgres-new/components/tools/executed-sql.tsx diff --git a/apps/web/components/tools/generated-chart.tsx b/apps/postgres-new/components/tools/generated-chart.tsx similarity index 100% rename from apps/web/components/tools/generated-chart.tsx rename to apps/postgres-new/components/tools/generated-chart.tsx diff --git a/apps/web/components/tools/generated-embedding.tsx b/apps/postgres-new/components/tools/generated-embedding.tsx similarity index 100% rename from apps/web/components/tools/generated-embedding.tsx rename to apps/postgres-new/components/tools/generated-embedding.tsx diff --git a/apps/web/components/tools/index.tsx b/apps/postgres-new/components/tools/index.tsx similarity index 100% rename from apps/web/components/tools/index.tsx rename to apps/postgres-new/components/tools/index.tsx diff --git a/apps/web/components/ui/accordion.tsx b/apps/postgres-new/components/ui/accordion.tsx similarity index 100% rename from apps/web/components/ui/accordion.tsx rename to apps/postgres-new/components/ui/accordion.tsx diff --git a/apps/web/components/ui/alert-dialog.tsx b/apps/postgres-new/components/ui/alert-dialog.tsx similarity index 100% rename from apps/web/components/ui/alert-dialog.tsx rename to apps/postgres-new/components/ui/alert-dialog.tsx diff --git a/apps/web/components/ui/badge.tsx b/apps/postgres-new/components/ui/badge.tsx similarity index 100% rename from apps/web/components/ui/badge.tsx rename to apps/postgres-new/components/ui/badge.tsx diff --git a/apps/web/components/ui/button.tsx b/apps/postgres-new/components/ui/button.tsx similarity index 100% rename from apps/web/components/ui/button.tsx rename to apps/postgres-new/components/ui/button.tsx diff --git a/apps/web/components/ui/dialog.tsx b/apps/postgres-new/components/ui/dialog.tsx similarity index 100% rename from apps/web/components/ui/dialog.tsx rename to apps/postgres-new/components/ui/dialog.tsx diff --git a/apps/web/components/ui/dropdown-menu.tsx b/apps/postgres-new/components/ui/dropdown-menu.tsx similarity index 100% rename from apps/web/components/ui/dropdown-menu.tsx rename to apps/postgres-new/components/ui/dropdown-menu.tsx diff --git a/apps/web/components/ui/input.tsx b/apps/postgres-new/components/ui/input.tsx similarity index 100% rename from apps/web/components/ui/input.tsx rename to apps/postgres-new/components/ui/input.tsx diff --git a/apps/web/components/ui/label.tsx b/apps/postgres-new/components/ui/label.tsx similarity index 100% rename from apps/web/components/ui/label.tsx rename to apps/postgres-new/components/ui/label.tsx diff --git a/apps/web/components/ui/popover.tsx b/apps/postgres-new/components/ui/popover.tsx similarity index 100% rename from apps/web/components/ui/popover.tsx rename to apps/postgres-new/components/ui/popover.tsx diff --git a/apps/web/components/ui/progress.tsx b/apps/postgres-new/components/ui/progress.tsx similarity index 100% rename from apps/web/components/ui/progress.tsx rename to apps/postgres-new/components/ui/progress.tsx diff --git a/apps/web/components/ui/skeleton.tsx b/apps/postgres-new/components/ui/skeleton.tsx similarity index 100% rename from apps/web/components/ui/skeleton.tsx rename to apps/postgres-new/components/ui/skeleton.tsx diff --git a/apps/web/components/ui/tabs.tsx b/apps/postgres-new/components/ui/tabs.tsx similarity index 100% rename from apps/web/components/ui/tabs.tsx rename to apps/postgres-new/components/ui/tabs.tsx diff --git a/apps/web/components/ui/tooltip.tsx b/apps/postgres-new/components/ui/tooltip.tsx similarity index 100% rename from apps/web/components/ui/tooltip.tsx rename to apps/postgres-new/components/ui/tooltip.tsx diff --git a/apps/web/components/workspace.tsx b/apps/postgres-new/components/workspace.tsx similarity index 100% rename from apps/web/components/workspace.tsx rename to apps/postgres-new/components/workspace.tsx diff --git a/apps/web/config/default-colors.js b/apps/postgres-new/config/default-colors.js similarity index 100% rename from apps/web/config/default-colors.js rename to apps/postgres-new/config/default-colors.js diff --git a/apps/web/config/tailwind.config.js b/apps/postgres-new/config/tailwind.config.js similarity index 100% rename from apps/web/config/tailwind.config.js rename to apps/postgres-new/config/tailwind.config.js diff --git a/apps/web/config/ui.config.js b/apps/postgres-new/config/ui.config.js similarity index 100% rename from apps/web/config/ui.config.js rename to apps/postgres-new/config/ui.config.js diff --git a/apps/web/data/databases/database-create-mutation.ts b/apps/postgres-new/data/databases/database-create-mutation.ts similarity index 100% rename from apps/web/data/databases/database-create-mutation.ts rename to apps/postgres-new/data/databases/database-create-mutation.ts diff --git a/apps/web/data/databases/database-delete-mutation.ts b/apps/postgres-new/data/databases/database-delete-mutation.ts similarity index 100% rename from apps/web/data/databases/database-delete-mutation.ts rename to apps/postgres-new/data/databases/database-delete-mutation.ts diff --git a/apps/web/data/databases/database-query.ts b/apps/postgres-new/data/databases/database-query.ts similarity index 100% rename from apps/web/data/databases/database-query.ts rename to apps/postgres-new/data/databases/database-query.ts diff --git a/apps/web/data/databases/database-update-mutation.ts b/apps/postgres-new/data/databases/database-update-mutation.ts similarity index 100% rename from apps/web/data/databases/database-update-mutation.ts rename to apps/postgres-new/data/databases/database-update-mutation.ts diff --git a/apps/web/data/databases/databases-query.ts b/apps/postgres-new/data/databases/databases-query.ts similarity index 100% rename from apps/web/data/databases/databases-query.ts rename to apps/postgres-new/data/databases/databases-query.ts diff --git a/apps/web/data/deploy-waitlist/deploy-waitlist-create-mutation.ts b/apps/postgres-new/data/deploy-waitlist/deploy-waitlist-create-mutation.ts similarity index 100% rename from apps/web/data/deploy-waitlist/deploy-waitlist-create-mutation.ts rename to apps/postgres-new/data/deploy-waitlist/deploy-waitlist-create-mutation.ts diff --git a/apps/web/data/deploy-waitlist/deploy-waitlist-query.ts b/apps/postgres-new/data/deploy-waitlist/deploy-waitlist-query.ts similarity index 100% rename from apps/web/data/deploy-waitlist/deploy-waitlist-query.ts rename to apps/postgres-new/data/deploy-waitlist/deploy-waitlist-query.ts diff --git a/apps/web/data/deployed-databases/deployed-databases-query.ts b/apps/postgres-new/data/deployed-databases/deployed-databases-query.ts similarity index 100% rename from apps/web/data/deployed-databases/deployed-databases-query.ts rename to apps/postgres-new/data/deployed-databases/deployed-databases-query.ts diff --git a/apps/web/data/integrations/integration-query.ts b/apps/postgres-new/data/integrations/integration-query.ts similarity index 100% rename from apps/web/data/integrations/integration-query.ts rename to apps/postgres-new/data/integrations/integration-query.ts diff --git a/apps/web/data/merged-databases/merged-databases.ts b/apps/postgres-new/data/merged-databases/merged-databases.ts similarity index 100% rename from apps/web/data/merged-databases/merged-databases.ts rename to apps/postgres-new/data/merged-databases/merged-databases.ts diff --git a/apps/web/data/messages/message-create-mutation.ts b/apps/postgres-new/data/messages/message-create-mutation.ts similarity index 100% rename from apps/web/data/messages/message-create-mutation.ts rename to apps/postgres-new/data/messages/message-create-mutation.ts diff --git a/apps/web/data/messages/messages-query.ts b/apps/postgres-new/data/messages/messages-query.ts similarity index 100% rename from apps/web/data/messages/messages-query.ts rename to apps/postgres-new/data/messages/messages-query.ts diff --git a/apps/web/data/tables/tables-query.ts b/apps/postgres-new/data/tables/tables-query.ts similarity index 100% rename from apps/web/data/tables/tables-query.ts rename to apps/postgres-new/data/tables/tables-query.ts diff --git a/apps/web/docker-compose.yml b/apps/postgres-new/docker-compose.yml similarity index 100% rename from apps/web/docker-compose.yml rename to apps/postgres-new/docker-compose.yml diff --git a/apps/web/global.d.ts b/apps/postgres-new/global.d.ts similarity index 100% rename from apps/web/global.d.ts rename to apps/postgres-new/global.d.ts diff --git a/apps/web/lib/db/index.ts b/apps/postgres-new/lib/db/index.ts similarity index 100% rename from apps/web/lib/db/index.ts rename to apps/postgres-new/lib/db/index.ts diff --git a/apps/web/lib/db/worker.ts b/apps/postgres-new/lib/db/worker.ts similarity index 100% rename from apps/web/lib/db/worker.ts rename to apps/postgres-new/lib/db/worker.ts diff --git a/apps/web/lib/embed/index.ts b/apps/postgres-new/lib/embed/index.ts similarity index 100% rename from apps/web/lib/embed/index.ts rename to apps/postgres-new/lib/embed/index.ts diff --git a/apps/web/lib/embed/worker.ts b/apps/postgres-new/lib/embed/worker.ts similarity index 100% rename from apps/web/lib/embed/worker.ts rename to apps/postgres-new/lib/embed/worker.ts diff --git a/apps/web/lib/files.ts b/apps/postgres-new/lib/files.ts similarity index 100% rename from apps/web/lib/files.ts rename to apps/postgres-new/lib/files.ts diff --git a/apps/web/lib/hooks.ts b/apps/postgres-new/lib/hooks.ts similarity index 100% rename from apps/web/lib/hooks.ts rename to apps/postgres-new/lib/hooks.ts diff --git a/apps/web/lib/indexed-db.ts b/apps/postgres-new/lib/indexed-db.ts similarity index 100% rename from apps/web/lib/indexed-db.ts rename to apps/postgres-new/lib/indexed-db.ts diff --git a/apps/web/lib/pg-wire-util.ts b/apps/postgres-new/lib/pg-wire-util.ts similarity index 100% rename from apps/web/lib/pg-wire-util.ts rename to apps/postgres-new/lib/pg-wire-util.ts diff --git a/apps/web/lib/schema.ts b/apps/postgres-new/lib/schema.ts similarity index 100% rename from apps/web/lib/schema.ts rename to apps/postgres-new/lib/schema.ts diff --git a/apps/web/lib/smooth-scroller.ts b/apps/postgres-new/lib/smooth-scroller.ts similarity index 100% rename from apps/web/lib/smooth-scroller.ts rename to apps/postgres-new/lib/smooth-scroller.ts diff --git a/apps/web/lib/sql-util.ts b/apps/postgres-new/lib/sql-util.ts similarity index 100% rename from apps/web/lib/sql-util.ts rename to apps/postgres-new/lib/sql-util.ts diff --git a/apps/web/lib/streams.ts b/apps/postgres-new/lib/streams.ts similarity index 100% rename from apps/web/lib/streams.ts rename to apps/postgres-new/lib/streams.ts diff --git a/apps/web/lib/tools.ts b/apps/postgres-new/lib/tools.ts similarity index 100% rename from apps/web/lib/tools.ts rename to apps/postgres-new/lib/tools.ts diff --git a/apps/web/lib/use-breakpoint.ts b/apps/postgres-new/lib/use-breakpoint.ts similarity index 100% rename from apps/web/lib/use-breakpoint.ts rename to apps/postgres-new/lib/use-breakpoint.ts diff --git a/apps/web/lib/util.ts b/apps/postgres-new/lib/util.ts similarity index 100% rename from apps/web/lib/util.ts rename to apps/postgres-new/lib/util.ts diff --git a/apps/web/lib/utils.ts b/apps/postgres-new/lib/utils.ts similarity index 100% rename from apps/web/lib/utils.ts rename to apps/postgres-new/lib/utils.ts diff --git a/apps/web/lib/websocket-protocol.ts b/apps/postgres-new/lib/websocket-protocol.ts similarity index 100% rename from apps/web/lib/websocket-protocol.ts rename to apps/postgres-new/lib/websocket-protocol.ts diff --git a/apps/web/middleware.ts b/apps/postgres-new/middleware.ts similarity index 100% rename from apps/web/middleware.ts rename to apps/postgres-new/middleware.ts diff --git a/apps/web/next.config.mjs b/apps/postgres-new/next.config.mjs similarity index 100% rename from apps/web/next.config.mjs rename to apps/postgres-new/next.config.mjs diff --git a/apps/web/package.json b/apps/postgres-new/package.json similarity index 100% rename from apps/web/package.json rename to apps/postgres-new/package.json diff --git a/apps/web/polyfills/readable-stream.ts b/apps/postgres-new/polyfills/readable-stream.ts similarity index 100% rename from apps/web/polyfills/readable-stream.ts rename to apps/postgres-new/polyfills/readable-stream.ts diff --git a/apps/web/postcss.config.mjs b/apps/postgres-new/postcss.config.mjs similarity index 100% rename from apps/web/postcss.config.mjs rename to apps/postgres-new/postcss.config.mjs diff --git a/apps/web/public/fonts/custom/CustomFont-Black.woff b/apps/postgres-new/public/fonts/custom/CustomFont-Black.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Black.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-Black.woff diff --git a/apps/web/public/fonts/custom/CustomFont-Black.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-Black.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Black.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-Black.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-BlackItalic.woff b/apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BlackItalic.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff diff --git a/apps/web/public/fonts/custom/CustomFont-BlackItalic.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BlackItalic.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-BlackItalic.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-Bold.woff b/apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Bold.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff diff --git a/apps/web/public/fonts/custom/CustomFont-Bold.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Bold.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-Bold.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-BoldItalic.woff b/apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BoldItalic.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff diff --git a/apps/web/public/fonts/custom/CustomFont-BoldItalic.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BoldItalic.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-BoldItalic.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-Book.woff b/apps/postgres-new/public/fonts/custom/CustomFont-Book.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Book.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-Book.woff diff --git a/apps/web/public/fonts/custom/CustomFont-Book.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-Book.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Book.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-Book.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-BookItalic.woff b/apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BookItalic.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff diff --git a/apps/web/public/fonts/custom/CustomFont-BookItalic.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-BookItalic.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-BookItalic.woff2 diff --git a/apps/web/public/fonts/custom/CustomFont-Medium.woff b/apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Medium.woff rename to apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff diff --git a/apps/web/public/fonts/custom/CustomFont-Medium.woff2 b/apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff2 similarity index 100% rename from apps/web/public/fonts/custom/CustomFont-Medium.woff2 rename to apps/postgres-new/public/fonts/custom/CustomFont-Medium.woff2 diff --git a/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.eot b/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.eot similarity index 100% rename from apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.eot rename to apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.eot diff --git a/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.svg b/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.svg similarity index 100% rename from apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.svg rename to apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.svg diff --git a/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.ttf b/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.ttf similarity index 100% rename from apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.ttf rename to apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.ttf diff --git a/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff b/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff similarity index 100% rename from apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff rename to apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff diff --git a/apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 b/apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 similarity index 100% rename from apps/web/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 rename to apps/postgres-new/public/fonts/source-code-pro/SourceCodePro-Regular.woff2 diff --git a/apps/web/tailwind.config.ts b/apps/postgres-new/tailwind.config.ts similarity index 100% rename from apps/web/tailwind.config.ts rename to apps/postgres-new/tailwind.config.ts diff --git a/apps/web/tsconfig.json b/apps/postgres-new/tsconfig.json similarity index 100% rename from apps/web/tsconfig.json rename to apps/postgres-new/tsconfig.json diff --git a/apps/web/types/highlightjs-curl.d.ts b/apps/postgres-new/types/highlightjs-curl.d.ts similarity index 100% rename from apps/web/types/highlightjs-curl.d.ts rename to apps/postgres-new/types/highlightjs-curl.d.ts diff --git a/apps/web/utils/supabase/admin.ts b/apps/postgres-new/utils/supabase/admin.ts similarity index 100% rename from apps/web/utils/supabase/admin.ts rename to apps/postgres-new/utils/supabase/admin.ts diff --git a/apps/web/utils/supabase/client.ts b/apps/postgres-new/utils/supabase/client.ts similarity index 100% rename from apps/web/utils/supabase/client.ts rename to apps/postgres-new/utils/supabase/client.ts diff --git a/apps/web/utils/supabase/db-types.ts b/apps/postgres-new/utils/supabase/db-types.ts similarity index 100% rename from apps/web/utils/supabase/db-types.ts rename to apps/postgres-new/utils/supabase/db-types.ts diff --git a/apps/web/utils/supabase/middleware.ts b/apps/postgres-new/utils/supabase/middleware.ts similarity index 100% rename from apps/web/utils/supabase/middleware.ts rename to apps/postgres-new/utils/supabase/middleware.ts diff --git a/apps/web/utils/supabase/server.ts b/apps/postgres-new/utils/supabase/server.ts similarity index 100% rename from apps/web/utils/supabase/server.ts rename to apps/postgres-new/utils/supabase/server.ts diff --git a/package-lock.json b/package-lock.json index d0760c7c..2a9bef21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,18 +71,6 @@ "dev": true, "license": "MIT" }, - "apps/db-service": { - "extraneous": true, - "dependencies": { - "@electric-sql/pglite": "0.2.0-alpha.9", - "pg-gateway": "^0.2.5-alpha.2" - }, - "devDependencies": { - "@types/node": "^20.14.11", - "tsx": "^4.16.2", - "typescript": "^5.5.3" - } - }, "apps/deploy-worker": { "name": "@database.build/deploy-worker", "dependencies": { @@ -120,21 +108,6 @@ "license": "MIT" }, "apps/postgres-new": { - "dependencies": { - "date-fns": "^4.1.0" - } - }, - "apps/postgres-new/node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "apps/web": { "name": "@database.build/web", "version": "0.0.0", "dependencies": { @@ -222,7 +195,17 @@ "webpack": "^5.95.0" } }, - "apps/web/node_modules/nanoid": { + "apps/postgres-new/node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "apps/postgres-new/node_modules/nanoid": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", @@ -240,7 +223,7 @@ "node": "^18 || >=20" } }, - "apps/web/node_modules/web-streams-polyfill": { + "apps/postgres-new/node_modules/web-streams-polyfill": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0.tgz", "integrity": "sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==", @@ -1517,7 +1500,7 @@ "link": true }, "node_modules/@database.build/web": { - "resolved": "apps/web", + "resolved": "apps/postgres-new", "link": true }, "node_modules/@electric-sql/pglite": { @@ -7461,6 +7444,7 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -13961,10 +13945,6 @@ "node": ">=0.10.0" } }, - "node_modules/postgres-new": { - "resolved": "apps/postgres-new", - "link": true - }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", From 0c9adb41350919b811ef2ae0afeffcedb0f2c2b3 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 14:45:49 -0700 Subject: [PATCH 47/59] chore(turbo): build task for web --- turbo.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/turbo.json b/turbo.json index fdff56c9..e839c0d6 100644 --- a/turbo.json +++ b/turbo.json @@ -25,6 +25,11 @@ "persistent": true, "cache": true }, + "@database.build/web#build": { + "dependsOn": ["^build"], + "outputs": [".next/**", "!.next/cache/**"], + "cache": true + }, "type-check": { "dependsOn": ["^type-check"] } From d3d819a44ed86323ea1c41fb25f3668b3f09aa84 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 19:53:08 -0700 Subject: [PATCH 48/59] chore: vercel build command --- vercel.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 00000000..948f5760 --- /dev/null +++ b/vercel.json @@ -0,0 +1,3 @@ +{ + "buildCommand": "turbo build" +} From 3e38bcefa7d7373a4c08ce903fef735096a14381 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Mon, 18 Nov 2024 19:57:25 -0700 Subject: [PATCH 49/59] chore(vercel): do not track turbo build --- vercel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vercel.json b/vercel.json index 948f5760..ce36d707 100644 --- a/vercel.json +++ b/vercel.json @@ -1,3 +1,3 @@ { - "buildCommand": "turbo build" + "buildCommand": "DO_NOT_TRACK=1 turbo build" } From b538237aa49f3300993db8c2ab4c23152b46de2c Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Tue, 19 Nov 2024 18:52:02 +0100 Subject: [PATCH 50/59] add a build step for deploy-worker --- apps/deploy-worker/package.json | 1 + turbo.json | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/apps/deploy-worker/package.json b/apps/deploy-worker/package.json index 5c3d064b..6c4b09b1 100644 --- a/apps/deploy-worker/package.json +++ b/apps/deploy-worker/package.json @@ -4,6 +4,7 @@ "scripts": { "start": "node --env-file=.env --experimental-strip-types src/index.ts", "dev": "npm run start", + "build": "echo 'built'", "type-check": "tsc", "generate:database-types": "npx supabase gen types --lang=typescript --local > ./supabase/database-types.ts", "generate:management-api-types": "npx openapi-typescript https://api.supabase.com/api/v1-json -o ./supabase/management-api/types.ts" diff --git a/turbo.json b/turbo.json index e839c0d6..a16ebaef 100644 --- a/turbo.json +++ b/turbo.json @@ -13,6 +13,10 @@ "interruptible": true, "cache": false }, + "@database.build/deploy-worker#build": { + "dependsOn": ["^build"], + "cache": false + }, "@database.build/browser-proxy#dev": { "dependsOn": ["^build"], "persistent": true, From efdfb1280683c5045d7217eee67c544805e5f326 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Tue, 19 Nov 2024 22:19:56 -0700 Subject: [PATCH 51/59] feat: update docker/fly config for monorepo --- .dockerignore | 4 +++ apps/deploy-worker/Dockerfile | 31 +++++++++++++++++-- .../fly.toml => fly.browser-proxy.toml | 3 ++ .../fly.toml => fly.deploy-worker.toml | 3 ++ 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 .dockerignore rename apps/browser-proxy/fly.toml => fly.browser-proxy.toml (84%) rename apps/deploy-worker/fly.toml => fly.deploy-worker.toml (79%) diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..186fe69a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +**/node_modules +**/.next +**/.turbo +**/.env* diff --git a/apps/deploy-worker/Dockerfile b/apps/deploy-worker/Dockerfile index e7bee1e4..b8070232 100644 --- a/apps/deploy-worker/Dockerfile +++ b/apps/deploy-worker/Dockerfile @@ -1,14 +1,39 @@ -FROM node:22-alpine +FROM node:22-alpine AS base + +FROM base AS builder RUN apk add --no-cache postgresql16-client WORKDIR /app -COPY --link package.json ./ -COPY --link src/ ./src/ +RUN npm install -g turbo@^2 +COPY . . + +# Generate a partial monorepo with a pruned lockfile for a target workspace. +RUN turbo prune @database.build/deploy-worker --docker +FROM base AS installer +WORKDIR /app + +# First install the dependencies (as they change less often) +COPY --from=builder /app/out/json/ . RUN npm install +# Build the project +COPY --from=builder /app/out/full/ . +RUN npx turbo run build --filter=@database.build/deploy-worker + +FROM base AS runner + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nodejs +USER nodejs + +COPY --from=installer --chown=nodejs:nodejs /app /app + +WORKDIR /app/apps/deploy-worker + EXPOSE 443 EXPOSE 5432 diff --git a/apps/browser-proxy/fly.toml b/fly.browser-proxy.toml similarity index 84% rename from apps/browser-proxy/fly.toml rename to fly.browser-proxy.toml index e23f6c12..4cc21dcb 100644 --- a/apps/browser-proxy/fly.toml +++ b/fly.browser-proxy.toml @@ -1,5 +1,8 @@ primary_region = 'iad' +[build] +dockerfile = "./apps/browser-proxy/Dockerfile" + [[services]] internal_port = 5432 protocol = "tcp" diff --git a/apps/deploy-worker/fly.toml b/fly.deploy-worker.toml similarity index 79% rename from apps/deploy-worker/fly.toml rename to fly.deploy-worker.toml index 0b6cc8b8..e450e323 100644 --- a/apps/deploy-worker/fly.toml +++ b/fly.deploy-worker.toml @@ -1,5 +1,8 @@ primary_region = 'iad' +[build] +dockerfile = "./apps/deploy-worker/Dockerfile" + [http_service] internal_port = 4000 force_https = true From 2c5d0c9ff37c56c27fdca07e9fbcd3ad1c21c6f3 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Wed, 20 Nov 2024 10:21:09 +0100 Subject: [PATCH 52/59] install postgresclient in the runner --- apps/deploy-worker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/deploy-worker/Dockerfile b/apps/deploy-worker/Dockerfile index b8070232..3e8238e4 100644 --- a/apps/deploy-worker/Dockerfile +++ b/apps/deploy-worker/Dockerfile @@ -2,8 +2,6 @@ FROM node:22-alpine AS base FROM base AS builder -RUN apk add --no-cache postgresql16-client - WORKDIR /app RUN npm install -g turbo@^2 @@ -25,6 +23,8 @@ RUN npx turbo run build --filter=@database.build/deploy-worker FROM base AS runner +RUN apk add --no-cache postgresql16-client + # Don't run production as root RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nodejs From ab3f89128925a48a662c57ce0cb0db7d6d7e57f2 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 20 Nov 2024 10:57:47 -0700 Subject: [PATCH 53/59] fix: only reference successful deployments for latest_deployment_at --- supabase/migrations/20241003131953_deployment.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index b2d33272..3075fd40 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -78,6 +78,8 @@ left join ( max(created_at) as created_at from deployments + where + status = 'success' group by deployed_database_id ) d From 07e001abe329fba0cc26f615b3344a58fbd4679e Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 20 Nov 2024 11:07:59 -0700 Subject: [PATCH 54/59] fix: security invoker on latest_deployed_databases --- supabase/migrations/20241003131953_deployment.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/supabase/migrations/20241003131953_deployment.sql b/supabase/migrations/20241003131953_deployment.sql index 3075fd40..d1e5a527 100644 --- a/supabase/migrations/20241003131953_deployment.sql +++ b/supabase/migrations/20241003131953_deployment.sql @@ -66,7 +66,9 @@ create trigger deployments_updated_at before update on deployments for each row execute procedure moddatetime (updated_at); -- view for getting deployed databases with their last deployment date -create view latest_deployed_databases as +create view latest_deployed_databases +with (security_invoker=true) +as select deployed_databases.*, d.created_at as last_deployment_at From 0bf02d48c63c993507aa628fcfe519418d012c49 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 20 Nov 2024 11:34:23 -0700 Subject: [PATCH 55/59] docs: update links to point back to ./apps/postgres-new --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0934b4fe..e61403a1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ How is this possible? [PGlite](https://pglite.dev/), a WASM version of Postgres This is a monorepo split into the following projects: -- [Web](./apps/web/): The primary web app built with Next.js +- [Web](./apps/postgres-new/): The primary web app built with Next.js - [Browser proxy](./apps/browser-proxy/): Proxies Postgres TCP connections back to the browser using [pg-gateway](https://github.com/supabase-community/pg-gateway) and Web Sockets - [Deploy worker](./apps/deploy-worker/): Deploys in-browser databases to database platforms (currently Supabase is supported) @@ -41,33 +41,33 @@ From the monorepo root: ```shell npx supabase start ``` -3. Store local Supabase URL/anon key in `./apps/web/.env.local`: +3. Store local Supabase URL/anon key in `./apps/postgres-new/.env.local`: ```shell npx supabase status -o env \ --override-name api.url=NEXT_PUBLIC_SUPABASE_URL \ --override-name auth.anon_key=NEXT_PUBLIC_SUPABASE_ANON_KEY | - grep NEXT_PUBLIC >> ./apps/web/.env.local + grep NEXT_PUBLIC >> ./apps/postgres-new/.env.local ``` -4. Create an [OpenAI API key](https://platform.openai.com/api-keys) and save to `./apps/web/.env.local`: +4. Create an [OpenAI API key](https://platform.openai.com/api-keys) and save to `./apps/postgres-new/.env.local`: ```shell - echo 'OPENAI_API_KEY=""' >> ./apps/web/.env.local + echo 'OPENAI_API_KEY=""' >> ./apps/postgres-new/.env.local ``` 5. Store local KV (Redis) vars. Use these exact values: ```shell - echo 'KV_REST_API_URL="http://localhost:8080"' >> ./apps/web/.env.local - echo 'KV_REST_API_TOKEN="local_token"' >> ./apps/web/.env.local + echo 'KV_REST_API_URL="http://localhost:8080"' >> ./apps/postgres-new/.env.local + echo 'KV_REST_API_TOKEN="local_token"' >> ./apps/postgres-new/.env.local ``` 6. Start local Redis containers (used for rate limiting). Serves an API on port 8080: ```shell - docker compose -f ./apps/web/docker-compose.yml up -d + docker compose -f ./apps/postgres-new/docker-compose.yml up -d ``` 7. Fill in the remaining variables for each app as seen in: - - `./apps/web/.env.example` + - `./apps/postgres-new/.env.example` - `./apps/browser-proxy/.env.example` - `./apps/deploy-worker/.env.example` From ec24fe292cfe15570f6e839d94ebf46d0012eac3 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 20 Nov 2024 11:58:00 -0700 Subject: [PATCH 56/59] feat: add supabase logo to every deploy dialog --- apps/postgres-new/app/deploy/[databaseId]/page.tsx | 6 +++++- .../components/deploy/deploy-success-dialog.tsx | 6 +++++- apps/postgres-new/components/deploy/integration-dialog.tsx | 6 +++++- apps/postgres-new/components/deploy/redeploy-dialog.tsx | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/postgres-new/app/deploy/[databaseId]/page.tsx b/apps/postgres-new/app/deploy/[databaseId]/page.tsx index e2f3b442..bf058366 100644 --- a/apps/postgres-new/app/deploy/[databaseId]/page.tsx +++ b/apps/postgres-new/app/deploy/[databaseId]/page.tsx @@ -9,6 +9,7 @@ import { createClient } from '~/utils/supabase/client' import { Loader2 } from 'lucide-react' import { ParticlesBackground } from '~/components/particles-background' import { getOauthUrl } from '~/lib/util' +import { SupabaseIcon } from '~/components/supabase-icon' class IntegrationRevokedError extends Error { constructor() { @@ -115,7 +116,10 @@ export default function Page() { overlay={false} > - Deploying your database + + + Deploying your database +
diff --git a/apps/postgres-new/components/deploy/deploy-success-dialog.tsx b/apps/postgres-new/components/deploy/deploy-success-dialog.tsx index 74afdeb1..81298dde 100644 --- a/apps/postgres-new/components/deploy/deploy-success-dialog.tsx +++ b/apps/postgres-new/components/deploy/deploy-success-dialog.tsx @@ -2,6 +2,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' import { SupabaseDeployInfo, SupabaseDeploymentInfo } from './deploy-info' +import { SupabaseIcon } from '../supabase-icon' export type DeploySuccessDialogProps = { open: boolean @@ -17,7 +18,10 @@ export function DeploySuccessDialog({ open, onOpenChange, deployInfo }: DeploySu - Database {deployText} + + + Database {deployText} +
diff --git a/apps/postgres-new/components/deploy/integration-dialog.tsx b/apps/postgres-new/components/deploy/integration-dialog.tsx index f4395f1d..5b0949f6 100644 --- a/apps/postgres-new/components/deploy/integration-dialog.tsx +++ b/apps/postgres-new/components/deploy/integration-dialog.tsx @@ -3,6 +3,7 @@ import { DialogProps } from '@radix-ui/react-dialog' import { Button } from '~/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '~/components/ui/dialog' +import { SupabaseIcon } from '../supabase-icon' export type IntegrationDialogProps = DialogProps & { onConfirm?: () => void @@ -13,7 +14,10 @@ export function IntegrationDialog({ onConfirm, ...props }: IntegrationDialogProp - Connect Supabase + + + Connect Supabase +
diff --git a/apps/postgres-new/components/deploy/redeploy-dialog.tsx b/apps/postgres-new/components/deploy/redeploy-dialog.tsx index a84c9ae3..f84b4e03 100644 --- a/apps/postgres-new/components/deploy/redeploy-dialog.tsx +++ b/apps/postgres-new/components/deploy/redeploy-dialog.tsx @@ -13,6 +13,7 @@ import { import { Input } from '~/components/ui/input' import { MergedDatabase } from '~/data/merged-databases/merged-databases' import { Button } from '../ui/button' +import { SupabaseIcon } from '../supabase-icon' export type RedeployDialogProps = { database: MergedDatabase @@ -28,7 +29,10 @@ export function RedeployDialog({ database, open, onOpenChange, onConfirm }: Rede - Confirm redeploy of {database.name} + + + Confirm redeploy of {database.name} +
From 84f7075c3a7ff2898c80ba5dd459db9d5e63e4a8 Mon Sep 17 00:00:00 2001 From: Greg Richardson Date: Wed, 20 Nov 2024 12:54:35 -0700 Subject: [PATCH 57/59] feat: warn user about overlapping supabase schemas --- apps/deploy-worker/src/deploy.ts | 28 ++------ .../components/deploy/deploy-dialog.tsx | 9 ++- .../components/deploy/redeploy-dialog.tsx | 2 + .../deploy/schema-overlap-warning.tsx | 66 +++++++++++++++++++ apps/postgres-new/lib/db/index.ts | 5 +- packages/deploy/src/supabase/index.ts | 1 + packages/deploy/src/supabase/schemas.ts | 20 ++++++ 7 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 apps/postgres-new/components/deploy/schema-overlap-warning.tsx create mode 100644 packages/deploy/src/supabase/schemas.ts diff --git a/apps/deploy-worker/src/deploy.ts b/apps/deploy-worker/src/deploy.ts index af253f86..c35b060d 100644 --- a/apps/deploy-worker/src/deploy.ts +++ b/apps/deploy-worker/src/deploy.ts @@ -1,18 +1,19 @@ -import { exec as execSync } from 'node:child_process' -import { promisify } from 'node:util' import { DeployError, IntegrationRevokedError } from '@database.build/deploy' import { - getAccessToken, - createManagementApiClient, createDeployedDatabase, + createManagementApiClient, generatePassword, + getAccessToken, getDatabaseUrl, getPoolerUrl, + SUPABASE_SCHEMAS, type SupabaseClient, type SupabaseDeploymentConfig, type SupabasePlatformConfig, type SupabaseProviderMetadata, } from '@database.build/deploy/supabase' +import { exec as execSync } from 'node:child_process' +import { promisify } from 'node:util' const exec = promisify(execSync) /** @@ -136,24 +137,7 @@ export async function deploy( databasePassword: remoteDatabasePassword, }) - const excludedSchemas = [ - 'auth', - 'cron', - 'extensions', - 'graphql', - 'graphql_public', - 'net', - 'pgbouncer', - 'pgsodium', - 'pgsodium_masks', - 'realtime', - 'storage', - 'supabase_functions', - 'supabase_migrations', - 'vault', - ] - .map((schema) => `--exclude-schema=${schema}`) - .join(' ') + const excludedSchemas = SUPABASE_SCHEMAS.map((schema) => `--exclude-schema=${schema}`).join(' ') // use pg_dump and pg_restore to transfer the data from the local database to the remote database const command = `pg_dump "${params.localDatabaseUrl}" -Fc ${excludedSchemas} -Z 0 | pg_restore -d "${remoteDatabaseUrl}" --clean --if-exists` diff --git a/apps/postgres-new/components/deploy/deploy-dialog.tsx b/apps/postgres-new/components/deploy/deploy-dialog.tsx index 3a8f2fd6..9f7e988e 100644 --- a/apps/postgres-new/components/deploy/deploy-dialog.tsx +++ b/apps/postgres-new/components/deploy/deploy-dialog.tsx @@ -7,12 +7,14 @@ import { Button } from '~/components/ui/button' import { Dialog, DialogContent, + DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '~/components/ui/dialog' import { useIntegrationQuery } from '~/data/integrations/integration-query' import { SupabaseIcon } from '../supabase-icon' +import { SchemaOverlapWarning } from './schema-overlap-warning' export type DeployDialogProps = { databaseId: string @@ -34,7 +36,7 @@ export function DeployDialog({ databaseId, open, onOpenChange, onConfirm }: Depl
-
+ {!integration ? ( ) : ( -
+
You are about to deploy your in-browser database to Supabase. This will create a new Supabase project under your linked organization. + Would you like to deploy this database?
)} -
+