import RipplingSDK, { DurableFunctionContext, FunctionEvent, FunctionResponse } from '@rippling/rippling-sdk'; type QueryReviewCompletedEvent = { status: 'approved' | 'rejected'; reviewerId?: string; rejectionReason?: string; completedAt?: string; }; export async function onRipplingEvent( event: FunctionEvent, context: DurableFunctionContext, ): Promise { const client = new RipplingSDK({ bearerToken: context.env.rippling_user_bearer_token, }); const workflowDefinitionId = event['workflow_definition_id'] as string | undefined; const initialQuery = event['initial_query'] as string | undefined; const followUpQuery = event['follow_up_query'] as string | undefined; const followUpTime = event['follow_up_time'] as string | undefined; if (!workflowDefinitionId || !initialQuery || !followUpQuery || !followUpTime) { context.fail('Missing required query inputs.', { code: 'missing_query_inputs', details: { hasWorkflowDefinitionId: Boolean(workflowDefinitionId), hasInitialQuery: Boolean(initialQuery), hasFollowUpQuery: Boolean(followUpQuery), hasFollowUpTime: Boolean(followUpTime), }, }); } await context.step('run initial query', async () => { await client.workflowActionExecutions.create({ action_type: 'run_query', payload: { query: initialQuery, }, workflow_definition_id: workflowDefinitionId, }); }); const queryReview = await context.waitForEvent('wait for query review', { type: 'query_review_completed', timeout: '7 days', }); if (queryReview.isTimeout()) { context.fail('The query was not reviewed before the deadline.', { code: 'query_review_timeout', details: queryReview, }); } if (queryReview.payload.status !== 'approved') { context.fail('The query was rejected.', { code: 'query_rejected', details: queryReview.payload, }); } await context.sleepUntil('wait until follow-up time', followUpTime); await context.step('run follow-up query', async () => { await client.workflowActionExecutions.create({ action_type: 'run_query', payload: { query: followUpQuery, }, workflow_definition_id: workflowDefinitionId, }); }); return new FunctionResponse({ statusCode: 200, body: { reviewStatus: queryReview.payload.status, reviewerId: queryReview.payload.reviewerId, completedAt: queryReview.payload.completedAt, followUpQueryCompleted: true, }, }); }