From aceff15352cdbb010b8b59ce2c8813cd45e856db Mon Sep 17 00:00:00 2001
From: Kevin Gao <kevinjamesgao@gmail.com>
Date: Wed, 20 Mar 2024 13:53:56 -0700
Subject: [PATCH 1/2] added descope as provider

---
 react-descope/package.json                    |  6 ++
 .../ConvexProviderWithDescope.test.tsx        | 17 ++++++
 .../ConvexProviderWithDescope.tsx             | 61 +++++++++++++++++++
 src/react-descope/index.ts                    |  6 ++
 4 files changed, 90 insertions(+)
 create mode 100644 react-descope/package.json
 create mode 100644 src/react-descope/ConvexProviderWithDescope.test.tsx
 create mode 100644 src/react-descope/ConvexProviderWithDescope.tsx
 create mode 100644 src/react-descope/index.ts

diff --git a/react-descope/package.json b/react-descope/package.json
new file mode 100644
index 0000000..de30aa5
--- /dev/null
+++ b/react-descope/package.json
@@ -0,0 +1,6 @@
+{
+    "main": "../dist/cjs/react-descope/index.js",
+    "module": "../dist/esm/react-descope/index.js",
+    "types": "../dist/internal-cjs-types/react-descope/index.d.ts"
+  }
+  
\ No newline at end of file
diff --git a/src/react-descope/ConvexProviderWithDescope.test.tsx b/src/react-descope/ConvexProviderWithDescope.test.tsx
new file mode 100644
index 0000000..4adc698
--- /dev/null
+++ b/src/react-descope/ConvexProviderWithDescope.test.tsx
@@ -0,0 +1,17 @@
+/**
+ * @jest-environment jsdom
+ */
+import { test } from "@jest/globals";
+import React from "react";
+import { ConvexProviderWithDescope } from "./ConvexProviderWithDescope.js";
+import { ConvexReactClient } from "../react/index.js";
+
+test("Helpers are valid children", () => {
+  const convex = new ConvexReactClient("https://localhost:3001");
+
+  const _ = (
+    <ConvexProviderWithDescope client={convex}>
+      Hello world
+    </ConvexProviderWithDescope>
+  );
+});
diff --git a/src/react-descope/ConvexProviderWithDescope.tsx b/src/react-descope/ConvexProviderWithDescope.tsx
new file mode 100644
index 0000000..09c4709
--- /dev/null
+++ b/src/react-descope/ConvexProviderWithDescope.tsx
@@ -0,0 +1,61 @@
+import { useSession, useDescope, getSessionToken } from "@descope/react-sdk";
+import React from "react";
+
+import { ReactNode, useCallback, useMemo } from "react";
+import { AuthTokenFetcher } from "../browser/sync/client.js";
+import { ConvexProviderWithAuth } from "../react/ConvexAuthState.js";
+
+// Until we can import from our own entry points (requires TypeScript 4.7),
+// just describe the interface enough to help users pass the right type.
+type IConvexReactClient = {
+  setAuth(fetchToken: AuthTokenFetcher): void;
+  clearAuth(): void;
+};
+
+/**
+ * A wrapper React component which provides a {@link react.ConvexReactClient}
+ * authenticated with Auth0.
+ *
+ * It must be wrapped by a configured `AuthProvider` from `@descope/reack-sdk`.
+ *
+ * See [Convex Descope](https://docs.convex.dev/auth/descope) on how to set up
+ * Convex with Descope.
+ *
+ * @public
+ */
+export function ConvexProviderWithDescope({
+  children,
+  client,
+}: {
+  children: ReactNode;
+  client: IConvexReactClient;
+}) {
+  return (
+    <ConvexProviderWithAuth client={client} useAuth={useAuthFromDescope}>
+      {children}
+    </ConvexProviderWithAuth>
+  );
+}
+
+function useAuthFromDescope() {
+  const { isLoading, isAuthenticated } = useSession();
+  const sdk = useDescope();
+  
+  const fetchAccessToken = useCallback(async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
+    try {
+      if (forceRefreshToken) {
+        sdk.refresh();
+      }
+      
+      const token = getSessionToken();
+      return token as string;
+    } catch (error) {
+      return null;
+    }
+  }, []);
+
+  return useMemo(
+    () => ({ isLoading, isAuthenticated, fetchAccessToken }),
+    [isLoading, isAuthenticated, fetchAccessToken],
+  );
+}
diff --git a/src/react-descope/index.ts b/src/react-descope/index.ts
new file mode 100644
index 0000000..d101f5e
--- /dev/null
+++ b/src/react-descope/index.ts
@@ -0,0 +1,6 @@
+/**
+ * React login component for use with Descope.
+ *
+ * @module
+ */
+export { ConvexProviderWithDescope } from "./ConvexProviderWithDescope.js";

From 5c61a30aa66446262b93aada220b52b6244a62bc Mon Sep 17 00:00:00 2001
From: Kevin Gao <kevinjamesgao@gmail.com>
Date: Wed, 20 Mar 2024 14:04:26 -0700
Subject: [PATCH 2/2] added package.json changes

---
 README.md                                      |  2 ++
 package.json                                   | 18 ++++++++++++++++++
 .../ConvexProviderWithDescope.tsx              |  6 +++---
 src/react/ConvexAuthState.tsx                  |  2 +-
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 44375ab..9679552 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,8 @@ This package includes several entry points for building apps on Convex:
   React component for authenticating users with Auth0.
 - [`convex/react-clerk`](https://docs.convex.dev/api/modules/react_clerk): A
   React component for authenticating users with Clerk.
+- [`convex/react-descope`](https://docs.convex.dev/api/modules/react_descope): A
+  React component for authenticating users with Descope.
 
 This package also includes [`convex`](https://docs.convex.dev/using/cli), the
 command-line interface for managing Convex projects.
diff --git a/package.json b/package.json
index ce01689..8fefffb 100644
--- a/package.json
+++ b/package.json
@@ -64,6 +64,16 @@
         "import": "./dist/esm/react-clerk/index.js"
       }
     },
+    "./react-descope": {
+      "require": {
+        "types": "./dist/internal-cjs-types/react-descope/index.d.ts",
+        "require": "./dist/cjs/react-descope/index.js"
+      },
+      "import": {
+        "types": "./dist/internal-esm-types/react-descope/index.d.ts",
+        "import": "./dist/esm/react-descope/index.js"
+      }
+    },
     "./nextjs": {
       "require": {
         "types": "./dist/internal-cjs-types/nextjs/index.d.ts",
@@ -119,6 +129,9 @@
       "react-clerk": [
         "./dist/internal-cjs-types/react-clerk/index.d.ts"
       ],
+      "react-descope": [
+        "./dist/internal-cjs-types/react-descope/index.d.ts"
+      ],
       "nextjs": [
         "./dist/internal-cjs-types/nextjs/index.d.ts"
       ],
@@ -168,6 +181,7 @@
   "peerDependencies": {
     "@auth0/auth0-react": "^2.0.1",
     "@clerk/clerk-react": "^4.12.8",
+    "@descope/react-sdk": "^2.0.10",
     "react": "^17.0.2 || ^18.0.0",
     "react-dom": "^17.0.2 || ^18.0.0"
   },
@@ -183,6 +197,9 @@
     },
     "@clerk/clerk-react": {
       "optional": true
+    },
+    "@descope/react-sdk": {
+      "optional": true
     }
   },
   "@comment devDependencies": [
@@ -193,6 +210,7 @@
     "@auth0/auth0-react": "2.0.1",
     "@babel/parser": "^7.21.3",
     "@clerk/clerk-react": "4.18.0",
+    "@descope/react-sdk": "2.0.10",
     "@commander-js/extra-typings": "^11.1.0",
     "@jest/globals": "^28.1.0",
     "@microsoft/api-extractor": "~7.36.4",
diff --git a/src/react-descope/ConvexProviderWithDescope.tsx b/src/react-descope/ConvexProviderWithDescope.tsx
index 09c4709..3cee0cc 100644
--- a/src/react-descope/ConvexProviderWithDescope.tsx
+++ b/src/react-descope/ConvexProviderWithDescope.tsx
@@ -14,9 +14,9 @@ type IConvexReactClient = {
 
 /**
  * A wrapper React component which provides a {@link react.ConvexReactClient}
- * authenticated with Auth0.
+ * authenticated with Descope.
  *
- * It must be wrapped by a configured `AuthProvider` from `@descope/reack-sdk`.
+ * It must be wrapped by a configured `AuthProvider` from `@descope/react-sdk`.
  *
  * See [Convex Descope](https://docs.convex.dev/auth/descope) on how to set up
  * Convex with Descope.
@@ -46,7 +46,7 @@ function useAuthFromDescope() {
       if (forceRefreshToken) {
         sdk.refresh();
       }
-      
+
       const token = getSessionToken();
       return token as string;
     } catch (error) {
diff --git a/src/react/ConvexAuthState.tsx b/src/react/ConvexAuthState.tsx
index a3c95ea..5c5329c 100644
--- a/src/react/ConvexAuthState.tsx
+++ b/src/react/ConvexAuthState.tsx
@@ -48,7 +48,7 @@ export function useConvexAuth(): {
   if (authContext === undefined) {
     throw new Error(
       "Could not find `ConvexProviderWithAuth` (or `ConvexProviderWithClerk` " +
-        "or `ConvexProviderWithAuth0`) " +
+        "or `ConvexProviderWithAuth0`" + "or `ConvexProviderWithDescope`) " +
         "as an ancestor component. This component may be missing, or you " +
         "might have two instances of the `convex/react` module loaded in your " +
         "project.",