diff --git a/.github/ISSUE_TEMPLATE/2_bug_provider.yml b/.github/ISSUE_TEMPLATE/2_bug_provider.yml index 630d8af92c..406084ea8d 100644 --- a/.github/ISSUE_TEMPLATE/2_bug_provider.yml +++ b/.github/ISSUE_TEMPLATE/2_bug_provider.yml @@ -57,10 +57,12 @@ body: - "Identity Server 4" - "Instagram" - "Kakao" + - "Frontegg" - "Keycloak" - "Kinde" - "Line" - "LinkedIn" + - "Loops" - "Mailchimp" - "Mail.ru" - "Mastodon" diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..ea6feea960 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + versioning-strategy: "increase" + allow: + - dependency-name: "oauth4webapi" + - dependency-name: "jose" diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml index 9e44ccb35f..0886682be2 100644 --- a/.github/pr-labeler.yml +++ b/.github/pr-labeler.yml @@ -9,6 +9,7 @@ drizzle: ["packages/adapter-drizzle/**/*"] documentation: ["packages/docs/docs/**/*"] dynamodb: ["packages/adapter-dynamodb/**/*"] examples: ["apps/examples/**/*"] +express: ["packages/frameworks-express/**/*"] fauna: ["packages/adapter-fauna/**/*"] firebase: ["packages/adapter-firebase/**/*"] hasura: ["packages/adapter-hasura/**/*"] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6a106bc90d..1ee78afa19 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ env: jobs: test: name: Test - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Init uses: actions/checkout@v4 @@ -107,7 +107,7 @@ jobs: run: cd apps/examples/nextjs-docker && pnpm test:docker - name: Run E2E tests continue-on-error: true # TODO: Make this less flakey - if: github.repository == 'nextauthjs/next-auth' + if: ${{ env.PACKAGES_CHANGES == 'true' || github.ref == 'refs/heads/main' }} timeout-minutes: 15 env: AUTH_SECRET: ${{ secrets.AUTH_SECRET }} diff --git a/.gitignore b/.gitignore index 66ce6a85ba..2ac352effe 100644 --- a/.gitignore +++ b/.gitignore @@ -87,7 +87,7 @@ docs/.next docs/manifest.mjs # Core -packages/core/src/providers/oauth-types.ts +packages/core/src/providers/provider-types.ts packages/core/lib packages/core/providers packages/core/src/lib/pages/styles.ts diff --git a/.prettierignore b/.prettierignore index af5e116db3..5838858cf7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -32,7 +32,7 @@ packages/**/*.js !packages/*/scripts/*.js # @auth/core -packages/core/src/providers/oauth-types.ts +packages/core/src/providers/provider-types.ts packages/core/src/lib/pages/styles.ts # @auth/sveltekit @@ -43,7 +43,7 @@ packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-* packages/frameworks-express/providers # next-auth -packages/next-auth/src/providers/oauth-types.ts +packages/next-auth/src/providers/provider-types.ts packages/next-auth/css/index.css # Adapters diff --git a/README.md b/README.md index c088ae7d9a..4a8005f3a1 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,15 @@ We have an [OpenCollective](https://opencollective.com/nextauth) for companies a
Encore
💵 + + + Sent.dm Logo +
+
Sent.dm
+ 💵 + + + Arcjet Logo @@ -173,8 +182,6 @@ We have an [OpenCollective](https://opencollective.com/nextauth) for companies a
Arcjet
💵 - -
Route4Me Logo diff --git a/apps/dev/nextjs/.env.local.example b/apps/dev/nextjs/.env.local.example index cb34099406..18f1f2945f 100644 --- a/apps/dev/nextjs/.env.local.example +++ b/apps/dev/nextjs/.env.local.example @@ -58,6 +58,10 @@ AUTH_TWITTER_SECRET= AUTH_WIKIMEDIA_ID= AUTH_WIKIMEDIA_SECRET= +AUTH_FRONTEGG_ID= +AUTH_FRONTEGG_SECRET= +AUTH_FRONTEGG_ISSUER= + # Yandex OAuth. new app -> https://oauth.yandex.com/client/new/id AUTH_YANDEX_ID= AUTH_YANDEX_SECRET= diff --git a/apps/dev/nextjs/app/client.tsx b/apps/dev/nextjs/app/client.tsx index 70708cfe65..f60777109c 100644 --- a/apps/dev/nextjs/app/client.tsx +++ b/apps/dev/nextjs/app/client.tsx @@ -34,7 +34,11 @@ export default function Client() { ) : ( <> - diff --git a/apps/dev/nextjs/auth.ts b/apps/dev/nextjs/auth.ts index 878250080b..0571764576 100644 --- a/apps/dev/nextjs/auth.ts +++ b/apps/dev/nextjs/auth.ts @@ -1,7 +1,7 @@ import NextAuth from "next-auth" -import type { NextAuthConfig } from "next-auth" import Credentials from "next-auth/providers/credentials" import Keycloak from "next-auth/providers/keycloak" +import GitHub from "next-auth/providers/github" // import { PrismaClient } from "@prisma/client" // import { PrismaAdapter } from "@auth/prisma-adapter" @@ -66,8 +66,10 @@ export const { handlers, auth, signIn, signOut, unstable_update } = NextAuth({ } }, }), + GitHub, Keycloak, ], + callbacks: { jwt({ token, trigger, session }) { if (trigger === "update") token.name = session.user.name diff --git a/apps/examples/nextjs/app/api/protected/route.ts b/apps/examples/nextjs/app/api/protected/route.ts index 76652b8ebb..99eb7f352d 100644 --- a/apps/examples/nextjs/app/api/protected/route.ts +++ b/apps/examples/nextjs/app/api/protected/route.ts @@ -6,4 +6,4 @@ export const GET = auth((req) => { } return Response.json({ message: "Not authenticated" }, { status: 401 }) -}) as any // TODO: Fix `auth()` return type +}) diff --git a/apps/examples/nextjs/auth.ts b/apps/examples/nextjs/auth.ts index e74e19599d..fa7c049ea3 100644 --- a/apps/examples/nextjs/auth.ts +++ b/apps/examples/nextjs/auth.ts @@ -37,7 +37,6 @@ import { createStorage } from "unstorage" import memoryDriver from "unstorage/drivers/memory" import vercelKVDriver from "unstorage/drivers/vercel-kv" import { UnstorageAdapter } from "@auth/unstorage-adapter" -import type { NextAuthConfig } from "next-auth" const storage = createStorage({ driver: process.env.VERCEL @@ -49,11 +48,12 @@ const storage = createStorage({ : memoryDriver(), }) -const config = { +export const { handlers, auth, signIn, signOut } = NextAuth({ + debug: !!process.env.AUTH_DEBUG, theme: { logo: "https://authjs.dev/img/logo-sm.png" }, adapter: UnstorageAdapter(storage), providers: [ - Apple({ redirectProxyUrl: "" }), + Apple, // Atlassian, Auth0, AzureB2C, @@ -97,9 +97,7 @@ const config = { Vipps({ issuer: "https://apitest.vipps.no/access-management-1.0/access/", }), - WorkOS({ - connection: process.env.AUTH_WORKOS_CONNECTION!, - }), + WorkOS({ connection: process.env.AUTH_WORKOS_CONNECTION! }), Zoom, ], basePath: "/auth", @@ -118,19 +116,13 @@ const config = { return token }, async session({ session, token }) { - if (token?.accessToken) { - session.accessToken = token.accessToken - } + if (token?.accessToken) session.accessToken = token.accessToken + return session }, }, - experimental: { - enableWebAuthn: true, - }, - debug: process.env.NODE_ENV !== "production" ? true : false, -} satisfies NextAuthConfig - -export const { handlers, auth, signIn, signOut } = NextAuth(config) + experimental: { enableWebAuthn: true }, +}) declare module "next-auth" { interface Session { diff --git a/apps/examples/sveltekit/package.json b/apps/examples/sveltekit/package.json index eeca83afd9..151c5e122d 100644 --- a/apps/examples/sveltekit/package.json +++ b/apps/examples/sveltekit/package.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "3.2.0", - "@sveltejs/kit": "2.5.7", + "@sveltejs/kit": "2.8.3", "@sveltejs/vite-plugin-svelte": "^3.1.0", "svelte": "4.2.19", "svelte-check": "3.6.9", diff --git a/docs/components/Footer/index.tsx b/docs/components/Footer/index.tsx index 3df4fb2fc6..3978a4ab8e 100644 --- a/docs/components/Footer/index.tsx +++ b/docs/components/Footer/index.tsx @@ -58,24 +58,6 @@ export function Footer({ className = "" }) { Discord Community -
  • - - Powered by - - Vercel - - - -
  • diff --git a/docs/components/OAuthProviderInstructions/OAuthProviderSelect.tsx b/docs/components/OAuthProviderInstructions/OAuthProviderSelect.tsx index 815c8b1885..aeff3bef6c 100644 --- a/docs/components/OAuthProviderInstructions/OAuthProviderSelect.tsx +++ b/docs/components/OAuthProviderInstructions/OAuthProviderSelect.tsx @@ -4,44 +4,68 @@ import { ComboboxPopover, ComboboxProvider, } from "@ariakit/react" -import { useOAuthProviderSelect } from "./useOAuthProviderSelect" import dynamic from "next/dynamic" -import type { ChangeEvent } from "react" - import { Link } from "@/components/Link" import manifest from "@/data/manifest.json" +import { + PreviewProviders, + type Provider, +} from "@/components/SearchBarProviders/PreviewProviders" +import { useSelectCombobox } from "@/hooks/use-select-combobox" const OAuthProviderInstructions = dynamic(() => import("./content").then((mod) => mod.OAuthInstructions) ) +const previewProviders: Provider[] = [ + { id: "google", name: "Google" }, + { id: "github", name: "GitHub" }, + { id: "twitter", name: "Twitter" }, + { id: "keycloak", name: "Keycloak" }, + { id: "okta", name: "Okta" }, +] + +const items = Object.entries(manifest.providersOAuth).map(([id, name]) => ({ + id, + name, +})) + export function OAuthProviderSelect() { - const { items, term, selected, handleSearchItem, handleSelectOption } = - useOAuthProviderSelect() + const { + selectedItem, + filteredItems, + hasMatchItem, + handleChange, + handleSelect, + } = useSelectCombobox({ + items, + }) return (
    - + ) => - handleSearchItem(e.target.value) - } + value={selectedItem.name} + onChange={handleChange} /> - {items.map((item) => ( + {filteredItems.map((item) => ( handleSelectOption(item)} + onClick={() => handleSelect(item)} > ))} - {!term ? ( + {!selectedItem.name && ( <>

    Or jump directly to one of the popular ones below.

    -
    -
    - handleSelectOption({ id: "google", name: "Google" }) - } - className="flex h-32 w-32 min-w-24 flex-col items-center justify-between rounded-lg border border-solid border-neutral-200 p-4 shadow-sm transition-colors duration-300 hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-950" - > - -
    Google
    -
    -
    - handleSelectOption({ id: "github", name: "GitHub" }) - } - > - -
    GitHub
    -
    -
    - handleSelectOption({ id: "twitter", name: "Twitter" }) - } - className="flex h-32 w-32 min-w-24 flex-col items-center justify-between rounded-lg border border-solid border-neutral-200 p-4 shadow-sm transition-colors duration-300 hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-950" - > - -
    Twitter
    -
    -
    - handleSelectOption({ id: "keycloak", name: "keycloak" }) - } - className="flex h-32 w-32 min-w-24 flex-col items-center justify-between rounded-lg border border-solid border-neutral-200 p-4 shadow-sm transition-colors duration-300 hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-950" - > - -
    Keycloak
    -
    -
    handleSelectOption({ id: "okta", name: "okta" })} - className="flex h-32 w-32 min-w-24 flex-col items-center justify-between rounded-lg border border-solid border-neutral-200 p-4 shadow-sm transition-colors duration-300 hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-950" - > - -
    Okta
    -
    -
    + - ) : null} - {term && items.length === 0 ? ( + )} + {!hasMatchItem && filteredItems.length === 0 && (

    Can't find the OAuth provider you're looking for? You can always{" "} @@ -119,17 +95,11 @@ export function OAuthProviderSelect() { .

    - ) : null} + )}
    - {selected && term && items.length !== 0 ? ( - - ) : null} + {hasMatchItem && ( + + )}
    ) } diff --git a/docs/components/OAuthProviderInstructions/content/components/SetupCode.tsx b/docs/components/OAuthProviderInstructions/content/components/SetupCode.tsx index a28c8bfe3d..cbbb25ed91 100644 --- a/docs/components/OAuthProviderInstructions/content/components/SetupCode.tsx +++ b/docs/components/OAuthProviderInstructions/content/components/SetupCode.tsx @@ -21,6 +21,7 @@ export function SetupCode({ providerId, providerName, highlight }: Props) { data-copy="" data-language="tsx" icon={TSIcon} + className="px-4" dangerouslySetInnerHTML={{ __html: highlight(` import NextAuth from "next-auth" @@ -40,6 +41,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` @@ -57,13 +59,14 @@ export const { GET, POST } = handlers data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` -import { SvelteKitAuth } from "@auth/sveltekit" -import ${providerName} from "@auth/sveltekit/providers/${providerId}" +import { QwikAuth$ } from "@auth/qwik" +import ${providerName} from "@auth/qwik/providers/${providerId}" -export const { handle, signIn, signOut } = SvelteKitAuth({ +export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$({ providers: [${providerName}], }) `), }} @@ -78,6 +81,7 @@ export const { handle, signIn, signOut } = SvelteKitAuth({ data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` @@ -98,6 +102,7 @@ export const { handle, signIn } = SvelteKitAuth({ data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(`export { handle } from "./auth"`), @@ -113,6 +118,7 @@ export const { handle, signIn } = SvelteKitAuth({ data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` @@ -134,6 +140,7 @@ export const load: LayoutServerLoad = async (event) => { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` diff --git a/docs/components/OAuthProviderInstructions/content/components/SignInCode.tsx b/docs/components/OAuthProviderInstructions/content/components/SignInCode.tsx index 062eccf8e5..eb0147c6f2 100644 --- a/docs/components/OAuthProviderInstructions/content/components/SignInCode.tsx +++ b/docs/components/OAuthProviderInstructions/content/components/SignInCode.tsx @@ -17,6 +17,7 @@ export function SignInCode({ providerId, providerName, highlight }: Props) { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` @@ -43,10 +44,12 @@ export default function SignIn() { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` "use client" + import { signIn } from "next-auth/react" export default function SignIn() { @@ -64,6 +67,7 @@ export default function SignIn() { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} dangerouslySetInnerHTML={{ __html: highlight(` @@ -107,6 +111,7 @@ export default component$(() => { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} data-filename="src/routes/+page.svelte" dangerouslySetInnerHTML={{ @@ -131,6 +136,7 @@ export default component$(() => { data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} data-filename="src/routes/signin/+page.server.ts" dangerouslySetInnerHTML={{ @@ -148,6 +154,7 @@ export const actions: Actions = { default: signIn } data-theme="default" data-copy="" data-language="tsx" + className="px-4" icon={TSIcon} data-filename="src/routes/+page.svelte" dangerouslySetInnerHTML={{ diff --git a/docs/components/OAuthProviderInstructions/content/components/StepTitle.tsx b/docs/components/OAuthProviderInstructions/content/components/StepTitle.tsx index 6843098d21..1c4137fb29 100644 --- a/docs/components/OAuthProviderInstructions/content/components/StepTitle.tsx +++ b/docs/components/OAuthProviderInstructions/content/components/StepTitle.tsx @@ -1,12 +1,29 @@ interface Props { children: React.ReactNode + count: number } -export function StepTitle({ children }: Props) { +export function StepTitle({ children, count }: Props) { return (

    + + {count} + {children}

    ) diff --git a/docs/components/OAuthProviderInstructions/content/index.tsx b/docs/components/OAuthProviderInstructions/content/index.tsx index 21729b741e..3d53c6a19b 100644 --- a/docs/components/OAuthProviderInstructions/content/index.tsx +++ b/docs/components/OAuthProviderInstructions/content/index.tsx @@ -1,8 +1,7 @@ import { useEffect, useState } from "react" -import { type Highlighter, getHighlighter } from "shiki" +import { type Highlighter, createHighlighter } from "shiki" import cx from "classnames" import { Callout, Pre, Code as NXCode } from "nextra/components" - import { StepTitle } from "./components/StepTitle" import { SetupCode } from "./components/SetupCode" import { SignInCode } from "./components/SignInCode" @@ -19,7 +18,7 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { const [highlighter, setHighlighter] = useState(null) useEffect(() => { ;(async () => { - const hl = await getHighlighter({ + const hl = await createHighlighter({ themes: ["github-light", "github-dark"], langs: ["ts", "tsx", "bash"], }) @@ -52,13 +51,14 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { return (
    {/* Step 1 */} - Register OAuth App in {providerName}'s dashboard + + Register OAuth App in {providerName}'s dashboard +

    First you have to setup an OAuth application on the {providerName}{" "} developers dashboard. @@ -115,7 +115,7 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { environment(s). {/* Step 2 */} - Setup Environment Variables + Setup Environment Variables

    Once registered, you should receive a{" "} {manifest.requiresIssuer.includes(providerId) ? ( @@ -132,40 +132,48 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) {

    -
    +          
    +            
    +
    +
    +
    -
    +          
    +            
    +
    +
    +
    -
    +          
    +            
    +
    +
    +
    -
    +          
    +            
    +
    +
    +

    Assuming{" "} @@ -188,7 +196,7 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { if needed, but then you’ll need to pass them to the provider manually.

    {/* Step 3 */} - Setup Provider + Setup Provider

    Let’s enable {providerName} as a sign in option in our Auth.js configuration. You’ll have to import the {providerName}{" "} @@ -201,7 +209,7 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { highlight={highlight} /> {/* Step 4 */} - Add Signin Button + Add Signin Button

    Next, we can add a signin button somewhere in your application like the Navbar. It will trigger Auth.js sign in when clicked. @@ -212,7 +220,7 @@ export function OAuthInstructions({ providerId, disabled = false }: Props) { highlight={highlight} /> {/* Step 5 */} - Ship it! + Ship it!

    Click the “Sign in with {providerName}" button and if all went well, you should be redirected to {providerName} and once authenticated, diff --git a/docs/components/OAuthProviderInstructions/useOAuthProviderSelect.ts b/docs/components/OAuthProviderInstructions/useOAuthProviderSelect.ts deleted file mode 100644 index 97d5072861..0000000000 --- a/docs/components/OAuthProviderInstructions/useOAuthProviderSelect.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { useState } from "react" -import manifest from "@/data/manifest.json" - -const providerList = Object.entries(manifest.providersOAuth).map( - ([id, name]) => { - return { id, name } - } -) - -export function useOAuthProviderSelect() { - const [term, setTerm] = useState("") - const [selected, setSelected] = useState("") - - function handleSearchItem(term: string) { - setTerm(term) - } - - function handleSelectOption(item: { id: string; name: string }) { - setTerm(item.name) - setSelected(item.id) - } - - return { - items: providerList.filter((item) => - item.name.toLowerCase().includes(term?.toLowerCase()) - ), - term, - selected, - handleSearchItem, - handleSelectOption, - } -} diff --git a/docs/components/SearchBarProviders/PreviewProviders.tsx b/docs/components/SearchBarProviders/PreviewProviders.tsx new file mode 100644 index 0000000000..d1fdfdb0f2 --- /dev/null +++ b/docs/components/SearchBarProviders/PreviewProviders.tsx @@ -0,0 +1,35 @@ +export interface Provider { + id: string + name: string +} + +export interface PreviewProvidersProps { + className?: string + providers: Provider[] + onSelected: (provider: Provider) => void +} + +export function PreviewProviders({ + className, + providers, + onSelected, +}: PreviewProvidersProps) { + return ( +

    + {providers.map((provider) => ( +
    onSelected(provider)} + > + +
    {provider.name}
    +
    + ))} +
    + ) +} diff --git a/docs/hooks/use-select-combobox.ts b/docs/hooks/use-select-combobox.ts new file mode 100644 index 0000000000..b8ee43a0dc --- /dev/null +++ b/docs/hooks/use-select-combobox.ts @@ -0,0 +1,48 @@ +import { ChangeEvent, useState } from "react" + +interface SelectComboboxValue { + id: string + name: string +} + +interface SelectComboboxProps { + defaultValue?: SelectComboboxValue + items: SelectComboboxValue[] +} + +export const useSelectCombobox = ({ + defaultValue = { id: "", name: "" }, + items, +}: SelectComboboxProps) => { + const [selectedItem, setSelectedItem] = + useState(defaultValue) + const [filteredItems, setFilteredItems] = useState(items) + const [hasMatchItem, setHasMatchItem] = useState(false) + + const handleSelect = (value: SelectComboboxValue) => { + let hasMatchItem = false + setFilteredItems( + items.filter((item) => { + if (item.id === value.id) { + hasMatchItem = true + } + return item.name.toLowerCase().includes(value.name.toLowerCase()) + }) + ) + setSelectedItem(value) + setHasMatchItem(hasMatchItem) + } + + const handleChange = (event: ChangeEvent) => { + const { value } = event.target + handleSelect({ id: value, name: value }) + } + + return { + selectedItem, + filteredItems, + handleSelect, + handleChange, + hasMatchItem, + } +} diff --git a/docs/package.json b/docs/package.json index 3e97446a33..75b2da8a8b 100644 --- a/docs/package.json +++ b/docs/package.json @@ -36,8 +36,8 @@ "framer-motion": "^11.11.8", "next": "14.2.15", "next-sitemap": "^4.2.3", - "nextra": "3.0.0-alpha.24", - "nextra-theme-docs": "3.0.0-alpha.24", + "nextra": "3.0.15", + "nextra-theme-docs": "3.0.15", "react": "18.3.1", "react-dom": "18.3.1", "react-instantsearch": "^7.13.3", diff --git a/docs/pages/data/manifest.json b/docs/pages/data/manifest.json index bbeb72499f..b9bba6f916 100644 --- a/docs/pages/data/manifest.json +++ b/docs/pages/data/manifest.json @@ -62,7 +62,7 @@ "box": "Box", "boxyhq-saml": "BoxyHQ SAML", "bungie": "Bungie", - "clickup": "ClickUp", + "click-up": "ClickUp", "cognito": "Cognito", "coinbase": "Coinbase", "descope": "Descope", diff --git a/docs/pages/getting-started/adapters/drizzle.mdx b/docs/pages/getting-started/adapters/drizzle.mdx index 84ed30eeda..95a440a543 100644 --- a/docs/pages/getting-started/adapters/drizzle.mdx +++ b/docs/pages/getting-started/adapters/drizzle.mdx @@ -34,8 +34,8 @@ To use this adapter, you must have setup Drizzle ORM and Drizzle Kit in your pro 1. Create your schema file, based off of one of the ones below. 2. Install a supported database driver to your project, like `@libsql/client`, `mysql2` or `postgres`. 3. Create a `drizzle.config.ts` [file](https://orm.drizzle.team/kit-docs/conf). -4. Generate the initial migration from your schema file with a command like, `drizzle-kit generate:pg`. -5. Apply migrations by using `migrate()` function or push changes directly to your database with a command like, `drizzle-kit push:pg`. +4. Generate the initial migration from your schema file with a command like, `drizzle-kit generate`. +5. Apply migrations by using `migrate()` function or push changes directly to your database with a command like, `drizzle-kit push`. 6. If your schemas differ from the default ones, pass them as the second parameter to the adapter. #### Schemas @@ -89,12 +89,14 @@ export const accounts = pgTable( id_token: text("id_token"), session_state: text("session_state"), }, - (account) => ({ - compoundKey: primaryKey({ - columns: [account.provider, account.providerAccountId], - }), - }) -) + (account) => [ + { + compoundKey: primaryKey({ + columns: [account.provider, account.providerAccountId], + }), + }, + ], +); export const sessions = pgTable("session", { sessionToken: text("sessionToken").primaryKey(), @@ -111,12 +113,14 @@ export const verificationTokens = pgTable( token: text("token").notNull(), expires: timestamp("expires", { mode: "date" }).notNull(), }, - (verificationToken) => ({ - compositePk: primaryKey({ - columns: [verificationToken.identifier, verificationToken.token], - }), - }) -) + (verificationToken) => [ + { + compositePk: primaryKey({ + columns: [verificationToken.identifier, verificationToken.token], + }), + }, + ], +); export const authenticators = pgTable( "authenticator", @@ -132,12 +136,14 @@ export const authenticators = pgTable( credentialBackedUp: boolean("credentialBackedUp").notNull(), transports: text("transports"), }, - (authenticator) => ({ - compositePK: primaryKey({ - columns: [authenticator.userId, authenticator.credentialID], - }), - }) -) + (authenticator) => [ + { + compositePK: primaryKey({ + columns: [authenticator.userId, authenticator.credentialID], + }), + }, + ], +); ``` diff --git a/docs/pages/getting-started/adapters/prisma.mdx b/docs/pages/getting-started/adapters/prisma.mdx index ece278073e..2c79e7bf9e 100644 --- a/docs/pages/getting-started/adapters/prisma.mdx +++ b/docs/pages/getting-started/adapters/prisma.mdx @@ -523,7 +523,7 @@ This will create an SQL migration file and execute it: npm exec prisma migrate dev ``` -Note that you will need to specify your database connection string in the environment variable `DATABASE_URL`. You can do this by setting it in a `.env` file at the root of your project. Note Prisma doesn't support `.env.local` syntax, it must be named `.env`. For more information, check out their [environment variables docs](https://www.prisma.io/docs/orm/more/development-environment/environment-variables/using-multiple-env-files). +Note that you will need to specify your database connection string in the environment variable `DATABASE_URL`. You can do this by setting it in a `.env` file at the root of your project. ### Generate Prisma Client diff --git a/docs/pages/getting-started/authentication/credentials.mdx b/docs/pages/getting-started/authentication/credentials.mdx index dec604d2ae..a30b4fe5f0 100644 --- a/docs/pages/getting-started/authentication/credentials.mdx +++ b/docs/pages/getting-started/authentication/credentials.mdx @@ -7,7 +7,29 @@ import { Code } from "@/components/Code" # Credentials -To setup Auth.js with external authentication mechanisms or simply use username and password, we need to use the `Credentials` provider. This provider is designed to forward any credentials inserted into the login form (i.e. username/password) to your authentication service via the `authorize` callback on the provider configuration. +To setup Auth.js with any external authentication mechanisms or use a traditional username/email and password flow, we can use the `Credentials` provider. This provider is designed to forward any credentials inserted into the login form (i.e. username/password, but not limited to) to your authentication service. + + + The industry has come a long way since usernames and passwords + as the go-to mechanism for authenticating and authorizing users to + web applications. Therefore, if possible, we recommend a more modern and + secure authentication mechanism such as any of the [OAuth + providers](/getting-started/authentication/oauth), [Email Magic + Links](/getting-started/authentication/email), or [WebAuthn + (Passkeys)](/getting-started/authentication/webauthn) options instead. + +However, we also want to be flexible and support anything +you deem appropriate for your application and use case, +so there are no plans to remove this provider. + + + + + By default, the Credentials provider does not persist data in the database. + However, you can still create and save any data in your database, you just + have to provide the necessary logic, eg. to encrypt passwords, add + rate-limiting, add password reset functionality, etc. + @@ -44,8 +66,8 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ if (!user) { // No user found, so this is their first attempt to login - // meaning this is also the place you could do registration - throw new Error("User not found.") + // Optionally, this is also the place you could do a user registration + throw new Error("Invalid credentials.") } // return user object with their profile data @@ -110,7 +132,9 @@ export const { signIn, signOut, handle } = SvelteKitAuth({ user = await getUserFromDb(credentials.email, pwHash) if (!user) { - throw new Error("User not found.") + // No user found, so this is their first attempt to login + // Optionally, this is also the place you could do a user registration + throw new Error("Invalid credentials.") } // return JSON object with the user data @@ -161,8 +185,8 @@ app.use( if (!user) { // No user found, so this is their first attempt to login - // meaning this is also the place you could do registration - throw new Error("User not found.") + // Optionally, this is also the place you could do a user registration + throw new Error("Invalid credentials.") } // return user object with the their profile data @@ -301,19 +325,47 @@ export default component$(() => { ``` + + + +```html filename="views/signin.html" + + + + + + Sign In + + +

    Sign In

    +
    + + +
    + + +
    + +
    + + +``` + +
    +
    -## Verifying Data with Zod +## Validating credentials -To improve the security of your `Credentials` provider use, we can leverage a run-time schema validation library like [Zod](https://zod.dev) to validate that the inputs match what we expect. +Always validate the credentials server-side, i.e. by leveraging a schema validation library like [Zod](https://zod.dev). ```bash npm2yarn npm install zod ``` -Next, we'll setup the schema and parsing in our `auth.ts` configuration file, using the `authorize` callback on the `Credentials` provider. +Next, we'll set up the schema and parsing in our `auth.ts` configuration file, using the `authorize` callback on the `Credentials` provider. @@ -363,7 +415,7 @@ export const { handlers, auth } = NextAuth({ user = await getUserFromDb(email, pwHash) if (!user) { - throw new Error("User not found.") + throw new Error("Invalid credentials.") } // return JSON object with the user data @@ -470,7 +522,7 @@ export const { handle } = SvelteKitAuth({ user = await getUserFromDb(email, pwHash) if (!user) { - throw new Error("User not found.") + throw new Error("Invalid credentials.") } // return JSON object with the user data @@ -489,24 +541,3 @@ export const { handle } = SvelteKitAuth({ - - - The industry has come a long way since usernames and passwords were first - introduced as the go-to mechanism for authenticating and authorizing users to - web applications. Therefore, if possible, we recommend a more modern and - secure authentication mechanism such as any of the [OAuth - providers](/getting-started/authentication/oauth), [Email Magic - Links](/getting-started/authentication/email), or [WebAuthn - (Passkeys)](/getting-started/authentication/webauthn) options instead of - username / password. - -However, we also want to be flexible and support anything -you deem appropriate for your application and use-case. - - - - - The Credentials provider only supports the JWT session strategy. You can still - create and save a database session and reference it from the JWT via an id, - but you'll need to provide that logic yourself. - diff --git a/docs/pages/getting-started/authentication/email.mdx b/docs/pages/getting-started/authentication/email.mdx index 81731d714a..ce51246686 100644 --- a/docs/pages/getting-started/authentication/email.mdx +++ b/docs/pages/getting-started/authentication/email.mdx @@ -72,6 +72,14 @@ This login mechanism starts by the user providing their email address at the log >
    Postmark
    + + + +
    Loops
    + + +### Loops Setup + + + +### Database Adapter + +Please make sure you've [setup a database adapter](/getting-started/database), as mentioned earlier, +a database is required for passwordless login to work as verification tokens need to be stored. + +### Create your Transactional Email Template on Loops + +Loops have provided a super handy [guide](https://loops.so/docs/transactional/guide) to help you get started with creating your transactional email template. +This provider only passes one data varaiable into the template, `url` which is the magic link to sign in. This is case sensitive, so make sure you use `url` in your template.
    +On the last page of Template creation, you'll need to copy the `TRANSACTIONAL ID`. If you skipped this step, don't worry, you can get this at any from the Template edit page. + +### Create an API Key on Loops + +You'll need to create an API key to authenticate with Loops. This key should be kept secret and not shared with anyone. +You can Generate a key by going to the [API Settings Page](https://app.loops.so/settings?page=api) and clicking Generate. +You should name the key something that makes sense to you, like "Auth.js". + +### Setup Environment Variables + +To implement Loops, you need to set up the following environment variables. You should have these from the previous steps. + +```bash filename=".env" +AUTH_LOOPS_KEY=abc123 +AUTH_LOOPS_TRANSACTIONAL_ID=def456 +``` + +### Setup Provider + +Let's enable `Loops` as a sign-in option for our Auth.js configuration. You'll have to import the `Loops` provider from the package and pass it to the providers array we set up earlier in the Auth.js config file: + + + + +```ts filename="./auth.ts" +import NextAuth from "next-auth" +import Loops from "next-auth/providers/loops" + +export const { handlers, auth, signIn, signOut } = NextAuth({ + providers: [ + Loops({ + apiKey: process.env.AUTH_LOOPS_KEY, + transactionalId: process.env.AUTH_LOOPS_TRANSACTIONAL_ID, + }), + ], +}) +``` + + + + +```ts filename="./src/auth.ts" +import SvelteKitAuth from "@auth/sveltekit" +import Loops from "@auth/sveltekit/providers/loops" +import { + AUTH_LOOPS_KEY, + AUTH_LOOPS_TRANSACTIONAL_ID, +} from "$env/static/private" + +export const { handle, signIn, signOut } = SvelteKitAuth({ + providers: [ + Loops({ + apiKey: AUTH_LOOPS_KEY, + transactionalId: AUTH_LOOPS_TRANSACTIONAL_ID, + }), + ], +}) +``` + +```ts filename="./src/hooks.server.ts" +export { handle } from "./auth" +``` + + + + +### Add Signin Button + +Next, we add a signin button somewhere in your application like the Navbar. This will send an email to the user containing the magic link to sign in. + + + + +```tsx filename="./components/sign-in.tsx" +import { signIn } from "../../auth.ts" + +export function SignIn() { + return ( +
    { + "use server" + await signIn("loops", formData) + }} + > + + +
    + ) +} +``` + +
    + + +```ts filename="src/routes/+page.svelte" + + + +
    + +
    + +``` + +
    +
    + +### Signin + +Start your application, click on the signin button we just added, and you should see Auth.js built-in sign in page with the option to sign in with your email. +A user can enter their email, click "Sign in with Loops", and receive their beautifully formatted signin email. +Clicking on the link in the email will redirect the user to your application, landing already authenticated! + +
    - +
    diff --git a/docs/pages/getting-started/database.mdx b/docs/pages/getting-started/database.mdx index af9d69a8da..b23aa3450c 100644 --- a/docs/pages/getting-started/database.mdx +++ b/docs/pages/getting-started/database.mdx @@ -11,7 +11,7 @@ import manifest from "@/data/manifest.json" use a Database Adapter. -**Database Adapters** are the bridge we use to connect Auth.js to your database. For instance, [when implementing magic links](/getting-started/authentication/email), the Email provider will require you to setup a database adapter to be able to store the [verification tokens](/concepts/database-models#verificationtoken-model) present on the links. +**Database Adapters** are the bridge we use to connect Auth.js to your database. For instance, [when implementing magic links](/getting-started/authentication/email), the Email provider will require you to setup a database adapter to be able to store the [verification tokens](/concepts/database-models#verificationtoken) present on the links. ## Official Adapters @@ -43,7 +43,7 @@ monorepo](https://github.com/nextauthjs/next-auth/tree/main/packages). If you're ## Models -This is a generic ER Diagram of what the full database schema should look like. Your database adapter of choice will include a template schema with more details for applying this schema to the underlying database. For more details, check out our [database models](/concepts/database-models) documentation. Please note, that the entire schema is not required for every use-case, for more details check out out our [database adapters guide](/guides/creating-a-database-adapter). +This is a generic ER Diagram of what the full database schema should look like. Your database adapter of choice will include a template schema with more details for applying this schema to the underlying database. For more details, check out our [database models](/concepts/database-models) documentation. Please note, that the entire schema is not required for every use-case, for more details check out our [database adapters guide](/guides/creating-a-database-adapter). ```mermaid %%{init: {'theme':'neutral'}}%% diff --git a/docs/pages/getting-started/deployment.mdx b/docs/pages/getting-started/deployment.mdx index c457c3099e..bcfe4f3031 100644 --- a/docs/pages/getting-started/deployment.mdx +++ b/docs/pages/getting-started/deployment.mdx @@ -49,6 +49,8 @@ This environment variable is mostly unnecessary with v5 as the host is inferred ### `AUTH_REDIRECT_PROXY_URL` +> **_NOTE:_** Some providers (eg Apple) do not support [redirect proxy](https://github.com/nextauthjs/next-auth/blob/3ec06842682a31e53fceabca701a362abda1e7dd/packages/core/src/lib/utils/providers.ts#L48) usage. + This environment variable is designed for advanced use-cases only, when using Auth.js as a proxy for preview deploys, for example. For more details, see the [securing preview deploys](#securing-a-preview-deployment) section below. ## Serverless @@ -163,12 +165,14 @@ CMD ["node", "server.js"] ## Securing a preview deployment +> **_NOTE:_** Some providers (eg Apple) do not support [redirect proxy](https://github.com/nextauthjs/next-auth/blob/3ec06842682a31e53fceabca701a362abda1e7dd/packages/core/src/lib/utils/providers.ts#L48) usage. + Most OAuth providers cannot be configured with multiple callback URLs or using a wildcard. -However, Auth.js **supports Preview deployments**, even **with OAuth providers**. The idea is to have one deployment which proxies authentication requests to the dynamic URLs of your main application. So you could have 1 stable deployment, like at `auth.company.com` where you would point all your OAuth provider's `callbackUrl`s, and this application would then, upon successful authentication, redirect the user back to the preview deploy URL, like `https://git-abc123-myapp.vercel.app`. Follow these steps to get started with securing preview deploys with Auth.js. +However, Auth.js **supports Preview deployments**, even **with most OAuth providers**. The idea is to have one deployment which proxies authentication requests to the dynamic URLs of your main application. So you could have 1 stable deployment, like at `auth.company.com` where you would point all your OAuth provider's `callbackUrl`s, and this application would then, upon successful authentication, redirect the user back to the preview deploy URL, like `https://git-abc123-myapp.vercel.app`. Follow these steps to get started with securing preview deploys with Auth.js. 1. Determine a stable deployment URL. For example, a deployment whose URL does not change between builds, for example. `auth.yourdomain.com` (using a subdomain is not a requirement, this can be the main site's URL too, for example.) -2. Set `AUTH_REDIRECT_PROXY_URL` to that stable deployment URL, including the path from where Auth.js handles the routes. Eg.: (`https://auth.yourdomain.com/api/auth`) +2. In **both the preview and stable environment**, set `AUTH_REDIRECT_PROXY_URL` to that stable deployment URL, including the path from where Auth.js handles the routes. Eg.: (`https://auth.yourdomain.com/api/auth`). If the variable is not set in the stable environment, the proxy functionality will not be enabled! 3. Update the `callbackUrl` in your OAuth provider's configuration to use the stable deployment URL. For example, for GitHub it would be `https://auth.yourdomain.com/api/auth/callback/github`. Fun fact: all of our example apps are using the proxy functionality! diff --git a/docs/pages/getting-started/index.mdx b/docs/pages/getting-started/index.mdx index 874efb1b4d..ceee02642a 100644 --- a/docs/pages/getting-started/index.mdx +++ b/docs/pages/getting-started/index.mdx @@ -51,7 +51,7 @@ Select your framework of choice to get started, or view the example application
    -Check the [integrations page](/getting-started/integrations) for all supported packages. We are working on supporting more frameworks, but you can create own or +Check the [integrations page](/getting-started/integrations) for all supported packages. We are working on supporting more frameworks, but you can create your own or help us create one for your favorite framework. diff --git a/docs/pages/getting-started/providers/apple.mdx b/docs/pages/getting-started/providers/apple.mdx index 7d2a2d5377..e881ad717a 100644 --- a/docs/pages/getting-started/providers/apple.mdx +++ b/docs/pages/getting-started/providers/apple.mdx @@ -10,6 +10,8 @@ import { Code } from "@/components/Code" - Sign in with Apple [REST API](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api) - [How to retrieve](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773) the user's information from Apple ID servers +> **_NOTE:_** Apple currently does not support [RedirectProxyUrl](https://github.com/nextauthjs/next-auth/blob/3ec06842682a31e53fceabca701a362abda1e7dd/packages/core/src/lib/utils/providers.ts#L48) usage. + ## Setup ### Callback URL diff --git a/docs/pages/getting-started/providers/asgardeo.mdx b/docs/pages/getting-started/providers/asgardeo.mdx index 2fb17b0c3c..b3ce1767e7 100644 --- a/docs/pages/getting-started/providers/asgardeo.mdx +++ b/docs/pages/getting-started/providers/asgardeo.mdx @@ -42,6 +42,7 @@ https://example.com/auth/callback/asgardeo ``` AUTH_ASGARDEO_ID AUTH_ASGARDEO_SECRET +AUTH_ASGARDEO_ISSUER ``` ### Configuration diff --git a/docs/pages/getting-started/providers/frontegg.mdx b/docs/pages/getting-started/providers/frontegg.mdx new file mode 100644 index 0000000000..a9bb2c9907 --- /dev/null +++ b/docs/pages/getting-started/providers/frontegg.mdx @@ -0,0 +1,93 @@ +import { Callout } from "nextra/components" +import { Code } from "@/components/Code" + + + +# Frontegg Provider + +## Resources + +- [Frontegg documentation](https://docs.frontegg.com/docs/how-to-use-our-docs) + +## Setup + +### Callback URL + + + + + ```bash + https://example.com/api/auth/callback/frontegg + ``` + + + + + ```bash + https://example.com/auth/callback/frontegg + ``` + + + + +### Environment Variables + +``` +AUTH_FRONTEGG_ID +AUTH_FRONTEGG_SECRET +AUTH_FRONTEGG_ISSUER +``` + +### Configuration + +Follow these steps: + +Log into the [Frontegg portal](https://portal.frontegg.com) + +Add the required environment variables to your `.env.local` file. + +``` +# Environments > Your environment > Env settings +AUTH_FRONTEGG_ID="" +# Environments > Your environment > Env settings +AUTH_FRONTEGG_SECRET="" +# Environments > Your environment > Env settings > Domains > Domain name +AUTH_FRONTEGG_ISSUER="" +``` + + + + +```ts filename="/auth.ts" +import NextAuth from "next-auth" +import Frontegg from "next-auth/providers/frontegg" + +export const { handlers, auth, signIn, signOut } = NextAuth({ + providers: [Frontegg], +}) +``` + + + + +```ts filename="/src/auth.ts" +import { SvelteKitAuth } from "@auth/sveltekit" +import Frontegg from "@auth/sveltekit/providers/frontegg" + +export const { handle, signIn, signOut } = SvelteKitAuth({ + providers: [Frontegg], +}) +``` + + + + +```ts filename="/src/app.ts" +import { ExpressAuth } from "@auth/express" +import Frontegg from "@auth/express/providers/frontegg" + +app.use("/auth/*", ExpressAuth({ providers: [Frontegg] })) +``` + + + diff --git a/docs/pages/getting-started/providers/loops.mdx b/docs/pages/getting-started/providers/loops.mdx new file mode 100644 index 0000000000..77a5672f38 --- /dev/null +++ b/docs/pages/getting-started/providers/loops.mdx @@ -0,0 +1,103 @@ +import { Callout } from "nextra/components" +import { Code } from "@/components/Code" + + + +# Loops Provider + +## Overview + +The Loops provider uses email to send "magic links" that contain URLs with verification tokens can be used to sign in. + +Adding support for signing in via email in addition to one or more OAuth services provides a way for users to sign in if they lose access to their OAuth account (e.g. if it is locked or deleted). + +The Loops provider can be used in conjunction with (or instead of) one or more OAuth providers. + +## How it works + +On initial sign in, a **Verification Token** is sent to the email address provided. By default this token is valid for 24 hours. If the Verification Token is used within that time (i.e. by clicking on the link in the email) an account is created for the user and they are signed in. + +If someone provides the email address of an _existing account_ when signing in, an email is sent and they are signed into the account associated with that email address when they follow the link in the email. + + + The Loops provider can be used with both JSON Web Token and database managed + sessions, however **you must configure a database** to use it. It is not + possible to enable email sign in without using a database. + + +## Configuration + +### Add and Verify your Domain on Loops + +First, you'll need to have completed the steps covered in the ['Start here'](https://loops.so/docs/start-here) Loops documentation. +The main thing required is to [set up your domain records](https://loops.so/docs/start-here#1-set-up-your-domain-records). + +### Generate an API Key + +Next, you will have to generate an API key in the [Loops Dashboard](https://loops.so/api-keys). You can save this API key as the `AUTH_LOOPS_KEY` environment variable. + +```sh +AUTH_LOOPS_KEY=abc +``` + +### Create a Transactional Email Template on Loops + +The easiest way to achieve this is using the [Loops email editor](https://loops.so/docs/creating-emails/editor) to create a transactional email template. +If you're new to Loops, you can find rich documentation [here](https://loops.so/docs/transactional/guide). + +
    +Copy the Transactional ID value from the last page of the template creation +process, and save this as the `AUTH_LOOPS_TRANSACTIONAL_ID` environment +variable. If you're following these steps, you should now have two environment +variables set up for Loops. + +```sh +AUTH_LOOPS_KEY=abc +AUTH_LOOPS_TRANSACTIONAL_ID=def +``` + + + When creating your email template, make sure to include the `url` variable in + the template. This is the URL that will sent to the user, allowing them to + signin. + + + + +### Configure AuthJS with the Loops Provider +```ts filename="./auth.ts" +import NextAuth from "next-auth" +import Loops from "next-auth/providers/loops" + +export const { handlers, auth, signIn, signOut } = NextAuth({ + adapter: ..., // database adapter of your choosing + providers: [ + Loops({ + apiKey: process.env.AUTH_LOOPS_KEY, + transactionalId: process.env.AUTH_LOOPS_TRANSACTIONAL_ID, + }), + ], +}) +``` + + + +### Configure AuthJS with the Loops Provider +```ts filename="./src/auth.ts" +import { SvelteKitAuth } from "@auth/sveltekit" +import Loops from "@auth/sveltekit/providers/loops" +import { AUTH_LOOPS_KEY, AUTH_LOOPS_TRANSACTIONAL_ID } from "@env/static/private" + +export const { handle, signIn, signOut } = SvelteKitAuth({ + adapter: ..., // database adapter of your choosing + providers: [ + Loops({ + apiKey: AUTH_LOOPS_KEY, + transactionalId: AUTH_LOOPS_TRANSACTIONAL_ID, + }), + ], +}) +``` + + + diff --git a/docs/pages/getting-started/providers/microsoft-entra-id.mdx b/docs/pages/getting-started/providers/microsoft-entra-id.mdx index 65307b1248..b50db46ca2 100644 --- a/docs/pages/getting-started/providers/microsoft-entra-id.mdx +++ b/docs/pages/getting-started/providers/microsoft-entra-id.mdx @@ -54,7 +54,7 @@ https://example.com/auth/callback/microsoft-entra-id ``` AUTH_MICROSOFT_ENTRA_ID_ID AUTH_MICROSOFT_ENTRA_ID_SECRET -AUTH_MICROSOFT_ENTRA_ID_TENANT_ID +AUTH_MICROSOFT_ENTRA_ID_ISSUER ``` ### Configuration @@ -71,7 +71,7 @@ const { handlers, auth, signIn, signOut } = NextAuth({ MicrosoftEntraID({ clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID, clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET, - tenantId: process.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID, + issuer: process.env.AUTH_MICROSOFT_ENTRA_ID_ISSUER, }), ], }) @@ -90,7 +90,7 @@ export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$( Entra({ clientId: import.meta.env.AUTH_MICROSOFT_ENTRA_ID_ID, clientSecret: import.meta.env.AUTH_MICROSOFT_ENTRA_ID_SECRET, - tenantId: import.meta.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID, + issuer: import.meta.env.AUTH_MICROSOFT_ENTRA_ID_ISSUER, }), ], }) @@ -110,7 +110,7 @@ export const { handle, signIn, signOut } = SvelteKitAuth({ Entra({ clientId: env.AUTH_MICROSOFT_ENTRA_ID_ID, clientSecret: env.AUTH_MICROSOFT_ENTRA_ID_SECRET, - tenantId: process.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID, + issuer: process.env.AUTH_MICROSOFT_ENTRA_ID_ISSUER, }), ], }) @@ -130,7 +130,7 @@ app.use( Entra({ clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID, clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET, - tenantId: process.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID, + issuer: process.env.AUTH_MICROSOFT_ENTRA_ID_ISSUER, }), ], }) @@ -153,15 +153,15 @@ app.use( - After your App Registration is created, under "Client Credential" create your Client secret. - Now copy your: - Application (client) ID - - Directory (tenant) ID - Client secret (value) + - Issuer In `.env.local` create the following entries: ``` AUTH_MICROSOFT_ENTRA_ID_ID= AUTH_MICROSOFT_ENTRA_ID_SECRET= -AUTH_MICROSOFT_ENTRA_ID_TENANT_ID= +AUTH_MICROSOFT_ENTRA_ID_ISSUER= ``` That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints). diff --git a/docs/pages/getting-started/providers/vipps-mobilepay.mdx b/docs/pages/getting-started/providers/vipps-mobilepay.mdx new file mode 100644 index 0000000000..700cd0d693 --- /dev/null +++ b/docs/pages/getting-started/providers/vipps-mobilepay.mdx @@ -0,0 +1,119 @@ +--- +title: Vipps MobilePay +--- + +import { Code } from "@/components/Code" + + + +# Vipps MobilePay Provider + +[Vipps MobilePay](https://vippsmobilepay.com/) is a widespread mobile payment application for mobile in Norway, Sweden, Denmark and Finland. The brand is split, where you have Vipps in Norway and Sweden, and MobilePay in Denmark and Finland, but both brands/apps are using the same API. + +## Resources + +- [Vipps MobilePay login documentation](https://developer.vippsmobilepay.com/docs/APIs/login-api/) +- [Official Vipps MobilePay Buttons](https://developer.vippsmobilepay.com/docs/knowledge-base/design-guidelines/buttons/) +- [Vipps MobilePay Public Testing discovery endpoint](https://apitest.vipps.no/access-management-1.0/access/.well-known/openid-configuration) +- [Vipps MobilePay Public Production discovery endpoint](https://api.vipps.no/access-management-1.0/access/.well-known/openid-configuration) + +## Setup + +### Callback URL + + + + +```bash +https://example.com/api/auth/callback/vipps +``` + + + + +```bash +https://example.com/auth/callback/vipps +``` + + + + +```bash +https://example.com/auth/callback/vipps +``` + + + + +### Environment Variables + +``` +AUTH_VIPPS_ID +AUTH_VIPPS_SECRET +``` + +### Test API + +To use the test mode, you need to override the issuer with the test API endpoint. + +``` +Vipps({ issuer: "https://apitest.vipps.no/access-management-1.0/access/" }) +``` + +### Configuration + + + + +```ts filename="/auth.ts" +import NextAuth from "next-auth" +import Vipps from "next-auth/providers/vipps" + +export const { handlers, auth, signIn, signOut } = NextAuth({ + providers: [Vipps], +}) +``` + + + + +```ts filename="/src/routes/plugin@auth.ts" +import { QwikAuth$ } from "@auth/qwik" +import Vipps from "@auth/qwik/providers/vipps" + +export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$( + () => ({ + providers: [Vipps], + }) +) +``` + + + + +```ts filename="/src/auth.ts" +import { SvelteKitAuth } from "@auth/sveltekit" +import Vipps from "@auth/sveltekit/providers/vipps" + +export const { handle, signIn, signOut } = SvelteKitAuth({ + providers: [Vipps], +}) +``` + + + + +```ts filename="/src/app.ts" +import { ExpressAuth } from "@auth/express" +import Vipps from "@auth/express/providers/vipps" + +app.use("/auth/*", ExpressAuth({ providers: [Vipps] })) +``` + + + diff --git a/docs/pages/getting-started/session-management/get-session.mdx b/docs/pages/getting-started/session-management/get-session.mdx index 392b08235a..85909f365f 100644 --- a/docs/pages/getting-started/session-management/get-session.mdx +++ b/docs/pages/getting-started/session-management/get-session.mdx @@ -14,7 +14,7 @@ import { auth } from "../auth" export default async function UserAvatar() { const session = await auth() - if (!session.user) return null + if (!session?.user) return null return (
    diff --git a/docs/pages/getting-started/session-management/login.mdx b/docs/pages/getting-started/session-management/login.mdx index 91fbf04442..4d0f7b5fe6 100644 --- a/docs/pages/getting-started/session-management/login.mdx +++ b/docs/pages/getting-started/session-management/login.mdx @@ -129,8 +129,47 @@ Just like in other frameworks, you can also pass a provider to the `signIn` func + The Express package runs server-side and therefore it doesn't make sense to create a "SignIn button component". However, to signin or signout with Express, send a request to the appropriate [REST API Endpoints](/reference/core/types#authaction) from your client (i.e. `/auth/signin`, `/auth/signout`, etc.). +To sign in users with Express, you can create a route that handles the sign-in logic. Here is an example: + +```js filename="src/routes/auth.js" +const express = require("express") +const router = express.Router() +const { signIn } = require("../auth") + +router.post("/auth/signin", async (req, res) => { + try { + await signIn(req, res) + res.redirect("/dashboard") + } catch (error) { + res.status(500).send("Sign in failed") + } +}) + +module.exports = router +``` + +To sign out users with Express, you can create a route that handles the sign-out logic. Here is an example: + +```js filename="src/routes/auth.js" +const express = require("express") +const router = express.Router() +const { signOut } = require("../auth") + +router.post("/auth/signout", async (req, res) => { + try { + await signOut(req, res) + res.redirect("/") + } catch (error) { + res.status(500).send("Sign out failed") + } +}) + +module.exports = router +``` + @@ -352,6 +391,44 @@ Client-side is a bit simpler as we just need to import a button `on:click` handl The Express package runs server-side and therefore it doesn't make sense to create a "SignIn button component". However, to signin or signout with Express, send a request to the appropriate [REST API Endpoints](/reference/core/types#authaction) from your client (i.e. `/auth/signin`, `/auth/signout`, etc.). +To sign in users with Express, you can create a route that handles the sign-in logic. Here is an example: + +```js filename="src/routes/auth.js" +const express = require("express") +const router = express.Router() +const { signIn } = require("../auth") + +router.post("/auth/signin", async (req, res) => { + try { + await signIn(req, res) + res.redirect("/dashboard") + } catch (error) { + res.status(500).send("Sign in failed") + } +}) + +module.exports = router +``` + +To sign out users with Express, you can create a route that handles the sign-out logic. Here is an example: + +```js filename="src/routes/auth.js" +const express = require("express") +const router = express.Router() +const { signOut } = require("../auth") + +router.post("/auth/signout", async (req, res) => { + try { + await signOut(req, res) + res.redirect("/") + } catch (error) { + res.status(500).send("Sign out failed") + } +}) + +module.exports = router +``` + diff --git a/docs/pages/global.css b/docs/pages/global.css index 419d63f812..fd5200cff4 100644 --- a/docs/pages/global.css +++ b/docs/pages/global.css @@ -7,6 +7,24 @@ details > *:not(summary) { @apply p-4; } +html[class~="dark"] + :is( + img[src$="42-school.svg"], + img[src$="apple.svg"], + img[src$="boxyhq-saml.svg"], + img[src$="eveonline.svg"], + img[src$="github.svg"], + img[src$="hasura.svg"], + img[src$="mailchimp.svg"], + img[src$="medium.svg"], + img[src$="okta.svg"], + img[src$="prisma.svg"], + img[src$="threads.svg"], + img[src$="wikimedia.svg"] + ) { + filter: invert(1); +} + :is(html[class~="dark"]) ::selection { @apply bg-purple-500/40; } @@ -247,3 +265,17 @@ div.nextra-search kbd { opacity: 0; } } + +:is(html[class~="dark"]) + > head:has(meta[content*="reference/core/providers"]) + + body + .provider { + color: #e2e8f0 !important; + background-color: transparent !important; +} + +html > head:has(meta[content*="reference/core/providers"]) + body .provider { + padding: 1rem; + font-size: 1rem; + color: #000 !important; +} diff --git a/docs/pages/guides/edge-compatibility.mdx b/docs/pages/guides/edge-compatibility.mdx index f2e489bfd5..4ae65343cb 100644 --- a/docs/pages/guides/edge-compatibility.mdx +++ b/docs/pages/guides/edge-compatibility.mdx @@ -108,7 +108,7 @@ export default async function Page() { return (
    -
    {session}
    +
    {JSON.stringify(session, null, 2)}
    ) } diff --git a/docs/pages/guides/refresh-token-rotation.mdx b/docs/pages/guides/refresh-token-rotation.mdx index 0fb1af5b52..71c60ded67 100644 --- a/docs/pages/guides/refresh-token-rotation.mdx +++ b/docs/pages/guides/refresh-token-rotation.mdx @@ -102,14 +102,15 @@ export const { handlers, auth } = NextAuth({ refresh_token?: string } - token.access_token = newTokens.access_token - token.expires_at = Math.floor( - Date.now() / 1000 + newTokens.expires_in - ) - // Some providers only issue refresh tokens once, so preserve if we did not get a new one - if (newTokens.refresh_token) - token.refresh_token = newTokens.refresh_token - return token + return { + ...token, + access_token: newTokens.access_token, + expires_at: Math.floor(Date.now() / 1000 + newTokens.expires_in), + // Some providers only issue refresh tokens once, so preserve if we did not get a new one + refresh_token: newTokens.refresh_token + ? newTokens.refresh_token + : token.refresh_token, + } } catch (error) { console.error("Error refreshing access_token", error) // If we fail to refresh the token, return an error so we can handle it on the page @@ -244,7 +245,7 @@ import { useEffect } from "react" import { auth, signIn } from "@/auth" export default async function Page() { - const session = await useSession() + const session = await auth() if (session?.error === "RefreshTokenError") { await signIn("google") // Force sign in to obtain a new set of access and refresh tokens } @@ -262,7 +263,7 @@ import { useEffect } from "react" import { signIn, useSession } from "next-auth/react" export default function Page() { - const { data: session } = useSession() + const { data: session } = useSession() // For this to work, the Page should be wrapped inside the SessionProvider component in Layout useEffect(() => { if (session?.error !== "RefreshTokenError") return signIn("google") // Force sign in to obtain a new set of access and refresh tokens diff --git a/docs/pages/sponsors.mdx b/docs/pages/sponsors.mdx index 83bb46ac21..4d8e0f4f4b 100644 --- a/docs/pages/sponsors.mdx +++ b/docs/pages/sponsors.mdx @@ -145,6 +145,11 @@ It would not be possible without the generous support of our sponsors. "https://avatars.githubusercontent.com/u/77690634?v=4", "Neon", ], + [ + "https://sent.dm", + "https://avatars.githubusercontent.com/u/153308555?v=4", + "Sent.dm", + ], ].map(([href, src, name]) => ( + + + + diff --git a/docs/public/img/providers/loops.svg b/docs/public/img/providers/loops.svg new file mode 100644 index 0000000000..8f831f634d --- /dev/null +++ b/docs/public/img/providers/loops.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/img/providers/vipps-mobilepay.svg b/docs/public/img/providers/vipps-mobilepay.svg new file mode 100644 index 0000000000..57bded639d --- /dev/null +++ b/docs/public/img/providers/vipps-mobilepay.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tsconfig.json b/docs/tsconfig.json index f509920619..6d428110ce 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -20,7 +20,8 @@ "@/utils/*": ["utils/*"], "@/icons/*": ["components/Icons/*"], "@/icons": ["components/Icons"], - "@/data/*": ["pages/data/*"] + "@/data/*": ["pages/data/*"], + "@/hooks/*": ["hooks/*"] }, "plugins": [ { diff --git a/eslint.config.mjs b/eslint.config.mjs index 5b901f5b8b..0abf1d0ab1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -164,7 +164,7 @@ export default tsEslint.config( "static", "coverage", "dist", - "packages/core/src/providers/oauth-types.ts", + "packages/core/src/providers/provider-types.ts", "packages/core/src/lib/pages/styles.ts", "packages/frameworks-sveltekit/package", "packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*", diff --git a/packages/adapter-azure-tables/package.json b/packages/adapter-azure-tables/package.json index f244666ccd..c80f45864d 100644 --- a/packages/adapter-azure-tables/package.json +++ b/packages/adapter-azure-tables/package.json @@ -1,6 +1,6 @@ { "name": "@auth/azure-tables-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Azure Tables Storage adapter for next-auth.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-d1/package.json b/packages/adapter-d1/package.json index aa57cafc17..ee70221a7b 100644 --- a/packages/adapter-d1/package.json +++ b/packages/adapter-d1/package.json @@ -1,6 +1,6 @@ { "name": "@auth/d1-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "A Cloudflare D1 adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-dgraph/package.json b/packages/adapter-dgraph/package.json index bf218d7c57..f9d38eca0b 100644 --- a/packages/adapter-dgraph/package.json +++ b/packages/adapter-dgraph/package.json @@ -1,6 +1,6 @@ { "name": "@auth/dgraph-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Dgraph adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-drizzle/package.json b/packages/adapter-drizzle/package.json index 20d7c98721..42eb92c69c 100644 --- a/packages/adapter-drizzle/package.json +++ b/packages/adapter-drizzle/package.json @@ -1,6 +1,6 @@ { "name": "@auth/drizzle-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Drizzle adapter for Auth.js.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-drizzle/src/lib/pg.ts b/packages/adapter-drizzle/src/lib/pg.ts index 5a12ded440..37891f5ed9 100644 --- a/packages/adapter-drizzle/src/lib/pg.ts +++ b/packages/adapter-drizzle/src/lib/pg.ts @@ -83,9 +83,9 @@ export function defineTables( token: text("token").notNull(), expires: timestamp("expires", { mode: "date" }).notNull(), }, - (verficationToken) => ({ + (verificationToken) => ({ compositePk: primaryKey({ - columns: [verficationToken.identifier, verficationToken.token], + columns: [verificationToken.identifier, verificationToken.token], }), }) ) satisfies DefaultPostgresVerificationTokenTable) diff --git a/packages/adapter-dynamodb/package.json b/packages/adapter-dynamodb/package.json index 6e5d01dcce..b7c5a44dcc 100644 --- a/packages/adapter-dynamodb/package.json +++ b/packages/adapter-dynamodb/package.json @@ -1,7 +1,7 @@ { "name": "@auth/dynamodb-adapter", "repository": "https://github.com/nextauthjs/next-auth", - "version": "2.7.2", + "version": "2.7.4", "description": "AWS DynamoDB adapter for next-auth.", "keywords": [ "next-auth", diff --git a/packages/adapter-edgedb/package.json b/packages/adapter-edgedb/package.json index 7310d0c933..e268dcf66f 100644 --- a/packages/adapter-edgedb/package.json +++ b/packages/adapter-edgedb/package.json @@ -1,6 +1,6 @@ { "name": "@auth/edgedb-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "EdgeDB adapter for next-auth.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-fauna/package.json b/packages/adapter-fauna/package.json index 36c22e7e9a..695459f6eb 100644 --- a/packages/adapter-fauna/package.json +++ b/packages/adapter-fauna/package.json @@ -1,6 +1,6 @@ { "name": "@auth/fauna-adapter", - "version": "3.7.2", + "version": "3.7.4", "description": "Fauna Adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-firebase/package.json b/packages/adapter-firebase/package.json index 402c94a032..1a7532d7d1 100644 --- a/packages/adapter-firebase/package.json +++ b/packages/adapter-firebase/package.json @@ -1,6 +1,6 @@ { "name": "@auth/firebase-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Firebase adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-hasura/package.json b/packages/adapter-hasura/package.json index 9d4baa3738..31b0336c6f 100644 --- a/packages/adapter-hasura/package.json +++ b/packages/adapter-hasura/package.json @@ -1,6 +1,6 @@ { "name": "@auth/hasura-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Hasura adapter for Auth.js.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-kysely/package.json b/packages/adapter-kysely/package.json index 212788d76f..17376d0f95 100644 --- a/packages/adapter-kysely/package.json +++ b/packages/adapter-kysely/package.json @@ -1,6 +1,6 @@ { "name": "@auth/kysely-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Kysely adapter for Auth.js", "homepage": "https://authjs.dev/reference/adapter/kysely", "repository": "https://github.com/nextauthjs/next-auth", @@ -38,11 +38,11 @@ "@auth/core": "workspace:*" }, "peerDependencies": { - "kysely": "^0.26.1" + "kysely": "^0.27.5" }, "devDependencies": { "@types/pg": "^8.6.5", - "kysely": "^0.24.2", + "kysely": "^0.27.5", "libsql": "^0.3.18", "mysql2": "^3.9.7", "pg": "^8.10.0" diff --git a/packages/adapter-mikro-orm/package.json b/packages/adapter-mikro-orm/package.json index 6210441540..d98ae42b25 100644 --- a/packages/adapter-mikro-orm/package.json +++ b/packages/adapter-mikro-orm/package.json @@ -1,6 +1,6 @@ { "name": "@auth/mikro-orm-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "MikroORM adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-mongodb/package.json b/packages/adapter-mongodb/package.json index d2ae4dca6d..3d9a58c67d 100644 --- a/packages/adapter-mongodb/package.json +++ b/packages/adapter-mongodb/package.json @@ -1,6 +1,6 @@ { "name": "@auth/mongodb-adapter", - "version": "3.7.2", + "version": "3.7.4", "description": "MongoDB adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-neo4j/package.json b/packages/adapter-neo4j/package.json index 4d7eb462d6..def7bfed54 100644 --- a/packages/adapter-neo4j/package.json +++ b/packages/adapter-neo4j/package.json @@ -1,6 +1,6 @@ { "name": "@auth/neo4j-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "neo4j adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-pg/package.json b/packages/adapter-pg/package.json index 865da839eb..c506099d3c 100644 --- a/packages/adapter-pg/package.json +++ b/packages/adapter-pg/package.json @@ -1,6 +1,6 @@ { "name": "@auth/pg-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Postgres adapter for next-auth.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-pouchdb/package.json b/packages/adapter-pouchdb/package.json index 285c1ada7c..7130e31c80 100644 --- a/packages/adapter-pouchdb/package.json +++ b/packages/adapter-pouchdb/package.json @@ -1,6 +1,6 @@ { "name": "@auth/pouchdb-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "PouchDB adapter for next-auth.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-prisma/package.json b/packages/adapter-prisma/package.json index 31fe253db5..4e78bc58ef 100644 --- a/packages/adapter-prisma/package.json +++ b/packages/adapter-prisma/package.json @@ -1,6 +1,6 @@ { "name": "@auth/prisma-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Prisma adapter for Auth.js", "homepage": "https://authjs.dev/reference/adapter/prisma", "repository": "https://github.com/nextauthjs/next-auth", @@ -53,12 +53,12 @@ "@auth/core": "workspace:*" }, "peerDependencies": { - "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5" + "@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5 || >=6" }, "devDependencies": { - "@prisma/client": "^5.20.0", + "@prisma/client": "^6.0.0", "@prisma/extension-accelerate": "1.1.0", "mongodb": "^6.9.0", - "prisma": "^5.20.0" + "prisma": "^6.0.0" } } diff --git a/packages/adapter-prisma/src/index.ts b/packages/adapter-prisma/src/index.ts index 769e5ede55..6daadab176 100644 --- a/packages/adapter-prisma/src/index.ts +++ b/packages/adapter-prisma/src/index.ts @@ -15,7 +15,8 @@ * * @module @auth/prisma-adapter */ -import type { PrismaClient, Prisma } from "@prisma/client" +import { type PrismaClient } from "@prisma/client" +import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library" import type { Adapter, AdapterAccount, @@ -35,7 +36,7 @@ export function PrismaAdapter( async getUserByAccount(provider_providerAccountId) { const account = await p.account.findUnique({ where: { provider_providerAccountId }, - select: { user: true }, + include: { user: true }, }) return (account?.user as AdapterUser) ?? null }, @@ -73,8 +74,8 @@ export function PrismaAdapter( const verificationToken = await p.verificationToken.create( stripUndefined(data) ) - // @ts-expect-errors // MongoDB needs an ID, but we don't - if (verificationToken.id) delete verificationToken.id + if ("id" in verificationToken && verificationToken.id) + delete verificationToken.id return verificationToken }, async useVerificationToken(identifier_token) { @@ -82,13 +83,16 @@ export function PrismaAdapter( const verificationToken = await p.verificationToken.delete({ where: { identifier_token }, }) - // @ts-expect-errors // MongoDB needs an ID, but we don't - if (verificationToken.id) delete verificationToken.id + if ("id" in verificationToken && verificationToken.id) + delete verificationToken.id return verificationToken - } catch (error) { + } catch (error: unknown) { // If token already used/deleted, just return null // https://www.prisma.io/docs/reference/api-reference/error-reference#p2025 - if ((error as Prisma.PrismaClientKnownRequestError).code === "P2025") + if ( + error instanceof PrismaClientKnownRequestError && + error.code === "P2025" + ) return null throw error } diff --git a/packages/adapter-sequelize/package.json b/packages/adapter-sequelize/package.json index aabd267deb..861511e72a 100644 --- a/packages/adapter-sequelize/package.json +++ b/packages/adapter-sequelize/package.json @@ -1,6 +1,6 @@ { "name": "@auth/sequelize-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Sequelize adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-supabase/package.json b/packages/adapter-supabase/package.json index 8d60cbfc37..ee8cc2024c 100644 --- a/packages/adapter-supabase/package.json +++ b/packages/adapter-supabase/package.json @@ -1,6 +1,6 @@ { "name": "@auth/supabase-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Supabase adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-surrealdb/package.json b/packages/adapter-surrealdb/package.json index 9bc51493be..7fa968c888 100644 --- a/packages/adapter-surrealdb/package.json +++ b/packages/adapter-surrealdb/package.json @@ -1,6 +1,6 @@ { "name": "@auth/surrealdb-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "SurrealDB adapter for next-auth.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-typeorm/package.json b/packages/adapter-typeorm/package.json index a53247bc80..eaf239459e 100644 --- a/packages/adapter-typeorm/package.json +++ b/packages/adapter-typeorm/package.json @@ -1,6 +1,6 @@ { "name": "@auth/typeorm-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "TypeORM adapter for Auth.js.", "homepage": "https://authjs.dev/reference/adapter/typeorm", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-unstorage/package.json b/packages/adapter-unstorage/package.json index 57d4093fa9..f39ec1b095 100644 --- a/packages/adapter-unstorage/package.json +++ b/packages/adapter-unstorage/package.json @@ -1,6 +1,6 @@ { "name": "@auth/unstorage-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Unstorage adapter for Auth.js.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-upstash-redis/package.json b/packages/adapter-upstash-redis/package.json index 2111e0de0f..d7d32d65cf 100644 --- a/packages/adapter-upstash-redis/package.json +++ b/packages/adapter-upstash-redis/package.json @@ -1,6 +1,6 @@ { "name": "@auth/upstash-redis-adapter", - "version": "2.7.2", + "version": "2.7.4", "description": "Upstash adapter for Auth.js.", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/adapter-xata/package.json b/packages/adapter-xata/package.json index 66d3dbac44..7746258632 100644 --- a/packages/adapter-xata/package.json +++ b/packages/adapter-xata/package.json @@ -1,6 +1,6 @@ { "name": "@auth/xata-adapter", - "version": "1.7.2", + "version": "1.7.4", "description": "Xata adapter for Auth.js", "homepage": "https://authjs.dev", "repository": "https://github.com/nextauthjs/next-auth", diff --git a/packages/core/package.json b/packages/core/package.json index a815bf16a5..fdc23567e6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@auth/core", - "version": "0.37.2", + "version": "0.37.4", "description": "Authentication for the Web.", "keywords": [ "authentication", @@ -68,12 +68,10 @@ "license": "ISC", "dependencies": { "@panva/hkdf": "^1.2.1", - "@types/cookie": "0.6.0", - "cookie": "0.7.1", - "jose": "^5.9.3", - "oauth4webapi": "^3.0.0", - "preact": "10.11.3", - "preact-render-to-string": "5.2.3" + "jose": "^5.9.6", + "oauth4webapi": "^3.1.4", + "preact": "10.24.3", + "preact-render-to-string": "6.5.11" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", @@ -109,7 +107,7 @@ "@types/react": "18.0.37", "autoprefixer": "10.4.13", "postcss": "8.4.19", - "postcss-nesting": "^12.0.2", + "postcss-nesting": "^12.1.5", "typedoc": "^0.25.12", "typedoc-plugin-markdown": "4.0.0-next.53" } diff --git a/packages/core/scripts/generate-providers.js b/packages/core/scripts/generate-providers.js index 11cc80d1b1..ff74012730 100644 --- a/packages/core/scripts/generate-providers.js +++ b/packages/core/scripts/generate-providers.js @@ -5,17 +5,50 @@ const providersPath = join(process.cwd(), "src/providers") const files = readdirSync(providersPath, "utf8") -const nonOAuthFile = ["oauth-types", "oauth", "index", "email", "credentials"] -const providers = files - .map((file) => { - const strippedProviderName = file.substring(0, file.indexOf(".")) - return `"${strippedProviderName}"` - }) - .filter((provider) => !nonOAuthFile.includes(provider.replace(/"/g, ""))) - -const result = ` +// TODO: Autogenerate +const emailProvidersFile = [ + "email", + "forwardemail", + "mailgun", + "nodemailer", + "passkey", + "postmark", + "resend", + "sendgrid", +] + +// TODO: Autogenerate +const nonOAuthFile = [ + "provider-types", + "oauth", + "index", + // Credentials + "credentials", + // Webauthn + "webauthn", + // Email providers + ...emailProvidersFile, +] + +const providers = files.map((file) => { + const strippedProviderName = file.substring(0, file.indexOf(".")) + return `"${strippedProviderName}"` +}) + +const oauthProviders = providers.filter( + (provider) => !nonOAuthFile.includes(provider.replace(/"/g, "")) +) + +const emailProviders = providers.filter((provider) => + emailProvidersFile.includes(provider.replace(/"/g, "")) +) + +const content = ` // THIS FILE IS AUTOGENERATED. DO NOT EDIT. -export type OAuthProviderType = - | ${providers.join("\n | ")}` +export type OAuthProviderId = + | ${oauthProviders.join("\n | ")} + +export type EmailProviderId = + | ${emailProviders.join("\n | ")}` -writeFileSync(join(providersPath, "oauth-types.ts"), result) +writeFileSync(join(providersPath, "provider-types.ts"), content) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 860a9ea952..748bf3e2de 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -361,12 +361,13 @@ export interface AuthConfig * async signIn({ profile }) { * // Only allow sign in for users with email addresses ending with "yourdomain.com" * return profile?.email?.endsWith("@yourdomain.com") + * } * } * ``` */ signIn?: (params: { user: User | AdapterUser - account: Account | null + account?: Account | null /** * If OAuth provider is used, it contains the full * OAuth profile returned by your provider. @@ -494,7 +495,7 @@ export interface AuthConfig * Also includes {@link TokenSet} * @note available when `trigger` is `"signIn"` or `"signUp"` */ - account: Account | null + account?: Account | null /** * The OAuth profile returned from your provider. * (In case of OIDC it will be the decoded ID Token or /userinfo response) @@ -539,7 +540,7 @@ export interface AuthConfig */ signIn?: (message: { user: User - account: Account | null + account?: Account | null profile?: Profile isNewUser?: boolean }) => Awaitable diff --git a/packages/core/src/jwt.ts b/packages/core/src/jwt.ts index e46b03309c..b92f990829 100644 --- a/packages/core/src/jwt.ts +++ b/packages/core/src/jwt.ts @@ -42,8 +42,9 @@ import { defaultCookies, SessionStore } from "./lib/utils/cookie.js" import { Awaitable } from "./types.js" import type { LoggerInstance } from "./lib/utils/logger.js" import { MissingSecret } from "./errors.js" -import { parse } from "cookie" +import * as cookie from "./lib/vendored/cookie.js" +const { parse: parseCookie } = cookie const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60 // 30 days const now = () => (Date.now() / 1000) | 0 @@ -161,7 +162,7 @@ export async function getToken( const sessionStore = new SessionStore( { name: cookieName, options: { secure: secureCookie } }, - parse(headers.get("cookie") ?? ""), + parseCookie(headers.get("cookie") ?? ""), logger ) diff --git a/packages/core/src/lib/actions/callback/oauth/callback.ts b/packages/core/src/lib/actions/callback/oauth/callback.ts index 9791ff0e3d..be56a5aade 100644 --- a/packages/core/src/lib/actions/callback/oauth/callback.ts +++ b/packages/core/src/lib/actions/callback/oauth/callback.ts @@ -264,7 +264,11 @@ export async function handleOAuth( as, client, processedCodeResponse.access_token, - { [o.customFetch]: provider[customFetch] } + { + [o.customFetch]: provider[customFetch], + // TODO: move away from allowing insecure HTTP requests + [o.allowInsecureRequests]: true, + } ) profile = await userinfoResponse.json() } else { diff --git a/packages/core/src/lib/pages/index.ts b/packages/core/src/lib/pages/index.ts index f93b30bcf6..89370f5293 100644 --- a/packages/core/src/lib/pages/index.ts +++ b/packages/core/src/lib/pages/index.ts @@ -134,7 +134,10 @@ export default function renderPage(config: Partial) { }, verifyRequest(props?: any) { if (pages?.verifyRequest) - return { redirect: pages.verifyRequest, cookies } + return { + redirect: `${pages.verifyRequest}${url?.search ?? ""}`, + cookies, + } return send({ cookies, theme, diff --git a/packages/core/src/lib/pages/styles.css b/packages/core/src/lib/pages/styles.css index be0a2ba9c4..8625021370 100644 --- a/packages/core/src/lib/pages/styles.css +++ b/packages/core/src/lib/pages/styles.css @@ -64,6 +64,19 @@ color: var(--provider-dark-bg) !important; } } + + img[src$="42-school.svg"], + img[src$="apple.svg"], + img[src$="boxyhq-saml.svg"], + img[src$="eveonline.svg"], + img[src$="github.svg"], + img[src$="mailchimp.svg"], + img[src$="medium.svg"], + img[src$="okta.svg"], + img[src$="threads.svg"], + img[src$="wikimedia.svg"] { + filter: invert(1); + } } html { diff --git a/packages/core/src/lib/utils/cookie.ts b/packages/core/src/lib/utils/cookie.ts index 5ef7b7a831..7932b37a09 100644 --- a/packages/core/src/lib/utils/cookie.ts +++ b/packages/core/src/lib/utils/cookie.ts @@ -7,7 +7,8 @@ import type { // Uncomment to recalculate the estimated size // of an empty session cookie -// import { serialize } from "cookie" +// import * as cookie from "../vendored/cookie.js" +// const { serialize } = cookie // console.log( // "Cookie estimated to be ", // serialize(`__Secure.authjs.session-token.0`, "", { diff --git a/packages/core/src/lib/utils/web.ts b/packages/core/src/lib/utils/web.ts index e3a4bfd748..9e782978bb 100644 --- a/packages/core/src/lib/utils/web.ts +++ b/packages/core/src/lib/utils/web.ts @@ -1,4 +1,4 @@ -import { parse as parseCookie, serialize } from "cookie" +import * as cookie from "../vendored/cookie.js" import { UnknownAction } from "../../errors.js" import { setLogger } from "./logger.js" @@ -10,6 +10,8 @@ import type { import { isAuthAction } from "./actions.js" import type { AuthConfig } from "../../index.js" +const { parse: parseCookie, serialize: serializeCookie } = cookie + async function getBody(req: Request): Promise | undefined> { if (!("body" in req) || !req.body || req.method !== "POST") return @@ -74,7 +76,7 @@ export function toResponse(res: ResponseInternal): Response { res.cookies?.forEach((cookie) => { const { name, value, options } = cookie - const cookieHeader = serialize(name, value, options) + const cookieHeader = serializeCookie(name, value, options) if (headers.has("Set-Cookie")) headers.append("Set-Cookie", cookieHeader) else headers.set("Set-Cookie", cookieHeader) }) diff --git a/packages/core/src/lib/vendored/cookie.ts b/packages/core/src/lib/vendored/cookie.ts new file mode 100644 index 0000000000..2e796e9ace --- /dev/null +++ b/packages/core/src/lib/vendored/cookie.ts @@ -0,0 +1,383 @@ +/** + * @source https://github.com/jshttp/cookie + * @author blakeembrey + * @license MIT + */ + +/** + * This is a workaround to support ESM-only environments, until `cookie` ships ESM builds. + * @see https://github.com/jshttp/cookie/issues/211 + */ + +/** + * RegExp to match cookie-name in RFC 6265 sec 4.1.1 + * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2 + * which has been replaced by the token definition in RFC 7230 appendix B. + * + * cookie-name = token + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / + * "*" / "+" / "-" / "." / "^" / "_" / + * "`" / "|" / "~" / DIGIT / ALPHA + */ +const cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/ + +/** + * RegExp to match cookie-value in RFC 6265 sec 4.1.1 + * + * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + * ; US-ASCII characters excluding CTLs, + * ; whitespace DQUOTE, comma, semicolon, + * ; and backslash + */ +const cookieValueRegExp = + /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/ + +/** + * RegExp to match domain-value in RFC 6265 sec 4.1.1 + * + * domain-value = + * ; defined in [RFC1034], Section 3.5, as + * ; enhanced by [RFC1123], Section 2.1 + * =
    + *
    * Built-in 42School integration. * * diff --git a/packages/core/src/providers/apple.ts b/packages/core/src/providers/apple.ts index bb347176a1..7183e17fb4 100644 --- a/packages/core/src/providers/apple.ts +++ b/packages/core/src/providers/apple.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with Apple integration. * diff --git a/packages/core/src/providers/asgardeo.ts b/packages/core/src/providers/asgardeo.ts index d65014445b..9b79cf6a32 100644 --- a/packages/core/src/providers/asgardeo.ts +++ b/packages/core/src/providers/asgardeo.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with Asgardeo integration. * diff --git a/packages/core/src/providers/auth0.ts b/packages/core/src/providers/auth0.ts index 0b239f0584..c588f3a2f1 100644 --- a/packages/core/src/providers/auth0.ts +++ b/packages/core/src/providers/auth0.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with Auth0 integration. * diff --git a/packages/core/src/providers/authentik.ts b/packages/core/src/providers/authentik.ts index 0bb3608a87..c00ef99ad8 100644 --- a/packages/core/src/providers/authentik.ts +++ b/packages/core/src/providers/authentik.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Authentik integration. * * diff --git a/packages/core/src/providers/azure-ad-b2c.ts b/packages/core/src/providers/azure-ad-b2c.ts index b78fabf874..2a87f29b8e 100644 --- a/packages/core/src/providers/azure-ad-b2c.ts +++ b/packages/core/src/providers/azure-ad-b2c.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Azure AD B2C integration. * * diff --git a/packages/core/src/providers/azure-ad.ts b/packages/core/src/providers/azure-ad.ts index 5a88f93459..a7192dcbb7 100644 --- a/packages/core/src/providers/azure-ad.ts +++ b/packages/core/src/providers/azure-ad.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Azure AD integration. * * diff --git a/packages/core/src/providers/bankid-no.ts b/packages/core/src/providers/bankid-no.ts index c715b22834..8bca214341 100644 --- a/packages/core/src/providers/bankid-no.ts +++ b/packages/core/src/providers/bankid-no.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with BankID Norway integration. * diff --git a/packages/core/src/providers/battlenet.ts b/packages/core/src/providers/battlenet.ts index c429709776..09c516b9c6 100644 --- a/packages/core/src/providers/battlenet.ts +++ b/packages/core/src/providers/battlenet.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Battle.net integration. * * diff --git a/packages/core/src/providers/beyondidentity.ts b/packages/core/src/providers/beyondidentity.ts index 68fe36c2ea..7fd5522497 100644 --- a/packages/core/src/providers/beyondidentity.ts +++ b/packages/core/src/providers/beyondidentity.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Beyond Identity integration. * * diff --git a/packages/core/src/providers/box.ts b/packages/core/src/providers/box.ts index b7f84a4cb3..4d06c310a4 100644 --- a/packages/core/src/providers/box.ts +++ b/packages/core/src/providers/box.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Box integration. * * diff --git a/packages/core/src/providers/boxyhq-saml.ts b/packages/core/src/providers/boxyhq-saml.ts index f1ae7a370d..e3353e484a 100644 --- a/packages/core/src/providers/boxyhq-saml.ts +++ b/packages/core/src/providers/boxyhq-saml.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in BoxyHQ SAML integration. * * diff --git a/packages/core/src/providers/bungie.ts b/packages/core/src/providers/bungie.ts index 3fcd803395..94a6b69d53 100644 --- a/packages/core/src/providers/bungie.ts +++ b/packages/core/src/providers/bungie.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Bungie integration. * * diff --git a/packages/core/src/providers/click-up.ts b/packages/core/src/providers/click-up.ts index f923424fcc..5435319b54 100644 --- a/packages/core/src/providers/click-up.ts +++ b/packages/core/src/providers/click-up.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in ClickUp integration. * * diff --git a/packages/core/src/providers/cognito.ts b/packages/core/src/providers/cognito.ts index 27bad9947c..89f87dc25b 100644 --- a/packages/core/src/providers/cognito.ts +++ b/packages/core/src/providers/cognito.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Cognito integration. * * diff --git a/packages/core/src/providers/coinbase.ts b/packages/core/src/providers/coinbase.ts index ccfeb52ff4..88266a99e6 100644 --- a/packages/core/src/providers/coinbase.ts +++ b/packages/core/src/providers/coinbase.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Coinbase integration. * * diff --git a/packages/core/src/providers/concept2.ts b/packages/core/src/providers/concept2.ts index 26bd5e6978..714608b899 100644 --- a/packages/core/src/providers/concept2.ts +++ b/packages/core/src/providers/concept2.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Concept2 integration. * * diff --git a/packages/core/src/providers/credentials.ts b/packages/core/src/providers/credentials.ts index 1f8a07e2ab..afe5c1bc8a 100644 --- a/packages/core/src/providers/credentials.ts +++ b/packages/core/src/providers/credentials.ts @@ -74,7 +74,7 @@ export interface CredentialsConfig< ) => Awaitable } -export type CredentialsProviderType = "Credentials" +export type CredentialsProviderId = "credentials" /** * The Credentials provider allows you to handle signing in with arbitrary credentials, diff --git a/packages/core/src/providers/descope.ts b/packages/core/src/providers/descope.ts index b6c1c64802..2a9c950461 100644 --- a/packages/core/src/providers/descope.ts +++ b/packages/core/src/providers/descope.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with Descope integration. * diff --git a/packages/core/src/providers/discord.ts b/packages/core/src/providers/discord.ts index 5fb6c103db..da5c61d62b 100644 --- a/packages/core/src/providers/discord.ts +++ b/packages/core/src/providers/discord.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Discord integration. * * @@ -146,8 +146,10 @@ export default function Discord

    ( id: "discord", name: "Discord", type: "oauth", - authorization: - "https://discord.com/api/oauth2/authorize?scope=identify+email", + authorization: { + url: "https://discord.com/api/oauth2/authorize", + params: { scope: "identify email" }, + }, token: "https://discord.com/api/oauth2/token", userinfo: "https://discord.com/api/users/@me", profile(profile) { diff --git a/packages/core/src/providers/dribbble.ts b/packages/core/src/providers/dribbble.ts index 10a8775fc2..1b9145a1e2 100644 --- a/packages/core/src/providers/dribbble.ts +++ b/packages/core/src/providers/dribbble.ts @@ -1,5 +1,5 @@ /** - *

    + *
    * Built-in Dribbble integration. * * diff --git a/packages/core/src/providers/dropbox.ts b/packages/core/src/providers/dropbox.ts index 52fcb2c9f4..cd2ee0b36c 100644 --- a/packages/core/src/providers/dropbox.ts +++ b/packages/core/src/providers/dropbox.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Dropbox integration. * * @@ -72,7 +72,7 @@ export default function Dropbox( authorization: { url: "https://www.dropbox.com/oauth2/authorize", params: { - access_type: "offline", + token_access_type: "offline", scope: "account_info.read", }, }, diff --git a/packages/core/src/providers/duende-identity-server6.ts b/packages/core/src/providers/duende-identity-server6.ts index 494cea0b4b..9a9b32c8e6 100644 --- a/packages/core/src/providers/duende-identity-server6.ts +++ b/packages/core/src/providers/duende-identity-server6.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in DuendeIdentityServer6 integration. * * diff --git a/packages/core/src/providers/email.ts b/packages/core/src/providers/email.ts index 6690cf2d1e..35bd306d77 100644 --- a/packages/core/src/providers/email.ts +++ b/packages/core/src/providers/email.ts @@ -1,5 +1,6 @@ import type { CommonProviderOptions } from "./index.js" import type { Awaitable, Theme } from "../types.js" +export type { EmailProviderId } from "./provider-types.js" // TODO: Kepts for backwards compatibility // Remove this import and encourage users @@ -26,21 +27,25 @@ export default function Email(config: NodemailerUserConfig): NodemailerConfig { // when started working on https://github.com/nextauthjs/next-auth/discussions/1465 export type EmailProviderType = "email" +export type EmailProviderSendVerificationRequestParams = { + identifier: string + url: string + expires: Date + provider: EmailConfig + token: string + theme: Theme + request: Request +} + export interface EmailConfig extends CommonProviderOptions { id: string - type: EmailProviderType + type: "email" name: string from?: string maxAge?: number - sendVerificationRequest: (params: { - identifier: string - url: string - expires: Date - provider: EmailConfig - token: string - theme: Theme - request: Request - }) => Awaitable + sendVerificationRequest: ( + params: EmailProviderSendVerificationRequestParams + ) => Awaitable /** Used to hash the verification token. */ secret?: string /** Used with HTTP-based email providers. */ diff --git a/packages/core/src/providers/eventbrite.ts b/packages/core/src/providers/eventbrite.ts index 915c1262eb..3598338062 100644 --- a/packages/core/src/providers/eventbrite.ts +++ b/packages/core/src/providers/eventbrite.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Eventbrite integration. * * diff --git a/packages/core/src/providers/eveonline.ts b/packages/core/src/providers/eveonline.ts index ce97824f25..7faaf8ac24 100644 --- a/packages/core/src/providers/eveonline.ts +++ b/packages/core/src/providers/eveonline.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in EVEOnline integration. * * diff --git a/packages/core/src/providers/facebook.ts b/packages/core/src/providers/facebook.ts index 3eab1c4883..7405116949 100644 --- a/packages/core/src/providers/facebook.ts +++ b/packages/core/src/providers/facebook.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Facebook integration. * * diff --git a/packages/core/src/providers/faceit.ts b/packages/core/src/providers/faceit.ts index 634fbbc227..818cecb157 100644 --- a/packages/core/src/providers/faceit.ts +++ b/packages/core/src/providers/faceit.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in FACEIT integration. * * diff --git a/packages/core/src/providers/foursquare.ts b/packages/core/src/providers/foursquare.ts index d428979cb7..f5806afcdf 100644 --- a/packages/core/src/providers/foursquare.ts +++ b/packages/core/src/providers/foursquare.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in FourSquare integration. * * diff --git a/packages/core/src/providers/freshbooks.ts b/packages/core/src/providers/freshbooks.ts index b21dc53cc0..96c6441cb8 100644 --- a/packages/core/src/providers/freshbooks.ts +++ b/packages/core/src/providers/freshbooks.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in FreshBooks integration. * * diff --git a/packages/core/src/providers/frontegg.ts b/packages/core/src/providers/frontegg.ts new file mode 100644 index 0000000000..15890c5c8d --- /dev/null +++ b/packages/core/src/providers/frontegg.ts @@ -0,0 +1,111 @@ +/** + * + * + * @module providers/frontegg + */ + +import type { OIDCConfig, OIDCUserConfig } from "./index.js" + +/** The returned user profile from Frontegg when using the profile callback. [Reference](https://docs.frontegg.com/docs/admin-portal-profile). */ +export interface FronteggProfile { + /** The user's unique Frontegg ID */ + sub: string + /** The user's name */ + name: string + /** The user's email */ + email: string + /** A boolean indicating if the user's email is verified */ + email_verified: boolean + /** The user's picture */ + profilePictureUrl: string + /** The user's roles */ + roles: string[] + /** The user's custom attributes */ + [claim: string]: unknown +} + +/** + * + * ### Setup + * + * #### Callback URL + * ``` + * https://example.com/api/auth/callback/frontegg + * ``` + * + * #### Configuration + * ```ts + * import { Auth } from "@auth/core" + * import Frontegg from "@auth/core/providers/frontegg" + * + * const request = new Request(origin) + * const response = await Auth(request, { + * providers: [ + * Frontegg({ + * clientId: AUTH_FRONTEGG_ID, + * clientSecret: AUTH_FRONTEGG_SECRET, + * issuer: AUTH_FRONTEGG_ISSUER + * }), + * ], + * }) + * ``` + * + * ### Configuring Frontegg + * + * Follow these steps: + * + * Log into the [Frontegg portal](https://portal.frontegg.com) + * + * Authentication > Login method > Hosted login > Add your callback url here <{{APP_URL}}/api/auth/callback/frontegg> + * + * Then, create a `.env.local` file in the project root add the following entries: + * + * Get the following from the Frontegg's portal: + * ``` + * AUTH_FRONTEGG_ID="" # Environments > Your environment > Env settings + * AUTH_FRONTEGG_SECRET="" # Environments > Your environment > Env settings + * AUTH_FRONTEGG_ISSUER="" # Environments > Your environment > Env settings > Domains > Domain name + * ``` + * + * ### Resources + * + * - [Frontegg Docs](https://docs.frontegg.com/docs/how-to-use-our-docs) + * + * ### Notes + * + * The Frontegg provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/frontegg.ts). To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/configuring-oauth-providers). + * + * :::info + * By default, Auth.js assumes that the Frontegg provider is based on the [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) spec + * ::: + * + * ## Help + * + * If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue). + * + * Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from + * the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec, + * we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions). + */ +export default function Frontegg( + options: OIDCUserConfig +): OIDCConfig { + return { + id: "frontegg", + name: "Frontegg", + type: "oidc", + authorization: `${options.issuer}/oauth/authorize`, + token: `${options.issuer}/oauth/token`, + userinfo: `${options.issuer}/identity/resources/users/v2/me`, + wellKnown: `${options.issuer}/oauth/.well-known/openid-configuration`, + issuer: options.issuer, + options, + } +} diff --git a/packages/core/src/providers/fusionauth.ts b/packages/core/src/providers/fusionauth.ts index 261ffd1a62..5bb3d31bd6 100644 --- a/packages/core/src/providers/fusionauth.ts +++ b/packages/core/src/providers/fusionauth.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in FusionAuth integration. * * diff --git a/packages/core/src/providers/github.ts b/packages/core/src/providers/github.ts index 7284a12116..54a5e53236 100644 --- a/packages/core/src/providers/github.ts +++ b/packages/core/src/providers/github.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in GitHub integration. * * diff --git a/packages/core/src/providers/gitlab.ts b/packages/core/src/providers/gitlab.ts index 78d32736a1..cc2562586d 100644 --- a/packages/core/src/providers/gitlab.ts +++ b/packages/core/src/providers/gitlab.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in GitLab integration. * * diff --git a/packages/core/src/providers/google.ts b/packages/core/src/providers/google.ts index 211472c6e7..9dc7dff2d1 100644 --- a/packages/core/src/providers/google.ts +++ b/packages/core/src/providers/google.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Google integration. * * diff --git a/packages/core/src/providers/hubspot.ts b/packages/core/src/providers/hubspot.ts index a14841e74f..a3f39ee019 100644 --- a/packages/core/src/providers/hubspot.ts +++ b/packages/core/src/providers/hubspot.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in HubSpot integration. * * diff --git a/packages/core/src/providers/identity-server4.ts b/packages/core/src/providers/identity-server4.ts index be58d531c5..47264cdd23 100644 --- a/packages/core/src/providers/identity-server4.ts +++ b/packages/core/src/providers/identity-server4.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in IdentityServer4 integration. * * diff --git a/packages/core/src/providers/index.ts b/packages/core/src/providers/index.ts index d2f97d2bc2..9edfe85872 100644 --- a/packages/core/src/providers/index.ts +++ b/packages/core/src/providers/index.ts @@ -1,15 +1,12 @@ import type { Profile } from "../types.js" import CredentialsProvider from "./credentials.js" -import type { - CredentialsConfig, - CredentialsProviderType, -} from "./credentials.js" +import type { CredentialsConfig, CredentialsProviderId } from "./credentials.js" import type EmailProvider from "./email.js" -import type { EmailConfig, EmailProviderType } from "./email.js" +import type { EmailConfig, EmailProviderId } from "./email.js" import type { OAuth2Config, OAuthConfig, - OAuthProviderType, + OAuthProviderId, OIDCConfig, } from "./oauth.js" import type { WebAuthnConfig, WebAuthnProviderType } from "./webauthn.js" @@ -91,11 +88,11 @@ export type Provider

    = ( InternalProviderOptions export type BuiltInProviders = Record< - OAuthProviderType, + OAuthProviderId, (config: Partial>) => OAuthConfig > & - Record & - Record & + Record & + Record & Record< WebAuthnProviderType, (config: Partial) => WebAuthnConfig @@ -110,9 +107,9 @@ export interface AppProvider extends CommonProviderOptions { callbackUrl: string } -export type RedirectableProviderType = "email" | "credentials" - -export type BuiltInProviderType = - | RedirectableProviderType - | OAuthProviderType +export type ProviderId = + | CredentialsProviderId + | EmailProviderId + | OAuthProviderId | WebAuthnProviderType + | (string & {}) // HACK: To allow user-defined providers in `signIn` diff --git a/packages/core/src/providers/instagram.ts b/packages/core/src/providers/instagram.ts index bc467890df..7dd3945f5e 100644 --- a/packages/core/src/providers/instagram.ts +++ b/packages/core/src/providers/instagram.ts @@ -1,5 +1,5 @@ /** - *

    + *
    * Built-in Instagram integration. * * diff --git a/packages/core/src/providers/kakao.ts b/packages/core/src/providers/kakao.ts index f6d7d1df2e..e18879a45a 100644 --- a/packages/core/src/providers/kakao.ts +++ b/packages/core/src/providers/kakao.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Kakao integration. * * diff --git a/packages/core/src/providers/keycloak.ts b/packages/core/src/providers/keycloak.ts index 8708a43999..62e1dc202d 100644 --- a/packages/core/src/providers/keycloak.ts +++ b/packages/core/src/providers/keycloak.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Keycloak integration. * * diff --git a/packages/core/src/providers/kinde.ts b/packages/core/src/providers/kinde.ts index 190d32bcf1..b550a8ab76 100644 --- a/packages/core/src/providers/kinde.ts +++ b/packages/core/src/providers/kinde.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * * Built-in sign in with Kinde integration. * diff --git a/packages/core/src/providers/line.ts b/packages/core/src/providers/line.ts index b4a2c32451..fdc8e8f25f 100644 --- a/packages/core/src/providers/line.ts +++ b/packages/core/src/providers/line.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in LINE integration. * * diff --git a/packages/core/src/providers/linkedin.ts b/packages/core/src/providers/linkedin.ts index 339e9510af..48dc92cf47 100644 --- a/packages/core/src/providers/linkedin.ts +++ b/packages/core/src/providers/linkedin.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in LinkedIn integration. * * diff --git a/packages/core/src/providers/loops.ts b/packages/core/src/providers/loops.ts new file mode 100644 index 0000000000..dd76fa1eb8 --- /dev/null +++ b/packages/core/src/providers/loops.ts @@ -0,0 +1,79 @@ +/** + * + * + * @module providers/loops + */ + +import type { EmailConfig, EmailUserConfig } from "./email.js" + +export type LoopsUserConfig = Omit, "options" | "type"> + +export interface LoopsConfig + extends Omit { + id: string + apiKey: string + transactionalId: string + sendVerificationRequest: (params: Params) => Promise + options: LoopsUserConfig +} + +type Params = Parameters[0] & { + provider: LoopsConfig +} + +/** + * + * @param config + * @returns LoopsConfig + * @requires LoopsUserConfig + * @example + * ```ts + * Loops({ + * apiKey: process.env.AUTH_LOOPS_KEY, + * transactionalId: process.env.AUTH_LOOPS_TRANSACTIONAL_ID, + * }) + * ``` + * + * @typedef LoopsUserConfig + */ + +export default function Loops(config: LoopsUserConfig): LoopsConfig { + return { + id: "loops", + apiKey: "", + type: "email", + name: "Loops", + from: "Auth.js ", + maxAge: 24 * 60 * 60, + transactionalId: config.transactionalId || "", + async sendVerificationRequest(params: Params) { + const { identifier: to, provider, url } = params + if (!provider.apiKey || !provider.transactionalId) + throw new TypeError("Missing Loops API Key or TransactionalId") + + const res = await fetch("https://app.loops.so/api/v1/transactional", { + method: "POST", + headers: { + Authorization: `Bearer ${provider.apiKey}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + transactionalId: provider.transactionalId, + email: to, + dataVariables: { + url: url, + }, + }), + }) + if (!res.ok) { + throw new Error("Loops Send Error: " + JSON.stringify(await res.json())) + } + }, + options: config, + } +} diff --git a/packages/core/src/providers/mailchimp.ts b/packages/core/src/providers/mailchimp.ts index a8786970e5..d88c1856be 100644 --- a/packages/core/src/providers/mailchimp.ts +++ b/packages/core/src/providers/mailchimp.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Mailchimp integration. * * diff --git a/packages/core/src/providers/mailgun.ts b/packages/core/src/providers/mailgun.ts index c0e0378844..84f29d3c52 100644 --- a/packages/core/src/providers/mailgun.ts +++ b/packages/core/src/providers/mailgun.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Mailgun integration. * * diff --git a/packages/core/src/providers/mailru.ts b/packages/core/src/providers/mailru.ts index b7c9503fd0..b5bac8878c 100644 --- a/packages/core/src/providers/mailru.ts +++ b/packages/core/src/providers/mailru.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Mailru integration. * * diff --git a/packages/core/src/providers/mastodon.ts b/packages/core/src/providers/mastodon.ts index 03d822f062..4113c6cfe7 100644 --- a/packages/core/src/providers/mastodon.ts +++ b/packages/core/src/providers/mastodon.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Mastodon integration. * * diff --git a/packages/core/src/providers/mattermost.ts b/packages/core/src/providers/mattermost.ts index 474a00f92b..fc578ec4ba 100644 --- a/packages/core/src/providers/mattermost.ts +++ b/packages/core/src/providers/mattermost.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Mattermost integration. * * diff --git a/packages/core/src/providers/medium.ts b/packages/core/src/providers/medium.ts index a1e38b0a56..786a777992 100644 --- a/packages/core/src/providers/medium.ts +++ b/packages/core/src/providers/medium.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Medium integration. * * diff --git a/packages/core/src/providers/microsoft-entra-id.ts b/packages/core/src/providers/microsoft-entra-id.ts index d4f7ff5b7c..be71594493 100644 --- a/packages/core/src/providers/microsoft-entra-id.ts +++ b/packages/core/src/providers/microsoft-entra-id.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Microsoft Entra ID integration. * * diff --git a/packages/core/src/providers/naver.ts b/packages/core/src/providers/naver.ts index 55b98f6285..f6987abaf6 100644 --- a/packages/core/src/providers/naver.ts +++ b/packages/core/src/providers/naver.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Naver integration. * * diff --git a/packages/core/src/providers/netlify.ts b/packages/core/src/providers/netlify.ts index a566efcce8..bc9e5fa4a9 100644 --- a/packages/core/src/providers/netlify.ts +++ b/packages/core/src/providers/netlify.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Netlify integration. * * diff --git a/packages/core/src/providers/netsuite.ts b/packages/core/src/providers/netsuite.ts index 54231a5669..ed10b0d3e2 100644 --- a/packages/core/src/providers/netsuite.ts +++ b/packages/core/src/providers/netsuite.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in NetSuite integration. * * diff --git a/packages/core/src/providers/nextcloud.ts b/packages/core/src/providers/nextcloud.ts index 92e9c29c63..54b416dbe8 100644 --- a/packages/core/src/providers/nextcloud.ts +++ b/packages/core/src/providers/nextcloud.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Nextcloud integration. * * diff --git a/packages/core/src/providers/notion.ts b/packages/core/src/providers/notion.ts index a2c2571d43..d96820cfcf 100644 --- a/packages/core/src/providers/notion.ts +++ b/packages/core/src/providers/notion.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Notion integration. * * diff --git a/packages/core/src/providers/oauth.ts b/packages/core/src/providers/oauth.ts index 1464684b2e..6e24343d2c 100644 --- a/packages/core/src/providers/oauth.ts +++ b/packages/core/src/providers/oauth.ts @@ -11,7 +11,7 @@ type IssuerMetadata = any type OAuthCallbackChecks = any type OpenIDCallbackChecks = any -export type { OAuthProviderType } from "./oauth-types.js" +export type { OAuthProviderId } from "./provider-types.js" export type OAuthChecks = OpenIDCallbackChecks | OAuthCallbackChecks diff --git a/packages/core/src/providers/okta.ts b/packages/core/src/providers/okta.ts index 6d98ea7dc0..0833f44e70 100644 --- a/packages/core/src/providers/okta.ts +++ b/packages/core/src/providers/okta.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Okta integration. * * diff --git a/packages/core/src/providers/onelogin.ts b/packages/core/src/providers/onelogin.ts index bccbc4ece6..b1c05a108c 100644 --- a/packages/core/src/providers/onelogin.ts +++ b/packages/core/src/providers/onelogin.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in OneLogin integration. * * diff --git a/packages/core/src/providers/ory-hydra.ts b/packages/core/src/providers/ory-hydra.ts index 25cb69a3bd..fb8a2d754d 100644 --- a/packages/core/src/providers/ory-hydra.ts +++ b/packages/core/src/providers/ory-hydra.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Ory Hydra integration. * * diff --git a/packages/core/src/providers/osso.ts b/packages/core/src/providers/osso.ts index 58e6c21d11..2f987d2f74 100644 --- a/packages/core/src/providers/osso.ts +++ b/packages/core/src/providers/osso.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Osso integration. * * diff --git a/packages/core/src/providers/osu.ts b/packages/core/src/providers/osu.ts index 1f419ce757..250dfc86ae 100644 --- a/packages/core/src/providers/osu.ts +++ b/packages/core/src/providers/osu.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in osu! integration. * * diff --git a/packages/core/src/providers/passage.ts b/packages/core/src/providers/passage.ts index 0a1b39f746..a15f4cdb5e 100644 --- a/packages/core/src/providers/passage.ts +++ b/packages/core/src/providers/passage.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Passage by 1Password integration. * * diff --git a/packages/core/src/providers/passkey.ts b/packages/core/src/providers/passkey.ts index 6e181bf4f6..de634c2c82 100644 --- a/packages/core/src/providers/passkey.ts +++ b/packages/core/src/providers/passkey.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Passkey integration. * * diff --git a/packages/core/src/providers/patreon.ts b/packages/core/src/providers/patreon.ts index 745b2d5ca8..95f93d47f0 100644 --- a/packages/core/src/providers/patreon.ts +++ b/packages/core/src/providers/patreon.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Patreon integration. * * diff --git a/packages/core/src/providers/pinterest.ts b/packages/core/src/providers/pinterest.ts index 500febbb74..29ee832b57 100644 --- a/packages/core/src/providers/pinterest.ts +++ b/packages/core/src/providers/pinterest.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Pinterest integration. * * diff --git a/packages/core/src/providers/pipedrive.ts b/packages/core/src/providers/pipedrive.ts index 09d257bb4e..b9ab49a5a2 100644 --- a/packages/core/src/providers/pipedrive.ts +++ b/packages/core/src/providers/pipedrive.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Pipedrive integration. * * diff --git a/packages/core/src/providers/reddit.ts b/packages/core/src/providers/reddit.ts index 2edaacd99e..3e5d22abaa 100644 --- a/packages/core/src/providers/reddit.ts +++ b/packages/core/src/providers/reddit.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Reddit integration. * * diff --git a/packages/core/src/providers/roblox.ts b/packages/core/src/providers/roblox.ts index e20579af70..421caaab6a 100644 --- a/packages/core/src/providers/roblox.ts +++ b/packages/core/src/providers/roblox.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Roblox integration. * * diff --git a/packages/core/src/providers/salesforce.ts b/packages/core/src/providers/salesforce.ts index e53f39c2e6..26870c1a2f 100644 --- a/packages/core/src/providers/salesforce.ts +++ b/packages/core/src/providers/salesforce.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Salesforce integration. * * diff --git a/packages/core/src/providers/simplelogin.ts b/packages/core/src/providers/simplelogin.ts index d0eee806e6..81728f2351 100644 --- a/packages/core/src/providers/simplelogin.ts +++ b/packages/core/src/providers/simplelogin.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in SimpleLogin integration. * * diff --git a/packages/core/src/providers/slack.ts b/packages/core/src/providers/slack.ts index e5f2549db5..26a6ce2748 100644 --- a/packages/core/src/providers/slack.ts +++ b/packages/core/src/providers/slack.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Slack integration. * * diff --git a/packages/core/src/providers/spotify.ts b/packages/core/src/providers/spotify.ts index fce6235be8..92d89c46ab 100644 --- a/packages/core/src/providers/spotify.ts +++ b/packages/core/src/providers/spotify.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Spotify integration. * * diff --git a/packages/core/src/providers/strava.ts b/packages/core/src/providers/strava.ts index e429166fb9..99443f1797 100644 --- a/packages/core/src/providers/strava.ts +++ b/packages/core/src/providers/strava.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Strava integration. * * diff --git a/packages/core/src/providers/threads.ts b/packages/core/src/providers/threads.ts index 51a82c3e94..d6779bc49f 100644 --- a/packages/core/src/providers/threads.ts +++ b/packages/core/src/providers/threads.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Threads integration. * * diff --git a/packages/core/src/providers/tiktok.ts b/packages/core/src/providers/tiktok.ts index 3b0ef7526f..bb60110b13 100644 --- a/packages/core/src/providers/tiktok.ts +++ b/packages/core/src/providers/tiktok.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in TikTok integration. * * @@ -8,13 +8,13 @@ * * @module providers/tiktok */ -import { TokenSet } from "../types.js" +import { customFetch } from "../lib/symbols.js" import type { OAuthConfig, OAuthUserConfig } from "./index.js" /** * [More info](https://developers.tiktok.com/doc/tiktok-api-v2-get-user-info/) */ -export interface TiktokProfile extends Record { +export interface TiktokProfile { data: { user: { /** @@ -137,6 +137,8 @@ export interface TiktokProfile extends Record { * ``` * * #### Configuration + * You can omit the client and secret if you have set the `AUTH_TIKTOK_ID` and `AUTH_TIKTOK_SECRET` environment variables. + * Remeber that the AUTH_TIKTOK_ID is the Client Key in the TikTok Application *```ts * import { Auth } from "@auth/core" * import TikTok from "@auth/core/providers/tiktok" @@ -144,7 +146,7 @@ export interface TiktokProfile extends Record { * const request = new Request(origin) * const response = await Auth(request, { * providers: [ - * TikTok({ clientId: TIKTOK_CLIENT_KEY, clientSecret: TIKTOK_CLIENT_SECRET }), + * TikTok({ clientId: AUTH_TIKTOK_ID, clientSecret: AUTH_TIKTOK_SECRET }), * ], * }) * ``` @@ -153,6 +155,7 @@ export interface TiktokProfile extends Record { * - [TikTok app console](https://developers.tiktok.com/) * - [TikTok login kit documentation](https://developers.tiktok.com/doc/login-kit-web/) * - [Avaliable Scopes](https://developers.tiktok.com/doc/tiktok-api-scopes/) + * - [Sandbox for testing](https://developers.tiktok.com/blog/introducing-sandbox) * * * ### Notes @@ -160,6 +163,7 @@ export interface TiktokProfile extends Record { * :::tip * * Production applications cannot use localhost URLs to sign in with TikTok. You need add the domain and Callback/Redirect url's to your TikTok app and have them review and approved by the TikTok Team. + * If you need to test your implementation, you can use the sandbox feature and ngrok for testing in localhost. * * ::: * @@ -171,7 +175,7 @@ export interface TiktokProfile extends Record { * * :::tip * - * Client_ID will be the Client Key in the TikTok Application + * AUTH_TIKTOK_ID will be the Client Key in the TikTok Application * * ::: * @@ -183,6 +187,64 @@ export interface TiktokProfile extends Record { * The TikTok provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/tiktok.ts). * To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/configuring-oauth-providers). * + * If You Need to Customize the TikTok Provider, You Can Use the Following Configuration as a custom provider + * + * ```ts + * { + * async [customFetch](...args) { + * const url = new URL(args[0] instanceof Request ? args[0].url : args[0]); + * if (url.pathname.endsWith("/token/")) { + * const [url, request] = args; + * const customHeaders = { + * ...request?.headers, + * "content-type": "application/x-www-form-urlencoded", + * }; + * + * const customBody = new URLSearchParams(request?.body as string); + * customBody.append("client_key", process.env.AUTH_TIKTOK_ID!); + * + * const response = await fetch(url, { + * ...request, + * headers: customHeaders, + * body: customBody.toString(), + * }); + * const json = await response.json(); + * return Response.json({ ...json }); + * } + * return fetch(...args); + * }, + * + * id: "tiktok", + * name: "TikTok", + * type: "oauth", + * client: { + * token_endpoint_auth_method: "client_secret_post", + * }, + * + * authorization: { + * url: "https://www.tiktok.com/v2/auth/authorize", + * params: { + * client_key: options.clientId, + * scope: "user.info.profile", //Add scopes you need eg(user.info.profile,user.info.stats,video.list) + * }, + * }, + * + * token: "https://open.tiktokapis.com/v2/oauth/token/", + * + * userinfo: "https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,username", //Add fields you need eg(open_id,avatar_url,display_name,username) + * + * profile(profile) { + * return { + * id: profile.data.user.open_id, + * name: profile.data.user.display_name, + * image: profile.data.user.avatar_url, + * email: profile.data.user.email || profile.data.user.username || null, + * }; + * }, + * } + * + * ``` + * * ::: * * :::info **Disclaimer** @@ -195,62 +257,50 @@ export interface TiktokProfile extends Record { * * ::: */ -export default function TikTok

    ( - options: OAuthUserConfig

    -): OAuthConfig

    { +export default function TikTok( + options: OAuthUserConfig +): OAuthConfig { return { + async [customFetch](...args) { + const url = new URL(args[0] instanceof Request ? args[0].url : args[0]) + if (url.pathname.endsWith("/token/")) { + const [url, request] = args + + const customHeaders = { + ...request?.headers, + "content-type": "application/x-www-form-urlencoded", + } + + const customBody = new URLSearchParams(request?.body as string) + customBody.append("client_key", options.clientId!) + const response = await fetch(url, { + ...request, + headers: customHeaders, + body: customBody.toString(), + }) + const json = await response.json() + return Response.json({ ...json }) + } + return fetch(...args) + }, id: "tiktok", name: "TikTok", type: "oauth", + client: { + token_endpoint_auth_method: "client_secret_post", + }, authorization: { url: "https://www.tiktok.com/v2/auth/authorize", params: { client_key: options.clientId, scope: "user.info.profile", - response_type: "code", }, }, - token: { - url: "https://open.tiktokapis.com/v2/oauth/token/", - async request({ params, provider }) { - const res = await fetch(provider.token?.url as unknown as string, { - method: "POST", - headers: { - "Cache-Control": "no-cache", - "Content-Type": "application/x-www-form-urlencoded", - }, - body: new URLSearchParams({ - client_key: provider.clientId!, - client_secret: provider.clientSecret!, - code: params.code!, - grant_type: "authorization_code", - redirect_uri: provider.callbackUrl!, - }), - }).then((res) => res.json()) + token: "https://open.tiktokapis.com/v2/oauth/token/", + userinfo: + "https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,username", - const tokens: TokenSet = { - access_token: res.access_token, - expires_at: res.expires_in, - refresh_token: res.refresh_token, - scope: res.scope, - id_token: res.open_id, - token_type: res.token_type, - session_state: res.open_id, - } - return { - tokens, - } - }, - }, - userinfo: { - url: "https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,username", - async request({ tokens, provider }) { - return await fetch(provider.userinfo?.url as URL, { - headers: { Authorization: `Bearer ${tokens.access_token}` }, - }).then(async (res) => await res.json()) - }, - }, profile(profile) { return { id: profile.data.user.open_id, diff --git a/packages/core/src/providers/todoist.ts b/packages/core/src/providers/todoist.ts index 3bc58b3c0c..2fd0505f28 100644 --- a/packages/core/src/providers/todoist.ts +++ b/packages/core/src/providers/todoist.ts @@ -1,5 +1,5 @@ /** - *

    + *
    * Built-in Todoist integration. * * diff --git a/packages/core/src/providers/trakt.ts b/packages/core/src/providers/trakt.ts index 1462b8818b..c4ddd8a401 100644 --- a/packages/core/src/providers/trakt.ts +++ b/packages/core/src/providers/trakt.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Trakt integration. * * diff --git a/packages/core/src/providers/twitch.ts b/packages/core/src/providers/twitch.ts index 4846d27010..ca4f50ff1d 100644 --- a/packages/core/src/providers/twitch.ts +++ b/packages/core/src/providers/twitch.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Twitch integration. * * diff --git a/packages/core/src/providers/twitter.ts b/packages/core/src/providers/twitter.ts index dd1b3cf776..436fc21600 100644 --- a/packages/core/src/providers/twitter.ts +++ b/packages/core/src/providers/twitter.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Twitter integration. * * diff --git a/packages/core/src/providers/united-effects.ts b/packages/core/src/providers/united-effects.ts index 734a982ce0..2e50153e5a 100644 --- a/packages/core/src/providers/united-effects.ts +++ b/packages/core/src/providers/united-effects.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in United Effects integration. * * diff --git a/packages/core/src/providers/vk.ts b/packages/core/src/providers/vk.ts index e4b5620b24..1d475aff90 100644 --- a/packages/core/src/providers/vk.ts +++ b/packages/core/src/providers/vk.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in VK integration. * * diff --git a/packages/core/src/providers/webex.ts b/packages/core/src/providers/webex.ts index fa1ee94457..df4ecfbc4b 100755 --- a/packages/core/src/providers/webex.ts +++ b/packages/core/src/providers/webex.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Webex integration. * * diff --git a/packages/core/src/providers/wechat.ts b/packages/core/src/providers/wechat.ts index 363f1386d0..7c06e77d63 100644 --- a/packages/core/src/providers/wechat.ts +++ b/packages/core/src/providers/wechat.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in WeChat integration. * * @@ -81,7 +81,7 @@ export default function WeChat( } ): OAuthConfig { const { clientId, clientSecret, platformType = "OfficialAccount" } = options - console.log(options) + return { id: "wechat", name: "WeChat", diff --git a/packages/core/src/providers/wikimedia.ts b/packages/core/src/providers/wikimedia.ts index 7043ff7ddb..bca61601aa 100644 --- a/packages/core/src/providers/wikimedia.ts +++ b/packages/core/src/providers/wikimedia.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Wikimedia integration. * * diff --git a/packages/core/src/providers/wordpress.ts b/packages/core/src/providers/wordpress.ts index e44dbe50c7..7a9f1717ff 100644 --- a/packages/core/src/providers/wordpress.ts +++ b/packages/core/src/providers/wordpress.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in WordPress integration. * * diff --git a/packages/core/src/providers/workos.ts b/packages/core/src/providers/workos.ts index 776aa95496..54d9ccda7d 100644 --- a/packages/core/src/providers/workos.ts +++ b/packages/core/src/providers/workos.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in WorkOS integration. * * diff --git a/packages/core/src/providers/yandex.ts b/packages/core/src/providers/yandex.ts index a477051d3e..80f19bcd73 100644 --- a/packages/core/src/providers/yandex.ts +++ b/packages/core/src/providers/yandex.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Yandex integration. * * diff --git a/packages/core/src/providers/zitadel.ts b/packages/core/src/providers/zitadel.ts index c8f55c616b..7ea39d310d 100644 --- a/packages/core/src/providers/zitadel.ts +++ b/packages/core/src/providers/zitadel.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Zitadel integration. * * diff --git a/packages/core/src/providers/zoho.ts b/packages/core/src/providers/zoho.ts index 113afd206f..a84be5f44b 100644 --- a/packages/core/src/providers/zoho.ts +++ b/packages/core/src/providers/zoho.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in ZOHO integration. * * diff --git a/packages/core/src/providers/zoom.ts b/packages/core/src/providers/zoom.ts index fdf9500d0a..ed97010afa 100644 --- a/packages/core/src/providers/zoom.ts +++ b/packages/core/src/providers/zoom.ts @@ -1,5 +1,5 @@ /** - *
    + *
    * Built-in Zoom integration. * * diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index fef9f1151d..137338a61d 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -51,7 +51,7 @@ * @module types */ -import type { CookieSerializeOptions } from "cookie" +import type { SerializeOptions } from "./lib/vendored/cookie.js" import type { TokenEndpointResponse } from "oauth4webapi" import type { Adapter } from "./adapters.js" import { AuthConfig } from "./index.js" @@ -183,7 +183,7 @@ export interface Profile { /** [Documentation](https://authjs.dev/reference/core#cookies) */ export interface CookieOption { name: string - options: CookieSerializeOptions + options: SerializeOptions } /** [Documentation](https://authjs.dev/reference/core#cookies) */ diff --git a/packages/core/test/actions/session.test.ts b/packages/core/test/actions/session.test.ts index 963a839e7f..c4ba254010 100644 --- a/packages/core/test/actions/session.test.ts +++ b/packages/core/test/actions/session.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" -import { parse } from "cookie" +import * as cookie from "../../src/lib/vendored/cookie.js" import { MemoryAdapter, initMemory } from "../memory-adapter.js" import { randomString } from "../../src/lib/utils/web.js" -import { AdapterUser } from "../../adapters.js" +import type { AdapterUser } from "../../src/adapters.js" import { decode, encode } from "../../src/jwt.js" import { callbacks, @@ -16,6 +16,8 @@ import { SESSION_COOKIE_NAME, } from "../utils.js" +const { parse: parseCookie } = cookie + describe("assert GET session action", () => { beforeEach(() => { vi.resetAllMocks() @@ -61,11 +63,9 @@ describe("assert GET session action", () => { }) const actualBodySession = await response.json() - let cookies = response.headers - .getSetCookie() - .reduce>((acc, cookie) => { - return { ...acc, ...parse(cookie) } - }, {}) + let cookies = response.headers.getSetCookie().reduce((acc, cookie) => { + return { ...acc, ...parseCookie(cookie) } + }, {}) const sessionToken = cookies[SESSION_COOKIE_NAME] const actualToken = await decode({ salt: SESSION_COOKIE_NAME, @@ -176,11 +176,9 @@ describe("assert GET session action", () => { const actualBodySession = await response.json() - let cookies = response.headers - .getSetCookie() - .reduce>((acc, cookie) => { - return { ...acc, ...parse(cookie) } - }, {}) + let cookies = response.headers.getSetCookie().reduce((acc, cookie) => { + return { ...acc, ...parseCookie(cookie) } + }, {}) const actualSessionToken = cookies[SESSION_COOKIE_NAME] expect(memory.users.get(expectedUserId)).toEqual(expectedUser) @@ -248,11 +246,9 @@ describe("assert GET session action", () => { const actualBodySession = await response.json() - let cookies = response.headers - .getSetCookie() - .reduce>((acc, cookie) => { - return { ...acc, ...parse(cookie) } - }, {}) + let cookies = response.headers.getSetCookie().reduce((acc, cookie) => { + return { ...acc, ...parseCookie(cookie) } + }, {}) const actualSessionToken = cookies[SESSION_COOKIE_NAME] expect(memory.users.get(expectedUserId)).toEqual(expectedUser) diff --git a/packages/frameworks-express/package.json b/packages/frameworks-express/package.json index 733c01e410..8cc30c7a43 100644 --- a/packages/frameworks-express/package.json +++ b/packages/frameworks-express/package.json @@ -1,7 +1,7 @@ { "name": "@auth/express", "description": "Authentication for Express.", - "version": "0.8.2", + "version": "0.8.4", "type": "module", "files": [ "*.js", diff --git a/packages/frameworks-qwik/package.json b/packages/frameworks-qwik/package.json index ba0d61117d..f9cff757c0 100644 --- a/packages/frameworks-qwik/package.json +++ b/packages/frameworks-qwik/package.json @@ -1,6 +1,6 @@ { "name": "@auth/qwik", - "version": "0.5.2", + "version": "0.5.4", "description": "Authentication for Qwik.", "license": "ISC", "author": "gioboa ", diff --git a/packages/frameworks-solid-start/package.json b/packages/frameworks-solid-start/package.json index 7a44e934b6..cbd93399c7 100644 --- a/packages/frameworks-solid-start/package.json +++ b/packages/frameworks-solid-start/package.json @@ -1,6 +1,6 @@ { "name": "@auth/solid-start", - "version": "0.15.2", + "version": "0.15.4", "description": "Authentication for SolidStart.", "license": "ISC", "author": "OrJDev ", diff --git a/packages/frameworks-solid-start/src/client.ts b/packages/frameworks-solid-start/src/client.ts index e52f3ede3a..ab809927fe 100644 --- a/packages/frameworks-solid-start/src/client.ts +++ b/packages/frameworks-solid-start/src/client.ts @@ -1,19 +1,30 @@ -import type { - BuiltInProviderType, - RedirectableProviderType, -} from "@auth/core/providers" +import type { ProviderId } from "@auth/core/providers" -type LiteralUnion = T | (U & Record) - -interface SignInOptions extends Record { +interface SignInOptions + extends Record { + /** @deprecated Use `redirectTo` instead. */ + callbackUrl?: string /** - * Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from. + * Specify where the user should be redirected to after a successful signin. * - * [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl) + * By default, it is the page the sign-in was initiated from. */ - callbackUrl?: string - /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */ - redirect?: boolean + redirectTo?: string + /** + * You might want to deal with the signin response on the same page, instead of redirecting to another page. + * For example, if an error occurs (like wrong credentials given by the user), you might want to show an inline error message on the input field. + * + * For this purpose, you can set this to option `redirect: false`. + */ + redirect?: Redirect +} + +export interface SignInResponse { + error: string | undefined + code: string | undefined + status: number + ok: boolean + url: string | null } interface SignOutParams { @@ -41,59 +52,81 @@ export type SignInAuthorizationParams = * signIn("provider") // example: signIn("github") * ``` */ -export async function signIn< - P extends RedirectableProviderType | undefined = undefined, ->( - providerId?: LiteralUnion< - P extends RedirectableProviderType - ? P | BuiltInProviderType - : BuiltInProviderType - >, - options?: SignInOptions, + +/** + * Initiates a signin flow or sends the user to the signin page listing all possible providers. + * Handles CSRF protection. + * + * @note This method can only be used from Client Components ("use client" or Pages Router). + * For Server Actions, use the `signIn` method imported from the `auth` config. + */ +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, authorizationParams?: SignInAuthorizationParams -) { - const { callbackUrl = window.location.href, redirect = true } = options ?? {} +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise { + const { callbackUrl, ...rest } = options ?? {} + const { + redirect = true, + redirectTo = callbackUrl ?? window.location.href, + ...signInParams + } = rest - // TODO: Support custom providers - const isCredentials = providerId === "credentials" - const isEmail = providerId === "email" - const isSupportingReturn = isCredentials || isEmail + const isCredentials = provider === "credentials" - // TODO: Handle custom base path const signInUrl = `/api/auth/${ isCredentials ? "callback" : "signin" - }/${providerId}` - - const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}` + }/${provider}` // TODO: Handle custom base path const csrfTokenResponse = await fetch("/api/auth/csrf") const { csrfToken } = await csrfTokenResponse.json() + const res = await fetch( + `${signInUrl}?${new URLSearchParams(authorizationParams)}`, + { + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "X-Auth-Return-Redirect": "1", + }, + body: new URLSearchParams({ + ...signInParams, + csrfToken, + callbackUrl: redirectTo, + }), + } + ) - const res = await fetch(_signInUrl, { - method: "post", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "X-Auth-Return-Redirect": "1", - }, - // @ts-ignore - body: new URLSearchParams({ - ...options, - csrfToken, - callbackUrl, - }), - }) + const data = await res.json() - const data = await res.clone().json() - const error = new URL(data.url).searchParams.get("error") - if (redirect || !isSupportingReturn || !error) { - // TODO: Do not redirect for Credentials and Email providers by default in next major - window.location.href = data.url ?? data.redirect ?? callbackUrl + if (redirect) { + const url = data.url ?? redirectTo + window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually - if (data.url.includes("#")) window.location.reload() + if (url.includes("#")) window.location.reload() return } - return res + + const error = new URL(data.url).searchParams.get("error") ?? undefined + const code = new URL(data.url).searchParams.get("code") ?? undefined + + return { + error, + code, + status: res.status, + ok: res.ok, + url: error ? null : data.url, + } } /** diff --git a/packages/frameworks-sveltekit/package.json b/packages/frameworks-sveltekit/package.json index 552eb633bf..b4d8e7f9fb 100644 --- a/packages/frameworks-sveltekit/package.json +++ b/packages/frameworks-sveltekit/package.json @@ -1,6 +1,6 @@ { "name": "@auth/sveltekit", - "version": "1.7.2", + "version": "1.7.4", "description": "Authentication for SvelteKit.", "keywords": [ "authentication", diff --git a/packages/frameworks-sveltekit/src/lib/client.ts b/packages/frameworks-sveltekit/src/lib/client.ts index cac737e69d..5e708acdc3 100644 --- a/packages/frameworks-sveltekit/src/lib/client.ts +++ b/packages/frameworks-sveltekit/src/lib/client.ts @@ -1,29 +1,44 @@ import { base } from "$app/paths" -import type { - BuiltInProviderType, - RedirectableProviderType, -} from "@auth/core/providers" -import type { LiteralUnion } from "./types.js" - -/* - * @internal - */ -export interface SignInOptions extends Record { +import type { ProviderId } from "@auth/core/providers" + +export interface SignInOptions + extends Record { + /** @deprecated Use `redirectTo` instead. */ + callbackUrl?: string /** - * Specify to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from. + * Specify where the user should be redirected to after a successful signin. * - * [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl) + * By default, it is the page the sign-in was initiated from. */ - callbackUrl?: string - /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */ - redirect?: boolean + redirectTo?: string + /** + * You might want to deal with the signin response on the same page, instead of redirecting to another page. + * For example, if an error occurs (like wrong credentials given by the user), you might want to show an inline error message on the input field. + * + * For this purpose, you can set this to option `redirect: false`. + */ + redirect?: Redirect +} + +export interface SignInResponse { + error: string | undefined + code: string | undefined + status: number + ok: boolean + url: string | null } -interface SignOutParams { - /** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */ +export interface SignOutParams { + /** @deprecated Use `redirectTo` instead. */ callbackUrl?: string + /** + * If you pass `redirect: false`, the page will not reload. + * The session will be deleted, and `useSession` is notified, so any indication about the user will be shown as logged out automatically. + * It can give a very nice experience for the user. + */ + redirectTo?: string /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */ - redirect?: R + redirect?: Redirect } /** Match `inputType` of `new URLSearchParams(inputType)` */ @@ -39,79 +54,122 @@ export type SignInAuthorizationParams = * * [Documentation](https://authjs.dev/reference/sveltekit/client#signin) */ -export async function signIn< - P extends RedirectableProviderType | undefined = undefined, ->( - providerId?: LiteralUnion< - P extends RedirectableProviderType - ? P | BuiltInProviderType - : BuiltInProviderType - >, - options?: SignInOptions, - authorizationParams?: SignInAuthorizationParams -) { - const { callbackUrl = window.location.href, redirect = true } = options ?? {} - // TODO: Support custom providers - const isCredentials = providerId === "credentials" - const isEmail = providerId === "email" - const isSupportingReturn = isCredentials || isEmail +/** + * Initiates a signin flow or sends the user to the signin page listing all possible providers. + * Handles CSRF protection. + * + * @note This method can only be used from Client Components ("use client" or Pages Router). + * For Server Actions, use the `signIn` method imported from the `auth` config. + */ +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise { + const { callbackUrl, ...rest } = options ?? {} + const { + redirect = true, + redirectTo = callbackUrl ?? window.location.href, + ...signInParams + } = rest - const basePath = base ?? "" - const signInUrl = `${basePath}/auth/${ - isCredentials ? "callback" : "signin" - }/${providerId}` + const baseUrl = base ?? "" - const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}` + const signInUrl = `${baseUrl}/${ + provider === "credentials" ? "callback" : "signin" + }/${provider}` - const res = await fetch(_signInUrl, { - method: "post", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "X-Auth-Return-Redirect": "1", - }, - // @ts-ignore - body: new URLSearchParams({ - ...options, - callbackUrl, - }), - }) + const res = await fetch( + `${signInUrl}?${new URLSearchParams(authorizationParams)}`, + { + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "X-Auth-Return-Redirect": "1", + }, + body: new URLSearchParams({ + ...signInParams, + callbackUrl: redirectTo, + }), + } + ) - const data = await res.clone().json() + const data = await res.json() - if (redirect || !isSupportingReturn) { - // TODO: Do not redirect for Credentials and Email providers by default in next major - window.location.href = data.url ?? callbackUrl + if (redirect) { + const url = data.url ?? redirectTo + window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually - if (data.url.includes("#")) window.location.reload() + if (url.includes("#")) window.location.reload() return } - return res + const error = new URL(data.url).searchParams.get("error") ?? undefined + const code = new URL(data.url).searchParams.get("code") ?? undefined + + return { + error, + code, + status: res.status, + ok: res.ok, + url: error ? null : data.url, + } +} + +export interface SignOutResponse { + url: string } /** - * Signs the user out, by removing the session cookie. + * Initiate a signout, by destroying the current session. + * Handles CSRF protection. * - * [Documentation](https://authjs.dev/reference/sveltekit/client#signout) + * @note This method can only be used from Client Components ("use client" or Pages Router). + * For Server Actions, use the `signOut` method imported from the `auth` config. */ -export async function signOut(options?: SignOutParams) { - const { callbackUrl = window.location.href } = options ?? {} - const basePath = base ?? "" - const res = await fetch(`${basePath}/auth/signout`, { +export async function signOut(options?: SignOutParams): Promise +export async function signOut( + options?: SignOutParams +): Promise +export async function signOut( + options?: SignOutParams +): Promise { + const { + redirect = true, + redirectTo = options?.callbackUrl ?? window.location.href, + } = options ?? {} + + const baseUrl = base ?? "" + const res = await fetch(`${baseUrl}/signout`, { method: "post", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Auth-Return-Redirect": "1", }, body: new URLSearchParams({ - callbackUrl, + callbackUrl: redirectTo, }), }) const data = await res.json() - const url = data.url ?? callbackUrl - window.location.href = url - // If url contains a hash, the browser does not reload the page. We reload manually - if (url.includes("#")) window.location.reload() + if (redirect) { + const url = data.url ?? redirectTo + window.location.href = url + // If url contains a hash, the browser does not reload the page. We reload manually + if (url.includes("#")) window.location.reload() + return + } + + return data } diff --git a/packages/frameworks-sveltekit/src/lib/components/SignIn.svelte b/packages/frameworks-sveltekit/src/lib/components/SignIn.svelte index 3026ee9950..01f07c7df6 100644 --- a/packages/frameworks-sveltekit/src/lib/components/SignIn.svelte +++ b/packages/frameworks-sveltekit/src/lib/components/SignIn.svelte @@ -16,6 +16,7 @@ : options?.redirectTo const redirect = options instanceof FormData ? options.get("redirect") : options?.redirectTo + const redirectTo = callbackUrl const authorizationParamsInputs = authorizationParams ? typeof authorizationParams === "string" && authorizationParams @@ -38,6 +39,9 @@ {#if redirect} {/if} + {#if redirectTo} + + {/if} {#if authorizationParamsInputs} {#each Object.entries(authorizationParamsInputs) as [key, value]} diff --git a/packages/frameworks-sveltekit/src/lib/index.ts b/packages/frameworks-sveltekit/src/lib/index.ts index e1007b4719..532ca2149d 100644 --- a/packages/frameworks-sveltekit/src/lib/index.ts +++ b/packages/frameworks-sveltekit/src/lib/index.ts @@ -65,12 +65,14 @@ * * ### Server-side * - * `` and `` are components that `@auth/sveltekit` provides out of the box - they handle the sign-in/signout flow, and can be used as-is as a starting point or customized for your own components. This is an example of how to use the `SignIn` and `SignOut` components to login and logout using SvelteKit's server-side form actions. You will need two things to make this work: + * `` and `` are components that `@auth/sveltekit` provides out of the box - they handle the sign-in/signout flow, and can be used as-is as a starting point or customized for your own components. This is an example of how to use the `SignIn` and `SignOut` components to login and logout using SvelteKit's server-side form actions. Another example is available on [our svelte-auth-example repo](https://github.com/nextauthjs/sveltekit-auth-example). * - * 1. Using the components in your SvelteKit app's frontend + * You will need two things to make this work: + * + * 1. Using the components in your SvelteKit app's frontend (for instance `src/routes/+page.svelte`) * 2. Add the required `page.server.ts` at `/signin` (for `SignIn`) and `/signout` (for `SignOut`) to handle the form actions * - * ```ts + * ```ts title="src/routes/+page.svelte" * * *
    @@ -177,7 +182,7 @@ * ``` * * What you return in the function `LayoutServerLoad` will be available inside the `$page` store, in the `data` property: `$page.data`. - * In this case we return an object with the 'session' property which is what we are accessing in the other code paths. + * In this case we return an object with the `session` property which is what we are accessing in the other code paths. * * ## Handling authorization * @@ -186,7 +191,7 @@ * ### Per component * * The simplest case is protecting a single page, in which case you should put the logic in the `+page.server.ts` file. - * Notice in this case that you could also await event.parent and grab the session from there, however this implementation works even if you haven't done the above in your root `+layout.server.ts` + * Notice in this case that you could also `await event.parent` and grab the session from there, however this implementation works even if you haven't done the above in your root `+layout.server.ts` * * ```ts * import { redirect } from '@sveltejs/kit'; @@ -202,7 +207,7 @@ * :::danger * Make sure to ALWAYS grab the session information from the parent instead of using the store in the case of a `PageLoad`. * Not doing so can lead to users being able to incorrectly access protected information in the case the `+layout.server.ts` does not run for that page load. - * This code sample already implements the correct method by using `const { session } = await parent();`. For more information on SvelteKit's `load` functionality behaviour and its implications on authentication, see this [SvelteKit docs section](https://kit.svelte.dev/docs/load#implications-for-authentication). + * For more information on SvelteKit's `load` functionality behaviour and its implications on authentication, see this [SvelteKit docs section](https://kit.svelte.dev/docs/load#implications-for-authentication). * ::: * * You should NOT put authorization logic in a `+layout.server.ts` as the logic is not guaranteed to propagate to leafs in the tree. diff --git a/packages/frameworks-sveltekit/src/lib/types.ts b/packages/frameworks-sveltekit/src/lib/types.ts index a1cfdff1d8..d57da40628 100644 --- a/packages/frameworks-sveltekit/src/lib/types.ts +++ b/packages/frameworks-sveltekit/src/lib/types.ts @@ -1,11 +1,7 @@ import type { AuthConfig } from "@auth/core" -import type { BuiltInProviderType } from "@auth/core/providers" +import type { ProviderId } from "@auth/core/providers" import type { Session } from "@auth/core/types" -export type LiteralUnion = - | T - | (U & Record) - /** Configure the {@link SvelteKitAuth} method. */ export interface SvelteKitAuthConfig extends Omit {} @@ -16,19 +12,16 @@ declare global { auth(): Promise /** @deprecated Use `auth` instead. */ getSession(): Promise - signIn: < - P extends BuiltInProviderType | (string & NonNullable), - R extends boolean = true, - >( + signIn: ( /** Provider to sign in to */ - provider?: P, // See: https://github.com/microsoft/TypeScript/issues/29729 + provider?: ProviderId, // See: https://github.com/microsoft/TypeScript/issues/29729 options?: | FormData | ({ /** The URL to redirect to after signing in. By default, the user is redirected to the current page. */ redirectTo?: string /** If set to `false`, the `signIn` method will return the URL to redirect to instead of redirecting automatically. */ - redirect?: R + redirect?: Redirect // eslint-disable-next-line @typescript-eslint/no-explicit-any } & Record), authorizationParams?: @@ -37,18 +30,18 @@ declare global { | string | URLSearchParams ) => Promise< - R extends false + Redirect extends false ? // eslint-disable-next-line @typescript-eslint/no-explicit-any any : never > - signOut: (options?: { + signOut: (options?: { /** The URL to redirect to after signing out. By default, the user is redirected to the current page. */ redirectTo?: string /** If set to `false`, the `signOut` method will return the URL to redirect to instead of redirecting automatically. */ - redirect?: R + redirect?: Redirect }) => Promise< - R extends false + Redirect extends false ? // eslint-disable-next-line @typescript-eslint/no-explicit-any any : never diff --git a/packages/frameworks-sveltekit/src/lib/webauthn.ts b/packages/frameworks-sveltekit/src/lib/webauthn.ts index 9ef4d4ed04..1847ea12eb 100644 --- a/packages/frameworks-sveltekit/src/lib/webauthn.ts +++ b/packages/frameworks-sveltekit/src/lib/webauthn.ts @@ -1,30 +1,36 @@ import { base } from "$app/paths" import { startAuthentication, startRegistration } from "@simplewebauthn/browser" -import type { - BuiltInProviderType, - RedirectableProviderType, -} from "@auth/core/providers" +import type { LoggerInstance } from "@auth/core/types" import type { WebAuthnOptionsResponseBody } from "@auth/core/types" -import type { SignInOptions, SignInAuthorizationParams } from "./client.js" -import type { LiteralUnion } from "./types.js" +import type { ProviderId } from "@auth/core/providers" +import type { + SignInAuthorizationParams, + SignInOptions, + SignInResponse, +} from "./client.js" + +const logger: LoggerInstance = { + debug: console.debug, + error: console.error, + warn: console.warn, +} /** * Fetch webauthn options from server and prompt user for authentication or registration. * Returns either the completed WebAuthn response or an error request. - * - * @param providerId provider ID - * @param options SignInOptions - * @returns WebAuthn response or error */ -async function webAuthnOptions(providerId: string, options?: SignInOptions) { - const baseUrl = `${base}/auth` +async function webAuthnOptions( + providerID: ProviderId, + options?: Omit +) { + const baseUrl = base ?? "" // @ts-expect-error const params = new URLSearchParams(options) const optionsResp = await fetch( - `${baseUrl}/webauthn-options/${providerId}?${params}` + `${baseUrl}/webauthn-options/${providerID}?${params}` ) if (!optionsResp.ok) { return { error: optionsResp } @@ -41,72 +47,84 @@ async function webAuthnOptions(providerId: string, options?: SignInOptions) { } /** - * Client-side method to initiate a webauthn signin flow - * or send the user to the signin page listing all possible providers. - * - * [Documentation](https://authjs.dev/reference/sveltekit/client#signin) + * Initiate a WebAuthn signin flow. + * @see https://authjs.dev/getting-started/authentication/webauthn */ -export async function signIn< - P extends RedirectableProviderType | undefined = undefined, ->( - providerId?: LiteralUnion< - P extends RedirectableProviderType - ? P | BuiltInProviderType - : BuiltInProviderType - >, - options?: SignInOptions, +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, authorizationParams?: SignInAuthorizationParams -) { - const { callbackUrl = window.location.href, redirect = true } = options ?? {} - - // TODO: Support custom providers - const isCredentials = providerId === "credentials" - const isEmail = providerId === "email" - const isWebAuthn = providerId === "webauthn" - const isSupportingReturn = isCredentials || isEmail || isWebAuthn +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise { + const { callbackUrl, ...rest } = options ?? {} + const { + redirectTo = callbackUrl ?? window.location.href, + redirect = true, + ...signInParams + } = rest - const basePath = base ?? "" - const signInUrl = `${basePath}/auth/${ - isCredentials || isWebAuthn ? "callback" : "signin" - }/${providerId}` + const baseUrl = base ?? "" - const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}` + if (!provider || provider !== "webauthn") { + // TODO: Add docs link with explanation + throw new TypeError( + [ + `Provider id "${provider}" does not refer to a WebAuthn provider.`, + 'Please use `import { signIn } from "@auth/sveltekit/client"` instead.', + ].join("\n") + ) + } - // Execute WebAuthn client flow if needed const webAuthnBody: Record = {} - if (isWebAuthn) { - const { data, error, action } = await webAuthnOptions(providerId, options) - if (error) { - // logger.error(new Error(await error.text())) - return - } - webAuthnBody.data = JSON.stringify(data) - webAuthnBody.action = action + const webAuthnResponse = await webAuthnOptions(provider, signInParams) + if (webAuthnResponse.error) { + logger.error(new Error(await webAuthnResponse.error.text())) + return } + webAuthnBody.data = JSON.stringify(webAuthnResponse.data) + webAuthnBody.action = webAuthnResponse.action - const res = await fetch(_signInUrl, { + const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}` + const res = await fetch(signInUrl, { method: "post", headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Auth-Return-Redirect": "1", }, - // @ts-ignore body: new URLSearchParams({ - ...options, - callbackUrl, + ...signInParams, ...webAuthnBody, + callbackUrl: redirectTo, }), }) - const data = await res.clone().json() + const data = await res.json() - if (redirect || !isSupportingReturn) { - // TODO: Do not redirect for Credentials and Email providers by default in next major - window.location.href = data.url ?? callbackUrl + if (redirect) { + const url = data.url ?? callbackUrl + window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually - if (data.url.includes("#")) window.location.reload() + if (url.includes("#")) window.location.reload() return } - return res + const error = new URL(data.url).searchParams.get("error") + const code = new URL(data.url).searchParams.get("code") + + return { + error, + code, + status: res.status, + ok: res.ok, + url: error ? null : data.url, + } as any } diff --git a/packages/next-auth/src/index.ts b/packages/next-auth/src/index.ts index 37be71b531..e6e5f06db3 100644 --- a/packages/next-auth/src/index.ts +++ b/packages/next-auth/src/index.ts @@ -73,7 +73,7 @@ import { initAuth } from "./lib/index.js" import { signIn, signOut, update } from "./lib/actions.js" import type { Awaitable, Session } from "@auth/core/types" -import type { BuiltInProviderType } from "@auth/core/providers" +import type { ProviderId } from "@auth/core/providers" import type { GetServerSidePropsContext, NextApiRequest, @@ -289,10 +289,7 @@ export interface NextAuthResult { * ``` * */ - signIn: < - P extends BuiltInProviderType | (string & {}), - R extends boolean = true, - >( + signIn:

    ( /** Provider to sign in to */ provider?: P, // See: https://github.com/microsoft/TypeScript/issues/29729 options?: diff --git a/packages/next-auth/src/lib/client.ts b/packages/next-auth/src/lib/client.ts index e702ac70e1..22b0f0cbb2 100644 --- a/packages/next-auth/src/lib/client.ts +++ b/packages/next-auth/src/lib/client.ts @@ -1,7 +1,7 @@ "use client" import * as React from "react" -import type { BuiltInProviderType, ProviderType } from "@auth/core/providers" +import type { ProviderId, ProviderType } from "@auth/core/providers" import type { LoggerInstance, Session } from "@auth/core/types" import { AuthError } from "@auth/core/errors" @@ -33,14 +33,8 @@ export interface UseSessionOptions { onUnauthenticated?: () => void } -// Util type that matches some strings literally, but allows any other string as well. -// @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611 -export type LiteralUnion = - | T - | (U & Record) - export interface ClientSafeProvider { - id: LiteralUnion + id: ProviderId name: string type: ProviderType signinUrl: string @@ -48,14 +42,14 @@ export interface ClientSafeProvider { redirectTo: string } -export interface SignInOptions extends Record { - /** - * @deprecated Use `redirectTo` instead. - */ +export interface SignInOptions + extends Record { + /** @deprecated Use `redirectTo` instead. */ callbackUrl?: string /** * Specify where the user should be redirected to after a successful signin. - * Defaults to the page URL the sign-in is initiated from. + * + * By default, it is the page the sign-in was initiated from. */ redirectTo?: string /** @@ -64,7 +58,7 @@ export interface SignInOptions extends Record { * * For this purpose, you can set this to option `redirect: false`. */ - redirect?: boolean + redirect?: Redirect } export interface SignInResponse { @@ -90,11 +84,9 @@ export interface SignOutResponse { url: string } -export interface SignOutParams { - /** @deprecated Use `redirectTo` instead. - */ +export interface SignOutParams { + /** @deprecated Use `redirectTo` instead. */ callbackUrl?: string - /** * If you pass `redirect: false`, the page will not reload. * The session will be deleted, and `useSession` is notified, so any indication about the user will be shown as logged out automatically. @@ -102,7 +94,7 @@ export interface SignOutParams { */ redirectTo?: string /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */ - redirect?: R + redirect?: Redirect } /** diff --git a/packages/next-auth/src/lib/types.ts b/packages/next-auth/src/lib/types.ts index 5617581780..e934a7a9e1 100644 --- a/packages/next-auth/src/lib/types.ts +++ b/packages/next-auth/src/lib/types.ts @@ -1,12 +1,13 @@ // @ts-expect-error Next.js does not yet correctly use the `package.json#exports` field import type { NextRequest } from "next/server" +import type { Awaitable } from "@auth/core/types" /** * AppRouteHandlerFnContext is the context that is passed to the handler as the * second argument. */ export type AppRouteHandlerFnContext = { - params?: Record + params: Awaitable> } /** * Handler function for app routes. If a non-Response value is returned, an error diff --git a/packages/next-auth/src/react.tsx b/packages/next-auth/src/react.tsx index e23e3609e0..a900155c68 100644 --- a/packages/next-auth/src/react.tsx +++ b/packages/next-auth/src/react.tsx @@ -22,15 +22,11 @@ import { useOnline, } from "./lib/client.js" -import type { - BuiltInProviderType, - RedirectableProviderType, -} from "@auth/core/providers" +import type { ProviderId } from "@auth/core/providers" import type { LoggerInstance, Session } from "@auth/core/types" import type { AuthClientConfig, ClientSafeProvider, - LiteralUnion, SessionProviderProps, SignInAuthorizationParams, SignInOptions, @@ -42,7 +38,6 @@ import type { // TODO: Remove/move to core? export type { - LiteralUnion, SignInOptions, SignInAuthorizationParams, SignOutParams, @@ -209,61 +204,74 @@ export async function getCsrfToken() { return response?.csrfToken ?? "" } -type ProvidersType = Record< - LiteralUnion, - ClientSafeProvider -> - -/** - * Returns a client-safe configuration object of the currently - * available providers. - */ export async function getProviders() { - return fetchData("providers", __NEXTAUTH, logger) + return fetchData>( + "providers", + __NEXTAUTH, + logger + ) } /** - * Initiate a signin flow or send the user to the signin page listing all possible providers. + * Initiates a signin flow or sends the user to the signin page listing all possible providers. * Handles CSRF protection. + * + * @note This method can only be used from Client Components ("use client" or Pages Router). + * For Server Actions, use the `signIn` method imported from the `auth` config. */ -export async function signIn< - P extends RedirectableProviderType | undefined = undefined, ->( - provider?: LiteralUnion< - P extends RedirectableProviderType - ? P | BuiltInProviderType - : BuiltInProviderType - >, - options?: SignInOptions, +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, authorizationParams?: SignInAuthorizationParams -): Promise< - P extends RedirectableProviderType ? SignInResponse | undefined : undefined -> { - const { redirect = true } = options ?? {} - const redirectTo = - options?.redirectTo ?? options?.callbackUrl ?? window.location.href +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise { + const { callbackUrl, ...rest } = options ?? {} + const { + redirect = true, + redirectTo = callbackUrl ?? window.location.href, + ...signInParams + } = rest const baseUrl = apiBaseUrl(__NEXTAUTH) const providers = await getProviders() if (!providers) { - window.location.href = `${baseUrl}/error` - return + const url = `${baseUrl}/error` + window.location.href = url + return // TODO: Return error if `redirect: false` } - if (!provider || !(provider in providers)) { - window.location.href = `${baseUrl}/signin?${new URLSearchParams({ + if (!provider || !providers[provider]) { + const url = `${baseUrl}/signin?${new URLSearchParams({ callbackUrl: redirectTo, })}` - return + window.location.href = url + return // TODO: Return error if `redirect: false` } - const isCredentials = providers[provider].type === "credentials" - const isEmail = providers[provider].type === "email" - const isSupportingReturn = isCredentials || isEmail + const providerType = providers[provider].type + + if (providerType === "webauthn") { + // TODO: Add docs link with explanation + throw new TypeError( + [ + `Provider id "${provider}" refers to a WebAuthn provider.`, + 'Please use `import { signIn } from "next-auth/webauthn"` instead.', + ].join("\n") + ) + } const signInUrl = `${baseUrl}/${ - isCredentials ? "callback" : "signin" + providerType === "credentials" ? "callback" : "signin" }/${provider}` const csrfToken = await getCsrfToken() @@ -275,9 +283,8 @@ export async function signIn< "Content-Type": "application/x-www-form-urlencoded", "X-Auth-Return-Redirect": "1", }, - // @ts-expect-error body: new URLSearchParams({ - ...options, + ...signInParams, csrfToken, callbackUrl: redirectTo, }), @@ -286,8 +293,7 @@ export async function signIn< const data = await res.json() - // TODO: Do not redirect for Credentials and Email providers by default in next major - if (redirect || !isSupportingReturn) { + if (redirect) { const url = data.url ?? redirectTo window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually @@ -295,8 +301,8 @@ export async function signIn< return } - const error = new URL(data.url).searchParams.get("error") - const code = new URL(data.url).searchParams.get("code") + const error = new URL(data.url).searchParams.get("error") ?? undefined + const code = new URL(data.url).searchParams.get("code") ?? undefined if (res.ok) { await __NEXTAUTH._getSession({ event: "storage" }) @@ -308,18 +314,28 @@ export async function signIn< status: res.status, ok: res.ok, url: error ? null : data.url, - } as any + } } /** * Initiate a signout, by destroying the current session. * Handles CSRF protection. + * + * @note This method can only be used from Client Components ("use client" or Pages Router). + * For Server Actions, use the `signOut` method imported from the `auth` config. */ +export async function signOut(options?: SignOutParams): Promise +export async function signOut( + options?: SignOutParams +): Promise export async function signOut( options?: SignOutParams -): Promise { - const redirectTo = - options?.redirectTo ?? options?.callbackUrl ?? window.location.href +): Promise { + const { + redirect = true, + redirectTo = options?.callbackUrl ?? window.location.href, + } = options ?? {} + const baseUrl = apiBaseUrl(__NEXTAUTH) const csrfToken = await getCsrfToken() const res = await fetch(`${baseUrl}/signout`, { @@ -334,12 +350,11 @@ export async function signOut( broadcast().postMessage({ event: "session", data: { trigger: "signout" } }) - if (options?.redirect ?? true) { + if (redirect) { const url = data.url ?? redirectTo window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually if (url.includes("#")) window.location.reload() - // @ts-expect-error return } diff --git a/packages/next-auth/src/webauthn.ts b/packages/next-auth/src/webauthn.ts index c0511b3761..e1ed98a96b 100644 --- a/packages/next-auth/src/webauthn.ts +++ b/packages/next-auth/src/webauthn.ts @@ -4,13 +4,9 @@ import { getCsrfToken, getProviders, __NEXTAUTH } from "./react.js" import type { LoggerInstance } from "@auth/core/types" import type { WebAuthnOptionsResponseBody } from "@auth/core/types" -import type { - BuiltInProviderType, - RedirectableProviderType, -} from "@auth/core/providers" +import type { ProviderId } from "@auth/core/providers" import type { AuthClientConfig, - LiteralUnion, SignInAuthorizationParams, SignInOptions, SignInResponse, @@ -25,15 +21,11 @@ const logger: LoggerInstance = { /** * Fetch webauthn options from server and prompt user for authentication or registration. * Returns either the completed WebAuthn response or an error request. - * - * @param providerID provider ID - * @param options SignInOptions - * @returns WebAuthn response or error */ async function webAuthnOptions( - providerID: string, + providerID: ProviderId, nextAuthConfig: AuthClientConfig, - options?: SignInOptions + options?: Omit ) { const baseUrl = apiBaseUrl(nextAuthConfig) @@ -58,87 +50,84 @@ async function webAuthnOptions( } /** - * Initiate a signin flow or send the user to the signin page listing all possible providers. - * Handles CSRF protection. + * Initiate a WebAuthn signin flow. + * @see https://authjs.dev/getting-started/authentication/webauthn */ -export async function signIn< - P extends RedirectableProviderType | undefined = undefined, ->( - provider?: LiteralUnion< - P extends RedirectableProviderType - ? P | BuiltInProviderType - : BuiltInProviderType - >, - options?: SignInOptions, +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, authorizationParams?: SignInAuthorizationParams -): Promise< - P extends RedirectableProviderType ? SignInResponse | undefined : undefined -> { - const { callbackUrl = window.location.href, redirect = true } = options ?? {} +): Promise +export async function signIn( + provider?: ProviderId, + options?: SignInOptions, + authorizationParams?: SignInAuthorizationParams +): Promise { + const { callbackUrl, ...rest } = options ?? {} + const { + redirectTo = callbackUrl ?? window.location.href, + redirect = true, + ...signInParams + } = rest const baseUrl = apiBaseUrl(__NEXTAUTH) const providers = await getProviders() if (!providers) { window.location.href = `${baseUrl}/error` - return - } - - if (!provider || !(provider in providers)) { - window.location.href = `${baseUrl}/signin?${new URLSearchParams({ - callbackUrl, - })}` - return + return // TODO: Return error if `redirect: false` } - const isCredentials = providers[provider].type === "credentials" - const isEmail = providers[provider].type === "email" - const isWebAuthn = providers[provider].type === "webauthn" - const isSupportingReturn = isCredentials || isEmail || isWebAuthn - - const signInUrl = `${baseUrl}/${ - isCredentials || isWebAuthn ? "callback" : "signin" - }/${provider}` - - // Execute WebAuthn client flow if needed - const webAuthnBody: Record = {} - if (isWebAuthn) { - const { data, error, action } = await webAuthnOptions( - provider, - __NEXTAUTH, - options + if ( + !provider || + !providers[provider] || + providers[provider].type !== "webauthn" + ) { + // TODO: Add docs link with explanation + throw new TypeError( + [ + `Provider id "${provider}" does not refer to a WebAuthn provider.`, + 'Please use `import { signIn } from "next-auth/react"` instead.', + ].join("\n") ) - if (error) { - logger.error(new Error(await error.text())) - return - } - webAuthnBody.data = JSON.stringify(data) - webAuthnBody.action = action } - const csrfToken = await getCsrfToken() - const res = await fetch( - `${signInUrl}?${new URLSearchParams(authorizationParams)}`, - { - method: "post", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - "X-Auth-Return-Redirect": "1", - }, - // @ts-expect-error - body: new URLSearchParams({ - ...options, - ...webAuthnBody, - csrfToken, - callbackUrl, - }), - } + const webAuthnBody: Record = {} + const webAuthnResponse = await webAuthnOptions( + provider, + __NEXTAUTH, + signInParams ) + if (webAuthnResponse.error) { + logger.error(new Error(await webAuthnResponse.error.text())) + return + } + webAuthnBody.data = JSON.stringify(webAuthnResponse.data) + webAuthnBody.action = webAuthnResponse.action + + const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}` + const res = await fetch(signInUrl, { + method: "post", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "X-Auth-Return-Redirect": "1", + }, + body: new URLSearchParams({ + ...signInParams, + ...webAuthnBody, + csrfToken: await getCsrfToken(), + callbackUrl: redirectTo, + }), + }) const data = await res.json() - // TODO: Do not redirect for Credentials and Email providers by default in next major - if (redirect || !isSupportingReturn) { + if (redirect) { const url = data.url ?? callbackUrl window.location.href = url // If url contains a hash, the browser does not reload the page. We reload manually diff --git a/packages/utils/scripts/providers.js b/packages/utils/scripts/providers.js index 4ab14b501c..57691369e5 100644 --- a/packages/utils/scripts/providers.js +++ b/packages/utils/scripts/providers.js @@ -13,7 +13,7 @@ const args = parseArgs({ const { out } = args.values const destinationDir = resolve(process.cwd(), join(out, "providers")) -const nonProvider = ["oauth-types.ts", "oauth.ts"] +const nonProvider = ["provider-types.ts", "oauth.ts"] try { await fs.mkdir(destinationDir, { recursive: true }) const files = (await fs.readdir(sourceDir)).filter( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f836236d91..2b88826609 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -278,11 +278,11 @@ importers: specifier: ^4.2.3 version: 4.2.3(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0)) nextra: - specifier: 3.0.0-alpha.24 - version: 3.0.0-alpha.24(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + specifier: 3.0.15 + version: 3.0.15(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) nextra-theme-docs: - specifier: 3.0.0-alpha.24 - version: 3.0.0-alpha.24(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(nextra@3.0.0-alpha.24(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 3.0.15 + version: 3.0.15(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(nextra@3.0.15(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: 18.3.1 version: 18.3.1 @@ -377,7 +377,7 @@ importers: version: 0.23.0 drizzle-orm: specifier: ^0.32.0 - version: 0.32.1(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@prisma/client@5.20.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6) + version: 0.32.1(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@prisma/client@6.0.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.27.5)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6) libsql: specifier: ^0.3.18 version: 0.3.18 @@ -463,8 +463,8 @@ importers: specifier: ^8.6.5 version: 8.11.0 kysely: - specifier: ^0.24.2 - version: 0.24.2 + specifier: ^0.27.5 + version: 0.27.5 libsql: specifier: ^0.3.18 version: 0.3.18 @@ -550,17 +550,17 @@ importers: version: link:../core devDependencies: '@prisma/client': - specifier: ^5.20.0 - version: 5.20.0(prisma@5.20.0) + specifier: ^6.0.0 + version: 6.0.0(prisma@6.0.0) '@prisma/extension-accelerate': specifier: 1.1.0 - version: 1.1.0(@prisma/client@5.20.0(prisma@5.20.0)) + version: 1.1.0(@prisma/client@6.0.0(prisma@6.0.0)) mongodb: specifier: ^6.9.0 version: 6.9.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0)(socks@2.7.1) prisma: - specifier: ^5.20.0 - version: 5.20.0 + specifier: ^6.0.0 + version: 6.0.0 packages/adapter-sequelize: dependencies: @@ -663,27 +663,21 @@ importers: '@panva/hkdf': specifier: ^1.2.1 version: 1.2.1 - '@types/cookie': - specifier: 0.6.0 - version: 0.6.0 - cookie: - specifier: 0.7.1 - version: 0.7.1 jose: - specifier: ^5.9.3 - version: 5.9.3 + specifier: ^5.9.6 + version: 5.9.6 nodemailer: specifier: ^6.8.0 version: 6.9.8 oauth4webapi: - specifier: ^3.0.0 - version: 3.0.0 + specifier: ^3.1.4 + version: 3.1.4 preact: - specifier: 10.11.3 - version: 10.11.3 + specifier: 10.24.3 + version: 10.24.3 preact-render-to-string: - specifier: 5.2.3 - version: 5.2.3(preact@10.11.3) + specifier: 6.5.11 + version: 6.5.11(preact@10.24.3) devDependencies: '@simplewebauthn/browser': specifier: 9.0.1 @@ -710,8 +704,8 @@ importers: specifier: 8.4.19 version: 8.4.19 postcss-nesting: - specifier: ^12.0.2 - version: 12.0.2(postcss@8.4.19) + specifier: ^12.1.5 + version: 12.1.5(postcss@8.4.19) typedoc: specifier: ^0.25.12 version: 0.25.13(typescript@5.6.3) @@ -879,7 +873,7 @@ importers: version: link:../core '@preact/preset-vite': specifier: ^2.8.1 - version: 2.8.1(@babel/core@7.23.9)(preact@10.24.2)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0)) + version: 2.8.1(@babel/core@7.23.9)(preact@10.24.3)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0)) dotenv: specifier: ^10.0.0 version: 10.0.0 @@ -952,6 +946,9 @@ packages: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} + '@antfu/install-pkg@0.4.1': + resolution: {integrity: sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==} + '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} @@ -1904,8 +1901,8 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@braintree/sanitize-url@6.0.4': - resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} + '@braintree/sanitize-url@7.1.0': + resolution: {integrity: sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==} '@builder.io/qwik-city@1.5.5': resolution: {integrity: sha512-Xi/1WqrB91CpZcAXs43OC87+7h89hJczJp43FXUMrvTHGeUsR/udhpz6SZWI/mHh0PFNx6f0A59tPmtDDzYl0Q==} @@ -1925,6 +1922,21 @@ packages: '@changesets/types@5.2.1': resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} + '@chevrotain/cst-dts-gen@11.0.3': + resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} + + '@chevrotain/gast@11.0.3': + resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} + + '@chevrotain/regexp-to-ast@11.0.3': + resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} + + '@chevrotain/types@11.0.3': + resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} + + '@chevrotain/utils@11.0.3': + resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} + '@clack/core@0.3.4': resolution: {integrity: sha512-H4hxZDXgHtWTwV3RAVenqcC4VbJZNegbBjlPvzOzCouXtS2y3sDvlO3IsbrPNWuLWPPlYVYPghQdSF64683Ldw==} @@ -1951,8 +1963,14 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@csstools/selector-specificity@3.0.1': - resolution: {integrity: sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==} + '@csstools/selector-resolve-nested@1.1.0': + resolution: {integrity: sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.13 + + '@csstools/selector-specificity@3.1.1': + resolution: {integrity: sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss-selector-parser: ^6.0.13 @@ -2744,6 +2762,18 @@ packages: '@floating-ui/dom@1.6.11': resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==} + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.26.25': + resolution: {integrity: sha512-hZOmgN0NTOzOuZxI1oIrDu3Gcl8WViIkvPMpB4xdd4QD6xAMtwgwr3VPoiyH/bLtRcS1cDnhxLSD1NsMJmwh/A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + '@floating-ui/utils@0.1.6': resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} @@ -2753,6 +2783,9 @@ packages: '@floating-ui/utils@0.2.8': resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} + '@formatjs/intl-localematcher@0.5.5': + resolution: {integrity: sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==} + '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} @@ -3000,12 +3033,12 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - '@headlessui/react@1.7.19': - resolution: {integrity: sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==} + '@headlessui/react@2.1.10': + resolution: {integrity: sha512-6mLa2fjMDAFQi+/R10B+zU3edsUk/MDtENB2zHho0lqKU1uzhAfJLUduWds4nCo8wbl3vULtC5rJfZAQ1yqIng==} engines: {node: '>=10'} peerDependencies: - react: ^16 || ^17 || ^18 - react-dom: ^16 || ^17 || ^18 + react: ^18 + react-dom: ^18 '@hexagon/base64@1.1.28': resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} @@ -3030,6 +3063,12 @@ packages: '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + '@iconify/types@2.0.0': + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + + '@iconify/utils@2.1.33': + resolution: {integrity: sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==} + '@img/sharp-darwin-arm64@0.33.5': resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -3391,6 +3430,9 @@ packages: '@types/react': '>=16' react: '>=16' + '@mermaid-js/parser@0.3.0': + resolution: {integrity: sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==} + '@microsoft/api-extractor-model@7.28.13': resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} @@ -3928,9 +3970,6 @@ packages: '@polka/url@1.0.0-next.24': resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} - '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@preact/preset-vite@2.8.1': resolution: {integrity: sha512-a9KV4opdj17X2gOFuGup0aE+sXYABX/tJi/QDptOrleX4FlnoZgDWvz45tHOdVfrZX+3uvVsIYPHxRsTerkDNA==} peerDependencies: @@ -3960,23 +3999,23 @@ packages: peerDependencies: prettier: ^3.0.0 - '@prisma/client@5.20.0': - resolution: {integrity: sha512-CLv55ZuMuUawMsxoqxGtLT3bEZoa2W8L3Qnp6rDIFWy+ZBrUcOFKdoeGPSnbBqxc3SkdxJrF+D1veN/WNynZYA==} - engines: {node: '>=16.13'} + '@prisma/client@6.0.0': + resolution: {integrity: sha512-tOBhG35ozqZ/5Y6B0TNOa6cwULUW8ijXqBXcgb12bfozqf6eGMyGs+jphywCsj6uojv5lAZZnxVSoLMVebIP+g==} + engines: {node: '>=18.18'} peerDependencies: prisma: '*' peerDependenciesMeta: prisma: optional: true - '@prisma/debug@5.20.0': - resolution: {integrity: sha512-oCx79MJ4HSujokA8S1g0xgZUGybD4SyIOydoHMngFYiwEwYDQ5tBQkK5XoEHuwOYDKUOKRn/J0MEymckc4IgsQ==} + '@prisma/debug@6.0.0': + resolution: {integrity: sha512-eUjoNThlDXdyJ1iQ2d7U6aTVwm59EwvODb5zFVNJEokNoSiQmiYWNzZIwZyDmZ+j51j42/0iTaHIJ4/aZPKFRg==} - '@prisma/engines-version@5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284': - resolution: {integrity: sha512-Lg8AS5lpi0auZe2Mn4gjuCg081UZf88k3cn0RCwHgR+6cyHHpttPZBElJTHf83ZGsRNAmVCZCfUGA57WB4u4JA==} + '@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e': + resolution: {integrity: sha512-JmIds0Q2/vsOmnuTJYxY4LE+sajqjYKhLtdOT6y4imojqv5d/aeVEfbBGC74t8Be1uSp0OP8lxIj2OqoKbLsfQ==} - '@prisma/engines@5.20.0': - resolution: {integrity: sha512-DtqkP+hcZvPEbj8t8dK5df2b7d3B8GNauKqaddRRqQBBlgkbdhJkxhoJTrOowlS3vaRt2iMCkU0+CSNn0KhqAQ==} + '@prisma/engines@6.0.0': + resolution: {integrity: sha512-ZZCVP3q22ifN6Ex6C8RIcTDBlRtMJS2H1ljV0knCiWNGArvvkEbE88W3uDdq/l4+UvyvHpGzdf9ZsCWSQR7ZQQ==} '@prisma/extension-accelerate@1.1.0': resolution: {integrity: sha512-sESjhBZ4ywQjAVpKzsfhxyNu+9txIM5I6M1MPBaJBq/xDlqmniIAhlwIEt9KLtO80zqPxqbZYes18zrkgYqNiQ==} @@ -3984,11 +4023,11 @@ packages: peerDependencies: '@prisma/client': '>=4.16.1' - '@prisma/fetch-engine@5.20.0': - resolution: {integrity: sha512-JVcaPXC940wOGpCOwuqQRTz6I9SaBK0c1BAyC1pcz9xBi+dzFgUu3G/p9GV1FhFs9OKpfSpIhQfUJE9y00zhqw==} + '@prisma/fetch-engine@6.0.0': + resolution: {integrity: sha512-j2m+iO5RDPRI7SUc7sHo8wX7SA4iTkJ+18Sxch8KinQM46YiCQD1iXKN6qU79C1Fliw5Bw/qDyTHaTsa3JMerA==} - '@prisma/get-platform@5.20.0': - resolution: {integrity: sha512-8/+CehTZZNzJlvuryRgc77hZCWrUDYd/PmlZ7p2yNXtmf2Una4BWnTbak3us6WVdqoz5wmptk6IhsXdG2v5fmA==} + '@prisma/get-platform@6.0.0': + resolution: {integrity: sha512-PS6nYyIm9g8C03E4y7LknOfdCw/t2KyEJxntMPQHQZCOUgOpF82Ma60mdlOD08w90I3fjLiZZ0+MadenR3naDQ==} '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -4195,6 +4234,37 @@ packages: '@types/react': optional: true + '@react-aria/focus@3.18.4': + resolution: {integrity: sha512-91J35077w9UNaMK1cpMUEFRkNNz0uZjnSwiyBCFuRdaVuivO53wNC9XtWSDNDdcO5cGy87vfJRVAiyoCn/mjqA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + + '@react-aria/interactions@3.22.4': + resolution: {integrity: sha512-E0vsgtpItmknq/MJELqYJwib+YN18Qag8nroqwjk1qOnBa9ROIkUhWJerLi1qs5diXq9LHKehZDXRlwPvdEFww==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + + '@react-aria/ssr@3.9.6': + resolution: {integrity: sha512-iLo82l82ilMiVGy342SELjshuWottlb5+VefO3jOQqQRNYnJBFpUSadswDPbRimSgJUZuFwIEYs6AabkP038fA==} + engines: {node: '>= 12'} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + + '@react-aria/utils@3.25.3': + resolution: {integrity: sha512-PR5H/2vaD8fSq0H/UB9inNbc8KDcVmW6fYAfSWkkn+OAdhTTMVKqXXrZuZBWyFfSD5Ze7VN6acr4hrOQm2bmrA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + + '@react-stately/utils@3.10.4': + resolution: {integrity: sha512-gBEQEIMRh5f60KCm7QKQ2WfvhB2gLUr9b72sqUdIZ2EG+xuPgaIlCBeSicvjmjBvYZwOjoOEnmIkcx2GHp/HWw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + + '@react-types/shared@3.25.0': + resolution: {integrity: sha512-OZSyhzU6vTdW3eV/mz5i6hQwQUhkRs7xwY2d1aqPvTdMe0+2cY7Fwp45PAiwYLEj73i9ro2FxF9qC4DvHGSCgQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 + '@redis/bloom@1.2.0': resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} peerDependencies: @@ -4871,13 +4941,13 @@ packages: '@tediousjs/connection-string@0.3.0': resolution: {integrity: sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ==} - '@theguild/remark-mermaid@0.0.5': - resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} + '@theguild/remark-mermaid@0.1.3': + resolution: {integrity: sha512-2FjVlaaKXK7Zj7UJAgOVTyaahn/3/EAfqYhyXg0BfDBVUl+lXcoIWRaxzqfnDr2rv8ax6GsC5mNh6hAaT86PDw==} peerDependencies: react: ^18.2.0 - '@theguild/remark-npm2yarn@0.3.0': - resolution: {integrity: sha512-Fofw+9airYgjBd9G6PiHHCrptjyUybQ50JH9/5o9LCH54kggJ7stpCofzHjICB8L7VQbQ1Gwu23P/3CMVY1R4Q==} + '@theguild/remark-npm2yarn@0.3.2': + resolution: {integrity: sha512-H9T/GOuS/+4H7AY1cfD5DJIIIcGIIw1zMCB8OeTgXk7azJULsnuOurZ/CR54rvuTD+Krx0MVQccaUCvCWfP+vw==} '@tootallnate/once@1.1.2': resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} @@ -4948,15 +5018,6 @@ packages: '@types/cookiejar@2.1.5': resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - '@types/d3-scale-chromatic@3.0.3': - resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} - - '@types/d3-scale@4.0.8': - resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} - - '@types/d3-time@3.0.3': - resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} - '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -5056,8 +5117,8 @@ packages: '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} - '@types/nlcst@1.0.4': - resolution: {integrity: sha512-ABoYdNQ/kBSsLvZAekMhIPMQ3YUZvavStpKYs7BjLLuKVmIMA0LUgZ7b54zzuWJRbHF80v1cNf4r90Vd6eMQDg==} + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -5909,14 +5970,17 @@ packages: abstract-leveldown@2.7.2: resolution: {integrity: sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==} + deprecated: Superseded by abstract-level (https://github.com/Level/community#faq) abstract-leveldown@6.2.3: resolution: {integrity: sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==} engines: {node: '>=6'} + deprecated: Superseded by abstract-level (https://github.com/Level/community#faq) abstract-leveldown@6.3.0: resolution: {integrity: sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ==} engines: {node: '>=6'} + deprecated: Superseded by abstract-level (https://github.com/Level/community#faq) accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -6349,7 +6413,7 @@ packages: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} buffer-equal-constant-time@1.0.1: - resolution: {integrity: sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=} + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -6483,6 +6547,14 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + chevrotain-allstar@0.3.1: + resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} + peerDependencies: + chevrotain: ^11.0.0 + + chevrotain@11.0.3: + resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -6716,7 +6788,7 @@ packages: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} concat-map@0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} @@ -6771,10 +6843,6 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} - cookie@0.7.1: - resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} - engines: {node: '>= 0.6'} - cookiejar@2.1.4: resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} @@ -6790,6 +6858,9 @@ packages: cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + cose-base@2.2.0: + resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} + cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} @@ -6881,6 +6952,11 @@ packages: peerDependencies: cytoscape: ^3.2.0 + cytoscape-fcose@2.2.0: + resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} + peerDependencies: + cytoscape: ^3.2.0 + cytoscape@3.30.2: resolution: {integrity: sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==} engines: {node: '>=0.10'} @@ -7132,6 +7208,7 @@ packages: deferred-leveldown@5.3.0: resolution: {integrity: sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw==} engines: {node: '>=6'} + deprecated: Superseded by abstract-level (https://github.com/Level/community#faq) define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} @@ -7404,7 +7481,7 @@ packages: hasBin: true ee-first@1.1.1: - resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} ejs@3.1.9: resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} @@ -7417,9 +7494,6 @@ packages: electron-to-chromium@1.5.36: resolution: {integrity: sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==} - elkjs@0.9.3: - resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -7961,9 +8035,6 @@ packages: focus-trap@7.5.2: resolution: {integrity: sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==} - focus-visible@5.2.1: - resolution: {integrity: sha512-8Bx950VD1bWTQJEH/AM6SpEk+SU55aVnp4Ujhuuxy3eMEBCRwBnTBnVXr9YAPvZL3/CNjCa8u4IWfNmEO53whA==} - follow-redirects@1.15.5: resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} engines: {node: '>=4.0'} @@ -8173,7 +8244,7 @@ packages: resolution: {integrity: sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==} github-from-package@0.0.0: - resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=} + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -8289,6 +8360,9 @@ packages: h3@1.11.1: resolution: {integrity: sha512-AbaH6IDnZN6nmbnJOH72y3c5Wwh9P97soSVdGSBbcDACRdkC0FEWf25pzx4f/NuOCK6quHmW18yF2Wx+G4Zi1A==} + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} @@ -8630,9 +8704,6 @@ packages: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} - intersection-observer@0.12.2: - resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} - invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} @@ -8962,8 +9033,8 @@ packages: jose@4.15.4: resolution: {integrity: sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==} - jose@5.9.3: - resolution: {integrity: sha512-egLIoYSpcd+QUF+UHgobt5YzI2Pkw/H39ou9suW687MY6PmCwPmkNV/4TNjn1p2tX5xO3j0d0sq5hiYE24bSlg==} + jose@5.9.6: + resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==} js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} @@ -9138,13 +9209,20 @@ packages: kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - kysely@0.24.2: - resolution: {integrity: sha512-+7eaTJNUYm2yRq1x+lEOZc+78TO35dTZ9b0dh49+Z9CTt2byMSbMiOKpwPlOyCAaHD4kILkAYWYZNywFlmBwRA==} + kysely@0.27.5: + resolution: {integrity: sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA==} engines: {node: '>=14.0.0'} + langium@3.0.0: + resolution: {integrity: sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==} + engines: {node: '>=16.0.0'} + layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + layout-base@2.0.1: + resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + leac@0.6.0: resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} @@ -9220,6 +9298,7 @@ packages: level-js@5.0.2: resolution: {integrity: sha512-SnBIDo2pdO5VXh02ZmtAyPP6/+6YTJg2ibLtl9C34pWvmtMEmRTWpra+qO/hifkUtBTOtfx6S9vLDjBsBK4gRg==} + deprecated: Superseded by browser-level (https://github.com/Level/community#faq) level-packager@5.1.1: resolution: {integrity: sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ==} @@ -9239,10 +9318,12 @@ packages: leveldown@5.6.0: resolution: {integrity: sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==} engines: {node: '>=8.6.0'} + deprecated: Superseded by classic-level (https://github.com/Level/community#faq) levelup@4.4.0: resolution: {integrity: sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ==} engines: {node: '>=6'} + deprecated: Superseded by abstract-level (https://github.com/Level/community#faq) levn@0.3.0: resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} @@ -9448,7 +9529,7 @@ packages: resolution: {integrity: sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==} ltgt@2.2.1: - resolution: {integrity: sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=} + resolution: {integrity: sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==} lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} @@ -9509,6 +9590,11 @@ packages: markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + marked@13.0.3: + resolution: {integrity: sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==} + engines: {node: '>= 18'} + hasBin: true + marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} @@ -9593,11 +9679,12 @@ packages: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} media-typer@0.3.0: - resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} memdown@1.4.1: resolution: {integrity: sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w==} + deprecated: Superseded by memory-level (https://github.com/Level/community#faq) memory-pager@1.5.0: resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} @@ -9620,8 +9707,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - mermaid@10.9.2: - resolution: {integrity: sha512-UkZyMSuIYcI1Q0H+2pv/5CiY84sOwQ2XlKoDZMl9Y/MtrLEtxQtyA6LWGkMxnZxj0dJqI+7nw51bYjNnrbdFsQ==} + mermaid@11.3.0: + resolution: {integrity: sha512-fFmf2gRXLtlGzug4wpIGN+rQdZ30M8IZEB1D3eZkXNqC7puhqeURBcD/9tbwXsqBO+A6Nzzo3MSSepmnw5xSeg==} meros@1.3.0: resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} @@ -10155,24 +10242,24 @@ packages: sass: optional: true - nextra-theme-docs@3.0.0-alpha.24: - resolution: {integrity: sha512-AUuv3o1xYzGGvUP/lxxf7i++Zyycy4bH22l6T8uDVez2n0j/RDbzqmSIdL4Jh4POUd0fyxEG+BUomKXKyj3L1g==} + nextra-theme-docs@3.0.15: + resolution: {integrity: sha512-AhvmgcjFYi7aT5nRjdozqCt1hW39tqCIRKi4+pIR62ri26miB3VxREBYlCTHezcML2VLunyYIjFiiQGUan09gA==} peerDependencies: next: '>=13' - nextra: 3.0.0-alpha.24 - react: '>=16.13.1' - react-dom: '>=16.13.1' + nextra: 3.0.15 + react: '>=18' + react-dom: '>=18' - nextra@3.0.0-alpha.24: - resolution: {integrity: sha512-KScl/DQG68JBGy6gfOFNdVcrlc24YvcegGnYwUXvpCoHx2YcBUSp6FE7LeaX/C/mI4PPIMmTJuEWIjGH9DXeCQ==} + nextra@3.0.15: + resolution: {integrity: sha512-iLKFNYwq8sciXPK9RPRmgifELSA2JLgEfL5y54stq7MvXuKn44MZJNzdhkJF4MXvx1HobzYLHl3/e37/Yf2htA==} engines: {node: '>=18'} peerDependencies: next: '>=13' - react: '>=16.13.1' - react-dom: '>=16.13.1' + react: '>=18' + react-dom: '>=18' - nlcst-to-string@3.1.1: - resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==} + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} @@ -10260,9 +10347,6 @@ packages: resolution: {integrity: sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==} engines: {node: '>=6.0.0'} - non-layered-tidy-tree-layout@2.0.2: - resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} - nopt@1.0.10: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true @@ -10307,8 +10391,8 @@ packages: resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - npm-to-yarn@2.2.1: - resolution: {integrity: sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==} + npm-to-yarn@3.0.0: + resolution: {integrity: sha512-76YnmsbfrYp0tMsWxM0RNX0Vs+x8JxpJGu6B/jDn4lW8+laiTcKmKi9MeMh4UikO4RkJ1oqURoDy9bXJmMXS6A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} npmlog@5.0.1: @@ -10329,8 +10413,8 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} - oauth4webapi@3.0.0: - resolution: {integrity: sha512-Rw9SxQYuQX9J41VgM4rVNGtm1ng0Qcd8ndv7JmhmwqQ3hHBokX+WjV379IJhKk7bVPHefgvrDgHoO/rB2dY7YA==} + oauth4webapi@3.1.4: + resolution: {integrity: sha512-eVfN3nZNbok2s/ROifO0UAc5G8nRoLSbrcKJ09OqmucgnhXEfdIQOR4gq1eJH1rN3gV7rNw62bDEgftsgFtBEg==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -10461,14 +10545,14 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-limit@5.0.0: resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} engines: {node: '>=18'} + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -10485,6 +10569,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-manager-detector@0.2.2: + resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} + packet-reader@1.0.0: resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} @@ -10510,8 +10597,8 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse-latin@5.0.1: - resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} parse-multipart-data@1.5.0: resolution: {integrity: sha512-ck5zaMF0ydjGfejNMnlo5YU2oJ+pT+80Jb1y4ybanT27j+zbVP/jkYmCrUGsEln0Ox/hZmuvgy8Ra7AxbXP2Mw==} @@ -10553,6 +10640,9 @@ packages: path-case@3.0.4: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -10717,6 +10807,12 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + postcss-discard-duplicates@6.0.3: resolution: {integrity: sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==} engines: {node: ^14 || ^16 || >=18.0} @@ -10783,8 +10879,8 @@ packages: peerDependencies: postcss: ^8.2.14 - postcss-nesting@12.0.2: - resolution: {integrity: sha512-63PpJHSeNs93S3ZUIyi+7kKx4JqOIEJ6QYtG3x+0qA4J03+4n0iwsyA1GAHyWxsHYljQS4/4ZK1o2sMi70b5wQ==} + postcss-nesting@12.1.5: + resolution: {integrity: sha512-N1NgI1PDCiAGWPTYrwqm8wpjv0bgDmkYHH72pNsqTCv9CObxjxftdYu6AKtGN+pnJa7FQjMm3v4sp8QJbFsYdQ==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss: ^8.4 @@ -10926,16 +11022,13 @@ packages: pouchdb@8.0.1: resolution: {integrity: sha512-xp5S83JOQn2NAL0ZQ5CU+DI26V9/YrYuVtkXnbGEIDrYiFfj5A8gAcfbxefXb/9O+Qn4n5RaT/19+8UBSZ42sw==} - preact-render-to-string@5.2.3: - resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} + preact-render-to-string@6.5.11: + resolution: {integrity: sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==} peerDependencies: preact: '>=10' - preact@10.11.3: - resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} - - preact@10.24.2: - resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} + preact@10.24.3: + resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} @@ -11029,17 +11122,14 @@ packages: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - pretty-format@3.8.0: - resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} - prism-react-renderer@2.1.0: resolution: {integrity: sha512-I5cvXHjA1PVGbGm1MsWCpvBCRrYyxEri0MC7/JbfIfYfcXAxHyO5PaUjs3A8H5GW6kJcLhTHxxMaOZZpRZD2iQ==} peerDependencies: react: '>=16.0.0' - prisma@5.20.0: - resolution: {integrity: sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==} - engines: {node: '>=16.13'} + prisma@6.0.0: + resolution: {integrity: sha512-RX7KtbW7IoEByf7MR32JK1PkVYLVYFqeODTtiIX3cqekq1aKdsF3Eud4zp2sUShMLjvdb5Jow0LbUjRq5LVxPw==} + engines: {node: '>=18.18'} hasBin: true prismjs@1.29.0: @@ -11404,11 +11494,11 @@ packages: rehype-parse@9.0.0: resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} - rehype-pretty-code@0.13.0: - resolution: {integrity: sha512-+22dz1StXlF7dlMyOySNaVxgcGhMI4BCxq0JxJJPWYGiKsI6cu5jyuIKGHXHvH18D8sv1rdKtvsY9UEfN3++SQ==} + rehype-pretty-code@0.14.0: + resolution: {integrity: sha512-hBeKF/Wkkf3zyUS8lal9RCUuhypDWLQc+h9UrP9Pav25FUm/AQAVh4m5gdvJxh4Oz+U+xKvdsV01p1LdvsZTiQ==} engines: {node: '>=18'} peerDependencies: - shiki: ^1.0.0 + shiki: ^1.3.0 rehype-raw@6.1.1: resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} @@ -11446,9 +11536,9 @@ packages: remark-rehype@11.1.0: resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} - remark-smartypants@2.1.0: - resolution: {integrity: sha512-qoF6Vz3BjU2tP6OfZqHOvCU0ACmu/6jhGaINSQRI9mM7wCxNQTKB3JUAN4SVoN2ybElEDTxBIABRep7e569iJw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} @@ -11502,17 +11592,17 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - retext-latin@3.1.0: - resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} - retext-smartypants@5.2.0: - resolution: {integrity: sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==} + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} - retext-stringify@3.1.0: - resolution: {integrity: sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==} + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} - retext@8.1.0: - resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==} + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} retry-as-promised@7.0.4: resolution: {integrity: sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==} @@ -11580,6 +11670,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + route-sort@1.0.0: resolution: {integrity: sha512-SFgmvjoIhp5S4iBEDW3XnbT+7PRuZ55oRuNjY+CDB1SGZkyCG9bqQ3/dhaZTctTBYMAvDxd2Uy9dStuaUfgJqQ==} engines: {node: '>= 6'} @@ -12416,6 +12509,9 @@ packages: tinybench@2.6.0: resolution: {integrity: sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==} + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + tinypool@0.8.2: resolution: {integrity: sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==} engines: {node: '>=14.0.0'} @@ -12460,7 +12556,7 @@ packages: engines: {node: '>=0.6'} token-stream@1.0.0: - resolution: {integrity: sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=} + resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==} toposort-class@1.0.1: resolution: {integrity: sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==} @@ -12843,9 +12939,6 @@ packages: unenv@1.9.0: resolution: {integrity: sha512-QKnFNznRxmbOF1hDgzpqrlIf6NC5sbZ2OJ+5Wl3OX8uM+LUJXbj4TXvLJCtwbPTmbMHCLIz6JLKNinNsMShK9g==} - unherit@3.0.1: - resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} - unicode-canonical-property-names-ecmascript@2.0.0: resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} engines: {node: '>=4'} @@ -12886,8 +12979,8 @@ packages: unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} - unist-util-modify-children@3.1.1: - resolution: {integrity: sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==} + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} unist-util-position-from-estree@2.0.0: resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} @@ -12910,8 +13003,8 @@ packages: unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - unist-util-visit-children@2.0.2: - resolution: {integrity: sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==} + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} unist-util-visit-parents@4.1.1: resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} @@ -13085,7 +13178,7 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} utils-merge@1.0.1: - resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=} + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} uuid@10.0.0: @@ -13278,12 +13371,32 @@ packages: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} engines: {node: '>=0.10.0'} + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + vue-template-compiler@2.7.16: resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} @@ -13311,9 +13424,6 @@ packages: resolution: {integrity: sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==} engines: {node: '>= 8'} - web-worker@1.3.0: - resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==} - webcrypto-core@1.7.8: resolution: {integrity: sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg==} @@ -13561,9 +13671,9 @@ packages: zen-observable@0.8.15: resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} - zod-validation-error@1.5.0: - resolution: {integrity: sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw==} - engines: {node: '>=16.0.0'} + zod-validation-error@3.4.0: + resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} + engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.18.0 @@ -13672,6 +13782,11 @@ snapshots: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.25 + '@antfu/install-pkg@0.4.1': + dependencies: + package-manager-detector: 0.2.2 + tinyexec: 0.3.1 + '@antfu/utils@0.7.10': {} '@apollo/client@3.9.5(@types/react@18.2.78)(graphql-ws@5.14.3(graphql@16.8.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -15291,7 +15406,7 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@braintree/sanitize-url@6.0.4': {} + '@braintree/sanitize-url@7.1.0': {} '@builder.io/qwik-city@1.5.5(@types/node@20.12.7)(rollup@4.18.0)(sass@1.70.0)(terser@5.27.0)': dependencies: @@ -15375,6 +15490,23 @@ snapshots: '@changesets/types@5.2.1': {} + '@chevrotain/cst-dts-gen@11.0.3': + dependencies: + '@chevrotain/gast': 11.0.3 + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/gast@11.0.3': + dependencies: + '@chevrotain/types': 11.0.3 + lodash-es: 4.17.21 + + '@chevrotain/regexp-to-ast@11.0.3': {} + + '@chevrotain/types@11.0.3': {} + + '@chevrotain/utils@11.0.3': {} + '@clack/core@0.3.4': dependencies: picocolors: 1.1.0 @@ -15404,9 +15536,13 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@csstools/selector-specificity@3.0.1(postcss-selector-parser@6.0.16)': + '@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.2)': dependencies: - postcss-selector-parser: 6.0.16 + postcss-selector-parser: 6.1.2 + + '@csstools/selector-specificity@3.1.1(postcss-selector-parser@6.1.2)': + dependencies: + postcss-selector-parser: 6.1.2 '@emnapi/runtime@1.2.0': dependencies: @@ -15904,12 +16040,30 @@ snapshots: '@floating-ui/core': 1.6.8 '@floating-ui/utils': 0.2.8 + '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/dom': 1.6.11 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@floating-ui/react@0.26.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/utils': 0.2.8 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tabbable: 6.2.0 + '@floating-ui/utils@0.1.6': {} '@floating-ui/utils@0.2.7': {} '@floating-ui/utils@0.2.8': {} + '@formatjs/intl-localematcher@0.5.5': + dependencies: + tslib: 2.7.0 + '@gar/promisify@1.1.3': optional: true @@ -16312,7 +16466,7 @@ snapshots: graphql-request: 6.1.0(encoding@0.1.13)(graphql@16.8.1) http-proxy-agent: 7.0.0 https-proxy-agent: 7.0.2 - jose: 5.9.3 + jose: 5.9.6 js-yaml: 4.1.0 json-stable-stringify: 1.1.1 lodash: 4.17.21 @@ -16407,10 +16561,12 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 - '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@headlessui/react@2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: + '@floating-ui/react': 0.26.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-aria/focus': 3.18.4(react@18.3.1) + '@react-aria/interactions': 3.22.4(react@18.3.1) '@tanstack/react-virtual': 3.10.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - client-only: 0.0.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16432,6 +16588,20 @@ snapshots: '@iarna/toml@2.2.5': {} + '@iconify/types@2.0.0': {} + + '@iconify/utils@2.1.33': + dependencies: + '@antfu/install-pkg': 0.4.1 + '@antfu/utils': 0.7.10 + '@iconify/types': 2.0.0 + debug: 4.3.7(supports-color@8.1.1) + kolorist: 1.8.0 + local-pkg: 0.5.0 + mlly: 1.7.2 + transitivePeerDependencies: + - supports-color + '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.4 @@ -16909,6 +17079,10 @@ snapshots: '@types/react': 18.2.78 react: 18.3.1 + '@mermaid-js/parser@0.3.0': + dependencies: + langium: 3.0.0 + '@microsoft/api-extractor-model@7.28.13(@types/node@22.7.5)': dependencies: '@microsoft/tsdoc': 0.14.2 @@ -17543,14 +17717,12 @@ snapshots: '@polka/url@1.0.0-next.24': {} - '@popperjs/core@2.11.8': {} - - '@preact/preset-vite@2.8.1(@babel/core@7.23.9)(preact@10.24.2)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0))': + '@preact/preset-vite@2.8.1(@babel/core@7.23.9)(preact@10.24.3)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0))': dependencies: '@babel/core': 7.23.9 '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.9) '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.9) - '@prefresh/vite': 2.4.5(preact@10.24.2)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0)) + '@prefresh/vite': 2.4.5(preact@10.24.3)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0)) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.23.9) debug: 4.3.7(supports-color@8.1.1) @@ -17565,20 +17737,20 @@ snapshots: '@prefresh/babel-plugin@0.5.1': {} - '@prefresh/core@1.5.2(preact@10.24.2)': + '@prefresh/core@1.5.2(preact@10.24.3)': dependencies: - preact: 10.24.2 + preact: 10.24.3 '@prefresh/utils@1.2.0': {} - '@prefresh/vite@2.4.5(preact@10.24.2)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0))': + '@prefresh/vite@2.4.5(preact@10.24.3)(vite@5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0))': dependencies: '@babel/core': 7.23.9 '@prefresh/babel-plugin': 0.5.1 - '@prefresh/core': 1.5.2(preact@10.24.2) + '@prefresh/core': 1.5.2(preact@10.24.3) '@prefresh/utils': 1.2.0 '@rollup/pluginutils': 4.2.1 - preact: 10.24.2 + preact: 10.24.3 vite: 5.3.1(@types/node@22.7.5)(sass@1.70.0)(terser@5.27.0) transitivePeerDependencies: - supports-color @@ -17588,34 +17760,34 @@ snapshots: prettier: 3.3.3 pug-lexer: 5.0.1 - '@prisma/client@5.20.0(prisma@5.20.0)': + '@prisma/client@6.0.0(prisma@6.0.0)': optionalDependencies: - prisma: 5.20.0 + prisma: 6.0.0 - '@prisma/debug@5.20.0': {} + '@prisma/debug@6.0.0': {} - '@prisma/engines-version@5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284': {} + '@prisma/engines-version@5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e': {} - '@prisma/engines@5.20.0': + '@prisma/engines@6.0.0': dependencies: - '@prisma/debug': 5.20.0 - '@prisma/engines-version': 5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284 - '@prisma/fetch-engine': 5.20.0 - '@prisma/get-platform': 5.20.0 + '@prisma/debug': 6.0.0 + '@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e + '@prisma/fetch-engine': 6.0.0 + '@prisma/get-platform': 6.0.0 - '@prisma/extension-accelerate@1.1.0(@prisma/client@5.20.0(prisma@5.20.0))': + '@prisma/extension-accelerate@1.1.0(@prisma/client@6.0.0(prisma@6.0.0))': dependencies: - '@prisma/client': 5.20.0(prisma@5.20.0) + '@prisma/client': 6.0.0(prisma@6.0.0) - '@prisma/fetch-engine@5.20.0': + '@prisma/fetch-engine@6.0.0': dependencies: - '@prisma/debug': 5.20.0 - '@prisma/engines-version': 5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284 - '@prisma/get-platform': 5.20.0 + '@prisma/debug': 6.0.0 + '@prisma/engines-version': 5.23.0-27.5dbef10bdbfb579e07d35cc85fb1518d357cb99e + '@prisma/get-platform': 6.0.0 - '@prisma/get-platform@5.20.0': + '@prisma/get-platform@6.0.0': dependencies: - '@prisma/debug': 5.20.0 + '@prisma/debug': 6.0.0 '@protobufjs/aspromise@1.1.2': optional: true @@ -17806,6 +17978,46 @@ snapshots: optionalDependencies: '@types/react': 18.2.78 + '@react-aria/focus@3.18.4(react@18.3.1)': + dependencies: + '@react-aria/interactions': 3.22.4(react@18.3.1) + '@react-aria/utils': 3.25.3(react@18.3.1) + '@react-types/shared': 3.25.0(react@18.3.1) + '@swc/helpers': 0.5.13 + clsx: 2.1.0 + react: 18.3.1 + + '@react-aria/interactions@3.22.4(react@18.3.1)': + dependencies: + '@react-aria/ssr': 3.9.6(react@18.3.1) + '@react-aria/utils': 3.25.3(react@18.3.1) + '@react-types/shared': 3.25.0(react@18.3.1) + '@swc/helpers': 0.5.13 + react: 18.3.1 + + '@react-aria/ssr@3.9.6(react@18.3.1)': + dependencies: + '@swc/helpers': 0.5.13 + react: 18.3.1 + + '@react-aria/utils@3.25.3(react@18.3.1)': + dependencies: + '@react-aria/ssr': 3.9.6(react@18.3.1) + '@react-stately/utils': 3.10.4(react@18.3.1) + '@react-types/shared': 3.25.0(react@18.3.1) + '@swc/helpers': 0.5.13 + clsx: 2.1.0 + react: 18.3.1 + + '@react-stately/utils@3.10.4(react@18.3.1)': + dependencies: + '@swc/helpers': 0.5.13 + react: 18.3.1 + + '@react-types/shared@3.25.0(react@18.3.1)': + dependencies: + react: 18.3.1 + '@redis/bloom@1.2.0(@redis/client@1.5.13)': dependencies: '@redis/client': 1.5.13 @@ -18751,17 +18963,17 @@ snapshots: '@tediousjs/connection-string@0.3.0': {} - '@theguild/remark-mermaid@0.0.5(react@18.3.1)': + '@theguild/remark-mermaid@0.1.3(react@18.3.1)': dependencies: - mermaid: 10.9.2 + mermaid: 11.3.0 react: 18.3.1 unist-util-visit: 5.0.0 transitivePeerDependencies: - supports-color - '@theguild/remark-npm2yarn@0.3.0': + '@theguild/remark-npm2yarn@0.3.2': dependencies: - npm-to-yarn: 2.2.1 + npm-to-yarn: 3.0.0 unist-util-visit: 5.0.0 '@tootallnate/once@1.1.2': @@ -18839,14 +19051,6 @@ snapshots: '@types/cookiejar@2.1.5': {} - '@types/d3-scale-chromatic@3.0.3': {} - - '@types/d3-scale@4.0.8': - dependencies: - '@types/d3-time': 3.0.3 - - '@types/d3-time@3.0.3': {} - '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -18951,9 +19155,9 @@ snapshots: dependencies: '@types/node': 20.12.7 - '@types/nlcst@1.0.4': + '@types/nlcst@2.0.3': dependencies: - '@types/unist': 2.0.11 + '@types/unist': 3.0.3 '@types/node@12.20.55': {} @@ -21228,6 +21432,20 @@ snapshots: dependencies: get-func-name: 2.0.2 + chevrotain-allstar@0.3.1(chevrotain@11.0.3): + dependencies: + chevrotain: 11.0.3 + lodash-es: 4.17.21 + + chevrotain@11.0.3: + dependencies: + '@chevrotain/cst-dts-gen': 11.0.3 + '@chevrotain/gast': 11.0.3 + '@chevrotain/regexp-to-ast': 11.0.3 + '@chevrotain/types': 11.0.3 + '@chevrotain/utils': 11.0.3 + lodash-es: 4.17.21 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -21519,8 +21737,6 @@ snapshots: cookie@0.6.0: {} - cookie@0.7.1: {} - cookiejar@2.1.4: {} core-js-compat@3.35.1: @@ -21535,6 +21751,10 @@ snapshots: dependencies: layout-base: 1.0.2 + cose-base@2.2.0: + dependencies: + layout-base: 2.0.1 + cosmiconfig@8.3.6(typescript@5.6.3): dependencies: import-fresh: 3.3.0 @@ -21625,6 +21845,11 @@ snapshots: cose-base: 1.0.3 cytoscape: 3.30.2 + cytoscape-fcose@2.2.0(cytoscape@3.30.2): + dependencies: + cose-base: 2.2.0 + cytoscape: 3.30.2 + cytoscape@3.30.2: {} d3-array@2.12.1: @@ -22011,19 +22236,19 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.1(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@prisma/client@5.20.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6): + drizzle-orm@0.32.1(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@prisma/client@6.0.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.27.5)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6): optionalDependencies: '@cloudflare/workers-types': 4.20240117.0 '@libsql/client': 0.6.0 '@opentelemetry/api': 1.7.0 - '@prisma/client': 5.20.0(prisma@5.20.0) + '@prisma/client': 6.0.0(prisma@6.0.0) '@types/better-sqlite3': 7.6.9 '@types/pg': 8.11.0 '@types/react': 18.2.78 '@xata.io/client': 0.28.0(typescript@5.3.3) better-sqlite3: 9.6.0 knex: 2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)) - kysely: 0.24.2 + kysely: 0.27.5 mysql2: 3.9.7 pg: 8.11.3 postgres: 3.4.3 @@ -22062,8 +22287,6 @@ snapshots: electron-to-chromium@1.5.36: {} - elkjs@0.9.3: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -23006,8 +23229,6 @@ snapshots: dependencies: tabbable: 6.2.0 - focus-visible@5.2.1: {} - follow-redirects@1.15.5(debug@4.3.7): optionalDependencies: debug: 4.3.7(supports-color@8.1.1) @@ -23418,6 +23639,8 @@ snapshots: transitivePeerDependencies: - uWebSockets.js + hachure-fill@0.5.2: {} + hard-rejection@2.1.0: {} has-bigints@1.0.2: {} @@ -23881,7 +24104,7 @@ snapshots: hogan.js: 3.0.2 htm: 3.1.1 instantsearch-ui-components: 0.9.0 - preact: 10.24.2 + preact: 10.24.3 qs: 6.9.7 search-insights: 2.17.2 @@ -23897,8 +24120,6 @@ snapshots: interpret@2.2.0: {} - intersection-observer@0.12.2: {} - invariant@2.2.4: dependencies: loose-envify: 1.4.0 @@ -24202,7 +24423,7 @@ snapshots: jose@4.15.4: {} - jose@5.9.3: {} + jose@5.9.6: {} js-base64@3.7.7: optional: true @@ -24397,10 +24618,20 @@ snapshots: kolorist@1.8.0: {} - kysely@0.24.2: {} + kysely@0.27.5: {} + + langium@3.0.0: + dependencies: + chevrotain: 11.0.3 + chevrotain-allstar: 0.3.1(chevrotain@11.0.3) + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 layout-base@1.0.2: {} + layout-base@2.0.1: {} + leac@0.6.0: {} lefthook-darwin-arm64@1.7.15: @@ -24825,6 +25056,8 @@ snapshots: markdown-table@3.0.3: {} + marked@13.0.3: {} + marked@4.3.0: {} mathjax-full@3.2.2: @@ -25013,7 +25246,7 @@ snapshots: mdast-util-phrasing@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 unist-util-is: 6.0.0 mdast-util-to-hast@12.3.0: @@ -25111,28 +25344,27 @@ snapshots: merge2@1.4.1: {} - mermaid@10.9.2: + mermaid@11.3.0: dependencies: - '@braintree/sanitize-url': 6.0.4 - '@types/d3-scale': 4.0.8 - '@types/d3-scale-chromatic': 3.0.3 + '@braintree/sanitize-url': 7.1.0 + '@iconify/utils': 2.1.33 + '@mermaid-js/parser': 0.3.0 cytoscape: 3.30.2 cytoscape-cose-bilkent: 4.1.0(cytoscape@3.30.2) + cytoscape-fcose: 2.2.0(cytoscape@3.30.2) d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.10 dayjs: 1.11.10 dompurify: 3.1.6 - elkjs: 0.9.3 katex: 0.16.9 khroma: 2.1.0 lodash-es: 4.17.21 - mdast-util-from-markdown: 1.3.1 - non-layered-tidy-tree-layout: 2.0.2 + marked: 13.0.3 + roughjs: 4.6.6 stylis: 4.3.1 ts-dedent: 2.2.0 uuid: 9.0.1 - web-worker: 1.3.0 transitivePeerDependencies: - supports-color @@ -25924,32 +26156,30 @@ snapshots: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@3.0.0-alpha.24(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(nextra@3.0.0-alpha.24(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@3.0.15(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(nextra@3.0.15(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@popperjs/core': 2.11.8 + '@headlessui/react': 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.0 escape-string-regexp: 5.0.0 flexsearch: 0.7.43 - focus-visible: 5.2.1 - intersection-observer: 0.12.2 next: 14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) next-themes: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 3.0.0-alpha.24(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + nextra: 3.0.15(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.22.4 - nextra@3.0.0-alpha.24(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3): + nextra@3.0.15(@types/react@18.2.78)(next@14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3): dependencies: - '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@formatjs/intl-localematcher': 0.5.5 + '@headlessui/react': 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mdx-js/mdx': 3.0.1 '@mdx-js/react': 3.0.0(@types/react@18.2.78)(react@18.3.1) '@napi-rs/simple-git': 0.1.16 '@shikijs/twoslash': 1.2.4(typescript@5.6.3) - '@theguild/remark-mermaid': 0.0.5(react@18.3.1) - '@theguild/remark-npm2yarn': 0.3.0 + '@theguild/remark-mermaid': 0.1.3(react@18.3.1) + '@theguild/remark-npm2yarn': 0.3.2 better-react-mathjax: 2.0.3(react@18.3.1) clsx: 2.1.0 estree-util-to-js: 2.0.0 @@ -25959,18 +26189,19 @@ snapshots: gray-matter: 4.0.3 hast-util-to-estree: 3.1.0 katex: 0.16.9 + negotiator: 0.6.3 next: 14.2.15(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) - p-limit: 4.0.0 + p-limit: 6.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) rehype-katex: 7.0.0 - rehype-pretty-code: 0.13.0(shiki@1.22.0) + rehype-pretty-code: 0.14.0(shiki@1.22.0) rehype-raw: 7.0.0 remark-frontmatter: 5.0.0 remark-gfm: 4.0.0 remark-math: 6.0.0 remark-reading-time: 2.0.1 - remark-smartypants: 2.1.0 + remark-smartypants: 3.0.2 shiki: 1.22.0 slash: 5.1.0 title: 3.5.3 @@ -25978,15 +26209,15 @@ snapshots: unist-util-visit: 5.0.0 yaml: 2.3.4 zod: 3.22.4 - zod-validation-error: 1.5.0(zod@3.22.4) + zod-validation-error: 3.4.0(zod@3.22.4) transitivePeerDependencies: - '@types/react' - supports-color - typescript - nlcst-to-string@3.1.1: + nlcst-to-string@4.0.0: dependencies: - '@types/nlcst': 1.0.4 + '@types/nlcst': 2.0.3 no-case@3.0.4: dependencies: @@ -26067,8 +26298,6 @@ snapshots: nodemailer@6.9.8: {} - non-layered-tidy-tree-layout@2.0.2: {} - nopt@1.0.10: dependencies: abbrev: 1.1.1 @@ -26113,7 +26342,7 @@ snapshots: dependencies: path-key: 4.0.0 - npm-to-yarn@2.2.1: {} + npm-to-yarn@3.0.0: {} npmlog@5.0.1: dependencies: @@ -26143,7 +26372,7 @@ snapshots: nullthrows@1.1.1: {} - oauth4webapi@3.0.0: {} + oauth4webapi@3.1.4: {} object-assign@4.1.1: {} @@ -26298,11 +26527,11 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: + p-limit@5.0.0: dependencies: yocto-queue: 1.1.1 - p-limit@5.0.0: + p-limit@6.1.0: dependencies: yocto-queue: 1.1.1 @@ -26320,6 +26549,8 @@ snapshots: p-try@2.2.0: {} + package-manager-detector@0.2.2: {} + packet-reader@1.0.0: {} param-case@3.0.4: @@ -26360,11 +26591,14 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse-latin@5.0.1: + parse-latin@7.0.0: dependencies: - nlcst-to-string: 3.1.1 - unist-util-modify-children: 3.1.1 - unist-util-visit-children: 2.0.2 + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.3 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 parse-multipart-data@1.5.0: {} @@ -26408,6 +26642,8 @@ snapshots: dot-case: 3.0.4 tslib: 2.7.0 + path-data-parser@0.1.0: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -26556,6 +26792,13 @@ snapshots: pluralize@8.0.0: {} + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + postcss-discard-duplicates@6.0.3(postcss@8.4.47): dependencies: postcss: 8.4.47 @@ -26619,11 +26862,12 @@ snapshots: postcss: 8.4.47 postcss-selector-parser: 6.0.16 - postcss-nesting@12.0.2(postcss@8.4.19): + postcss-nesting@12.1.5(postcss@8.4.19): dependencies: - '@csstools/selector-specificity': 3.0.1(postcss-selector-parser@6.0.16) + '@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.1.2) + '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) postcss: 8.4.19 - postcss-selector-parser: 6.0.16 + postcss-selector-parser: 6.1.2 postcss-normalize-whitespace@6.0.2(postcss@8.4.47): dependencies: @@ -26844,14 +27088,11 @@ snapshots: transitivePeerDependencies: - encoding - preact-render-to-string@5.2.3(preact@10.11.3): + preact-render-to-string@6.5.11(preact@10.24.3): dependencies: - preact: 10.11.3 - pretty-format: 3.8.0 - - preact@10.11.3: {} + preact: 10.24.3 - preact@10.24.2: {} + preact@10.24.3: {} prebuild-install@7.1.1: dependencies: @@ -26901,17 +27142,15 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.2.0 - pretty-format@3.8.0: {} - prism-react-renderer@2.1.0(react@18.3.1): dependencies: '@types/prismjs': 1.26.3 clsx: 1.2.1 react: 18.3.1 - prisma@5.20.0: + prisma@6.0.0: dependencies: - '@prisma/engines': 5.20.0 + '@prisma/engines': 6.0.0 optionalDependencies: fsevents: 2.3.3 @@ -27370,7 +27609,7 @@ snapshots: hast-util-from-html: 2.0.1 unified: 11.0.5 - rehype-pretty-code@0.13.0(shiki@1.22.0): + rehype-pretty-code@0.14.0(shiki@1.22.0): dependencies: '@types/hast': 3.0.4 hast-util-to-string: 3.0.0 @@ -27475,10 +27714,11 @@ snapshots: unified: 11.0.5 vfile: 6.0.1 - remark-smartypants@2.1.0: + remark-smartypants@3.0.2: dependencies: - retext: 8.1.0 - retext-smartypants: 5.2.0 + retext: 9.0.0 + retext-smartypants: 6.2.0 + unified: 11.0.5 unist-util-visit: 5.0.0 remark-stringify@11.0.0: @@ -27529,32 +27769,30 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - retext-latin@3.1.0: + retext-latin@4.0.0: dependencies: - '@types/nlcst': 1.0.4 - parse-latin: 5.0.1 - unherit: 3.0.1 - unified: 10.1.2 + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 - retext-smartypants@5.2.0: + retext-smartypants@6.2.0: dependencies: - '@types/nlcst': 1.0.4 - nlcst-to-string: 3.1.1 - unified: 10.1.2 - unist-util-visit: 4.1.2 + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.0.0 - retext-stringify@3.1.0: + retext-stringify@4.0.0: dependencies: - '@types/nlcst': 1.0.4 - nlcst-to-string: 3.1.1 - unified: 10.1.2 + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 - retext@8.1.0: + retext@9.0.0: dependencies: - '@types/nlcst': 1.0.4 - retext-latin: 3.1.0 - retext-stringify: 3.1.0 - unified: 10.1.2 + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 retry-as-promised@7.0.4: {} @@ -27632,6 +27870,13 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + route-sort@1.0.0: {} run-applescript@5.0.0: @@ -28634,6 +28879,8 @@ snapshots: tinybench@2.6.0: {} + tinyexec@0.3.1: {} + tinypool@0.8.2: {} tinyspy@2.2.0: {} @@ -29014,8 +29261,6 @@ snapshots: node-fetch-native: 1.6.4 pathe: 1.1.2 - unherit@3.0.1: {} - unicode-canonical-property-names-ecmascript@2.0.0: {} unicode-match-property-ecmascript@2.0.0: @@ -29070,11 +29315,11 @@ snapshots: unist-util-is@6.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 - unist-util-modify-children@3.1.1: + unist-util-modify-children@4.0.0: dependencies: - '@types/unist': 2.0.11 + '@types/unist': 3.0.3 array-iterate: 2.0.1 unist-util-position-from-estree@2.0.0: @@ -29108,9 +29353,9 @@ snapshots: dependencies: '@types/unist': 3.0.2 - unist-util-visit-children@2.0.2: + unist-util-visit-children@3.0.0: dependencies: - '@types/unist': 2.0.11 + '@types/unist': 3.0.3 unist-util-visit-parents@4.1.1: dependencies: @@ -29511,10 +29756,27 @@ snapshots: void-elements@3.1.0: {} + vscode-jsonrpc@8.2.0: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + vscode-oniguruma@1.7.0: {} vscode-textmate@8.0.0: {} + vscode-uri@3.0.8: {} + vue-template-compiler@2.7.16: dependencies: de-indent: 1.0.2 @@ -29547,8 +29809,6 @@ snapshots: web-streams-polyfill@3.3.2: {} - web-worker@1.3.0: {} - webcrypto-core@1.7.8: dependencies: '@peculiar/asn1-schema': 2.3.8 @@ -29802,7 +30062,7 @@ snapshots: zen-observable@0.8.15: {} - zod-validation-error@1.5.0(zod@3.22.4): + zod-validation-error@3.4.0(zod@3.22.4): dependencies: zod: 3.22.4 diff --git a/turbo.json b/turbo.json index 9e42a71a33..4836ab91ce 100644 --- a/turbo.json +++ b/turbo.json @@ -13,7 +13,7 @@ "*.d.ts", "*.d.ts.map", "src/lib/pages/styles.ts", - "src/providers/oauth-types.ts", + "src/providers/provider-types.ts", ".svelte-kit/**" ], "outputLogs": "new-only"