feat: typed login() rejection shape across platforms (+ useAssetLinks plist passthrough docs/constant) - #111
Merged
dianaKhortiuk-frontegg merged 2 commits intoJul 30, 2026
Conversation
Implements frontegg#110. login() now rejects with a stable, documented FronteggLoginError: code ('user_cancelled' | 'oauth_failed' | 'network' | 'unknown'), message, userCancelled, plus the raw platform details preserved as nativeCode / nativeMessage. - iOS: the previous reject code was error.failureReason on the outer FronteggError, which is nil (only the inner Authentication enum implements it), so JS always saw EUNSPECIFIED. Map the FronteggError cases onto the stable codes and carry the raw failure reason in the NSError userInfo. - Android: the SDK's (Exception?) -> Unit login callback was already forwarded into the promise (rejecting as LOGIN_ERROR); normalize the rejection code instead (CanceledByUserException -> user_cancelled, FailedToAuthenticateException -> oauth_failed, IOException -> network) and carry the exception class name/message in userInfo. - JS: normalizeLoginError() guarantees the shape even for older native layers or unexpected rejections; types exported from the package root. - Docs: new 'Handling login errors' section in docs/usage.md. - Tests: jest coverage for login()/normalizeLoginError; Android JVM unit tests for the new code mapping.
Companion to frontegg/frontegg-ios-swift#293 (option proposed in a separate native PR); follow-up to the typed login() errors work for frontegg#110. iOS configuration is plist-driven: FronteggSwift decodes Frontegg.plist directly, so the plist is the wrapper's config passthrough. Unknown keys are ignored by the SDK's Codable decode, which makes setting <key>useAssetLinks</key> today a safe no-op that takes effect with no wrapper change once a FronteggSwift version supporting it ships. - Read the useAssetLinks key from Frontegg.plist in the bridge and expose it via getConstants() (parity with Android's useAssetsLinks BuildConfig constant), so JS can introspect the configuration. - Type getConstants() with a FronteggConstants interface including the optional useAssetLinks flag. - Document the plist-key forwarding in docs/setup.md.
dianaKhortiuk-frontegg
marked this pull request as ready for review
July 30, 2026 07:53
dianaKhortiuk-frontegg
approved these changes
Jul 30, 2026
dianaKhortiuk-frontegg
left a comment
Collaborator
There was a problem hiding this comment.
Approving. Verified the JS layer locally, because CI did not run it.
Only Android E2E and iOS E2E reported on this PR — Install | Build | Test and Lint and Typecheck never ran, so the 77 lines of new tests and the new TypeScript types were unverified. Ran them against the PR head:
jest— 8/8 pass, includingloginresolve/reject and allnormalizeLoginErrorcases (stable codes, unknown-code passthrough, null/non-error rejections).tsc --noEmit— no errors insrc/.eslint— 0 errors. The oneno-shadowwarning onFronteggNative.ts:177is pre-existing on master and untouched here.
The fix itself is right: the iOS bridge rejected with error.failureReason, which is nil on the outer FronteggError (only the inner Authentication enum implements it), so every iOS login failure surfaced as EUNSPECIFIED. Android's mapping is unit-tested for all four codes.
Two follow-ups, neither blocking:
- The iOS mapping has no unit test — this repo has no Swift unit-test target (only
ReactNativeExampleUITests), so there's nowhere to put one. Worth adding that target separately. - The missing CI jobs are worth investigating — a PR that changes JS/TS should not merge without the JS test and typecheck jobs running.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #110 — a documented, typed error shape for
login()rejections across platforms — plus companion plumbing for frontegg/frontegg-ios-swift#293.What
Typed login errors (commit 1):
FronteggLoginErrorCode('user_cancelled' | 'oauth_failed' | 'network' | 'unknown'),FronteggLoginError { code, message, userCancelled, nativeCode?, nativeMessage? },normalizeLoginError();login()rethrows the normalized shape so consumers get it even against older native layers. Documented indocs/usage.md.rejecter(error.failureReason, …)passes nil (failureReasononly exists on the innerFronteggError.Authenticationenum), so JS always receivedEUNSPECIFIED. NewnormalizedLoginError(_:)switches on the real error cases (verified against FronteggSwift 1.3.13, the podspec pin):.operationCanceled → user_cancelled; the OAuth family →oauth_failed;.networkError → network; conservativeunknownotherwise, raw reason preserved inuserInfo.LOGIN_ERROR; now normalized —CanceledByUserException → user_cancelled,FailedToAuthenticateException → oauth_failed,IOException → network— with the raw exception class/message preserved.useAssetLinks passthrough (commit 2): the wrapper passes no config to native init (FronteggSwift decodes
Frontegg.plistitself), so a JS option would be dead plumbing. Instead:docs/setup.mddocuments the plist key as the passthrough (Codable ignores unknown keys today; takes effect automatically if/when #293's native option ships), andgetConstants()now exposesuseAssetLinks(typed via a newFronteggConstantsinterface), matching how Android surfaces its config.Validation
yarn test: 8/8 (5 new tests covering the normalization paths)yarn typecheck/ eslint: clean vs. baseline (the twoexample/errors and one warning exist identically on master):frontegg_react-native:testDebugUnitTestBUILD SUCCESSFUL viaexample/android(module Kotlin + new JVM tests)swiftc -parseclean; the error-mapping function additionally typechecked against the real FronteggSwift 1.3.13 error model. A full pod-install host-app build is the remaining verification — draft until we've done that.One mapping judgment call flagged for review: iOS
.authError(.other(Error))may wrap URLError network failures; we left itunknown(raw reason preserved) rather than guess.