feat(react-auth): add createMultiAuth for multi-provider support#241
feat(react-auth): add createMultiAuth for multi-provider support#241
createMultiAuth for multi-provider support#241Conversation
Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/0be64a5f-8e5a-4377-87d7-3978b06e89d2 Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
createMultiAuth for multi-provider support
There was a problem hiding this comment.
Pull request overview
Adds a new createMultiAuth API to support multiple AuthClient instances under a single provider, while also fixing a multi-client correctness issue in wrapAuthClient caused by global prototype mutation.
Changes:
- Added
createMultiAuthwith keyeduseAuth(id)and a sharedAuthProviderthat initializes all clients. - Fixed
wrapAuthClientto avoid cross-client method bleed by building a per-instance prototype chain. - Exported
createMultiAuth/EnhancedAuthClientfrom the public barrel and added comprehensive Vitest coverage.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
lib/src/auth.tsx |
Adds createMultiAuth and updates wrapAuthClient to use per-instance prototype wiring. |
lib/src/index.ts |
Re-exports createMultiAuth and EnhancedAuthClient from the package entrypoint. |
lib/test/multiAuth.spec.tsx |
Adds tests covering multi-client init, context access by id, error/loading components, and client isolation regression. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot have a look at review comments and fix reported issues if considered correct. Also update documentation in README.md to feature sample for the multi-provider functionality. Also update the existing |
…teMultiAuth Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/3e98ce4e-137e-43ea-9582-f13bfe494699 Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
Done in ae29a68. Here's what was addressed: Review comments fixed:
|
Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/dc5e5d91-0c76-4981-be2d-7a45d09981e6 Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
Yes, it's been removed in b3ed4c2. Both |
|
@copilot please resolve conflicts in lock-file. Running |
…vider-support # Conflicts: # pnpm-lock.yaml Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
Done in 03f8bdc. Merged |
Affected Package(s)
@forward-software/react-auth(lib)@forward-software/react-auth-google(packages/google-signin)Related Issue(s)
Motivation
The library previously supported only a single
AuthClientpercreateAuthcall. This addscreateMultiAuth, enabling multiple auth providers to coexist under a singleAuthProvider, each addressable by a typed string key.createAuthhas also been refactored to be a thin wrapper overcreateMultiAuthto share the same initialisation logic. As a result of the refactor, theuse-sync-external-storeruntime dependency has been eliminated — the library now has zero runtime dependencies.Description of Changes
lib/src/auth.tsxcreateMultiAuth<M, E>(authClientsMap: M)— returns{ AuthProvider, authClients, useAuth }.AuthProviderinitialises all clients in parallel, honoursLoadingComponent/ErrorComponent(loading until all settle, error if any fail).useAuth(id)is generic overkeyof M— return type isEnhancedAuthClient<M[K], E>(per-key precision). Runtime guard inuseAuththrows a descriptive error for unknown ids.wrapAuthClientglobal prototype mutation: replacedObject.setPrototypeOf(AuthClientEnhancements.prototype, authClient)with a per-instance prototype built viaObject.create(authClient)+ copying enhancement method descriptors. Direct calls to rawAuthClientinterface methods (e.g.authClients.primary.onLogin()) now correctly dispatch to each client's own implementation.init()call is wrapped with.catch((): boolean => false)so that a rejection from one client (e.g. anonPostIniterror) does not short-circuit the others — all clients always get the chance to finish initialising before the provider state is updated.enhancedClientsMapnow usesObject.create(null)to prevent prototype pollution from user-controlled keys (e.g.__proto__).{ allInitialized, failed }singleuseState) avoids a flash-of-children on init failure in React <18.createAuthto be a thin wrapper overcreateMultiAuth({ default: authClient }). The public API (AuthProvider,authClient,useAuthClient) is unchanged. Removed the now-unnecessaryuseSyncExternalStoresubscription from the provider and the internalAuthContext/AuthProviderStatetypes.lib/package.jsonuse-sync-external-storeruntime dependency and@types/use-sync-external-storedevDependency — the library no longer callsuseSyncExternalStoreinternally. Thesubscribe/getSnapshotmethods onEnhancedAuthClientremain as public API for consumers to use directly withuseSyncExternalStoreif needed.lib/src/index.tscreateMultiAuthandEnhancedAuthClient(type was missing from the public barrel).lib/README.mdcreateMultiAuthsection with setup code,AuthProviderprops explanation, and auseAuthhook example with multiple providers.pnpm-lock.yamlorigin/maininto the branch and resolved lockfile conflicts viapnpm install --no-frozen-lockfile+pnpm dedupeto incorporate the removal ofuse-sync-external-storealongside upstream changes.lib/test/multiAuth.spec.tsx— 13 new tests covering:authClients,useAuthoutside provider, per-id client identity, allonInitcalled, init error handling,LoadingComponent,ErrorComponent, context access by both ids, per-clientonLoginrouting isolation (regression guard for the prototype fix), empty map, unknown-id runtime error.lib/test/provider.spec.tsxLoadingComponenttest: the old implementation showedLoadingComponentforever when init failed without anErrorComponent(artifact ofuseSyncExternalStore). The new correct behaviour hidesLoadingComponentonce init settles; the test now asserts visibility before init completes, consistent with themultiAuthspec pattern.Breaking Changes
None
How to Test
Vitest) and build steps pass successfully on this PR.pnpm installto install dependencies.pnpm --filter @forward-software/react-auth testto run tests for the affected package.pnpm --filter @forward-software/react-auth buildto verify the build succeeds.pnpm --filter @forward-software/react-auth lintto check for linting errors.Checklist
Notes for Reviewers
wrapAuthClientprototype fix changes instance identity:enhancedClient instanceof AuthClientEnhancementsnow returnsfalse(prototype chain no longer includesAuthClientEnhancements.prototype). Nothing in the library or tests relies oninstanceof, but worth noting if consumers do.createAuthnow delegates tocreateMultiAuthinternally. TheuseSyncExternalStoresubscription that previously drove the provider's reactive re-renders on auth state changes has been removed. Auth state updates (login, logout, refresh) are still fully observable viauseSyncExternalStore(client.subscribe, client.getSnapshot)directly on the returnedauthClient— the provider simply no longer re-renders all children automatically on every state change. This is a deliberate improvement: components subscribe to exactly what they need rather than getting blanket re-renders from the provider.subscribe/getSnapshotwithuseSyncExternalStorewill need to installuse-sync-external-storethemselves (or use React 18+ where it is built in).Original prompt
⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.