@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 CHANGED
@@ -1,308 +1,164 @@
1
- #### README's for [Next](https://github.com/rownd/react/tree/main/packages/next) and [Remix](https://github.com/rownd/react/tree/main/packages/remix).
1
+ # SuperTokens Rownd React SDK
2
2
 
3
- # React
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
- ## Installation
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
- ## Usage
7
+ ## Installation
10
8
 
11
- ### React
9
+ ```bash
10
+ npm install @supertokens/rownd-react
11
+ # or
12
+ yarn add @supertokens/rownd-react
13
+ ```
12
14
 
13
- The library provides a React provider and hook for the Rownd browser API.
15
+ ## Provider Setup
14
16
 
15
- In your app's main entrypoint, add the Rownd provider, likely before other providers:
17
+ Add `RowndProvider` near the root of your React app.
16
18
 
17
- ```jsx
18
- import React from 'react',
19
- import ReactDOM from 'react-dom';
20
- import { RowndProvider } from '@rownd/react';
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
- {% hint style="warning" %}
34
- The Rownd React SDK automatically injects the Rownd Hub snippet into your React application, so you should _not_ manually include the Hub snippet in your HTML page. Doing so will produce unexpected results.
35
- {% endhint %}
36
-
37
- ### RowndProvider props
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
- - `appKey` (required): This is the key generated by the [Rownd dashboard](https://app.rownd.io).
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
- ### Provider props
70
+ ## useRownd
44
71
 
45
- * `appKey` (required): This is the key generated by the [Rownd dashboard](https://app.rownd.io).
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
- Later on within your app's components, you can use the Rownd hook to access the Rownd browser API:
74
+ ```tsx
75
+ import { useEffect } from 'react';
76
+ import { useRownd } from '@supertokens/rownd-react';
50
77
 
51
- ```jsx
52
- import React from 'react';
53
- import { useRownd } from '@rownd/react';
54
-
55
- export default function MyProtectedComponent(props) {
56
- const { is_authenticated, user, requestSignIn, is_initializing } = useRownd();
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 (!is_authenticated && !is_initializing) {
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
- let getAccessToken;
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 (config.skipAuth || !config.url.startsWith('/api')) {
101
- return config;
98
+ if (!is_authenticated) {
99
+ return <button onClick={() => requestSignIn()}>Sign in</button>;
102
100
  }
103
101
 
104
- const accessToken = await getAccessToken({ waitForToken: true });
105
-
106
- config.headers.common.Authorization = `Bearer ${accessToken}`;
107
- return config;
108
- });
109
-
110
- export function setAccessTokenHelper(fn) {
111
- getAccessToken = fn;
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
- Here's another example, this time using [ky](https://npmjs.com/package/ky):
114
+ ## Common Methods
118
115
 
119
- ```javascript
120
- // api-client.js
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
- import ky from 'ky';
127
+ ## Authenticated Requests
123
128
 
124
- let getAccessToken;
129
+ Call `getAccessToken({ waitForToken: true })` before requests that require the SuperTokens session.
125
130
 
126
- ky.extend({
127
- hooks: {
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
- if (request.skipAuth || !request.url.startsWith('/api')) {
136
- return;
137
- }
134
+ export function ProtectedRequestButton() {
135
+ const { getAccessToken } = useRownd();
138
136
 
139
- const accessToken = await getAccessToken({ waitForToken: true });
137
+ async function callApi() {
138
+ const accessToken = await getAccessToken({ waitForToken: true });
140
139
 
141
- request.headers.set(
142
- 'Authorization',
143
- `Bearer ${tokenResp.access_token}`
144
- );
140
+ const response = await fetch('/api/protected', {
141
+ headers: {
142
+ Authorization: `Bearer ${accessToken}`,
145
143
  },
146
- ],
147
- },
148
- });
144
+ });
149
145
 
150
- function setAccessTokenHelper(fn) {
151
- getAccessToken = fn;
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 <App />;
149
+ return <button onClick={callApi}>Call protected API</button>;
174
150
  }
175
151
  ```
176
152
 
177
- That's one way to solve this problem. Another might be to wrap the redux provider in your own component and simply pass the `getAccessToken` function down into the store during initialization. If you come up with a better mousetrap here, let us know!
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
- auto_sign_in: false, // optional
192
- identifier: 'me@company.com' || '+19105551212', // optional
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.&#x20;
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
- - `waitForToken: boolean` - when `true`, if no access token is present or if it's expired, the promise will not resolve until a valid token is available. While unlikely, this could result in waiting forever.
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 _ } from "react";
2
- function t(s, o) {
3
- o && (window == null || window._rphConfig.push([s, o]));
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 m = "2026-01-21";
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: s,
9
+ appKey: i,
10
10
  apiUrl: o,
11
11
  supertokens: p,
12
12
  hubUrlOverride: a,
13
13
  stateListener: l,
14
- apiVersion: u = m,
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.rownd.io";
21
- w.push(["setBaseUrl", d]), t("setAppKey", s), t("setStateListener", l), t("setLocationHash", f), t("setApiVersion", u), t("setSupertokens", p), t("setLegacyRowndApiUrl", o);
22
- const n = document, r = n.createElement("script"), i = n.createElement("script"), e = n.getElementsByTagName("script")[0];
23
- r.noModule = !0, r.async = !0, r.src = d + "/static/scripts/rph.js", i.type = "module", i.async = !0, i.src = d + "/static/scripts/rph.mjs", e != null && e.parentNode ? (e.parentNode.insertBefore(r, e), e.parentNode.insertBefore(i, e)) : (n.body.appendChild(r), n.body.appendChild(i)), window.localStorage.getItem("rph_log_level") === "debug" && console.debug("[debug] rest:", c), c && (Object.entries(c).forEach(([g, b]) => {
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
- }, [s, o, p, l, f, a, u, c]), null;
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\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://hub.rownd.io';\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 }, [appKey, apiUrl, supertokens, stateListener, locationHash, hubUrlOverride, apiVersion, rest]);\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;AAEzB,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,CAACK,GAAQC,GAAQC,GAAaE,GAAeP,GAAcM,GAAgBE,GAAYC,CAAI,CAAC,GAExF;AACT;"}
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 { handleRowndTokenCallback as l } from "../../remix/server/withRowndActionHandler.js";
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 R = (i) => (n) => {
5
- var t, o, a;
6
- return (o = (t = n == null ? void 0 : n.nextUrl) == null ? void 0 : t.pathname) != null && o.startsWith(h) ? l(n) : d(((a = n.cookies.get(m)) == null ? void 0 : a.value) || null).then((r) => (n.auth = r, i(n)));
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
- R as withRowndMiddleware
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 { handleRowndTokenCallback } from '../../remix/server/withRowndActionHandler';\nimport { ROWND_COOKIE_ID, ROWND_TOKEN_CALLBACK_PATH } 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(request.cookies.get(ROWND_COOKIE_ID)?.value || null).then((tokenInfo) => {\n request.auth = tokenInfo;\n\n return middleware(request);\n });\n };\n};\n"],"names":["withRowndMiddleware","middleware","request","_b","_a","ROWND_TOKEN_CALLBACK_PATH","handleRowndTokenCallback","getRowndAuthenticationStatus","_c","ROWND_COOKIE_ID","tokenInfo"],"mappings":";;;AAOO,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,IAA6BC,IAAAN,EAAQ,QAAQ,IAAIO,CAAe,MAAnC,gBAAAD,EAAsC,UAAS,IAAI,EAAE,KAAK,CAACE,OAC7FR,EAAQ,OAAOQ,GAERT,EAAWC,CAAO,EAC1B;AACH;"}
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
@@ -30,5 +30,5 @@
30
30
  "type": "git",
31
31
  "url": "https://github.com/rownd/react.git"
32
32
  },
33
- "version": "0.1.0-beta.0"
33
+ "version": "0.1.0-beta.1"
34
34
  }