Skip to content

feat: update store function for web version#59

Open
p-stam001 wants to merge 3 commits into
kinde-oss:mainfrom
p-stam001:feature/web-compatibility
Open

feat: update store function for web version#59
p-stam001 wants to merge 3 commits into
kinde-oss:mainfrom
p-stam001:feature/web-compatibility

Conversation

@p-stam001

@p-stam001 p-stam001 commented Nov 19, 2025

Copy link
Copy Markdown

Explain your changes

Fix 51
#51

  • Added storage for web version.

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

@p-stam001 p-stam001 requested a review from a team as a code owner November 19, 2025 01:26
@coderabbitai

coderabbitai Bot commented Nov 19, 2025

Copy link
Copy Markdown

Walkthrough

KindeAuthProvider now chooses storage at runtime via a new getStorageInstance helper: LocalStorage on web when accessible, MemoryStorage as a web fallback, and ExpoSecureStore on native. Initialization uses that storage, sets activeStorage, and calls maybeCompleteAuthSession on web.

Changes

Cohort / File(s) Change Summary
Platform-aware storage initialization and web session completion
lib/KindeAuthProvider.tsx
Adds getStorageInstance helper to pick LocalStorage (when available) or MemoryStorage on web, or ExpoSecureStore on native; replaces direct ExpoSecureStore use with the helper; persists chosen storage via setActiveStorage and storage state; invokes maybeCompleteAuthSession during web initialization; imports Platform, LocalStorage, MemoryStorage, and maybeCompleteAuthSession.

Sequence Diagram

sequenceDiagram
    participant Init as Initialization
    participant Platform as Platform Detection
    participant Storage as Storage Layer
    participant Session as Session Handler

    Init->>Platform: Detect platform (web/native)
    alt Web
        Platform->>Storage: getStorageInstance()
        alt localStorage usable
            Storage->>Storage: return LocalStorage
        else
            Storage->>Storage: return MemoryStorage
        end
        Storage-->>Init: Storage instance
        Init->>Session: maybeCompleteAuthSession()
        Session-->>Init: Session status
    else Native
        Platform->>Storage: getStorageInstance()
        Storage->>Storage: return ExpoSecureStore
        Storage-->>Init: Storage instance
    end
    Init->>Init: setActiveStorage(instance)
    Init-->>Init: Provider Ready
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify getStorageInstance safely checks localStorage availability and handles exceptions.
  • Confirm maybeCompleteAuthSession is invoked only on web and does not affect native flow.
  • Check setActiveStorage usage and state updates integrate correctly with provider initialization.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: update store function for web version' is related to the main changes in the PR, which updates storage initialization for web environments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description is directly related to the changeset, referencing issue #51 and mentioning the addition of storage for web version, which aligns with the code changes.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/KindeAuthProvider.tsx (1)

149-198: Confirm stale closure risks in error handlers and add ref-based solution.

The useEffect has an empty dependency array but captures callbacks and contextValue in the error handler (line 185), creating stale closure issues. This problem extends beyond the useEffect:

  • Line 185 (useEffect error handler): If callbacks prop changes after mount but before storage initialization fails, the error handler calls the stale callbacks object
  • Line 267 (setRefreshTimer callback): Same issue—the error handler captures callbacks and contextValue at the time authenticate() is called; if either changes before the refresh timer triggers and an error occurs, stale references are used
  • Lines 294, 351, 410: Similar callback captures elsewhere

Recommended fix: Use a ref to track the current callbacks object:

const callbacksRef = useRef(callbacks);
useEffect(() => {
  callbacksRef.current = callbacks;
}, [callbacks]);

Then replace callbacks?.onError?.() calls with callbacksRef.current?.onError?.(). For contextValue, either ensure it's stable or pass contextValue via ref as well.

Alternatively, require that the parent component memoize callbacks with useCallback to maintain referential equality across renders.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba7b4a5 and 029ccc1.

📒 Files selected for processing (1)
  • lib/KindeAuthProvider.tsx (5 hunks)
🔇 Additional comments (3)
lib/KindeAuthProvider.tsx (3)

19-20: LGTM! Imports are appropriate for web compatibility.

The new imports (LocalStorage, MemoryStorage, maybeCompleteAuthSession, Platform) are correctly added to support platform-aware storage and web auth flow completion.

Also applies to: 37-41, 61-61


73-75: LGTM! Proper web auth session initialization.

Calling maybeCompleteAuthSession at module level is the correct pattern for handling OAuth redirects on web platforms. The platform and window checks ensure this only runs in the appropriate environment.


166-171: LGTM! Storage initialization flow is correct.

The storage instance is properly initialized, registered globally via setActiveStorage, and stored in component state. The type safety via SessionManager ensures all storage implementations are compatible.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 029ccc1 and b4d9240.

📒 Files selected for processing (1)
  • lib/KindeAuthProvider.tsx (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-08T06:21:44.638Z
Learnt from: didley
Repo: kinde-oss/expo PR: 5
File: lib/KindeAuthProvider.tsx:38-45
Timestamp: 2024-11-08T06:21:44.638Z
Learning: In `lib/KindeAuthProvider.tsx`, for the `KindeAuthProvider` component, the `config.domain` and `config.clientId` properties should be typed as `string | undefined` because users may pass `process.env` values, which can be `undefined`.

Applied to files:

  • lib/KindeAuthProvider.tsx
🔇 Additional comments (4)
lib/KindeAuthProvider.tsx (4)

19-20: LGTM!

The imports for LocalStorage and MemoryStorage are correctly added to support the new web storage strategy.


61-61: LGTM!

The Platform import is correctly added to enable platform-specific storage selection.


177-182: LGTM!

The initializeStorage function correctly integrates the new getStorageInstance helper to enable platform-aware storage selection while maintaining the existing initialization flow.


73-75: Verification complete—module-level invocation is correct.

The pattern of calling maybeCompleteAuthSession() once at app startup on web is the recommended usage pattern for expo-web-browser. Your implementation in KindeAuthProvider.tsx aligns with this guidance: the conditional platform check ensures it runs only on web, and the function is a no-op on native (iOS/Android), so there is no platform-specific risk. The code is sound.

Comment thread lib/KindeAuthProvider.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
lib/KindeAuthProvider.tsx (2)

150-173: Runtime storage selection and web fallback behavior look solid.

getStorageInstance now:

  • Uses Platform.OS === "web" to branch into a web-specific path.
  • Probes window.localStorage in a try/catch to detect private-browsing / restricted-cookie scenarios before instantiating LocalStorage.
  • Falls back to MemoryStorage with clear warnings when localStorage is unavailable or window is missing, avoiding hard failures on web/SSR.
  • Uses ExpoSecureStore.default() on native to keep storing secrets in a secure store.

Wiring this into initializeStorage via const storageInstance = await getStorageInstance(); and then calling setActiveStorage(storageInstance) and setStorage(storageInstance) is consistent with the SessionManager abstraction.

If you ever want to unit-test this selection logic in isolation, consider hoisting getStorageInstance to a module-level helper and injecting Platform/window via parameters, but that’s purely optional.

Also applies to: 177-177


175-207: Callbacks invoked during initialization see the first-render context; consider making that explicit or reworking.

Because the storage-initialization useEffect has an empty dependency array and is declared before useMemo(contextValue) and useCallback(onRefresh), the effect runs with the first-render instances of contextValue and onRefresh. That means:

  • callbacks?.onError inside the effect, and
  • callbacks?.onEvent(AuthEvent.tokenRefreshed, data, contextValue) triggered via onRefresh during the initial refreshToken call

receive a context object whose storage, isAuthenticated, isLoading, etc. still reflect the pre-initialization render.

If consumers of these callbacks expect to call methods on the passed context during bootstrap (e.g., getAccessToken right after a successful refresh), they’ll interact with a slightly stale view.

Not urgent, but you might consider one of:

  • Documenting that the context passed into these initialization-time callbacks may not be fully hydrated yet, or
  • Refactoring so the effect depends on a stable onRefresh that itself is based on the post-storage contextValue (for example, by guarding the effect with a useRef “initialized” flag and adding onRefresh/config as dependencies), or
  • Passing only primitives (domain, clientId, data) into these callbacks during init, and relying on the normal context for subsequent events.

Functionally this is a subtle edge case rather than a blocker, but worth being aware of.

Also applies to: 601-706

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4d9240 and 831dbed.

📒 Files selected for processing (1)
  • lib/KindeAuthProvider.tsx (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-11-08T06:21:44.638Z
Learnt from: didley
Repo: kinde-oss/expo PR: 5
File: lib/KindeAuthProvider.tsx:38-45
Timestamp: 2024-11-08T06:21:44.638Z
Learning: In `lib/KindeAuthProvider.tsx`, for the `KindeAuthProvider` component, the `config.domain` and `config.clientId` properties should be typed as `string | undefined` because users may pass `process.env` values, which can be `undefined`.

Applied to files:

  • lib/KindeAuthProvider.tsx
🔇 Additional comments (2)
lib/KindeAuthProvider.tsx (2)

116-121: Config typing for domain / clientId still correctly allows env-driven undefined.

KindeAuthConfig keeps domain and clientId as string | undefined and then explicitly guards against undefined at runtime, which matches the earlier guidance about supporting process.env values that may be missing. No changes needed here.
Based on learnings


37-41: Web auth-session completion is gated safely for browser-only environments.

Importing openAuthSessionAsync, openBrowserAsync, and maybeCompleteAuthSession from expo-web-browser, and then calling maybeCompleteAuthSession() only when Platform.OS === "web" and typeof window !== "undefined", keeps SSR/tests safe while enabling proper completion of web auth flows. This looks correct and aligns with Expo’s expectations.

Also applies to: 61-61, 73-75

@dtoxvanilla1991 dtoxvanilla1991 self-assigned this May 6, 2026
@dtoxvanilla1991

Copy link
Copy Markdown
Contributor

I'll look into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants