diff --git a/.changeset/export-subscribe-method.md b/.changeset/export-subscribe-method.md new file mode 100644 index 0000000000..b6e923c53a --- /dev/null +++ b/.changeset/export-subscribe-method.md @@ -0,0 +1,6 @@ +--- +'@forgerock/journey-client': minor +'@forgerock/oidc-client': minor +--- + +Expose `subscribe` method on journey and oidc client instances, consistent with davinci-client. Allows consumers to listen for store state changes. diff --git a/packages/journey-client/api-report/journey-client.api.md b/packages/journey-client/api-report/journey-client.api.md index 9e471c8784..0766624d7b 100644 --- a/packages/journey-client/api-report/journey-client.api.md +++ b/packages/journey-client/api-report/journey-client.api.md @@ -194,6 +194,8 @@ export interface JourneyClient { // (undocumented) start: (options?: StartParam) => Promise; // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) terminate: (options?: { query?: Record; }) => Promise; diff --git a/packages/journey-client/api-report/journey-client.types.api.md b/packages/journey-client/api-report/journey-client.types.api.md index c9d45ac5a5..e796925f15 100644 --- a/packages/journey-client/api-report/journey-client.types.api.md +++ b/packages/journey-client/api-report/journey-client.types.api.md @@ -181,6 +181,8 @@ export interface JourneyClient { // (undocumented) start: (options?: StartParam) => Promise; // (undocumented) + subscribe: (listener: () => void) => () => void; + // (undocumented) terminate: (options?: { query?: Record; }) => Promise; diff --git a/packages/journey-client/src/lib/client.store.test.ts b/packages/journey-client/src/lib/client.store.test.ts index 69b12553fb..5c2dfc54fb 100644 --- a/packages/journey-client/src/lib/client.store.test.ts +++ b/packages/journey-client/src/lib/client.store.test.ts @@ -108,6 +108,7 @@ describe('journey-client', () => { expect(client.redirect).toBeInstanceOf(Function); expect(client.resume).toBeInstanceOf(Function); expect(client.terminate).toBeInstanceOf(Function); + expect(client.subscribe).toBeInstanceOf(Function); }); test('journey_InvalidWellknownUrl_ThrowsError', async () => { diff --git a/packages/journey-client/src/lib/client.store.ts b/packages/journey-client/src/lib/client.store.ts index 129386a864..57bc2e7f03 100644 --- a/packages/journey-client/src/lib/client.store.ts +++ b/packages/journey-client/src/lib/client.store.ts @@ -36,6 +36,7 @@ export type JourneyResult = JourneyStep | JourneyLoginSuccess | JourneyLoginFail /** The journey client instance returned by the `journey()` function. */ export interface JourneyClient { + subscribe: (listener: () => void) => () => void; start: (options?: StartParam) => Promise; next: (step: JourneyStep, options?: NextOptions) => Promise; redirect: (step: JourneyStep) => Promise; @@ -154,6 +155,8 @@ export async function journey({ }); const self: JourneyClient = { + subscribe: store.subscribe, + start: async (options?: StartParam) => { const { data } = await store.dispatch(journeyApi.endpoints.start.initiate(options)); if (!data) { diff --git a/packages/oidc-client/api-report/oidc-client.api.md b/packages/oidc-client/api-report/oidc-client.api.md index 283d363dc9..8108079f89 100644 --- a/packages/oidc-client/api-report/oidc-client.api.md +++ b/packages/oidc-client/api-report/oidc-client.api.md @@ -27,6 +27,7 @@ import { StoreEnhancer } from '@reduxjs/toolkit'; import { ThunkDispatch } from '@reduxjs/toolkit'; import { Tuple } from '@reduxjs/toolkit'; import { UnknownAction } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; import { WellknownResponse } from '@forgerock/sdk-types'; export { ActionTypes } @@ -252,10 +253,12 @@ export function oidc(input: { }): Promise<{ error: string; type: string; + subscribe?: undefined; authorize?: undefined; token?: undefined; user?: undefined; } | { + subscribe: (listener: () => void) => Unsubscribe; authorize: { url: (options?: GetAuthorizationUrlOptions) => Promise; background: (options?: GetAuthorizationUrlOptions) => Promise; diff --git a/packages/oidc-client/api-report/oidc-client.types.api.md b/packages/oidc-client/api-report/oidc-client.types.api.md index 283d363dc9..8108079f89 100644 --- a/packages/oidc-client/api-report/oidc-client.types.api.md +++ b/packages/oidc-client/api-report/oidc-client.types.api.md @@ -27,6 +27,7 @@ import { StoreEnhancer } from '@reduxjs/toolkit'; import { ThunkDispatch } from '@reduxjs/toolkit'; import { Tuple } from '@reduxjs/toolkit'; import { UnknownAction } from '@reduxjs/toolkit'; +import { Unsubscribe } from '@reduxjs/toolkit'; import { WellknownResponse } from '@forgerock/sdk-types'; export { ActionTypes } @@ -252,10 +253,12 @@ export function oidc(input: { }): Promise<{ error: string; type: string; + subscribe?: undefined; authorize?: undefined; token?: undefined; user?: undefined; } | { + subscribe: (listener: () => void) => Unsubscribe; authorize: { url: (options?: GetAuthorizationUrlOptions) => Promise; background: (options?: GetAuthorizationUrlOptions) => Promise; diff --git a/packages/oidc-client/src/lib/client.store.test.ts b/packages/oidc-client/src/lib/client.store.test.ts index 87703d308a..b6838ceac6 100644 --- a/packages/oidc-client/src/lib/client.store.test.ts +++ b/packages/oidc-client/src/lib/client.store.test.ts @@ -129,6 +129,18 @@ describe('PingOne token get method', async () => { expect(tokens.error).toBe('No tokens found'); }); + it('exposes a subscribe method', async () => { + const oidcClient = await oidc({ config, storage: customStorageConfig }); + + if ('error' in oidcClient) { + throw new Error('Error creating OIDC Client'); + } + + expect(oidcClient.subscribe).toBeInstanceOf(Function); + const unsubscribe = oidcClient.subscribe(vi.fn()); + expect(unsubscribe).toBeInstanceOf(Function); + }); + it('Get tokens', async () => { customStorage.set( storageKey, diff --git a/packages/oidc-client/src/lib/client.store.ts b/packages/oidc-client/src/lib/client.store.ts index da6c3de99c..7a0924de7e 100644 --- a/packages/oidc-client/src/lib/client.store.ts +++ b/packages/oidc-client/src/lib/client.store.ts @@ -95,6 +95,9 @@ export async function oidc({ } return { + // Pass store methods to the client + subscribe: store.subscribe, + /** * An object containing methods for the creation, and background use, of the authorization URL */