Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .changeset/lucky-parts-own.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 2 additions & 2 deletions e2e/davinci-app/components/polling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<PollingCollector>,
submitForm: () => Promise<void>,
) {
Expand All @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion e2e/davinci-app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
);
Expand Down
9 changes: 6 additions & 3 deletions packages/davinci-client/src/lib/client.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,11 +415,14 @@ export async function davinci<ActionType extends ActionTypes = ActionTypes>({
},

/**
* @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<PollingStatus | InternalErrorResponse>} - 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 })),
Expand Down
Loading