SuperTokens lazy user migration#41
Conversation
Reviewer's GuideImplements a lazy SuperTokens migration flow that only runs after new Rownd sign-ups, exposes SuperTokens config on the React provider, and adds a full backend/frontend example app demonstrating the migration integration. Sequence diagram for lazy SuperTokens migration on new Rownd sign-upsequenceDiagram
actor User
participant FrontendApp
participant ReactRowndProvider
participant HubEvents
participant SuperTokensBackend
User->>FrontendApp: Clicks requestSignIn
FrontendApp->>ReactRowndProvider: requestSignIn()
ReactRowndProvider->>HubEvents: Start Rownd auth flow
HubEvents-->>ReactRowndProvider: sign_in_completed (user_type new_user)
ReactRowndProvider->>ReactRowndProvider: shouldSyncToSuperTokens.current = true
Note over ReactRowndProvider: Later, when hubState.access_token and props.supertokens.appInfo are set
ReactRowndProvider->>ReactRowndProvider: useEffect(access_token, appInfo)
ReactRowndProvider->>ReactRowndProvider: Check accessToken && appInfo && shouldSyncToSuperTokens.current
ReactRowndProvider->>ReactRowndProvider: shouldSyncToSuperTokens.current = false
ReactRowndProvider->>SuperTokensBackend: POST /auth/plugin/rownd/migrate\nAuthorization: Bearer accessToken
SuperTokensBackend-->>ReactRowndProvider: 2xx or error
ReactRowndProvider-->>FrontendApp: Rownd context updated
FrontendApp-->>User: Shows authenticated UI
Class diagram for updated ReactRowndProvider and SuperTokens configclassDiagram
class RowndProviderProps {
string apiVersion
SuperTokensConfig supertokens
}
class SuperTokensConfig {
AppInfo appInfo
}
class AppInfo {
string appName
string apiDomain
string apiBasePath
}
class ReactRowndProvider {
RowndProviderProps props
any hubState
boolean shouldSyncToSuperTokens_current
stateListener(state, api)
useEffectAuthState()
useEffectSubscribeSignInCompleted()
useEffectSyncUserToSuperTokens()
}
class SuperTokensSync {
+syncUserToSuperTokens(accessToken, appName, apiDomain, apiBasePath) Promise~void~
}
RowndProviderProps --> SuperTokensConfig : optional supertokens
SuperTokensConfig --> AppInfo : has appInfo
ReactRowndProvider --> RowndProviderProps : uses props
ReactRowndProvider ..> SuperTokensSync : calls
Flow diagram for syncUserToSuperTokens migration helperflowchart TD
A[Start syncUserToSuperTokens] --> B[Build base URL from apiDomain and apiBasePath]
B --> C[Set Authorization header with Bearer accessToken]
C --> D[fetch POST base/plugin/rownd/migrate\nwith credentials include]
D --> E{res.ok?}
E -- Yes --> F[Log migrate success]
E -- No --> G[console.warn migrate failed with status]
F --> H[End]
G --> H[End]
D --> I[Network or runtime error]
I --> J[console.warn migrate failed non-fatal]
J --> H
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
syncUserToSuperTokens, the success log runs even whenres.okis false; consider moving the success log into theif (res.ok)branch (or returning early on non-OK) so logs accurately reflect the outcome. - The call to
syncUserToSuperTokens(accessToken, appInfo).catch(() => {});inReactRowndProvidersilently swallows errors even thoughsyncUserToSuperTokensalready handles its own errors with a try/catch, so you can drop the outer.catchor surface errors in a more visible way if needed.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `syncUserToSuperTokens`, the success log runs even when `res.ok` is false; consider moving the success log into the `if (res.ok)` branch (or returning early on non-OK) so logs accurately reflect the outcome.
- The call to `syncUserToSuperTokens(accessToken, appInfo).catch(() => {});` in `ReactRowndProvider` silently swallows errors even though `syncUserToSuperTokens` already handles its own errors with a try/catch, so you can drop the outer `.catch` or surface errors in a more visible way if needed.
## Individual Comments
### Comment 1
<location path="src/utils/supertokens-sync.ts" line_range="14-17" />
<code_context>
+ headers,
+ credentials: 'include',
+ });
+ if (!res.ok) {
+ console.warn(`[Rownd->ST] migrate failed with status: ${res.status}`);
+ }
+ console.log('[Rownd->ST] migrate success');
+ } catch (e) {
+ console.warn('[Rownd->ST] migrate failed (non-fatal):', e);
</code_context>
<issue_to_address>
**suggestion:** Success logging is emitted even when the response is not OK, which can be misleading.
Because `migrate success` is logged regardless of `res.ok`, failures appear as successes in the logs. Please either return early when `!res.ok` or move the success log into an `if (res.ok)` block so logs accurately reflect the outcome.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
4e09735 to
fcbf3ae
Compare
| }; | ||
| }, [hubState.events]); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
This has an ordering race. Mutating a ref doesn't trigger a re-render, so this effect only runs when access_token or props.supertokens changes after the flag is set.
If Hub updates access_token first and then emits sign_in_completed (likely as state settles before events fire), the effect runs while the flag is still false, then the event sets the flag and nothing re-triggers the effect → migration silently never runs.
Two fixes:
- Call
syncUserToSuperTokensdirectly from thesign_in_completedhandler, readingaccess_tokenvia a ref that mirrorshubState.access_token. Mirrors the iOS/Android impls and removes the multi-hop dance. - Make
shouldSyncToSuperTokensauseStateinstead of auseRef, so flipping it re-runs the effect.
Option 1 is smaller and more obviously correct.
| @@ -0,0 +1,30 @@ | |||
| import { useRownd } from 'supertokens-rownd-react'; | |||
There was a problem hiding this comment.
This should probably be @rownd/react, right?
There was a problem hiding this comment.
Yep. Copied it directly from the internal repo and forgot to change it.
2ed716d to
4434043
Compare
Summary
This change introduces the SuperTokens lazy migration flow to new sign ups .
The migration endpoint only runs when a user has just created a new Rownd account. Existing users who simply sign in should not trigger the migration flow again.
How it works
sign_in_completedevent.user_type: "new_user", the provider sets an internal flag indicating that this auth flow was a sign up.Summary by Sourcery
Add SuperTokens user migration support triggered on new Rownd sign-ups and provide an example app demonstrating the integration.
New Features:
Enhancements: