@supertokens/rownd-react 0.1.0-beta.0 → 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -258
- package/dist/context/HubScriptInjector/HubScriptInjector.js +21 -12
- package/dist/context/HubScriptInjector/HubScriptInjector.js.map +1 -1
- package/dist/next/server/withRowndMiddleware.d.ts +2 -0
- package/dist/next/server/withRowndMiddleware.js +25 -6
- package/dist/next/server/withRowndMiddleware.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,308 +1,164 @@
|
|
|
1
|
-
|
|
1
|
+
# SuperTokens Rownd React SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React bindings for the SuperTokens Rownd Hub. The SDK injects the SuperTokens Rownd Hub script, keeps React state in sync with the Hub, and exposes auth helpers through `useRownd()`.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Simply run `npm install @rownd/react` or `yarn add @rownd/react`.
|
|
5
|
+
For Next.js, use `@supertokens/rownd-nextjs` and see `packages/next/README.md`.
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## Installation
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
```bash
|
|
10
|
+
npm install @supertokens/rownd-react
|
|
11
|
+
# or
|
|
12
|
+
yarn add @supertokens/rownd-react
|
|
13
|
+
```
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## Provider Setup
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
Add `RowndProvider` near the root of your React app.
|
|
16
18
|
|
|
17
|
-
```
|
|
18
|
-
import React from 'react'
|
|
19
|
-
import ReactDOM from 'react-dom';
|
|
20
|
-
import { RowndProvider } from '@rownd
|
|
19
|
+
```tsx
|
|
20
|
+
import React from 'react';
|
|
21
|
+
import ReactDOM from 'react-dom/client';
|
|
22
|
+
import { RowndProvider } from '@supertokens/rownd-react';
|
|
21
23
|
import App from './App';
|
|
22
24
|
|
|
23
|
-
ReactDOM.render(
|
|
25
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
24
26
|
<RowndProvider
|
|
25
|
-
appKey="<your app key>"
|
|
27
|
+
appKey="<your Rownd app key>"
|
|
28
|
+
supertokens={{
|
|
29
|
+
appInfo: {
|
|
30
|
+
appName: 'My App',
|
|
31
|
+
apiDomain: 'http://localhost:3001',
|
|
32
|
+
apiBasePath: '/auth',
|
|
33
|
+
},
|
|
34
|
+
}}
|
|
26
35
|
>
|
|
27
36
|
<App />
|
|
28
|
-
</RowndProvider
|
|
29
|
-
document.getElementById('root')
|
|
37
|
+
</RowndProvider>
|
|
30
38
|
);
|
|
31
39
|
```
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
Do not manually include the Hub snippet in your HTML. The provider injects the SuperTokens Rownd Hub bundle for you.
|
|
42
|
+
|
|
43
|
+
## RowndProvider Props
|
|
44
|
+
|
|
45
|
+
| Prop | Required | Default | Description |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `appKey` | Yes | - | Rownd app key used by the Hub. |
|
|
48
|
+
| `supertokens` | Yes | - | SuperTokens app config passed to the Hub. |
|
|
49
|
+
| `hubUrlOverride` | No | `https://rownd-hub.supertokens.com` | Alternate SuperTokens Rownd Hub URL. Mostly used for staging or local Hub development. |
|
|
50
|
+
| `apiUrl` | No | - | Legacy Rownd API URL override, forwarded to the Hub as `setLegacyRowndApiUrl`. |
|
|
51
|
+
| `rootOrigin` | No | - | Root origin for multi-domain deployments. |
|
|
52
|
+
| `postRegistrationUrl` | No | - | URL the Hub should use after registration when that flow needs a redirect. |
|
|
53
|
+
| `postSignOutRedirect` | No | - | URL the Hub should redirect to after sign-out. |
|
|
54
|
+
| `apiVersion` | No | `2026-01-21` | Hub API version date. Set an earlier date to opt out of newer Hub behavior. |
|
|
55
|
+
|
|
56
|
+
`supertokens` has this shape:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
type SuperTokensConfig = {
|
|
60
|
+
appInfo: {
|
|
61
|
+
appName?: string;
|
|
62
|
+
apiDomain: string;
|
|
63
|
+
apiBasePath?: string;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
```
|
|
38
67
|
|
|
39
|
-
|
|
40
|
-
- `postLoginRedirect` (optional): Where the browser should redirect the user after a successful sign-in. If not supplied, the user will remain on the same page.
|
|
41
|
-
- `rootOrigin` (optional): If you're using Rownd across multiple domains (e.g., `rownd.io` and `app.rownd.io`), set this to the "root" _origin_ (e.g., https://rownd.io).
|
|
68
|
+
`apiDomain` and `apiBasePath` must match the SuperTokens backend that the Hub should use for session creation and refresh.
|
|
42
69
|
|
|
43
|
-
|
|
70
|
+
## useRownd
|
|
44
71
|
|
|
45
|
-
|
|
46
|
-
* `postLoginRedirect` (optional): Where the browser should redirect the user after a successful sign-in. If not supplied, the user will remain on the same page.
|
|
47
|
-
* `rootOrigin` (optional): If you're using Rownd across multiple domains (e.g., `rownd.io` and `app.rownd.io`), set this to the "root" _origin_ (e.g., https://rownd.io).
|
|
72
|
+
Use `useRownd()` inside provider children to read auth state and call Hub APIs.
|
|
48
73
|
|
|
49
|
-
|
|
74
|
+
```tsx
|
|
75
|
+
import { useEffect } from 'react';
|
|
76
|
+
import { useRownd } from '@supertokens/rownd-react';
|
|
50
77
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
78
|
+
export function ProtectedContent() {
|
|
79
|
+
const {
|
|
80
|
+
is_authenticated,
|
|
81
|
+
is_initializing,
|
|
82
|
+
user,
|
|
83
|
+
requestSignIn,
|
|
84
|
+
signOut,
|
|
85
|
+
getAccessToken,
|
|
86
|
+
} = useRownd();
|
|
57
87
|
|
|
58
88
|
useEffect(() => {
|
|
59
|
-
if (!
|
|
89
|
+
if (!is_initializing && !is_authenticated) {
|
|
60
90
|
requestSignIn();
|
|
61
91
|
}
|
|
62
|
-
}, [is_authenticated, is_initializing]);
|
|
63
|
-
|
|
64
|
-
return (
|
|
65
|
-
<div>
|
|
66
|
-
{is_authenticated ? (
|
|
67
|
-
<div>
|
|
68
|
-
<h1>Welcome {user.data.first_name}</h1>
|
|
69
|
-
<h2>Email:{user.data.email}</h2>
|
|
70
|
-
<button onClick={() => getAccessToken()}>Get access token</button>
|
|
71
|
-
</div>
|
|
72
|
-
) : (
|
|
73
|
-
<div>
|
|
74
|
-
<h1>Please sign in to continue</h1>
|
|
75
|
-
</div>
|
|
76
|
-
)}
|
|
77
|
-
</div>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Usage with redux, etc
|
|
83
|
-
|
|
84
|
-
Often, sending and receiving data from your server will rely on the Rownd access token as a means of authenticating the user within your back-end (see our [Node.js SDK](node.js.md) as an example of this). Many React apps leverage Redux or similar technologies to manage an app's global state.
|
|
85
|
-
|
|
86
|
-
The key here is to call Rownd's `getAccessToken({ waitForToken: true })` method when calling your own authenticated APIs. For example, if you're using [axios](https://npmjs.com/package/axios), you'd likely set up an interceptor that looks something like this:
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
// api-client.js
|
|
90
|
-
|
|
91
|
-
import axios from 'axios';
|
|
92
|
+
}, [is_authenticated, is_initializing, requestSignIn]);
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
axios.interceptors.request.use(async (config) => {
|
|
96
|
-
if (!getAccessToken) {
|
|
97
|
-
return config;
|
|
94
|
+
if (is_initializing) {
|
|
95
|
+
return <div>Loading...</div>;
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
if (
|
|
101
|
-
return
|
|
98
|
+
if (!is_authenticated) {
|
|
99
|
+
return <button onClick={() => requestSignIn()}>Sign in</button>;
|
|
102
100
|
}
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
return (
|
|
103
|
+
<div>
|
|
104
|
+
<p>Welcome {user.data.email ?? user.data.user_id}</p>
|
|
105
|
+
<button onClick={() => signOut()}>Sign out</button>
|
|
106
|
+
<button onClick={() => getAccessToken({ waitForToken: true })}>
|
|
107
|
+
Get access token
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
112
111
|
}
|
|
113
|
-
|
|
114
|
-
export default axios;
|
|
115
112
|
```
|
|
116
113
|
|
|
117
|
-
|
|
114
|
+
## Common Methods
|
|
118
115
|
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
| Method | Description |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| `requestSignIn(options?)` | Opens the Hub sign-in UI. |
|
|
119
|
+
| `signOut()` | Signs out the current user. |
|
|
120
|
+
| `getAccessToken(options?)` | Gets the current Rownd/SuperTokens access token. Use `{ waitForToken: true }` when making authenticated API calls. |
|
|
121
|
+
| `setUser(data)` | Merges data into the Rownd user profile. |
|
|
122
|
+
| `setUserValue(key, value)` | Updates one user profile field. |
|
|
123
|
+
| `manageAccount()` | Opens the Hub account management UI. |
|
|
124
|
+
| `getAppConfig()` | Reads the active Hub app config. |
|
|
125
|
+
| `onAuthenticated(callback)` | Runs a callback when a user becomes authenticated. Returns an unsubscribe function. |
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
## Authenticated Requests
|
|
123
128
|
|
|
124
|
-
|
|
129
|
+
Call `getAccessToken({ waitForToken: true })` before requests that require the SuperTokens session.
|
|
125
130
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
beforeRequest: [
|
|
129
|
-
// Auto-refresh tokens
|
|
130
|
-
async (request) => {
|
|
131
|
-
if (!getAccessToken) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
131
|
+
```ts
|
|
132
|
+
import { useRownd } from '@supertokens/rownd-react';
|
|
134
133
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
134
|
+
export function ProtectedRequestButton() {
|
|
135
|
+
const { getAccessToken } = useRownd();
|
|
138
136
|
|
|
139
|
-
|
|
137
|
+
async function callApi() {
|
|
138
|
+
const accessToken = await getAccessToken({ waitForToken: true });
|
|
140
139
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
);
|
|
140
|
+
const response = await fetch('/api/protected', {
|
|
141
|
+
headers: {
|
|
142
|
+
Authorization: `Bearer ${accessToken}`,
|
|
145
143
|
},
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
});
|
|
144
|
+
});
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export { api, setAccessTokenHelper };
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
In both of the cases above, our async actions would use these instances of axios or ky to make requests back to the server, but before any of those fire, we need to set the access token helper from our React app like this:
|
|
158
|
-
|
|
159
|
-
```javascript
|
|
160
|
-
// AppWrapper.jsx
|
|
161
|
-
|
|
162
|
-
import { useRownd } from '@rownd/react';
|
|
163
|
-
import { setAccessTokenHelper } from './api-client';
|
|
164
|
-
import App from './app';
|
|
165
|
-
|
|
166
|
-
export default function MyReactAppWrapper() {
|
|
167
|
-
const { getAccessToken } = useRownd();
|
|
168
|
-
|
|
169
|
-
useEffect(() => {
|
|
170
|
-
setAccessTokenHelper(getAccessToken);
|
|
171
|
-
}, [getAccessToken]);
|
|
146
|
+
return response.json();
|
|
147
|
+
}
|
|
172
148
|
|
|
173
|
-
return <
|
|
149
|
+
return <button onClick={callApi}>Call protected API</button>;
|
|
174
150
|
}
|
|
175
151
|
```
|
|
176
152
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
## API reference
|
|
180
|
-
|
|
181
|
-
Most API methods are made available via the Rownd Provider and its associated `useRownd` React hook. Unless otherwise noted, we're assuming that you're using hooks.
|
|
182
|
-
|
|
183
|
-
#### requestSignIn()
|
|
184
|
-
|
|
185
|
-
Trigger the Rownd sign in dialog
|
|
186
|
-
|
|
187
|
-
```javascript
|
|
188
|
-
const { requestSignIn } = useRownd();
|
|
153
|
+
## Sign-In Options
|
|
189
154
|
|
|
155
|
+
```ts
|
|
190
156
|
requestSignIn({
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
- `auto_sign_in: boolean` - when `true`, automatically trigger a sign-in attempt _if_ `identifier` is included or an email address or phone number has already been set in the user data.
|
|
197
|
-
- `identifier: string` - an email address or phone number (in E164 format) to which a verification message may be sent. If the Rownd app is configured to allow unverified users, then sign-in will complete without verification if the user has not signed in previously.
|
|
198
|
-
|
|
199
|
-
#### signOut()
|
|
200
|
-
|
|
201
|
-
Sign out the user and clear their profile, returning them to a completely unauthenticated state.
|
|
202
|
-
|
|
203
|
-
```javascript
|
|
204
|
-
const { signOut } = useRownd();
|
|
205
|
-
signOut();
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
#### **getAccessToken()**
|
|
209
|
-
|
|
210
|
-
Retrieves the active, valid access token for the current user. 
|
|
211
|
-
|
|
212
|
-
```javascript
|
|
213
|
-
const { getAccessToken } = useRownd();
|
|
214
|
-
|
|
215
|
-
let accessToken = await getAccessToken({
|
|
216
|
-
waitForToken: false,
|
|
157
|
+
identifier: 'me@company.com',
|
|
158
|
+
auto_sign_in: false,
|
|
159
|
+
method: 'email',
|
|
160
|
+
post_login_redirect: '/profile',
|
|
217
161
|
});
|
|
218
162
|
```
|
|
219
163
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
**is_initializing**
|
|
223
|
-
|
|
224
|
-
`is_initializing` will be `true` until the Hub has fully loaded, recalled its state, and resolved the current user's authentication status. This usually takes only a few milliseconds, but if you make decisions that depend on the `is_authenticated` flag while `is_initializing` is still `true`, your code/logic may not work as you expect.
|
|
225
|
-
|
|
226
|
-
```javascript
|
|
227
|
-
const { is_initializing } = useRownd();
|
|
228
|
-
|
|
229
|
-
if (is_initializing) {
|
|
230
|
-
// return loading state or null
|
|
231
|
-
}
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
#### is_authenticated
|
|
235
|
-
|
|
236
|
-
Indicates whether the current user is signed in or not.
|
|
237
|
-
|
|
238
|
-
```javascript
|
|
239
|
-
const { is_authenticated } = useRownd();
|
|
240
|
-
|
|
241
|
-
return (
|
|
242
|
-
<>
|
|
243
|
-
{is_authenticated && <ProtectedRoute />}
|
|
244
|
-
{!is_authenticated && <PublicRoute />}
|
|
245
|
-
</>
|
|
246
|
-
);
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
#### access_token
|
|
250
|
-
|
|
251
|
-
Represents the current access token for the user.
|
|
252
|
-
|
|
253
|
-
```javascript
|
|
254
|
-
const { access_token } = useRownd();
|
|
255
|
-
|
|
256
|
-
useEffect(() => {
|
|
257
|
-
axios({
|
|
258
|
-
method: 'post',
|
|
259
|
-
url: '/api/sessions'
|
|
260
|
-
headers: {
|
|
261
|
-
authorization: `Bearer ${access_token}`
|
|
262
|
-
}
|
|
263
|
-
}).then(console.log);
|
|
264
|
-
}, [access_token]);
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
#### user
|
|
268
|
-
|
|
269
|
-
Represents information about the current user, specifically their profile information. In the example below, we use the existing data to display the current value of `first_name` in a form field, update a local copy of that data as the user changes it, and then save the changes to Rownd once the user submits the form.
|
|
270
|
-
|
|
271
|
-
```javascript
|
|
272
|
-
const { user } = useRownd();
|
|
273
|
-
|
|
274
|
-
const [profile, setProfile] = useState(user.data);
|
|
275
|
-
|
|
276
|
-
return (
|
|
277
|
-
<form onSubmit={() => user.set(profile)}>
|
|
278
|
-
<label htmlFor="first_name">
|
|
279
|
-
<input
|
|
280
|
-
id="first_name"
|
|
281
|
-
type="text"
|
|
282
|
-
value={profile?.first_name}
|
|
283
|
-
onInput={(evt) =>
|
|
284
|
-
setProfile({ ...profile, first_name: evt.target.value })
|
|
285
|
-
}
|
|
286
|
-
/>
|
|
287
|
-
</label>
|
|
288
|
-
<button type="submit">Save</button>
|
|
289
|
-
</form>
|
|
290
|
-
);
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
**Merge data into the user profile**
|
|
294
|
-
|
|
295
|
-
```javascript
|
|
296
|
-
const { user } = useRownd();
|
|
297
|
-
user.set({
|
|
298
|
-
first_name: 'Alice',
|
|
299
|
-
last_name: 'Ranier',
|
|
300
|
-
});
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
Set a specific field in the user profile
|
|
304
|
-
|
|
305
|
-
```javascript
|
|
306
|
-
const { user } = useRownd();
|
|
307
|
-
user.setValue('first_name', 'Alice');
|
|
308
|
-
```
|
|
164
|
+
Supported fields include `identifier`, `auto_sign_in`, `init_data`, `post_login_redirect`, `include_user_data`, `redirect`, `intent`, `group_to_join`, `prevent_closing`, `method`, and method-specific `method_options`.
|
|
@@ -1,32 +1,41 @@
|
|
|
1
|
-
import { useEffect as
|
|
2
|
-
function t(
|
|
3
|
-
o && (window == null || window._rphConfig.push([
|
|
1
|
+
import { useEffect as m } from "react";
|
|
2
|
+
function t(i, o) {
|
|
3
|
+
o && (window == null || window._rphConfig.push([i, o]));
|
|
4
4
|
}
|
|
5
|
-
const
|
|
5
|
+
const _ = "2026-01-21";
|
|
6
6
|
var h;
|
|
7
7
|
const f = typeof window < "u" ? (h = window == null ? void 0 : window.location) == null ? void 0 : h.hash : void 0;
|
|
8
8
|
function y({
|
|
9
|
-
appKey:
|
|
9
|
+
appKey: i,
|
|
10
10
|
apiUrl: o,
|
|
11
11
|
supertokens: p,
|
|
12
12
|
hubUrlOverride: a,
|
|
13
13
|
stateListener: l,
|
|
14
|
-
apiVersion: u =
|
|
14
|
+
apiVersion: u = _,
|
|
15
15
|
...c
|
|
16
16
|
}) {
|
|
17
|
-
return
|
|
17
|
+
return m(() => {
|
|
18
18
|
if (!window)
|
|
19
19
|
return;
|
|
20
|
-
const w = window._rphConfig = window._rphConfig || [], d = window.localStorage.getItem("rph_base_url_override") || a || "https://hub.
|
|
21
|
-
w.push(["setBaseUrl", d]), t("setAppKey",
|
|
22
|
-
const n = document, r = n.createElement("script"),
|
|
23
|
-
r.noModule = !0, r.async = !0, r.src = d + "/static/scripts/rph.js",
|
|
20
|
+
const w = window._rphConfig = window._rphConfig || [], d = window.localStorage.getItem("rph_base_url_override") || a || "https://rownd-hub.supertokens.com";
|
|
21
|
+
w.push(["setBaseUrl", d]), t("setAppKey", i), t("setStateListener", l), t("setLocationHash", f), t("setApiVersion", u), t("setSupertokens", p), t("setLegacyRowndApiUrl", o);
|
|
22
|
+
const n = document, r = n.createElement("script"), s = n.createElement("script"), e = n.getElementsByTagName("script")[0];
|
|
23
|
+
r.noModule = !0, r.async = !0, r.src = d + "/static/scripts/rph.js", s.type = "module", s.async = !0, s.src = d + "/static/scripts/rph.mjs", e != null && e.parentNode ? (e.parentNode.insertBefore(r, e), e.parentNode.insertBefore(s, e)) : (n.body.appendChild(r), n.body.appendChild(s)), window.localStorage.getItem("rph_log_level") === "debug" && console.debug("[debug] rest:", c), c && (Object.entries(c).forEach(([g, b]) => {
|
|
24
24
|
t(
|
|
25
25
|
`set${g.charAt(0).toUpperCase() + g.substring(1)}`,
|
|
26
26
|
b
|
|
27
27
|
);
|
|
28
28
|
}), window.localStorage.getItem("rph_log_level") === "debug" && console.debug("[debug] hubConfig:", window._rphConfig));
|
|
29
|
-
}, [
|
|
29
|
+
}, [
|
|
30
|
+
i,
|
|
31
|
+
o,
|
|
32
|
+
p,
|
|
33
|
+
l,
|
|
34
|
+
f,
|
|
35
|
+
a,
|
|
36
|
+
u,
|
|
37
|
+
c
|
|
38
|
+
]), null;
|
|
30
39
|
}
|
|
31
40
|
export {
|
|
32
41
|
y as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HubScriptInjector.js","sources":["../../../src/context/HubScriptInjector/HubScriptInjector.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport { HubListenerProps, SuperTokensConfig } from '../RowndContext';\n\ndeclare global {\n interface Window {\n _rphConfig: any;\n }\n}\n\nfunction setConfigValue(key: string, value: any) {\n if (!value) {\n return;\n }\n\n window?._rphConfig.push([key, value]);\n}\n\n/**\n * Default API version for new SDK releases.\n * This controls which Hub features are enabled by default.\n */\nconst DEFAULT_API_VERSION = '2026-01-21';\n\nexport type HubScriptInjectorProps = {\n appKey: string;\n stateListener: ({ state, api }: HubListenerProps) => void;\n apiUrl?: string;\n supertokens: SuperTokensConfig;\n hubUrlOverride?: string;\n locationHash?: string;\n apiVersion?: string;\n};\n\n// Grab the URL hash ASAP in case it contains an `rph_init` param\nconst locationHash =\n typeof window !== 'undefined' ? window?.location?.hash : void 0;\n\nexport default function HubScriptInjector({\n appKey,\n apiUrl,\n supertokens,\n hubUrlOverride,\n stateListener,\n apiVersion = DEFAULT_API_VERSION,\n ...rest\n}: HubScriptInjectorProps) {\n
|
|
1
|
+
{"version":3,"file":"HubScriptInjector.js","sources":["../../../src/context/HubScriptInjector/HubScriptInjector.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport { HubListenerProps, SuperTokensConfig } from '../RowndContext';\n\ndeclare global {\n interface Window {\n _rphConfig: any;\n }\n}\n\nfunction setConfigValue(key: string, value: any) {\n if (!value) {\n return;\n }\n\n window?._rphConfig.push([key, value]);\n}\n\n/**\n * Default API version for new SDK releases.\n * This controls which Hub features are enabled by default.\n */\nconst DEFAULT_API_VERSION = '2026-01-21';\n\nexport type HubScriptInjectorProps = {\n appKey: string;\n stateListener: ({ state, api }: HubListenerProps) => void;\n apiUrl?: string;\n supertokens: SuperTokensConfig;\n hubUrlOverride?: string;\n locationHash?: string;\n apiVersion?: string;\n};\n\n// Grab the URL hash ASAP in case it contains an `rph_init` param\nconst locationHash =\n typeof window !== 'undefined' ? window?.location?.hash : void 0;\n\nexport default function HubScriptInjector({\n appKey,\n apiUrl,\n supertokens,\n hubUrlOverride,\n stateListener,\n apiVersion = DEFAULT_API_VERSION,\n ...rest\n}: HubScriptInjectorProps) {\n useEffect(() => {\n if (!window) {\n return; // compat with server-side rendering\n }\n\n const _rphConfig = (window._rphConfig = window._rphConfig || []);\n const baseUrl =\n window.localStorage.getItem('rph_base_url_override') ||\n hubUrlOverride ||\n 'https://rownd-hub.supertokens.com';\n _rphConfig.push(['setBaseUrl', baseUrl]);\n\n setConfigValue('setAppKey', appKey);\n setConfigValue('setStateListener', stateListener);\n setConfigValue('setLocationHash', locationHash);\n setConfigValue('setApiVersion', apiVersion);\n setConfigValue('setSupertokens', supertokens);\n setConfigValue('setLegacyRowndApiUrl', apiUrl);\n\n const d = document,\n g = d.createElement('script'),\n m = d.createElement('script'),\n s = d.getElementsByTagName('script')[0];\n g.noModule = true;\n g.async = true;\n g.src = baseUrl + '/static/scripts/rph.js';\n m.type = 'module';\n m.async = true;\n m.src = baseUrl + '/static/scripts/rph.mjs';\n\n if (s?.parentNode) {\n s.parentNode.insertBefore(g, s);\n s.parentNode.insertBefore(m, s);\n } else {\n d.body.appendChild(g);\n d.body.appendChild(m);\n }\n\n if (window.localStorage.getItem('rph_log_level') === 'debug') {\n console.debug('[debug] rest:', rest);\n }\n\n if (rest) {\n Object.entries(rest).forEach(([key, value]) => {\n setConfigValue(\n `set${key.charAt(0).toUpperCase() + key.substring(1)}`,\n value\n );\n });\n\n if (window.localStorage.getItem('rph_log_level') === 'debug') {\n console.debug('[debug] hubConfig:', window._rphConfig);\n }\n }\n }, [\n appKey,\n apiUrl,\n supertokens,\n stateListener,\n locationHash,\n hubUrlOverride,\n apiVersion,\n rest,\n ]);\n\n return null;\n}\n"],"names":["setConfigValue","key","value","DEFAULT_API_VERSION","locationHash","_a","HubScriptInjector","appKey","apiUrl","supertokens","hubUrlOverride","stateListener","apiVersion","rest","useEffect","_rphConfig","baseUrl","d","g","m","s"],"mappings":";AASA,SAASA,EAAeC,GAAaC,GAAY;AAC/C,EAAKA,MAIL,yBAAQ,WAAW,KAAK,CAACD,GAAKC,CAAK;AACrC;AAMA,MAAMC,IAAsB;;AAa5B,MAAMC,IACJ,OAAO,SAAW,OAAcC,IAAA,iCAAQ,aAAR,gBAAAA,EAAkB,OAAO;AAE3D,SAAwBC,EAAkB;AAAA,EACxC,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,aAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,YAAAC,IAAaT;AAAA,EACb,GAAGU;AACL,GAA2B;AACzB,SAAAC,EAAU,MAAM;AACd,QAAI,CAAC;AACH;AAGF,UAAMC,IAAc,OAAO,aAAa,OAAO,cAAc,CAAA,GACvDC,IACJ,OAAO,aAAa,QAAQ,uBAAuB,KACnDN,KACA;AACF,IAAAK,EAAW,KAAK,CAAC,cAAcC,CAAO,CAAC,GAEvChB,EAAe,aAAaO,CAAM,GAClCP,EAAe,oBAAoBW,CAAa,GAChDX,EAAe,mBAAmBI,CAAY,GAC9CJ,EAAe,iBAAiBY,CAAU,GAC1CZ,EAAe,kBAAkBS,CAAW,GAC5CT,EAAe,wBAAwBQ,CAAM;AAE7C,UAAMS,IAAI,UACRC,IAAID,EAAE,cAAc,QAAQ,GAC5BE,IAAIF,EAAE,cAAc,QAAQ,GAC5BG,IAAIH,EAAE,qBAAqB,QAAQ,EAAE,CAAC;AACxC,IAAAC,EAAE,WAAW,IACbA,EAAE,QAAQ,IACVA,EAAE,MAAMF,IAAU,0BAClBG,EAAE,OAAO,UACTA,EAAE,QAAQ,IACVA,EAAE,MAAMH,IAAU,2BAEdI,KAAA,QAAAA,EAAG,cACLA,EAAE,WAAW,aAAaF,GAAGE,CAAC,GAC9BA,EAAE,WAAW,aAAaD,GAAGC,CAAC,MAE9BH,EAAE,KAAK,YAAYC,CAAC,GACpBD,EAAE,KAAK,YAAYE,CAAC,IAGlB,OAAO,aAAa,QAAQ,eAAe,MAAM,WACnD,QAAQ,MAAM,iBAAiBN,CAAI,GAGjCA,MACF,OAAO,QAAQA,CAAI,EAAE,QAAQ,CAAC,CAACZ,GAAKC,CAAK,MAAM;AAC7C,MAAAF;AAAA,QACE,MAAMC,EAAI,OAAO,CAAC,EAAE,gBAAgBA,EAAI,UAAU,CAAC,CAAC;AAAA,QACpDC;AAAA,MAAA;AAAA,IAEJ,CAAC,GAEG,OAAO,aAAa,QAAQ,eAAe,MAAM,WACnD,QAAQ,MAAM,sBAAsB,OAAO,UAAU;AAAA,EAG3D,GAAG;AAAA,IACDK;AAAA,IACAC;AAAA,IACAC;AAAA,IACAE;AAAA,IACAP;AAAA,IACAM;AAAA,IACAE;AAAA,IACAC;AAAA,EAAA,CACD,GAEM;AACT;"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
type NextResponse = any;
|
|
2
2
|
type NextRequest = any;
|
|
3
3
|
export declare const withRowndMiddleware: (middleware: (request: NextRequest) => NextResponse) => (request: NextRequest) => Promise<any>;
|
|
4
|
+
export declare function withRowndHandleRequest(handleRequest: (request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: any, loadContext: any) => Promise<unknown>): (request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: any, loadContext: any) => Promise<unknown>;
|
|
5
|
+
export declare function handleRowndTokenCallback(request: Request): Promise<Response>;
|
|
4
6
|
export {};
|
|
@@ -1,11 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ROWND_TOKEN_CALLBACK_PATH as h, ROWND_COOKIE_ID as m } from "../../ssr/server/cookie.js";
|
|
1
|
+
import { ROWND_TOKEN_CALLBACK_PATH as s, ROWND_COOKIE_ID as c, rowndCookie as i } from "../../ssr/server/cookie.js";
|
|
3
2
|
import { getRowndAuthenticationStatus as d } from "../../ssr/server/token.js";
|
|
4
|
-
const
|
|
5
|
-
var
|
|
6
|
-
return (
|
|
3
|
+
const k = (r) => (o) => {
|
|
4
|
+
var n, e, t;
|
|
5
|
+
return (e = (n = o == null ? void 0 : o.nextUrl) == null ? void 0 : n.pathname) != null && e.startsWith(s) ? l(o) : d(
|
|
6
|
+
((t = o.cookies.get(c)) == null ? void 0 : t.value) || null
|
|
7
|
+
).then((a) => (o.auth = a, r(o)));
|
|
7
8
|
};
|
|
9
|
+
async function l(r) {
|
|
10
|
+
const o = r.body;
|
|
11
|
+
try {
|
|
12
|
+
const n = await new Response(o).text(), e = JSON.parse(n), t = e == null ? void 0 : e.accessToken;
|
|
13
|
+
if (!t)
|
|
14
|
+
throw new Error("Missing access token");
|
|
15
|
+
return new Response("Success", {
|
|
16
|
+
headers: {
|
|
17
|
+
"Set-Cookie": i.serialize({
|
|
18
|
+
accessToken: t
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
} catch (n) {
|
|
23
|
+
return console.error("Failed to decode body text", n), new Response("Failed", { status: 400 });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
8
26
|
export {
|
|
9
|
-
|
|
27
|
+
l as handleRowndTokenCallback,
|
|
28
|
+
k as withRowndMiddleware
|
|
10
29
|
};
|
|
11
30
|
//# sourceMappingURL=withRowndMiddleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withRowndMiddleware.js","sources":["../../../src/next/server/withRowndMiddleware.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"withRowndMiddleware.js","sources":["../../../src/next/server/withRowndMiddleware.ts"],"sourcesContent":["import {\n ROWND_COOKIE_ID,\n ROWND_TOKEN_CALLBACK_PATH,\n rowndCookie,\n} from '../../ssr/server/cookie';\nimport { getRowndAuthenticationStatus } from '../../ssr/server/token';\n\ntype NextResponse = any;\ntype NextRequest = any;\n\nexport const withRowndMiddleware = (\n middleware: (request: NextRequest) => NextResponse\n) => {\n return (request: NextRequest) => {\n if (request?.nextUrl?.pathname?.startsWith(ROWND_TOKEN_CALLBACK_PATH)) {\n return handleRowndTokenCallback(request);\n }\n\n return getRowndAuthenticationStatus(\n request.cookies.get(ROWND_COOKIE_ID)?.value || null\n ).then((tokenInfo) => {\n request.auth = tokenInfo;\n\n return middleware(request);\n });\n };\n};\n\nexport function withRowndHandleRequest(\n handleRequest: (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n remixContext: any,\n loadContext: any\n ) => Promise<unknown>\n) {\n return async function (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n remixContext: any,\n loadContext: any\n ) {\n const url = new URL(request.url);\n if (url.pathname === ROWND_TOKEN_CALLBACK_PATH) {\n return handleRowndTokenCallback(request);\n }\n\n return handleRequest(\n request,\n responseStatusCode,\n responseHeaders,\n remixContext,\n loadContext\n );\n };\n}\n\nexport async function handleRowndTokenCallback(request: Request) {\n const body = request.body;\n try {\n const text = await new Response(body).text();\n const res = JSON.parse(text);\n\n const accessToken = res?.accessToken;\n if (!accessToken) {\n throw new Error('Missing access token');\n }\n\n return new Response('Success', {\n headers: {\n 'Set-Cookie': rowndCookie.serialize({\n accessToken,\n }),\n },\n });\n } catch (err) {\n console.error('Failed to decode body text', err);\n return new Response('Failed', { status: 400 });\n }\n}\n"],"names":["withRowndMiddleware","middleware","request","_b","_a","ROWND_TOKEN_CALLBACK_PATH","handleRowndTokenCallback","getRowndAuthenticationStatus","_c","ROWND_COOKIE_ID","tokenInfo","body","text","res","accessToken","rowndCookie","err"],"mappings":";;AAUO,MAAMA,IAAsB,CACjCC,MAEO,CAACC,MAAyB;;AAC/B,UAAIC,KAAAC,IAAAF,KAAA,gBAAAA,EAAS,YAAT,gBAAAE,EAAkB,aAAlB,QAAAD,EAA4B,WAAWE,KAClCC,EAAyBJ,CAAO,IAGlCK;AAAA,MACLC,IAAAN,EAAQ,QAAQ,IAAIO,CAAe,MAAnC,gBAAAD,EAAsC,UAAS;AAAA,EAAA,EAC/C,KAAK,CAACE,OACNR,EAAQ,OAAOQ,GAERT,EAAWC,CAAO,EAC1B;AACH;AAkCF,eAAsBI,EAAyBJ,GAAkB;AAC/D,QAAMS,IAAOT,EAAQ;AACrB,MAAI;AACF,UAAMU,IAAO,MAAM,IAAI,SAASD,CAAI,EAAE,KAAA,GAChCE,IAAM,KAAK,MAAMD,CAAI,GAErBE,IAAcD,KAAA,gBAAAA,EAAK;AACzB,QAAI,CAACC;AACH,YAAM,IAAI,MAAM,sBAAsB;AAGxC,WAAO,IAAI,SAAS,WAAW;AAAA,MAC7B,SAAS;AAAA,QACP,cAAcC,EAAY,UAAU;AAAA,UAClC,aAAAD;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IACH,CACD;AAAA,EACH,SAASE,GAAK;AACZ,mBAAQ,MAAM,8BAA8BA,CAAG,GACxC,IAAI,SAAS,UAAU,EAAE,QAAQ,KAAK;AAAA,EAC/C;AACF;"}
|
package/package.json
CHANGED