diff --git a/.changeset/lucky-parts-own.md b/.changeset/lucky-parts-own.md index bb4eb4bc5b..49fac48e1f 100644 --- a/.changeset/lucky-parts-own.md +++ b/.changeset/lucky-parts-own.md @@ -3,4 +3,12 @@ '@forgerock/davinci-client': minor --- -Support both challenge polling and continue polling in DaVinci +Adds `pollStatus()` method and `PollingCollector` to `@forgerock/davinci-client` for polling support in DaVinci flows. + +Pass a `PollingCollector` to `davinciClient.pollStatus(collector)` to get a poller function. The polling mode is detected automatically from the collector: + +- **Challenge polling**: Periodically calls the `/status` endpoint until the challenge is resolved. + +- **Continue polling**: Performs a delay and returns a status based on remaining poll retries. Call the returned poller function repeatedly in a loop until it resolves with the next node in the flow or an error. + +Adds ability to intercept the polling request with middleware. diff --git a/e2e/davinci-app/components/polling.ts b/e2e/davinci-app/components/polling.ts index f0e55ee123..12450e03af 100644 --- a/e2e/davinci-app/components/polling.ts +++ b/e2e/davinci-app/components/polling.ts @@ -9,7 +9,7 @@ import type { PollingCollector, Poller, Updater } from '@forgerock/davinci-clien export default function pollingComponent( formEl: HTMLFormElement, collector: PollingCollector, - poll: Poller, + pollStatus: Poller, updater: Updater, submitForm: () => Promise, ) { @@ -26,7 +26,7 @@ export default function pollingComponent( p.innerText = 'Polling...'; formEl?.appendChild(p); - const status = await poll(); + const status = await pollStatus(); if (typeof status !== 'string' && 'error' in status) { console.error(status.error?.message); diff --git a/e2e/davinci-app/main.ts b/e2e/davinci-app/main.ts index a1a93b54d4..85249a8b5b 100644 --- a/e2e/davinci-app/main.ts +++ b/e2e/davinci-app/main.ts @@ -273,7 +273,7 @@ const urlParams = new URLSearchParams(window.location.search); pollingComponent( formEl, // You can ignore this; it's just for rendering collector, // This is the plain object of the collector - davinciClient.poll(collector), // Returns a poll function + davinciClient.pollStatus(collector), // Returns a poll function davinciClient.update(collector), // Returns an update function for this collector submitForm, ); diff --git a/packages/davinci-client/src/lib/client.store.ts b/packages/davinci-client/src/lib/client.store.ts index 3e2d3adcd8..04f29f7a48 100644 --- a/packages/davinci-client/src/lib/client.store.ts +++ b/packages/davinci-client/src/lib/client.store.ts @@ -415,11 +415,14 @@ export async function davinci({ }, /** - * @method poll - Perform challenge polling or continue polling - * @param {PollingCollector} collector - the polling collector + * @method pollStatus - A helper for challenge or continue polling + * @description - In challenge polling mode, periodically polls the `/status` endpoint and returns a status. + * In continue polling mode, returns a polling status after a delay based on poll retries remaining. + * The polling mode is automatically detected. + * @param {PollingCollector} collector - The polling collector * @returns {Promise} - Returns a promise that resolves to a polling status or error */ - poll: (collector: PollingCollector): Poller => { + pollStatus: (collector: PollingCollector): Poller => { return async () => { const result = await getPollingModeµ(collector).pipe( Micro.flatMap((mode) => pollingµ({ mode, collector, store, log })),