diff --git a/README.md b/README.md index bf2cbcf8..5305757c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Follow the installation instructions in the [Getting Started](https://unsaged.co - **Multi-User Support**: Easily switch between users and manage their respective conversations. - **Cloud Sync**: Synchronize your conversations across different devices seamlessly with Supabase. - **System Prompts**: Personalize your conversation context and the AI's personality with system prompts. -- **Message Templates**: Speed up message generation with support for variable templates. +- **Message Templates**: Speed up message generation with support for variable templates. ## 🤖 Supported AI Models diff --git a/apps/docs/docs/configuration/general-configuration.md b/apps/docs/docs/configuration/general-configuration.md index 4ef78da0..058d1e08 100644 --- a/apps/docs/docs/configuration/general-configuration.md +++ b/apps/docs/docs/configuration/general-configuration.md @@ -48,48 +48,6 @@ SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key --- -### SUPABASE_JWT_SECRET - -#### Description - -The JWT secret for your Supabase instance. This is a required environment variable. - -#### Example - -```sh -SUPABASE_JWT_SECRET=your_supabase_jwt_secret -``` - ---- - -### NEXTAUTH_SECRET - -#### Description - -The secret used to encrypt cookies. This is a required environment variable. - -#### Example - -```sh -NEXTAUTH_SECRET=your_nextauth_secret -``` - ---- - -### NEXTAUTH_URL - -#### Description - -The base url for your app. This is a required environment variable when running in production. - -#### Example - -```sh -NEXTAUTH_URL=https://yourdomain.com -``` - ---- - ### NEXT_PUBLIC_DEFAULT_MODEL #### Description diff --git a/apps/docs/docs/getting-started/installation.md b/apps/docs/docs/getting-started/installation.md index 1bf453e3..35cab6a7 100644 --- a/apps/docs/docs/getting-started/installation.md +++ b/apps/docs/docs/getting-started/installation.md @@ -21,13 +21,6 @@ This will do the following: - Enable Row Level Security for the tables required by unSAGED. - Apply the Row Level Security policies required by unSAGED. -## Expose the `next_auth` schema - -Expose the `next_auth` schema in the [API settings](https://app.supabase.com/project/_/settings/api) by adding `next_auth` to the "Exposed schemas" list. - -More information [here](https://authjs.dev/reference/adapter/supabase#expose-the-nextauth-schema-in-supabase). - -Then copy the output and save it for the next step. ## Switch to the `apps/unsaged` directory @@ -42,28 +35,17 @@ cd apps/unsaged The `.env.local` file is the main configuration file for unSAGED. It should be located in the `apps/unsaged` directory of the project. Create the `apps/unsaged/.env.local` file to set your environment variables. -### Set Auth Secret - -Create your secret with the following command: - -```sh -openssl rand -base64 32 -``` - -Set the `NEXTAUTH_SECRET` environment variable to the secret you just created. -```sh title="apps/unsaged/.env.local" -NEXTAUTH_SECRET=my_secret -``` +## Supabase auth +Configure your auth provider in supabase including the allowed redirect URL. See [Auth.js Documentation](https://next-auth.js.org/configuration/providers#supabase-provider) for more information. -See [Auth.js Documentation](https://next-auth.js.org/configuration/options#nextauth_secret) for more information. +See https://supabase.com/dashboard/project/xxxxxxx/auth/url-configuration ### Set Supabase Variables ```sh title="apps/unsaged/.env.local" NEXT_PUBLIC_SUPABASE_URL="https://xxxxxxxxxxxxxxxx.supabase.co" NEXT_PUBLIC_SUPABASE_ANON_KEY=supabase_anon_key -SUPABASE_JWT_SECRET=supabase_jwt_secret SUPABASE_SERVICE_ROLE_KEY=supabase_service_role_key ``` @@ -92,10 +74,4 @@ docker run --env-file=.env.local -p 127.0.0.1:3000:3000 --name unsaged unsaged ## Running in Production -To run in production, you will need to set the following environment variable. - -See [Auth.js Documentation](https://next-auth.js.org/configuration/options#nextauth_url) for more information. - -```sh title="apps/unsaged/.env.local" -NEXTAUTH_URL=https://yourdomain.com -``` +Make sure the prod domain or vercel preview domain is added to the supabase auth provider and URL configuration diff --git a/apps/unsaged/.env.local.example b/apps/unsaged/.env.local.example index 4b7e1396..22226ddb 100644 --- a/apps/unsaged/.env.local.example +++ b/apps/unsaged/.env.local.example @@ -6,6 +6,13 @@ NEXT_PUBLIC_DEFAULT_MODEL="gpt-3.5-turbo" NEXT_PUBLIC_TITLE="unsaged" NEXT_PUBLIC_DESCRIPTION="Open source chat kit engineered for seamless interaction with AI models" + +#Model providers to enable. You should disable the ones that you are not using. //test +NEXT_PUBLIC_OPENAI_ENABLED=true +NEXT_PUBLIC_ANTHROPIC_ENABLED=true +NEXT_PUBLIC_GOOGLE_ENABLED=true +NEXT_PUBLIC_OLLAMA_ENABLED=true + # OpenAI OPENAI_API_URL="https://api.openai.com/v1" OPENAI_API_KEY=openai_key @@ -52,19 +59,7 @@ PALM_API_KEY=palm_key # NEXT_PUBLIC_DEFAULT_PALM_TOP_P=1.0 # NEXT_PUBLIC_DEFAULT_PALM_TOP_K=40 -# NextAuth (Required) -NEXTAUTH_EMAIL_PATTERN= -NEXTAUTH_URL="http://localhost:3000" -# You can get secret with `openssl rand -base64 32` -NEXTAUTH_SECRET=nextauth_secret - -# At least one provider is required -# Google Auth Provider -GOOGLE_CLIENT_ID="xxxxxxxxxxxxxxxxx.apps.googleusercontent.com" -GOOGLE_CLIENT_SECRET=google_client_secret - # Supabase (Required) NEXT_PUBLIC_SUPABASE_URL="https://xxxxxxxxxxxxxxxx.supabase.co" NEXT_PUBLIC_SUPABASE_ANON_KEY=supabase_anon_key -SUPABASE_JWT_SECRET=supabase_jwt_secret -SUPABASE_SERVICE_ROLE_KEY=supabase_service_role_key + diff --git a/apps/unsaged/app/api/auth/[...nextauth]/route.ts b/apps/unsaged/app/api/auth/[...nextauth]/route.ts deleted file mode 100644 index 4db1c69c..00000000 --- a/apps/unsaged/app/api/auth/[...nextauth]/route.ts +++ /dev/null @@ -1,44 +0,0 @@ -import NextAuth, { NextAuthOptions } from 'next-auth'; - -import { getProviders } from '@/utils/app/auth/providers'; -import { - SUPABASE_JWT_SECRET, - SUPABASE_SERVICE_ROLE_KEY, - SUPABASE_URL, -} from '@/utils/app/const'; - -import { SupabaseAdapter } from '@next-auth/supabase-adapter'; -import jwt from 'jsonwebtoken'; - -const authOptions: NextAuthOptions = { - providers: await getProviders(), - session: { strategy: 'jwt' }, - - // Supabase adapter is only enabled if JWT secret is specified - adapter: SUPABASE_JWT_SECRET - ? SupabaseAdapter({ - url: SUPABASE_URL, - secret: SUPABASE_SERVICE_ROLE_KEY, - }) - : undefined, - callbacks: { - async session({ session, token }) { - const signingSecret = SUPABASE_JWT_SECRET; - if (signingSecret) { - const payload = { - aud: 'authenticated', - exp: Math.floor(new Date(session.expires).getTime() / 1000), - sub: token.sub, - email: token.email, - role: 'authenticated', - }; - session.customAccessToken = jwt.sign(payload, signingSecret); - } - return session; - }, - }, -}; - -const handler = NextAuth(authOptions); - -export { handler as GET, handler as POST }; diff --git a/apps/unsaged/app/api/models/route.ts b/apps/unsaged/app/api/models/route.ts index e0ef41d6..4f3ff0dc 100644 --- a/apps/unsaged/app/api/models/route.ts +++ b/apps/unsaged/app/api/models/route.ts @@ -1,4 +1,4 @@ -import { DEBUG_MODE } from '@/utils/app/const'; +import { DEBUG_MODE,OPENAI_ENABLED,ANTHROPIC_ENABLED, GOOGLE_ENABLED, OLLAMA_ENABLED } from '@/utils/app/const'; import { printEnvVariables } from '@/utils/app/debug/env-vars'; import { getAvailableAnthropicModels } from '@/utils/server/ai_vendors/anthropic/models'; import { getAvailablePalm2Models } from '@/utils/server/ai_vendors/google/models'; @@ -10,10 +10,11 @@ import { AiModel } from '@/types/ai-models'; export const runtime = 'edge'; const handler = async (req: Request): Promise => { + try { if (DEBUG_MODE) { console.log('----------SERVER-SIDE ENVIRONMENT VARIABLES----------'); - printEnvVariables(); + // printEnvVariables(); } const { openai_key, anthropic_key, palm_key } = (await req.json()) as { @@ -23,29 +24,54 @@ const handler = async (req: Request): Promise => { }; const models: AiModel[] = []; - const { error: openaiError, data: openaiModels } = - await getAvailableOpenAIModels(openai_key); - if (openaiError) { - console.error('Error getting OpenAI models'); - } else { - models.push(...(openaiModels as AiModel[])); - } - const { data: anthropicModels } = await getAvailableAnthropicModels( - anthropic_key, - ); + // Check if OpenAI provider is enabled +if (OPENAI_ENABLED === 'true') { + const response = await getAvailableOpenAIModels(openai_key); + let openaiModels; + + if (response) { + // If response is not null, destructure the data. + openaiModels = response.data; + models.push(...(openaiModels as AiModel[])); + } else { + // Handle the null case appropriately. + openaiModels = null; // or set it to a default value like [] if that makes sense for your application. + } +} + + +// Check if Anthropic provider is enabled +if (ANTHROPIC_ENABLED === 'true') { + const { data: anthropicModels } = await getAvailableAnthropicModels(anthropic_key); + if (anthropicModels && anthropicModels.length > 0) { // Check if there are any models models.push(...(anthropicModels as AiModel[])); + } +} - const { data: palm2Models } = await getAvailablePalm2Models(palm_key); +// Check if Google (Palm2) provider is enabled +if (GOOGLE_ENABLED === 'true') { + const { data: palm2Models } = await getAvailablePalm2Models(palm_key); + if (palm2Models && palm2Models.length > 0) { // Check if there are any models models.push(...(palm2Models as AiModel[])); + } +} - const { data: ollamaModels } = await getAvailableOllamaModels(); +// Check if Ollama provider is enabled +if (OLLAMA_ENABLED === 'true') { + const { data: ollamaModels } = await getAvailableOllamaModels(); + if (ollamaModels && ollamaModels.length > 0) { // Check if there are any models models.push(...(ollamaModels as AiModel[])); + } +} + return new Response(JSON.stringify(models), { status: 200 }); } catch (error) { + console.log('⭐⭐⭐⭐⭐⭐'); console.error(error); - return new Response('Error getting available models', { status: 500 }); + const defaultResponse = { models: [] }; + return new Response(JSON.stringify(defaultResponse), { status: 500 }); } }; diff --git a/apps/unsaged/app/auth/callback/route.ts b/apps/unsaged/app/auth/callback/route.ts new file mode 100644 index 00000000..1d06e001 --- /dev/null +++ b/apps/unsaged/app/auth/callback/route.ts @@ -0,0 +1,38 @@ +import { cookies } from 'next/headers' +import { NextResponse } from 'next/server' +import { type CookieOptions, createBrowserClient } from '@supabase/ssr' + +export async function GET(request: Request) { + const { searchParams, origin } = new URL(request.url) + const code = searchParams.get('code') + // if "next" is in param, use it as the redirect URL + const next = searchParams.get('next') ?? '/' + + if (code) { + const cookieStore = cookies() + const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + cookieStore.set({ name, value, ...options }) + }, + remove(name: string, options: CookieOptions) { + cookieStore.delete({ name, ...options }) + }, + }, + } + ) + const { error } = await supabase.auth.exchangeCodeForSession(code) + if (!error) { + return NextResponse.redirect(`${origin}${next}`) + } + } + + // return the user to an error page with instructions + return NextResponse.redirect(`${origin}/auth/auth-code-error`) +} \ No newline at end of file diff --git a/apps/unsaged/app/auth/signin/auth-form.tsx b/apps/unsaged/app/auth/signin/auth-form.tsx new file mode 100644 index 00000000..57bf1fca --- /dev/null +++ b/apps/unsaged/app/auth/signin/auth-form.tsx @@ -0,0 +1,32 @@ +'use client' +import { Auth } from '@supabase/auth-ui-react' +import { ThemeSupa } from '@supabase/auth-ui-shared' +import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs' +import { Database } from '@/types/supabase.types' +import { NEXT_PUBLIC_SITE_URL } from '@/utils/app/const'; + +export default function AuthForm() { + const supabase = createBrowserSupabaseClient() + + return ( + + ) +} diff --git a/apps/unsaged/app/auth/signin/page.tsx b/apps/unsaged/app/auth/signin/page.tsx new file mode 100644 index 00000000..65d1be7c --- /dev/null +++ b/apps/unsaged/app/auth/signin/page.tsx @@ -0,0 +1,20 @@ +import AuthForm from './auth-form'; + +export default function Home() { + // Access the title from the environment variables + const title = process.env.NEXT_PUBLIC_TITLE || 'Default Title'; + + return ( +
+
+

{title}

+

+ Please sign in to your account +

+
+ +
+
+
+ ); +} \ No newline at end of file diff --git a/apps/unsaged/app/auth/signout/route.ts b/apps/unsaged/app/auth/signout/route.ts new file mode 100644 index 00000000..7ad9fa6b --- /dev/null +++ b/apps/unsaged/app/auth/signout/route.ts @@ -0,0 +1,28 @@ +'use client' +import { cookies } from 'next/headers' +import { redirect } from 'next/navigation' +import { type CookieOptions, createBrowserClient } from '@supabase/ssr' + + +export async function POST() { + const cookieStore = cookies() + const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + cookieStore.set({ name, value, ...options }) + }, + remove(name: string, options: CookieOptions) { + cookieStore.delete({ name, ...options }) + }, + }, + } + ) + await supabase.auth.signOut() + return redirect('/login') +} \ No newline at end of file diff --git a/apps/unsaged/components/Home/components/PrimaryMenu/components/ActivityBar/ActivityBar.tsx b/apps/unsaged/components/Home/components/PrimaryMenu/components/ActivityBar/ActivityBar.tsx index dbd4ac15..a2cbddf8 100644 --- a/apps/unsaged/components/Home/components/PrimaryMenu/components/ActivityBar/ActivityBar.tsx +++ b/apps/unsaged/components/Home/components/PrimaryMenu/components/ActivityBar/ActivityBar.tsx @@ -4,9 +4,9 @@ import { IconLogout, IconSettings, } from '@tabler/icons-react'; -import { signOut } from 'next-auth/react'; import { useContext } from 'react'; + import { localSaveShowPrimaryMenu } from '@/utils/app/storage/local/ui-state'; import { deleteSelectedConversationId } from '@/utils/app/storage/selectedConversation'; @@ -16,6 +16,11 @@ import HomeContext from '@/components/Home/home.context'; import PrimaryMenuContext from '../../PrimaryMenu.context'; +import type { Database } from '@/types/database' +import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs' +import { useRouter } from 'next/navigation' +const supabase = createBrowserSupabaseClient() + const ActivityBar = ({ icons }: { icons: JSX.Element[] }) => { const { state: { user, database, showPrimaryMenu, display }, @@ -40,14 +45,15 @@ const ActivityBar = ({ icons }: { icons: JSX.Element[] }) => { primaryMenuDispatch({ field: 'selectedIndex', value: index }); }; - const handleSignOut = () => { + const handleSignOut = async () => { if (database!.name !== 'local') { - deleteSelectedConversationId(user!); + await deleteSelectedConversationId(user!); } - - signOut(); + + await supabase.auth.signOut() + window.location.replace('/'); }; - + const handleShowSettings = () => { if (display !== 'settings') { homeDispatch({ field: 'display', value: 'settings' }); @@ -106,4 +112,4 @@ const ActivityBar = ({ icons }: { icons: JSX.Element[] }) => { ); }; -export default ActivityBar; +export default ActivityBar; \ No newline at end of file diff --git a/apps/unsaged/components/Home/components/SecondaryMenu/components/Menu/components/Screens/ModelSettings/components/model.tsx b/apps/unsaged/components/Home/components/SecondaryMenu/components/Menu/components/Screens/ModelSettings/components/model.tsx index 2bc58455..8009de45 100644 --- a/apps/unsaged/components/Home/components/SecondaryMenu/components/Menu/components/Screens/ModelSettings/components/model.tsx +++ b/apps/unsaged/components/Home/components/SecondaryMenu/components/Menu/components/Screens/ModelSettings/components/model.tsx @@ -22,14 +22,15 @@ export const ModelSelect = () => { const [sortedModels, setSortedModels] = useState(models); useEffect(() => { - const _sorted = models.sort((a, b) => { - if (a.id < b.id) return -1; - if (a.id > b.id) return 1; - - return 0; - }); - - setSortedModels(_sorted); + if (Array.isArray(models)) { + const _sorted = models.sort((a, b) => { + if (a.id < b.id) return -1; + if (a.id > b.id) return 1; + return 0; + }); + + setSortedModels(_sorted); + } }, [models]); const handleChange = (value: string) => { @@ -60,7 +61,7 @@ export const ModelSelect = () => { - {sortedModels.map((model) => ( + {Array.isArray(sortedModels) && sortedModels.map((model) => ( {model.id} - {model.vendor} diff --git a/apps/unsaged/db/GenerationScript.sql b/apps/unsaged/db/GenerationScript.sql index b862df7c..358b6e50 100644 --- a/apps/unsaged/db/GenerationScript.sql +++ b/apps/unsaged/db/GenerationScript.sql @@ -1,105 +1,3 @@ --- --- Name: next_auth; Type: SCHEMA; --- -CREATE SCHEMA next_auth; - -GRANT USAGE ON SCHEMA next_auth TO service_role; -GRANT ALL ON SCHEMA next_auth TO postgres; - --- --- Create users table --- -CREATE TABLE IF NOT EXISTS next_auth.users -( - id uuid NOT NULL DEFAULT uuid_generate_v4(), - name text, - email text, - "emailVerified" timestamp with time zone, - image text, - CONSTRAINT users_pkey PRIMARY KEY (id), - CONSTRAINT email_unique UNIQUE (email) -); - -GRANT ALL ON TABLE next_auth.users TO postgres; -GRANT ALL ON TABLE next_auth.users TO service_role; - ---- uid() function to be used in RLS policies -CREATE FUNCTION next_auth.uid() RETURNS uuid - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim.sub', true), ''), - (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub') - )::uuid -$$; - --- --- Create sessions table --- -CREATE TABLE IF NOT EXISTS next_auth.sessions -( - id uuid NOT NULL DEFAULT uuid_generate_v4(), - expires timestamp with time zone NOT NULL, - "sessionToken" text NOT NULL, - "userId" uuid, - CONSTRAINT sessions_pkey PRIMARY KEY (id), - CONSTRAINT sessionToken_unique UNIQUE ("sessionToken"), - CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") - REFERENCES next_auth.users (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE CASCADE -); - -GRANT ALL ON TABLE next_auth.sessions TO postgres; -GRANT ALL ON TABLE next_auth.sessions TO service_role; - --- --- Create accounts table --- -CREATE TABLE IF NOT EXISTS next_auth.accounts -( - id uuid NOT NULL DEFAULT uuid_generate_v4(), - type text NOT NULL, - provider text NOT NULL, - "providerAccountId" text NOT NULL, - refresh_token text, - access_token text, - expires_at bigint, - token_type text, - scope text, - id_token text, - session_state text, - oauth_token_secret text, - oauth_token text, - "userId" uuid, - CONSTRAINT accounts_pkey PRIMARY KEY (id), - CONSTRAINT provider_unique UNIQUE (provider, "providerAccountId"), - CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") - REFERENCES next_auth.users (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE CASCADE -); - -GRANT ALL ON TABLE next_auth.accounts TO postgres; -GRANT ALL ON TABLE next_auth.accounts TO service_role; - --- --- Create verification_tokens table --- -CREATE TABLE IF NOT EXISTS next_auth.verification_tokens -( - identifier text, - token text, - expires timestamp with time zone NOT NULL, - CONSTRAINT verification_tokens_pkey PRIMARY KEY (token), - CONSTRAINT token_unique UNIQUE (token), - CONSTRAINT token_identifier_unique UNIQUE (token, identifier) -); - -GRANT ALL ON TABLE next_auth.verification_tokens TO postgres; -GRANT ALL ON TABLE next_auth.verification_tokens TO service_role; - -- public.conversations definition @@ -115,7 +13,7 @@ CREATE TABLE public.conversations ( temperature float4 NULL, folder_id uuid NULL, "timestamp" timestamptz NOT NULL, - user_id uuid NOT NULL DEFAULT next_auth.uid(), + user_id uuid NOT NULL DEFAULT auth.uid(), params jsonb NOT NULL DEFAULT '{}'::jsonb, CONSTRAINT unique_conversation_id PRIMARY KEY (id) ); @@ -131,7 +29,7 @@ CREATE TABLE public.folders ( id uuid NOT NULL DEFAULT uuid_generate_v4(), "name" text NOT NULL, folder_type text NOT NULL, - user_id uuid NOT NULL DEFAULT next_auth.uid(), + user_id uuid NOT NULL DEFAULT auth.uid(), CONSTRAINT unique_folder_id PRIMARY KEY (id) ); @@ -148,7 +46,7 @@ CREATE TABLE public.messages ( "content" text NOT NULL, "timestamp" timestamptz NOT NULL, conversation_id uuid NOT NULL, - user_id uuid NOT NULL DEFAULT next_auth.uid(), + user_id uuid NOT NULL DEFAULT auth.uid(), CONSTRAINT unique_message_id PRIMARY KEY (id) ); @@ -166,7 +64,7 @@ CREATE TABLE public.prompts ( "content" text NOT NULL, models _text NOT NULL, folder_id uuid NULL, - user_id uuid NOT NULL DEFAULT next_auth.uid(), + user_id uuid NOT NULL DEFAULT auth.uid(), CONSTRAINT unique_prompt_id PRIMARY KEY (id) ); @@ -183,37 +81,37 @@ CREATE TABLE public.system_prompts ( "content" text NOT NULL, models _text NOT NULL, folder_id uuid NULL, - user_id uuid NOT NULL DEFAULT next_auth.uid(), + user_id uuid NOT NULL DEFAULT auth.uid(), CONSTRAINT unique_system_prompt_id PRIMARY KEY (id) ); -- public.conversations foreign keys -ALTER TABLE public.conversations ADD CONSTRAINT conversation_owner FOREIGN KEY (user_id) REFERENCES next_auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE public.conversations ADD CONSTRAINT conversation_owner FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE public.conversations ADD CONSTRAINT conversation_owner_folder FOREIGN KEY (folder_id) REFERENCES public.folders(id) ON UPDATE CASCADE; -- public.folders foreign keys -ALTER TABLE public.folders ADD CONSTRAINT folder_owner FOREIGN KEY (user_id) REFERENCES next_auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE public.folders ADD CONSTRAINT folder_owner FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; -- public.messages foreign keys -ALTER TABLE public.messages ADD CONSTRAINT message_owner FOREIGN KEY (user_id) REFERENCES next_auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE public.messages ADD CONSTRAINT message_owner FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE public.messages ADD CONSTRAINT message_owner_convo FOREIGN KEY (conversation_id) REFERENCES public.conversations(id) ON DELETE CASCADE ON UPDATE CASCADE; -- public.prompts foreign keys -ALTER TABLE public.prompts ADD CONSTRAINT prompt_owner FOREIGN KEY (user_id) REFERENCES next_auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE public.prompts ADD CONSTRAINT prompt_owner FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE public.prompts ADD CONSTRAINT prompt_owner_folder FOREIGN KEY (folder_id) REFERENCES public.folders(id) ON UPDATE CASCADE; -- public.system_prompts foreign keys -ALTER TABLE public.system_prompts ADD CONSTRAINT system_prompt_owner FOREIGN KEY (user_id) REFERENCES next_auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE public.system_prompts ADD CONSTRAINT system_prompt_owner FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE public.system_prompts ADD CONSTRAINT system_prompt_owner_folder FOREIGN KEY (folder_id) REFERENCES public.folders(id) ON UPDATE CASCADE; @@ -241,18 +139,18 @@ CREATE POLICY "Enable insert for authenticated users only" ON "public"."folders" CREATE POLICY "Enable select for owners" ON "public"."folders" AS PERMISSIVE FOR SELECT TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); CREATE POLICY "Enable update for owners" ON "public"."folders" AS PERMISSIVE FOR UPDATE TO public - USING (next_auth.uid() = user_id) - WITH CHECK (next_auth.uid() = user_id); + USING (auth.uid() = user_id) + WITH CHECK (auth.uid() = user_id); CREATE POLICY "Enable delete for owners" ON "public"."folders" AS PERMISSIVE FOR DELETE TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); @@ -265,18 +163,18 @@ CREATE POLICY "Enable insert for authenticated users only" ON "public"."conversa CREATE POLICY "Enable select for owners" ON "public"."conversations" AS PERMISSIVE FOR SELECT TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); CREATE POLICY "Enable update for owners" ON "public"."conversations" AS PERMISSIVE FOR UPDATE TO public - USING (next_auth.uid() = user_id) - WITH CHECK (next_auth.uid() = user_id); + USING (auth.uid() = user_id) + WITH CHECK (auth.uid() = user_id); CREATE POLICY "Enable delete for owners" ON "public"."conversations" AS PERMISSIVE FOR DELETE TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); @@ -289,18 +187,18 @@ CREATE POLICY "Enable insert for authenticated users only" ON "public"."prompts" CREATE POLICY "Enable select for owners" ON "public"."prompts" AS PERMISSIVE FOR SELECT TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); CREATE POLICY "Enable update for owners" ON "public"."prompts" AS PERMISSIVE FOR UPDATE TO public - USING (next_auth.uid() = user_id) - WITH CHECK (next_auth.uid() = user_id); + USING (auth.uid() = user_id) + WITH CHECK (auth.uid() = user_id); CREATE POLICY "Enable delete for owners" ON "public"."prompts" AS PERMISSIVE FOR DELETE TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); @@ -313,18 +211,18 @@ CREATE POLICY "Enable insert for authenticated users only" ON "public"."messages CREATE POLICY "Enable select for owners" ON "public"."messages" AS PERMISSIVE FOR SELECT TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); CREATE POLICY "Enable update for owners" ON "public"."messages" AS PERMISSIVE FOR UPDATE TO public - USING (next_auth.uid() = user_id) - WITH CHECK (next_auth.uid() = user_id); + USING (auth.uid() = user_id) + WITH CHECK (auth.uid() = user_id); CREATE POLICY "Enable delete for owners" ON "public"."messages" AS PERMISSIVE FOR DELETE TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); @@ -337,16 +235,16 @@ CREATE POLICY "Enable insert for authenticated users only" ON "public"."system_p CREATE POLICY "Enable select for owners" ON "public"."system_prompts" AS PERMISSIVE FOR SELECT TO public - USING (next_auth.uid() = user_id); + USING (auth.uid() = user_id); CREATE POLICY "Enable update for owners" ON "public"."system_prompts" AS PERMISSIVE FOR UPDATE TO public - USING (next_auth.uid() = user_id) - WITH CHECK (next_auth.uid() = user_id); + USING (auth.uid() = user_id) + WITH CHECK (auth.uid() = user_id); CREATE POLICY "Enable delete for owners" ON "public"."system_prompts" AS PERMISSIVE FOR DELETE TO public - USING (next_auth.uid() = user_id); - + USING (auth.uid() = user_id); + \ No newline at end of file diff --git a/apps/unsaged/middleware.ts b/apps/unsaged/middleware.ts index 73c90549..ecfc0b25 100644 --- a/apps/unsaged/middleware.ts +++ b/apps/unsaged/middleware.ts @@ -1,43 +1,43 @@ -import { withAuth } from 'next-auth/middleware'; -import { get } from '@vercel/edge-config'; - -import { dockerEnvVarFix } from './utils/app/docker/envFix'; - -const getSecret = () => { - return dockerEnvVarFix(process.env.NEXTAUTH_SECRET); -}; - -const getEmailPatterns = async () => { - let patternsString = dockerEnvVarFix(process.env.NEXTAUTH_EMAIL_PATTERNS); - - if (dockerEnvVarFix(process.env.EDGE_CONFIG)) - patternsString = await get('NEXTAUTH_EMAIL_PATTERNS'); - - return patternsString ? patternsString.split(',') : []; -}; - -export default withAuth({ - callbacks: { - async authorized({ token }) { - if (!token?.email) { - return false; - } else { - const patterns = await getEmailPatterns(); - if (patterns.length === 0) { - return true; // No patterns specified, allow access - } - - const email = token.email.toLowerCase(); - for (const pattern of patterns) { - const regex = new RegExp(pattern.trim()); - if (email.match(regex)) { - return true; // Email matches one of the patterns, allow access - } - } - - return false; // Email does not match any of the patterns, deny access - } - }, - }, - secret: getSecret(), -}); +import { NextResponse, type NextRequest } from 'next/server' +import { createClient } from '@/utils/supabase/middleware' + +export async function middleware(request: NextRequest) { + try { + // This `try/catch` block is only here for the interactive tutorial. + // Feel free to remove once you have Supabase connected. + const { supabase, response } = createClient(request) + + // Refresh session if expired - required for Server Components + // https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware + await supabase.auth.getSession() + + const { + data: { user }, + } = await supabase.auth.getUser() + + // if user is signed in and the current path is / redirect the user to /account + if (user && request.nextUrl.pathname !== '/') { + return NextResponse.redirect(new URL('/', request.url)) + } + + // if user is not signed in and the current path is not / redirect the user to / + if (!user && request.nextUrl.pathname !== '/auth/signin') { + return NextResponse.redirect(new URL('/auth/signin', request.url)) + } + + return response + } catch (e) { + // If you are here, a Supabase client could not be created! + // This is likely because you have not set up environment variables. + // Check out http://localhost:3000 for Next Steps. + return NextResponse.next({ + request: { + headers: request.headers, + }, + }) + } +} + +export const config = { + matcher: ['/','/auth/signin', '/account'], +} \ No newline at end of file diff --git a/apps/unsaged/package.json b/apps/unsaged/package.json index f1c99277..eaaa6edf 100644 --- a/apps/unsaged/package.json +++ b/apps/unsaged/package.json @@ -14,16 +14,19 @@ "dependencies": { "@auth/supabase-adapter": "^0.1.9", "@dqbd/tiktoken": "^1.0.7", - "@next-auth/supabase-adapter": "^0.2.1", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", - "@supabase/auth-helpers-nextjs": "^0.6.1", - "@supabase/supabase-js": "^2.38.5", + "@supabase/auth-helpers-nextjs": "^0.8.7", + "@supabase/auth-ui-react": "^0.4.6", + "@supabase/auth-ui-shared": "^0.1.8", + "@supabase/ssr": "latest", + "@supabase/supabase-js": "latest", "@tabler/icons-react": "^2.42.0", + "@tailwindcss/typography": "^0.5.10", "@vercel/analytics": "^1.1.1", "@vercel/edge-config": "^0.4.1", "class-variance-authority": "^0.7.0", @@ -31,18 +34,18 @@ "date-fns": "^2.30.0", "encoding": "^0.1.13", "eventsource-parser": "^0.1.0", - "i18next": "^22.5.1", + "i18next": "^23.7.6", + "install": "^0.13.0", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.2", - "next": "^13.5.6", - "next-auth": "^4.24.5", + "next": "latest", "next-axiom": "^1.1.1", "next-i18next": "^13.3.0", "next-themes": "^0.2.1", "nextra": "^2.13.2", "nextra-theme-docs": "^2.13.2", "nodemailer": "^6.9.7", - "openai": "^4.19.1", + "openai": "^4.20.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", @@ -65,7 +68,7 @@ "@types/js-yaml": "^4.0.9", "@types/jsdom": "^21.1.6", "@types/jsonwebtoken": "^9.0.5", - "@types/node": "^20.9.4", + "@types/node": "^20.10.0", "@types/react": "18.2.37", "@types/react-dom": "18.2.0", "@types/react-syntax-highlighter": "^15.5.10", @@ -81,7 +84,7 @@ "supabase": "^1.113.2", "tailwindcss": "^3.3.5", "tsconfig": "workspace:*", - "typescript": "^5.2.2", + "typescript": "^5.3.2", "vitest": "^0.29.8" } } diff --git a/apps/unsaged/tsconfig.json b/apps/unsaged/tsconfig.json index a1c1c24a..e93378ce 100644 --- a/apps/unsaged/tsconfig.json +++ b/apps/unsaged/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "tsconfig/nextjs.json", + "extends": "../../packages/tsconfig/nextjs.json", "compilerOptions": { "skipLibCheck": true, "strict": true, diff --git a/apps/unsaged/types/auth-provider.ts b/apps/unsaged/types/auth-provider.ts deleted file mode 100644 index 023e6786..00000000 --- a/apps/unsaged/types/auth-provider.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type AuthProvider = - | 'apple' - | 'auth0' - | 'azure' - | 'cognito' - | 'discord' - | 'facebook' - | 'github' - | 'gitlab' - | 'google' - | 'okta' - | 'reddit' - | 'salesforce' - | 'slack' - | 'spotify' - | 'twitch' - | 'twitter'; diff --git a/apps/unsaged/types/next-auth.d.ts b/apps/unsaged/types/next-auth.d.ts deleted file mode 100644 index 1b5c8e49..00000000 --- a/apps/unsaged/types/next-auth.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import NextAuth, { DefaultSession } from 'next-auth'; - -declare module 'next-auth' { - // Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context - interface Session { - // A JWT which can be used as Authorization header with supabase-js for RLS. - customAccessToken: string; - expiresAt: number; - } -} diff --git a/apps/unsaged/types/supabase.types.ts b/apps/unsaged/types/supabase.types.ts new file mode 100644 index 00000000..b22133ac --- /dev/null +++ b/apps/unsaged/types/supabase.types.ts @@ -0,0 +1,446 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[] + +export interface Database { + public: { + Tables: { + conversations: { + Row: { + folder_id: string | null + id: string + model_id: string + name: string + params: Json + system_prompt_id: string | null + temperature: number | null + timestamp: string + user_id: string + } + Insert: { + folder_id?: string | null + id?: string + model_id: string + name: string + params?: Json + system_prompt_id?: string | null + temperature?: number | null + timestamp: string + user_id?: string + } + Update: { + folder_id?: string | null + id?: string + model_id?: string + name?: string + params?: Json + system_prompt_id?: string | null + temperature?: number | null + timestamp?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "conversation_owner" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + { + foreignKeyName: "conversation_owner_folder" + columns: ["folder_id"] + isOneToOne: false + referencedRelation: "folders" + referencedColumns: ["id"] + } + ] + } + customers: { + Row: { + id: string + stripe_customer_id: string | null + } + Insert: { + id: string + stripe_customer_id?: string | null + } + Update: { + id?: string + stripe_customer_id?: string | null + } + Relationships: [ + { + foreignKeyName: "customers_id_fkey" + columns: ["id"] + isOneToOne: true + referencedRelation: "users" + referencedColumns: ["id"] + } + ] + } + folders: { + Row: { + folder_type: string + id: string + name: string + user_id: string + } + Insert: { + folder_type: string + id?: string + name: string + user_id?: string + } + Update: { + folder_type?: string + id?: string + name?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "folder_owner" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + } + ] + } + messages: { + Row: { + content: string + conversation_id: string + id: string + role: string + timestamp: string + user_id: string + } + Insert: { + content: string + conversation_id: string + id?: string + role: string + timestamp: string + user_id?: string + } + Update: { + content?: string + conversation_id?: string + id?: string + role?: string + timestamp?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "message_owner" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + { + foreignKeyName: "message_owner_convo" + columns: ["conversation_id"] + isOneToOne: false + referencedRelation: "conversations" + referencedColumns: ["id"] + } + ] + } + prices: { + Row: { + active: boolean | null + currency: string | null + description: string | null + id: string + interval: Database["public"]["Enums"]["pricing_plan_interval"] | null + interval_count: number | null + metadata: Json | null + product_id: string | null + trial_period_days: number | null + type: Database["public"]["Enums"]["pricing_type"] | null + unit_amount: number | null + } + Insert: { + active?: boolean | null + currency?: string | null + description?: string | null + id: string + interval?: Database["public"]["Enums"]["pricing_plan_interval"] | null + interval_count?: number | null + metadata?: Json | null + product_id?: string | null + trial_period_days?: number | null + type?: Database["public"]["Enums"]["pricing_type"] | null + unit_amount?: number | null + } + Update: { + active?: boolean | null + currency?: string | null + description?: string | null + id?: string + interval?: Database["public"]["Enums"]["pricing_plan_interval"] | null + interval_count?: number | null + metadata?: Json | null + product_id?: string | null + trial_period_days?: number | null + type?: Database["public"]["Enums"]["pricing_type"] | null + unit_amount?: number | null + } + Relationships: [ + { + foreignKeyName: "prices_product_id_fkey" + columns: ["product_id"] + isOneToOne: false + referencedRelation: "products" + referencedColumns: ["id"] + } + ] + } + products: { + Row: { + active: boolean | null + description: string | null + id: string + image: string | null + metadata: Json | null + name: string | null + } + Insert: { + active?: boolean | null + description?: string | null + id: string + image?: string | null + metadata?: Json | null + name?: string | null + } + Update: { + active?: boolean | null + description?: string | null + id?: string + image?: string | null + metadata?: Json | null + name?: string | null + } + Relationships: [] + } + prompts: { + Row: { + content: string + description: string + folder_id: string | null + id: string + models: string[] + name: string + user_id: string + } + Insert: { + content: string + description: string + folder_id?: string | null + id?: string + models: string[] + name: string + user_id?: string + } + Update: { + content?: string + description?: string + folder_id?: string | null + id?: string + models?: string[] + name?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "prompt_owner" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + { + foreignKeyName: "prompt_owner_folder" + columns: ["folder_id"] + isOneToOne: false + referencedRelation: "folders" + referencedColumns: ["id"] + } + ] + } + subscriptions: { + Row: { + cancel_at: string | null + cancel_at_period_end: boolean | null + canceled_at: string | null + created: string + current_period_end: string + current_period_start: string + ended_at: string | null + id: string + metadata: Json | null + price_id: string | null + quantity: number | null + status: Database["public"]["Enums"]["subscription_status"] | null + trial_end: string | null + trial_start: string | null + user_id: string + } + Insert: { + cancel_at?: string | null + cancel_at_period_end?: boolean | null + canceled_at?: string | null + created?: string + current_period_end?: string + current_period_start?: string + ended_at?: string | null + id: string + metadata?: Json | null + price_id?: string | null + quantity?: number | null + status?: Database["public"]["Enums"]["subscription_status"] | null + trial_end?: string | null + trial_start?: string | null + user_id: string + } + Update: { + cancel_at?: string | null + cancel_at_period_end?: boolean | null + canceled_at?: string | null + created?: string + current_period_end?: string + current_period_start?: string + ended_at?: string | null + id?: string + metadata?: Json | null + price_id?: string | null + quantity?: number | null + status?: Database["public"]["Enums"]["subscription_status"] | null + trial_end?: string | null + trial_start?: string | null + user_id?: string + } + Relationships: [ + { + foreignKeyName: "subscriptions_price_id_fkey" + columns: ["price_id"] + isOneToOne: false + referencedRelation: "prices" + referencedColumns: ["id"] + }, + { + foreignKeyName: "subscriptions_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + } + ] + } + system_prompts: { + Row: { + content: string + folder_id: string | null + id: string + models: string[] + name: string + user_id: string + } + Insert: { + content: string + folder_id?: string | null + id?: string + models: string[] + name: string + user_id?: string + } + Update: { + content?: string + folder_id?: string | null + id?: string + models?: string[] + name?: string + user_id?: string + } + Relationships: [ + { + foreignKeyName: "system_prompt_owner" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["id"] + }, + { + foreignKeyName: "system_prompt_owner_folder" + columns: ["folder_id"] + isOneToOne: false + referencedRelation: "folders" + referencedColumns: ["id"] + } + ] + } + users: { + Row: { + avatar_url: string | null + billing_address: Json | null + full_name: string | null + id: string + payment_method: Json | null + } + Insert: { + avatar_url?: string | null + billing_address?: Json | null + full_name?: string | null + id: string + payment_method?: Json | null + } + Update: { + avatar_url?: string | null + billing_address?: Json | null + full_name?: string | null + id?: string + payment_method?: Json | null + } + Relationships: [ + { + foreignKeyName: "users_id_fkey" + columns: ["id"] + isOneToOne: true + referencedRelation: "users" + referencedColumns: ["id"] + } + ] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + pricing_plan_interval: "day" | "week" | "month" | "year" + pricing_type: "one_time" | "recurring" + subscription_status: + | "trialing" + | "active" + | "canceled" + | "incomplete" + | "incomplete_expired" + | "past_due" + | "unpaid" + | "paused" + } + CompositeTypes: { + [_ in never]: never + } + } +} diff --git a/apps/unsaged/utils/app/auth/helpers.ts b/apps/unsaged/utils/app/auth/helpers.ts index 8f52313c..73fea378 100644 --- a/apps/unsaged/utils/app/auth/helpers.ts +++ b/apps/unsaged/utils/app/auth/helpers.ts @@ -1,44 +1,49 @@ -import { getSession } from 'next-auth/react'; - -import { Session, User } from '@/types/auth'; - -export const getClientSession = async () => { - const authjsSession = await getSession(); - - if (authjsSession) { - let user: User | undefined = undefined; - if (authjsSession.user) { - user = { - email: authjsSession?.user?.email, - name: authjsSession?.user?.name, - image: authjsSession?.user?.image, - }; - } - - const session: Session = { - user: user, - expires: authjsSession.expires, - customAccessToken: authjsSession.customAccessToken, +import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'; +import { Database } from '@/types/supabase.types'; + +// Initialize your Supabase client once here +const supabaseClient = createClientComponentClient(); + +export async function getClientSession() { + try { + const { + data: { session }, + } = await supabaseClient.auth.getSession(); + + const sessionData = { + user: session?.user?.email || '', + expires: session?.expires_at || '', + customAccessToken: session?.access_token || '', }; - return session; + return sessionData; + } catch (error) { + console.error(error); + return null; } - - return null; -}; - -export const getUser = async () => { - const session = await getClientSession(); - - let user = session?.user; - - if (!user) { - user = { - email: 'default_user', - image: null, - name: 'Default User', - }; +} + +export async function getUser() { + try { + const { + data: { session }, + } = await supabaseClient.auth.getSession(); + + const user = session?.user + ? { + email: session.user.email || 'default_user', + image: session.user.user_metadata?.avatar_url || '', + name: session.user.user_metadata?.full_name || 'Default User', + } + : { + email: 'default_user', + image: '', + name: 'Default User', + }; + + return user; + } catch (error) { + console.error(error); + return null; } - - return user; -}; +} diff --git a/apps/unsaged/utils/app/auth/providers.ts b/apps/unsaged/utils/app/auth/providers.ts deleted file mode 100644 index 8d60ae81..00000000 --- a/apps/unsaged/utils/app/auth/providers.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { - APPLE_CLIENT_ID, - APPLE_CLIENT_SECRET, - AUTH0_CLIENT_ID, - AUTH0_CLIENT_SECRET, - AUTH0_ISSUER, - COGNITO_CLIENT_ID, - COGNITO_CLIENT_SECRET, - DISCORD_CLIENT_ID, - DISCORD_CLIENT_SECRET, - EMAIL_FROM, - EMAIL_SERVER, - FACEBOOK_CLIENT_ID, - FACEBOOK_CLIENT_SECRET, - GITHUB_CLIENT_ID, - GITHUB_CLIENT_SECRET, - GITLAB_CLIENT_ID, - GITLAB_CLIENT_SECRET, - GOOGLE_CLIENT_ID, - GOOGLE_CLIENT_SECRET, - OKTA_CLIENT_ID, - OKTA_CLIENT_SECRET, - REDDIT_CLIENT_ID, - REDDIT_CLIENT_SECRET, - SALESFORCE_CLIENT_ID, - SALESFORCE_CLIENT_SECRET, - SLACK_CLIENT_ID, - SLACK_CLIENT_SECRET, - SPOTIFY_CLIENT_ID, - SPOTIFY_CLIENT_SECRET, - TWITCH_CLIENT_ID, - TWITCH_CLIENT_SECRET, - TWITTER_CLIENT_ID, - TWITTER_CLIENT_SECRET, -} from './constants'; - -const authorization = { - params: { - prompt: 'consent', - access_type: 'offline', - response_type: 'code', - }, -}; - -export async function getProviders() { - const providers = []; - if (APPLE_CLIENT_ID) { - const provider = await import('next-auth/providers/apple'); - const AppleProvider = provider.default; - providers.push( - AppleProvider({ - clientId: APPLE_CLIENT_ID!, - clientSecret: APPLE_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (AUTH0_CLIENT_ID) { - const provider = await import('next-auth/providers/auth0'); - const Auth0Provider = provider.default; - providers.push( - Auth0Provider({ - clientId: AUTH0_CLIENT_ID!, - clientSecret: AUTH0_CLIENT_SECRET!, - issuer: AUTH0_ISSUER, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (COGNITO_CLIENT_ID) { - const provider = await import('next-auth/providers/cognito'); - const CognitoProvider = provider.default; - providers.push( - CognitoProvider({ - clientId: COGNITO_CLIENT_ID!, - clientSecret: COGNITO_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (DISCORD_CLIENT_ID) { - const provider = await import('next-auth/providers/discord'); - const DiscordProvider = provider.default; - providers.push( - DiscordProvider({ - clientId: DISCORD_CLIENT_ID!, - clientSecret: DISCORD_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (EMAIL_FROM) { - const provider = await import('next-auth/providers/email'); - const EmailProvider = provider.default; - providers.push( - EmailProvider({ - server: EMAIL_SERVER, - from: EMAIL_FROM, - }), - ); - } - if (FACEBOOK_CLIENT_ID) { - const provider = await import('next-auth/providers/facebook'); - const FacebookProvider = provider.default; - providers.push( - FacebookProvider({ - clientId: FACEBOOK_CLIENT_ID!, - clientSecret: FACEBOOK_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (GITHUB_CLIENT_ID) { - const provider = await import('next-auth/providers/github'); - const GithubProvider = provider.default; - providers.push( - GithubProvider({ - clientId: GITHUB_CLIENT_ID!, - clientSecret: GITHUB_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (GITLAB_CLIENT_ID) { - const provider = await import('next-auth/providers/gitlab'); - const GitlabProvider = provider.default; - providers.push( - GitlabProvider({ - clientId: GITLAB_CLIENT_ID!, - clientSecret: GITLAB_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (GOOGLE_CLIENT_ID) { - const provider = await import('next-auth/providers/google'); - const GoogleProvider = provider.default; - providers.push( - GoogleProvider({ - clientId: GOOGLE_CLIENT_ID!, - clientSecret: GOOGLE_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (OKTA_CLIENT_ID) { - const provider = await import('next-auth/providers/okta'); - const OktaProvider = provider.default; - providers.push( - OktaProvider({ - clientId: OKTA_CLIENT_ID!, - clientSecret: OKTA_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (REDDIT_CLIENT_ID) { - const provider = await import('next-auth/providers/reddit'); - const RedditProvider = provider.default; - providers.push( - RedditProvider({ - clientId: REDDIT_CLIENT_ID!, - clientSecret: REDDIT_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - if (SALESFORCE_CLIENT_ID) { - const provider = await import('next-auth/providers/salesforce'); - const SalesforceProvider = provider.default; - providers.push( - SalesforceProvider({ - clientId: SALESFORCE_CLIENT_ID!, - clientSecret: SALESFORCE_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - - if (SLACK_CLIENT_ID) { - const provider = await import('next-auth/providers/slack'); - const SlackProvider = provider.default; - providers.push( - SlackProvider({ - clientId: SLACK_CLIENT_ID!, - clientSecret: SLACK_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - - if (SPOTIFY_CLIENT_ID) { - const provider = await import('next-auth/providers/spotify'); - const SpotifyProvider = provider.default; - providers.push( - SpotifyProvider({ - clientId: SPOTIFY_CLIENT_ID!, - clientSecret: SPOTIFY_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - - if (TWITCH_CLIENT_ID) { - const provider = await import('next-auth/providers/twitch'); - const TwitchProvider = provider.default; - providers.push( - TwitchProvider({ - clientId: TWITCH_CLIENT_ID!, - clientSecret: TWITCH_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - - if (TWITTER_CLIENT_ID) { - const provider = await import('next-auth/providers/twitter'); - const TwitterProvider = provider.default; - providers.push( - TwitterProvider({ - clientId: TWITTER_CLIENT_ID!, - clientSecret: TWITTER_CLIENT_SECRET!, - authorization: authorization, - allowDangerousEmailAccountLinking: true, - }), - ); - } - - return providers; -} diff --git a/apps/unsaged/utils/app/const.ts b/apps/unsaged/utils/app/const.ts index a074f6b5..d6ec0f4b 100644 --- a/apps/unsaged/utils/app/const.ts +++ b/apps/unsaged/utils/app/const.ts @@ -7,11 +7,33 @@ export const DEFAULT_MODEL = dockerEnvVarFix( process.env.NEXT_PUBLIC_DEFAULT_MODEL, ); +export const OPENAI_ENABLED = dockerEnvVarFix( + process.env.NEXT_PUBLIC_OPENAI_ENABLED, +); + +export const ANTHROPIC_ENABLED = dockerEnvVarFix( + process.env.NEXT_PUBLIC_ANTHROPIC_ENABLED, +); + +export const GOOGLE_ENABLED = dockerEnvVarFix( + process.env.NEXT_PUBLIC_GOOGLE_ENABLED, +); + +export const OLLAMA_ENABLED = dockerEnvVarFix( + process.env.NEXT_PUBLIC_OLLAMA_ENABLED, +); + + +export const NEXT_PUBLIC_SITE_URL = dockerEnvVarFix( + process.env.NEXT_PUBLIC_SITE_URL) || "https://localhost:3000"; + + export const DEFAULT_TITLE = dockerEnvVarFix(process.env.NEXT_PUBLIC_TITLE) || "unsaged"; export const DEFAULT_DESCRIPTION = dockerEnvVarFix(process.env.NEXT_PUBLIC_DESCRIPTION) || "Open source chat kit engineered for seamless interaction with AI models"; + export const DEFAULT_OPENAI_SYSTEM_PROMPT = dockerEnvVarFix(process.env.NEXT_PUBLIC_DEFAULT_OPENAI_SYSTEM_PROMPT) || "You are ChatGPT, a large language model trained by OpenAI. Follow the user's instructions carefully. Respond using markdown."; @@ -141,7 +163,4 @@ export const SUPABASE_SERVICE_ROLE_KEY = dockerEnvVarFix(process.env.SUPABASE_SERVICE_ROLE_KEY) || ''; export const SUPABASE_ANON_KEY = - dockerEnvVarFix(process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) || ''; - -export const SUPABASE_JWT_SECRET = - dockerEnvVarFix(process.env.SUPABASE_JWT_SECRET) || ''; + dockerEnvVarFix(process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) || ''; \ No newline at end of file diff --git a/apps/unsaged/utils/app/debug/env-vars.ts b/apps/unsaged/utils/app/debug/env-vars.ts index 4773efeb..0d77cb0e 100644 --- a/apps/unsaged/utils/app/debug/env-vars.ts +++ b/apps/unsaged/utils/app/debug/env-vars.ts @@ -49,12 +49,10 @@ export function printEnvVariables() { process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, ); - const SUPABASE_JWT_SECRET = dockerEnvVarFix(process.env.SUPABASE_JWT_SECRET); const DEFAULT_MODEL = dockerEnvVarFix(process.env.NEXT_PUBLIC_DEFAULT_MODEL); console.log('SUPABASE_SERVICE_ROLE_KEY', SUPABASE_SERVICE_ROLE_KEY); - console.log('SUPABASE_JWT_SECRET', SUPABASE_JWT_SECRET); console.log('NEXT_PUBLIC_SUPABASE_URL', SUPABASE_URL); console.log('NEXT_PUBLIC_SUPABASE_ANON_KEY', SUPABASE_ANON_KEY); diff --git a/apps/unsaged/utils/app/extensions/database.ts b/apps/unsaged/utils/app/extensions/database.ts index 429de2bd..ec58a739 100644 --- a/apps/unsaged/utils/app/extensions/database.ts +++ b/apps/unsaged/utils/app/extensions/database.ts @@ -5,7 +5,7 @@ import { getClientSession } from '../auth/helpers'; import { ChatConfig } from '@/chat.config'; export const getDatabase = async () => { - const database: Database = new ChatConfig.database(); + const database: Database = new ChatConfig.database() as Database; let customAccessToken: string | undefined = undefined; const session = await getClientSession(); customAccessToken = session?.customAccessToken; diff --git a/apps/unsaged/utils/app/storage/supabase/client-side.ts b/apps/unsaged/utils/app/storage/supabase/client-side.ts index 9f73183a..7dc93874 100644 --- a/apps/unsaged/utils/app/storage/supabase/client-side.ts +++ b/apps/unsaged/utils/app/storage/supabase/client-side.ts @@ -60,33 +60,33 @@ import { supaUpdateSystemPrompts, } from './helpers/systemPrompts'; -import { SupabaseClient, createClient } from '@supabase/supabase-js'; + +import { createBrowserClient } from '@supabase/ssr'; + + export class ClientDatabase implements Database { name = 'supabase'; - supabase: SupabaseClient | null = null; - - async connect({ - customAccessToken, - }: { - customAccessToken: string; - }): Promise { - if (!this.supabase) { - this.supabase = createClient( - SUPABASE_URL, - SUPABASE_ANON_KEY, - { - global: { - headers: { - Authorization: `Bearer ${customAccessToken}`, - }, - }, - auth: { - persistSession: false, - }, - }, - ); - } + + // Define a custom type for SupabaseClient + private supabaseClient: any; + + constructor() { + this.supabaseClient = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + ); + } + + get client() { + return this.supabaseClient; + } + + // Add a connect method + connect() { + // You can perform any connection-related tasks here if needed + // For now, let's just return the Supabase client instance + return this.supabaseClient; } async disconnect(): Promise {} @@ -97,133 +97,136 @@ export class ClientDatabase implements Database { user: User, newConversation: Conversation, ): Promise { - return await supaCreateConversation(this.supabase!, newConversation); + return await supaCreateConversation(this.client!, newConversation); } async updateConversation( user: User, updatedConversation: Conversation, ): Promise { - return await supaUpdateConversation(this.supabase!, updatedConversation); + return await supaUpdateConversation(this.client!, updatedConversation); } async deleteConversation( user: User, conversationId: string, ): Promise { - return await supaDeleteConversation(this.supabase!, conversationId); + return await supaDeleteConversation(this.client!, conversationId); } // -----------------------------------Conversations----------------------------------- async getConversations( user: User, systemPrompts: SystemPrompt[], - models: AiModel[], + models: AiModel[] ): Promise { - return await supaGetConversations(this.supabase!, systemPrompts, models); + const conversations = await supaGetConversations(this.client!, systemPrompts, models); + // Handle the case where conversations is undefined and return an empty array + return conversations || []; } + async updateConversations( user: User, updatedConversations: Conversation[], ): Promise { - return await supaUpdateConversations(this.supabase!, updatedConversations); + return await supaUpdateConversations(this.client!, updatedConversations); } async deleteConversations(user: User): Promise { - return await supaDeleteConversations(this.supabase!); + return await supaDeleteConversations(this.client!); } // -----------------------------------Folder----------------------------------- async createFolder(user: User, newFolder: FolderInterface): Promise { - return await supaCreateFolder(this.supabase!, newFolder); + return await supaCreateFolder(this.client!, newFolder); } async updateFolder( user: User, updatedFolder: FolderInterface, ): Promise { - return await supaUpdateFolder(this.supabase!, updatedFolder); + return await supaUpdateFolder(this.client!, updatedFolder); } async deleteFolder(user: User, folderId: string): Promise { - return await supaDeleteFolder(this.supabase!, folderId); + return await supaDeleteFolder(this.client!, folderId); } // -----------------------------------Folders----------------------------------- async getFolders(user: User): Promise { - return await supaGetFolders(this.supabase!); + return await supaGetFolders(this.client!); } async updateFolders( user: User, updatedFolders: FolderInterface[], ): Promise { - return await supaUpdateFolders(this.supabase!, updatedFolders); + return await supaUpdateFolders(this.client!, updatedFolders); } async deleteFolders(user: User, folderIds: string[]): Promise { - return await supaDeleteFolders(this.supabase!, folderIds); + return await supaDeleteFolders(this.client!, folderIds); } // -----------------------------------Message----------------------------------- async createMessage(user: User, newMessage: Message): Promise { - return await supaCreateMessage(this.supabase!, newMessage); + return await supaCreateMessage(this.client!, newMessage); } async updateMessage(user: User, updatedMessage: Message): Promise { - return await supaUpdateMessage(this.supabase!, updatedMessage); + return await supaUpdateMessage(this.client!, updatedMessage); } async deleteMessage(user: User, messageId: string): Promise { - return await supaDeleteMessage(this.supabase!, messageId); + return await supaDeleteMessage(this.client!, messageId); } // -----------------------------------Messages----------------------------------- async getMessages(user: User, conversationId?: string): Promise { - return await supaGetMessages(this.supabase!, conversationId); + return await supaGetMessages(this.client!, conversationId); } async createMessages(user: User, newMessages: Message[]): Promise { - return await supaCreateMessages(this.supabase!, newMessages); + return await supaCreateMessages(this.client!, newMessages); } async updateMessages( user: User, updatedMessages: Message[], ): Promise { - return await supaUpdateMessages(this.supabase!, updatedMessages); + return await supaUpdateMessages(this.client!, updatedMessages); } async deleteMessages(user: User, messageIds: string[]): Promise { - return await supaDeleteMessages(this.supabase!, messageIds); + return await supaDeleteMessages(this.client!, messageIds); } // -----------------------------------Prompt----------------------------------- async createPrompt(user: User, newPrompt: Prompt): Promise { - return await supaCreatePrompt(this.supabase!, newPrompt); + return await supaCreatePrompt(this.client!, newPrompt); } async updatePrompt(user: User, updatedPrompt: Prompt): Promise { - return await supaUpdatePrompt(this.supabase!, updatedPrompt); + return await supaUpdatePrompt(this.client!, updatedPrompt); } async deletePrompt(user: User, promptId: string): Promise { - return await supaDeletePrompt(this.supabase!, promptId); + return await supaDeletePrompt(this.client!, promptId); } // -----------------------------------Prompts----------------------------------- async getPrompts(user: User): Promise { - return await supaGetPrompts(this.supabase!); + return await supaGetPrompts(this.client!); } async updatePrompts(user: User, updatedPrompts: Prompt[]): Promise { - return await supaUpdatePrompts(this.supabase!, updatedPrompts); + return await supaUpdatePrompts(this.client!, updatedPrompts); } async deletePrompts(user: User, promptIds: string[]): Promise { - return await supaDeletePrompts(this.supabase!, promptIds); + return await supaDeletePrompts(this.client!, promptIds); } // -----------------------------------SystemPrompt----------------------------------- @@ -231,39 +234,39 @@ export class ClientDatabase implements Database { user: User, newSystemPrompt: SystemPrompt, ): Promise { - return await supaCreateSystemPrompt(this.supabase!, newSystemPrompt); + return await supaCreateSystemPrompt(this.client!, newSystemPrompt); } async updateSystemPrompt( user: User, updatedSystemPrompt: SystemPrompt, ): Promise { - return await supaUpdateSystemPrompt(this.supabase!, updatedSystemPrompt); + return await supaUpdateSystemPrompt(this.client!, updatedSystemPrompt); } async deleteSystemPrompt( user: User, systemPromptId: string, ): Promise { - return await supaDeleteSystemPrompt(this.supabase!, systemPromptId); + return await supaDeleteSystemPrompt(this.client!, systemPromptId); } // -----------------------------------SystemPrompts----------------------------------- async getSystemPrompts(user: User): Promise { - return await supaGetSystemPrompts(this.supabase!); + return await supaGetSystemPrompts(this.client!); } async updateSystemPrompts( user: User, updatedSystemPrompts: SystemPrompt[], ): Promise { - return await supaUpdateSystemPrompts(this.supabase!, updatedSystemPrompts); + return await supaUpdateSystemPrompts(this.client!, updatedSystemPrompts); } async deleteSystemPrompts( user: User, systemPromptIds: string[], ): Promise { - return await supaDeleteSystemPrompts(this.supabase!, systemPromptIds); + return await supaDeleteSystemPrompts(this.client!, systemPromptIds); } } diff --git a/apps/unsaged/utils/app/storage/supabase/helpers/conversations.ts b/apps/unsaged/utils/app/storage/supabase/helpers/conversations.ts index 1d9dfd7c..63b89ca4 100644 --- a/apps/unsaged/utils/app/storage/supabase/helpers/conversations.ts +++ b/apps/unsaged/utils/app/storage/supabase/helpers/conversations.ts @@ -39,6 +39,12 @@ export const supaGetConversations = async ( supaConversation.model_id = 'claude-2'; } + if (!Array.isArray(models)) { + console.error('models is not an array:'); + console.log(models); + return; // or handle the error appropriately + } + const selectedModel = models.find( (model) => model.id === supaConversation.model_id, ); diff --git a/apps/unsaged/utils/server/ai_vendors/openai/models.ts b/apps/unsaged/utils/server/ai_vendors/openai/models.ts index de24138f..900b3c77 100644 --- a/apps/unsaged/utils/server/ai_vendors/openai/models.ts +++ b/apps/unsaged/utils/server/ai_vendors/openai/models.ts @@ -10,34 +10,41 @@ export const config = { runtime: 'edge', }; -export async function getAvailableOpenAIModels(key?: string): Promise { - const openai = await getOpenAi(key); +export async function getAvailableOpenAIModels(key?: string): Promise { + try { + const openai = await getOpenAi(key); - const list = await openai.models.list(); + const list = await openai.models.list(); - const models: (AiModel | null)[] = list.data - .map((openaiModel: any) => { - const model_name = - OPENAI_API_TYPE === 'azure' ? openaiModel.model : openaiModel.id; + const models: (AiModel | null)[] = list.data + .map((openaiModel: any) => { + const model_name = + OPENAI_API_TYPE === 'azure' ? openaiModel.model : openaiModel.id; - if (!PossibleAiModels[model_name]) { - if (DEBUG_MODE) - console.warn('OpenAI model not implemented:', model_name); + if (!PossibleAiModels[model_name]) { + if (DEBUG_MODE) + console.warn('OpenAI model not implemented:', model_name); - return null; - } + return null; + } - const model = PossibleAiModels[model_name]; + const model = PossibleAiModels[model_name]; - if (OPENAI_API_TYPE === 'azure') { - model.id = openaiModel.id; - } + if (OPENAI_API_TYPE === 'azure') { + model.id = openaiModel.id; + } - return model; - }); + return model; + }); - // Drop null values - const modelsWithoutNull = models.filter(Boolean); + // Drop null values + const modelsWithoutNull = models.filter(Boolean); - return { data: modelsWithoutNull }; + return { data: modelsWithoutNull }; + } catch (error) { + if (DEBUG_MODE) { + console.error('Error fetching OpenAI models:', error); + } + return null; // Return null if there's an error + } } diff --git a/apps/unsaged/utils/supabase/middleware.ts b/apps/unsaged/utils/supabase/middleware.ts new file mode 100644 index 00000000..f9629c04 --- /dev/null +++ b/apps/unsaged/utils/supabase/middleware.ts @@ -0,0 +1,61 @@ +import { createBrowserClient, type CookieOptions } from '@supabase/ssr' +import { type NextRequest, NextResponse } from 'next/server' + +export const createClient = (request: NextRequest) => { + // Create an unmodified response + let response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + + const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return request.cookies.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + // If the cookie is updated, update the cookies for the request and response + request.cookies.set({ + name, + value, + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value, + ...options, + }) + }, + remove(name: string, options: CookieOptions) { + // If the cookie is removed, update the cookies for the request and response + request.cookies.set({ + name, + value: '', + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value: '', + ...options, + }) + }, + }, + } + ) + + return { supabase, response } +} diff --git a/apps/unsaged/utils/supabase/server.ts b/apps/unsaged/utils/supabase/server.ts new file mode 100644 index 00000000..e69de29b diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21704ec9..c2846f47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - importers: .: @@ -84,9 +80,6 @@ importers: '@dqbd/tiktoken': specifier: ^1.0.7 version: 1.0.7 - '@next-auth/supabase-adapter': - specifier: ^0.2.1 - version: 0.2.1(@supabase/supabase-js@2.38.5)(next-auth@4.24.5) '@radix-ui/react-icons': specifier: ^1.3.0 version: 1.3.0(react@18.2.0) @@ -106,14 +99,26 @@ importers: specifier: ^1.0.7 version: 1.0.7(@types/react-dom@18.2.0)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@supabase/auth-helpers-nextjs': - specifier: ^0.6.1 - version: 0.6.1(@supabase/supabase-js@2.38.5) + specifier: ^0.8.7 + version: 0.8.7(@supabase/supabase-js@2.38.5) + '@supabase/auth-ui-react': + specifier: ^0.4.6 + version: 0.4.6(@supabase/supabase-js@2.38.5) + '@supabase/auth-ui-shared': + specifier: ^0.1.8 + version: 0.1.8(@supabase/supabase-js@2.38.5) + '@supabase/ssr': + specifier: latest + version: 0.0.10(@supabase/supabase-js@2.38.5) '@supabase/supabase-js': - specifier: ^2.38.5 + specifier: latest version: 2.38.5 '@tabler/icons-react': specifier: ^2.42.0 version: 2.42.0(react@18.2.0) + '@tailwindcss/typography': + specifier: ^0.5.10 + version: 0.5.10(tailwindcss@3.3.5) '@vercel/analytics': specifier: ^1.1.1 version: 1.1.1 @@ -136,8 +141,11 @@ importers: specifier: ^0.1.0 version: 0.1.0 i18next: - specifier: ^22.5.1 - version: 22.5.1 + specifier: ^23.7.6 + version: 23.7.6 + install: + specifier: ^0.13.0 + version: 0.13.0 js-yaml: specifier: ^4.1.0 version: 4.1.0 @@ -145,32 +153,29 @@ importers: specifier: ^9.0.2 version: 9.0.2 next: - specifier: ^13.5.6 - version: 13.5.6(react-dom@18.2.0)(react@18.2.0) - next-auth: - specifier: ^4.24.5 - version: 4.24.5(next@13.5.6)(nodemailer@6.9.7)(react-dom@18.2.0)(react@18.2.0) + specifier: latest + version: 14.0.3(react-dom@18.2.0)(react@18.2.0) next-axiom: specifier: ^1.1.1 - version: 1.1.1(next@13.5.6)(react@18.2.0) + version: 1.1.1(next@14.0.3)(react@18.2.0) next-i18next: specifier: ^13.3.0 - version: 13.3.0(i18next@22.5.1)(next@13.5.6)(react-i18next@12.3.1)(react@18.2.0) + version: 13.3.0(i18next@23.7.6)(next@14.0.3)(react-i18next@12.3.1)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@14.0.3)(react-dom@18.2.0)(react@18.2.0) nextra: specifier: ^2.13.2 - version: 2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) + version: 2.13.2(next@14.0.3)(react-dom@18.2.0)(react@18.2.0) nextra-theme-docs: specifier: ^2.13.2 - version: 2.13.2(next@13.5.6)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0) + version: 2.13.2(next@14.0.3)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0) nodemailer: specifier: ^6.9.7 version: 6.9.7 openai: - specifier: ^4.19.1 - version: 4.19.1(encoding@0.1.13) + specifier: ^4.20.0 + version: 4.20.0(encoding@0.1.13) react: specifier: ^18.2.0 version: 18.2.0 @@ -182,7 +187,7 @@ importers: version: 2.4.1(csstype@3.1.2)(react-dom@18.2.0)(react@18.2.0) react-i18next: specifier: ^12.3.1 - version: 12.3.1(i18next@22.5.1)(react-dom@18.2.0)(react@18.2.0) + version: 12.3.1(i18next@23.7.6)(react-dom@18.2.0)(react@18.2.0) react-markdown: specifier: ^8.0.7 version: 8.0.7(@types/react@18.2.37)(react@18.2.0) @@ -217,9 +222,6 @@ importers: '@mozilla/readability': specifier: ^0.4.4 version: 0.4.4 - '@tailwindcss/typography': - specifier: ^0.5.10 - version: 0.5.10(tailwindcss@3.3.5) '@trivago/prettier-plugin-sort-imports': specifier: ^4.3.0 version: 4.3.0(prettier@2.8.8) @@ -233,8 +235,8 @@ importers: specifier: ^9.0.5 version: 9.0.5 '@types/node': - specifier: ^20.9.4 - version: 20.9.4 + specifier: ^20.10.0 + version: 20.10.0 '@types/react': specifier: 18.2.37 version: 18.2.37 @@ -281,8 +283,8 @@ importers: specifier: workspace:* version: link:../../packages/tsconfig typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.2 + version: 5.3.2 vitest: specifier: ^0.29.8 version: 0.29.8(jsdom@21.1.2) @@ -291,7 +293,7 @@ importers: dependencies: eslint-config-next: specifier: ^14.0.2 - version: 14.0.3(eslint@8.54.0)(typescript@5.2.2) + version: 14.0.3(eslint@8.54.0)(typescript@5.3.2) eslint-config-prettier: specifier: ^9.0.0 version: 9.0.0(eslint@8.54.0) @@ -527,7 +529,7 @@ packages: resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.23.4 + '@babel/types': 7.17.0 jsesc: 2.5.2 source-map: 0.5.7 dev: true @@ -758,7 +760,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.23.4 + '@babel/types': 7.17.0 /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.23.3): resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} @@ -1807,7 +1809,6 @@ packages: dependencies: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true /@babel/types@7.23.4: resolution: {integrity: sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==} @@ -2954,7 +2955,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.9.4 + '@types/node': 20.10.0 '@types/yargs': 17.0.31 chalk: 4.1.2 dev: false @@ -3207,18 +3208,8 @@ packages: '@napi-rs/simple-git-win32-x64-msvc': 0.1.9 dev: false - /@next-auth/supabase-adapter@0.2.1(@supabase/supabase-js@2.38.5)(next-auth@4.24.5): - resolution: {integrity: sha512-BlIbBRd8QjdV84h/XH2QuuleZAFcmfRwT0pyvc9iqrVztxmjWOalNRvSA7xsbqsQq9mK16PMmNPRvsDEUAAgfQ==} - peerDependencies: - '@supabase/supabase-js': ^2.0.5 - next-auth: ^4.18.7 - dependencies: - '@supabase/supabase-js': 2.38.5 - next-auth: 4.24.5(next@13.5.6)(nodemailer@6.9.7)(react-dom@18.2.0)(react@18.2.0) - dev: false - - /@next/env@13.5.6: - resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} + /@next/env@14.0.3: + resolution: {integrity: sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==} dev: false /@next/eslint-plugin-next@14.0.3: @@ -3227,8 +3218,8 @@ packages: glob: 7.1.7 dev: false - /@next/swc-darwin-arm64@13.5.6: - resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} + /@next/swc-darwin-arm64@14.0.3: + resolution: {integrity: sha512-64JbSvi3nbbcEtyitNn2LEDS/hcleAFpHdykpcnrstITFlzFgB/bW0ER5/SJJwUPj+ZPY+z3e+1jAfcczRLVGw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -3236,8 +3227,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.5.6: - resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} + /@next/swc-darwin-x64@14.0.3: + resolution: {integrity: sha512-RkTf+KbAD0SgYdVn1XzqE/+sIxYGB7NLMZRn9I4Z24afrhUpVJx6L8hsRnIwxz3ERE2NFURNliPjJ2QNfnWicQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -3245,8 +3236,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.5.6: - resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} + /@next/swc-linux-arm64-gnu@14.0.3: + resolution: {integrity: sha512-3tBWGgz7M9RKLO6sPWC6c4pAw4geujSwQ7q7Si4d6bo0l6cLs4tmO+lnSwFp1Tm3lxwfMk0SgkJT7EdwYSJvcg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -3254,8 +3245,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.5.6: - resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} + /@next/swc-linux-arm64-musl@14.0.3: + resolution: {integrity: sha512-v0v8Kb8j8T23jvVUWZeA2D8+izWspeyeDGNaT2/mTHWp7+37fiNfL8bmBWiOmeumXkacM/AB0XOUQvEbncSnHA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -3263,8 +3254,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.5.6: - resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} + /@next/swc-linux-x64-gnu@14.0.3: + resolution: {integrity: sha512-VM1aE1tJKLBwMGtyBR21yy+STfl0MapMQnNrXkxeyLs0GFv/kZqXS5Jw/TQ3TSUnbv0QPDf/X8sDXuMtSgG6eg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -3272,8 +3263,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.5.6: - resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} + /@next/swc-linux-x64-musl@14.0.3: + resolution: {integrity: sha512-64EnmKy18MYFL5CzLaSuUn561hbO1Gk16jM/KHznYP3iCIfF9e3yULtHaMy0D8zbHfxset9LTOv6cuYKJgcOxg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -3281,8 +3272,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.5.6: - resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} + /@next/swc-win32-arm64-msvc@14.0.3: + resolution: {integrity: sha512-WRDp8QrmsL1bbGtsh5GqQ/KWulmrnMBgbnb+59qNTW1kVi1nG/2ndZLkcbs2GX7NpFLlToLRMWSQXmPzQm4tog==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -3290,8 +3281,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.5.6: - resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} + /@next/swc-win32-ia32-msvc@14.0.3: + resolution: {integrity: sha512-EKffQeqCrj+t6qFFhIFTRoqb2QwX1mU7iTOvMyLbYw3QtqTw9sMwjykyiMlZlrfm2a4fA84+/aeW+PMg1MjuTg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -3299,8 +3290,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.5.6: - resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} + /@next/swc-win32-x64-msvc@14.0.3: + resolution: {integrity: sha512-ERhKPSJ1vQrPiwrs15Pjz/rvDHZmkmvbf/BjPN/UCOI++ODftT0GtasDPi0j+y6PPJi5HsXw+dpRaXUaw4vjuQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -3987,24 +3978,50 @@ packages: webpack-sources: 3.2.3 dev: false - /@supabase/auth-helpers-nextjs@0.6.1(@supabase/supabase-js@2.38.5): - resolution: {integrity: sha512-ffDAR4pW2Cosj/CuuGRAhzOFfHtqzdgax7zqRGGyq334gxxPplsmJFGaLPRJ3Z/4mTSIJHyFd6LYdHMN0a+5Bw==} + /@stitches/core@1.2.8: + resolution: {integrity: sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==} + dev: false + + /@supabase/auth-helpers-nextjs@0.8.7(@supabase/supabase-js@2.38.5): + resolution: {integrity: sha512-iYdOjFo0GkRvha340l8JdCiBiyXQuG9v8jnq7qMJ/2fakrskRgHTCOt7ryWbip1T6BExcWKC8SoJrhCzPOxhhg==} peerDependencies: - '@supabase/supabase-js': ^2.0.4 + '@supabase/supabase-js': ^2.19.0 dependencies: - '@supabase/auth-helpers-shared': 0.3.4(@supabase/supabase-js@2.38.5) + '@supabase/auth-helpers-shared': 0.6.3(@supabase/supabase-js@2.38.5) '@supabase/supabase-js': 2.38.5 + set-cookie-parser: 2.6.0 dev: false - /@supabase/auth-helpers-shared@0.3.4(@supabase/supabase-js@2.38.5): - resolution: {integrity: sha512-8I3D0SPHHexkFTSfPg0nZgJSVazWoB3tZDpT6IjRv6w89vDMUzO99Lit4H9anVLF4teW8c/nJJxawDNbDlgbgg==} + /@supabase/auth-helpers-shared@0.6.3(@supabase/supabase-js@2.38.5): + resolution: {integrity: sha512-xYQRLFeFkL4ZfwC7p9VKcarshj3FB2QJMgJPydvOY7J5czJe6xSG5/wM1z63RmAzGbCkKg+dzpq61oeSyWiGBQ==} peerDependencies: - '@supabase/supabase-js': ^2.0.4 + '@supabase/supabase-js': ^2.19.0 dependencies: '@supabase/supabase-js': 2.38.5 jose: 4.15.4 dev: false + /@supabase/auth-ui-react@0.4.6(@supabase/supabase-js@2.38.5): + resolution: {integrity: sha512-uvjcH/K0rvFKUE5Uam5JI6IGXUWSv55GTYcVRRQFEwfav2sT4hzBh6A0gkX9gEZEprhSA9S5Pp5+TzkCAKgcbg==} + peerDependencies: + '@supabase/supabase-js': ^2.21.0 + dependencies: + '@stitches/core': 1.2.8 + '@supabase/auth-ui-shared': 0.1.8(@supabase/supabase-js@2.38.5) + '@supabase/supabase-js': 2.38.5 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@supabase/auth-ui-shared@0.1.8(@supabase/supabase-js@2.38.5): + resolution: {integrity: sha512-ouQ0DjKcEFg+0gZigFIEgu01V3e6riGZPzgVD0MJsCBNsMsiDT74+GgCEIElMUpTGkwSja3xLwdFRFgMNFKcjg==} + peerDependencies: + '@supabase/supabase-js': ^2.21.0 + dependencies: + '@supabase/supabase-js': 2.38.5 + dev: false + /@supabase/functions-js@2.1.5: resolution: {integrity: sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==} dependencies: @@ -4041,6 +4058,16 @@ packages: - supports-color dev: false + /@supabase/ssr@0.0.10(@supabase/supabase-js@2.38.5): + resolution: {integrity: sha512-eVs7+bNlff8Fd79x8K3Jbfpmf8P8QRA1Z6rUDN+fi4ReWvRBZyWOFfR6eqlsX6vTjvGgTiEqujFSkv2PYW5kbQ==} + peerDependencies: + '@supabase/supabase-js': ^2.33.1 + dependencies: + '@supabase/supabase-js': 2.38.5 + cookie: 0.5.0 + ramda: 0.29.1 + dev: false + /@supabase/storage-js@2.5.4: resolution: {integrity: sha512-yspHD19I9uQUgfTh0J94+/r/g6hnhdQmw6Y7OWqr/EbnL6uvicGV1i1UDkkmeUHqfF9Mbt2sLtuxRycYyKv2ew==} dependencies: @@ -4250,7 +4277,7 @@ packages: lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 tailwindcss: 3.3.5 - dev: true + dev: false /@theguild/remark-mermaid@0.0.5(react@18.2.0): resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} @@ -4331,13 +4358,13 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/bonjour@3.5.13: resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/chai-subset@1.3.5: @@ -4354,13 +4381,13 @@ packages: resolution: {integrity: sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==} dependencies: '@types/express-serve-static-core': 4.17.41 - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/d3-scale-chromatic@3.0.3: @@ -4407,7 +4434,7 @@ packages: /@types/express-serve-static-core@4.17.41: resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 '@types/qs': 6.9.10 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -4463,7 +4490,7 @@ packages: /@types/http-proxy@1.17.14: resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/istanbul-lib-coverage@2.0.6: @@ -4487,7 +4514,7 @@ packages: /@types/jsdom@21.1.6: resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 dev: true @@ -4502,7 +4529,7 @@ packages: /@types/jsonwebtoken@9.0.5: resolution: {integrity: sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: true /@types/katex@0.16.7: @@ -4540,28 +4567,28 @@ packages: /@types/node-fetch@2.6.9: resolution: {integrity: sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 form-data: 4.0.0 dev: false /@types/node-forge@1.3.9: resolution: {integrity: sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} dev: false - /@types/node@18.18.12: - resolution: {integrity: sha512-G7slVfkwOm7g8VqcEF1/5SXiMjP3Tbt+pXDU3r/qhlM2KkGm786DUD4xyMA2QzEElFrv/KZV9gjygv4LnkpbMQ==} + /@types/node@18.18.13: + resolution: {integrity: sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==} dependencies: undici-types: 5.26.5 dev: false - /@types/node@20.9.4: - resolution: {integrity: sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==} + /@types/node@20.10.0: + resolution: {integrity: sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==} dependencies: undici-types: 5.26.5 @@ -4637,7 +4664,7 @@ packages: /@types/sax@1.2.7: resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} dependencies: - '@types/node': 20.9.4 + '@types/node': 17.0.45 dev: false /@types/scheduler@0.16.8: @@ -4647,7 +4674,7 @@ packages: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/serve-index@1.9.4: @@ -4661,13 +4688,13 @@ packages: dependencies: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/sockjs@0.3.36: resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/tough-cookie@4.0.5: @@ -4689,13 +4716,13 @@ packages: /@types/websocket@1.0.10: resolution: {integrity: sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/ws@8.5.9: resolution: {integrity: sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 dev: false /@types/yargs-parser@21.0.3: @@ -4708,7 +4735,7 @@ packages: '@types/yargs-parser': 21.0.3 dev: false - /@typescript-eslint/parser@6.12.0(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/parser@6.12.0(eslint@8.54.0)(typescript@5.3.2): resolution: {integrity: sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -4720,11 +4747,11 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.12.0 '@typescript-eslint/types': 6.12.0 - '@typescript-eslint/typescript-estree': 6.12.0(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.12.0(typescript@5.3.2) '@typescript-eslint/visitor-keys': 6.12.0 debug: 4.3.4 eslint: 8.54.0 - typescript: 5.2.2 + typescript: 5.3.2 transitivePeerDependencies: - supports-color dev: false @@ -4742,7 +4769,7 @@ packages: engines: {node: ^16.0.0 || >=18.0.0} dev: false - /@typescript-eslint/typescript-estree@6.12.0(typescript@5.2.2): + /@typescript-eslint/typescript-estree@6.12.0(typescript@5.3.2): resolution: {integrity: sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -4757,8 +4784,8 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.2) + typescript: 5.3.2 transitivePeerDependencies: - supports-color dev: false @@ -5506,7 +5533,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001564 - electron-to-chromium: 1.4.590 + electron-to-chromium: 1.4.593 node-releases: 2.0.13 update-browserslist-db: 1.0.13(browserslist@4.22.1) @@ -5522,7 +5549,7 @@ packages: engines: {node: '>=6.14.2'} requiresBuild: true dependencies: - node-gyp-build: 4.7.0 + node-gyp-build: 4.7.1 dev: false /busboy@1.6.0: @@ -7010,8 +7037,8 @@ packages: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false - /electron-to-chromium@1.4.590: - resolution: {integrity: sha512-hohItzsQcG7/FBsviCYMtQwUSWvVF7NVqPOnJCErWsAshsP/CR2LAXdmq276RbESNdhxiAq5/vRo1g2pxGXVww==} + /electron-to-chromium@1.4.593: + resolution: {integrity: sha512-c7+Hhj87zWmdpmjDONbvNKNo24tvmD4mjal1+qqTYTrlF0/sNpAcDlU0Ki84ftA/5yj3BF2QhSGEC0Rky6larg==} /elkjs@0.8.2: resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==} @@ -7260,7 +7287,7 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-next@14.0.3(eslint@8.54.0)(typescript@5.2.2): + /eslint-config-next@14.0.3(eslint@8.54.0)(typescript@5.3.2): resolution: {integrity: sha512-IKPhpLdpSUyKofmsXUfrvBC49JMUTdeaD8ZIH4v9Vk0sC1X6URTuTJCLtA0Vwuj7V/CQh0oISuSTvNn5//Buew==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 @@ -7271,7 +7298,7 @@ packages: dependencies: '@next/eslint-plugin-next': 14.0.3 '@rushstack/eslint-patch': 1.6.0 - '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.2) eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.12.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.54.0) @@ -7279,7 +7306,7 @@ packages: eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) eslint-plugin-react: 7.33.2(eslint@8.54.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.54.0) - typescript: 5.2.2 + typescript: 5.3.2 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color @@ -7357,7 +7384,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.2) debug: 3.2.7 eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 @@ -7376,7 +7403,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.12.0(eslint@8.54.0)(typescript@5.3.2) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -7672,7 +7699,7 @@ packages: resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} engines: {node: '>= 0.8'} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 require-like: 0.1.2 dev: false @@ -8941,8 +8968,8 @@ packages: resolution: {integrity: sha512-N0SS2WojoVIh2x/QkajSps8RPKzXqryZsQh12VoFY4cLZgkD+62EPY2fY+ZjkNADu8xA5I5EadQQXa8TXBKN3w==} dev: false - /i18next@22.5.1: - resolution: {integrity: sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==} + /i18next@23.7.6: + resolution: {integrity: sha512-O66BhXBw0fH4bEJMA0/klQKPEbcwAp5wjXEL803pdAynNbg2f4qhLIYlNHJyE7icrL6XmSZKPYaaXwy11kJ6YQ==} dependencies: '@babel/runtime': 7.23.4 dev: false @@ -9037,6 +9064,11 @@ packages: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} dev: false + /install@0.13.0: + resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==} + engines: {node: '>= 0.10'} + dev: false + /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} @@ -9478,7 +9510,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.9.4 + '@types/node': 20.10.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -9489,7 +9521,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -9497,7 +9529,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -9809,7 +9841,7 @@ packages: /lodash.castarray@4.4.0: resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} - dev: true + dev: false /lodash.curry@4.1.1: resolution: {integrity: sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA==} @@ -9857,6 +9889,7 @@ packages: /lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false /lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} @@ -11313,46 +11346,20 @@ packages: /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - /next-auth@4.24.5(next@13.5.6)(nodemailer@6.9.7)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==} - peerDependencies: - next: ^12.2.5 || ^13 || ^14 - nodemailer: ^6.6.5 - react: ^17.0.2 || ^18 - react-dom: ^17.0.2 || ^18 - peerDependenciesMeta: - nodemailer: - optional: true - dependencies: - '@babel/runtime': 7.23.4 - '@panva/hkdf': 1.1.1 - cookie: 0.5.0 - jose: 4.15.4 - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) - nodemailer: 6.9.7 - oauth: 0.9.15 - openid-client: 5.6.1 - preact: 10.19.2 - preact-render-to-string: 5.2.6(preact@10.19.2) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - uuid: 8.3.2 - dev: false - - /next-axiom@1.1.1(next@13.5.6)(react@18.2.0): + /next-axiom@1.1.1(next@14.0.3)(react@18.2.0): resolution: {integrity: sha512-0r/TJ+/zetD+uDc7B+2E7WpC86hEtQ1U+DuWYrP/JNmUz+ZdPFbrZgzOSqaZ6TwYbXP56VVlPfYwq1YsKHTHYQ==} engines: {node: '>=18'} peerDependencies: next: '>=13.4' react: '>=18.0.0' dependencies: - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 remeda: 1.29.0 whatwg-fetch: 3.6.19 dev: false - /next-i18next@13.3.0(i18next@22.5.1)(next@13.5.6)(react-i18next@12.3.1)(react@18.2.0): + /next-i18next@13.3.0(i18next@23.7.6)(next@14.0.3)(react-i18next@12.3.1)(react@18.2.0): resolution: {integrity: sha512-X4kgi51BCOoGdKbv87eZ8OU7ICQDg5IP+T5fNjqDY3os9ea0OKTY4YpAiVFiwcI9XimcUmSPbKO4a9jFUyYSgg==} engines: {node: '>=14'} peerDependencies: @@ -11365,11 +11372,11 @@ packages: '@types/hoist-non-react-statics': 3.3.5 core-js: 3.33.3 hoist-non-react-statics: 3.3.2 - i18next: 22.5.1 + i18next: 23.7.6 i18next-fs-backend: 2.3.0 - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 - react-i18next: 12.3.1(i18next@22.5.1)(react-dom@18.2.0)(react@18.2.0) + react-i18next: 12.3.1(i18next@23.7.6)(react-dom@18.2.0)(react@18.2.0) dev: false /next-mdx-remote@4.4.1(react-dom@18.2.0)(react@18.2.0): @@ -11389,26 +11396,26 @@ packages: - supports-color dev: false - /next-seo@6.4.0(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): + /next-seo@6.4.0(next@14.0.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-XQFxkOL2hw0YE+P100HbI3EAvcludlHPxuzMgaIjKb7kPK0CvjGvLFjd9hszZFEDc5oiQkGFA8+cuWcnip7eYA==} peerDependencies: next: ^8.1.1-canary.54 || >=9.0.0 react: '>=16.0.0' react-dom: '>=16.0.0' dependencies: - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /next-themes@0.2.1(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@14.0.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -11417,9 +11424,9 @@ packages: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false - /next@13.5.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} - engines: {node: '>=16.14.0'} + /next@14.0.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-AbYdRNfImBr3XGtvnwOxq8ekVCwbFTv/UJoLwmaX89nk9i051AEY4/HAWzU0YpaTDw8IofUpmuIlvzWF13jxIw==} + engines: {node: '>=18.17.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -11432,7 +11439,7 @@ packages: sass: optional: true dependencies: - '@next/env': 13.5.6 + '@next/env': 14.0.3 '@swc/helpers': 0.5.2 busboy: 1.6.0 caniuse-lite: 1.0.30001564 @@ -11442,21 +11449,21 @@ packages: styled-jsx: 5.1.1(react@18.2.0) watchpack: 2.4.0 optionalDependencies: - '@next/swc-darwin-arm64': 13.5.6 - '@next/swc-darwin-x64': 13.5.6 - '@next/swc-linux-arm64-gnu': 13.5.6 - '@next/swc-linux-arm64-musl': 13.5.6 - '@next/swc-linux-x64-gnu': 13.5.6 - '@next/swc-linux-x64-musl': 13.5.6 - '@next/swc-win32-arm64-msvc': 13.5.6 - '@next/swc-win32-ia32-msvc': 13.5.6 - '@next/swc-win32-x64-msvc': 13.5.6 + '@next/swc-darwin-arm64': 14.0.3 + '@next/swc-darwin-x64': 14.0.3 + '@next/swc-linux-arm64-gnu': 14.0.3 + '@next/swc-linux-arm64-musl': 14.0.3 + '@next/swc-linux-x64-gnu': 14.0.3 + '@next/swc-linux-x64-musl': 14.0.3 + '@next/swc-win32-arm64-msvc': 14.0.3 + '@next/swc-win32-ia32-msvc': 14.0.3 + '@next/swc-win32-x64-msvc': 14.0.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros dev: false - /nextra-theme-docs@2.13.2(next@13.5.6)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0): + /nextra-theme-docs@2.13.2(next@14.0.3)(nextra@2.13.2)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yE4umXaImp1/kf/sFciPj2+EFrNSwd9Db26hi98sIIiujzGf3+9eUgAz45vF9CwBw50FSXxm1QGRcY+slQ4xQQ==} peerDependencies: next: '>=9.5.3' @@ -11473,17 +11480,17 @@ packages: git-url-parse: 13.1.1 intersection-observer: 0.12.2 match-sorter: 6.3.1 - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) - next-seo: 6.4.0(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) - next-themes: 0.2.1(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) - nextra: 2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) + next-seo: 6.4.0(next@14.0.3)(react-dom@18.2.0)(react@18.2.0) + next-themes: 0.2.1(next@14.0.3)(react-dom@18.2.0)(react@18.2.0) + nextra: 2.13.2(next@14.0.3)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) scroll-into-view-if-needed: 3.1.0 zod: 3.22.4 dev: false - /nextra@2.13.2(next@13.5.6)(react-dom@18.2.0)(react@18.2.0): + /nextra@2.13.2(next@14.0.3)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-pIgOSXNUqTz1laxV4ChFZOU7lzJAoDHHaBPj8L09PuxrLKqU1BU/iZtXAG6bQeKCx8EPdBsoXxEuENnL9QGnGA==} engines: {node: '>=16'} peerDependencies: @@ -11503,7 +11510,7 @@ packages: gray-matter: 4.0.3 katex: 0.16.9 lodash.get: 4.4.2 - next: 13.5.6(react-dom@18.2.0)(react@18.2.0) + next: 14.0.3(react-dom@18.2.0)(react@18.2.0) next-mdx-remote: 4.4.1(react-dom@18.2.0)(react@18.2.0) p-limit: 3.1.0 react: 18.2.0 @@ -11571,8 +11578,8 @@ packages: engines: {node: '>= 6.13.0'} dev: false - /node-gyp-build@4.7.0: - resolution: {integrity: sha512-PbZERfeFdrHQOOXiAKOY0VPbykZy90ndPKk0d+CFDegTKmWp1VgOTz2xACVbr1BjCWxrQp68CXtvNsveFhqDJg==} + /node-gyp-build@4.7.1: + resolution: {integrity: sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==} hasBin: true dev: false @@ -11648,19 +11655,10 @@ packages: resolution: {integrity: sha512-ZWl8ov8HeGVyc9Icl1cag76HvIcDAp23eIIT+UVGir+dEu8BMgMlvZeZwqLVd0P8DqaumH4N+QLQXN69G1QjSA==} dev: false - /oauth@0.9.15: - resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} - dev: false - /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-hash@2.2.0: - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} - engines: {node: '>= 6'} - dev: false - /object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -11735,11 +11733,6 @@ packages: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} dev: false - /oidc-token-hash@5.0.3: - resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} - engines: {node: ^10.13.0 || >=12.0.0} - dev: false - /on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -11773,11 +11766,11 @@ packages: is-wsl: 2.2.0 dev: false - /openai@4.19.1(encoding@0.1.13): - resolution: {integrity: sha512-9TddzuZBn2xxhghGGTHLZ4EeNBGTLs3xVzh266NiSJvtUsCsZQ5yVV6H5NhnhyAkKK8uUiZOUUlUAk3HdV+4xg==} + /openai@4.20.0(encoding@0.1.13): + resolution: {integrity: sha512-VbAYerNZFfIIeESS+OL9vgDkK8Mnri55n+jN0UN/HZeuM0ghGh6nDN6UGRZxslNgyJ7XmY/Ca9DO4YYyvrszGA==} hasBin: true dependencies: - '@types/node': 18.18.12 + '@types/node': 18.18.13 '@types/node-fetch': 2.6.9 abort-controller: 3.0.0 agentkeepalive: 4.5.0 @@ -11795,15 +11788,6 @@ packages: hasBin: true dev: false - /openid-client@5.6.1: - resolution: {integrity: sha512-PtrWsY+dXg6y8mtMPyL/namZSYVz8pjXz3yJiBNZsEdCnu9miHLB4ELVC85WvneMKo2Rg62Ay7NkuCpM0bgiLQ==} - dependencies: - jose: 4.15.4 - lru-cache: 6.0.0 - object-hash: 2.2.0 - oidc-token-hash: 5.0.3 - dev: false - /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -12491,7 +12475,7 @@ packages: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: true + dev: false /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} @@ -12560,23 +12544,10 @@ packages: pretty-format: 3.8.0 dev: false - /preact-render-to-string@5.2.6(preact@10.19.2): - resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} - peerDependencies: - preact: '>=10' - dependencies: - preact: 10.19.2 - pretty-format: 3.8.0 - dev: false - /preact@10.11.3: resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} dev: false - /preact@10.19.2: - resolution: {integrity: sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==} - dev: false - /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -12854,6 +12825,10 @@ packages: engines: {node: '>=10'} dev: false + /ramda@0.29.1: + resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==} + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -12984,7 +12959,7 @@ packages: - csstype dev: false - /react-i18next@12.3.1(i18next@22.5.1)(react-dom@18.2.0)(react@18.2.0): + /react-i18next@12.3.1(i18next@23.7.6)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==} peerDependencies: i18next: '>= 19.0.0' @@ -12999,7 +12974,7 @@ packages: dependencies: '@babel/runtime': 7.23.4 html-parse-stringify: 3.0.1 - i18next: 22.5.1 + i18next: 23.7.6 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -13846,6 +13821,10 @@ packages: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} dev: false + /set-cookie-parser@2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + dev: false + /set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} engines: {node: '>= 0.4'} @@ -14571,13 +14550,13 @@ packages: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} dev: false - /ts-api-utils@1.0.3(typescript@5.2.2): + /ts-api-utils@1.0.3(typescript@5.3.2): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.2 dev: false /ts-dedent@2.2.0: @@ -14751,6 +14730,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + /typescript@5.3.2: + resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} + engines: {node: '>=14.17'} + hasBin: true + /ua-parser-js@1.0.37: resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} dev: false @@ -15101,7 +15085,7 @@ packages: engines: {node: '>=6.14.2'} requiresBuild: true dependencies: - node-gyp-build: 4.7.0 + node-gyp-build: 4.7.1 dev: false /util-deprecate@1.0.2: @@ -15212,7 +15196,7 @@ packages: vfile-message: 4.0.2 dev: false - /vite-node@0.29.8(@types/node@20.9.4): + /vite-node@0.29.8(@types/node@20.10.0): resolution: {integrity: sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw==} engines: {node: '>=v14.16.0'} hasBin: true @@ -15222,7 +15206,7 @@ packages: mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.5.0(@types/node@20.9.4) + vite: 4.5.0(@types/node@20.10.0) transitivePeerDependencies: - '@types/node' - less @@ -15234,7 +15218,7 @@ packages: - terser dev: true - /vite@4.5.0(@types/node@20.9.4): + /vite@4.5.0(@types/node@20.10.0): resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -15262,7 +15246,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.9.4 + '@types/node': 20.10.0 esbuild: 0.18.20 postcss: 8.4.31 rollup: 3.29.4 @@ -15303,7 +15287,7 @@ packages: dependencies: '@types/chai': 4.3.11 '@types/chai-subset': 1.3.5 - '@types/node': 20.9.4 + '@types/node': 20.10.0 '@vitest/expect': 0.29.8 '@vitest/runner': 0.29.8 '@vitest/spy': 0.29.8 @@ -15323,8 +15307,8 @@ packages: tinybench: 2.5.1 tinypool: 0.4.0 tinyspy: 1.1.1 - vite: 4.5.0(@types/node@20.9.4) - vite-node: 0.29.8(@types/node@20.9.4) + vite: 4.5.0(@types/node@20.10.0) + vite-node: 0.29.8(@types/node@20.10.0) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -15857,3 +15841,7 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: false + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/turbo.json b/turbo.json index e95b0d98..3731153e 100644 --- a/turbo.json +++ b/turbo.json @@ -41,8 +41,7 @@ "OLLAMA_BASIC_PWD", "NEXT_PUBLIC_SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", - "NEXT_PUBLIC_SUPABASE_ANON_KEY", - "SUPABASE_JWT_SECRET" + "NEXT_PUBLIC_SUPABASE_ANON_KEY" ], "pipeline": { "build": {