import RipplingSDK, { DurableFunctionContext, FunctionEvent, FunctionResponse } from '@rippling/rippling-sdk'; type OfferLetterCompletedEvent = { status: 'signed' | 'declined'; signedDocumentId?: string; declinedReason?: 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 supergroupId = event['employee_id'] as string | undefined; const offerLetterDocumentId = event['offer_letter_document_id'] as string | undefined; const startDate = event['start_date'] as string | undefined; const signingBonusAmount = Number(event['signing_bonus_amount'] ?? 0); if (!workflowDefinitionId || !supergroupId || !offerLetterDocumentId || !startDate) { context.fail('Missing required onboarding inputs.', { code: 'missing_onboarding_inputs', details: { hasWorkflowDefinitionId: Boolean(workflowDefinitionId), hasSupergroupId: Boolean(supergroupId), hasOfferLetterDocumentId: Boolean(offerLetterDocumentId), hasStartDate: Boolean(startDate), }, }); } await context.step('send offer letter document', async () => { await client.workflowActionExecutions.create({ action_type: 'send_document', payload: { document: offerLetterDocumentId, recipients: supergroupId, }, workflow_definition_id: workflowDefinitionId, }); }); const offerCompletion = await context.waitForEvent( 'wait for signed offer letter', { type: 'offer_letter_completed', timeout: '7 days', }, ); if (offerCompletion.isTimeout()) { context.fail('Offer letter was not completed before the deadline.', { code: 'offer_letter_timeout', details: offerCompletion, }); } if (offerCompletion.payload.status !== 'signed') { context.fail('Offer letter was declined.', { code: 'offer_letter_declined', details: offerCompletion.payload, }); } await context.sleepUntil('wait until employee start date', startDate); if (signingBonusAmount > 0) { await context.step('schedule signing bonus payment', async () => { await client.workflowActionExecutions.create({ action_type: 'make_payment', payload: { apply_cap: false, description: `Signing bonus for durable run ${context.function.run_id}`, payment_amount: signingBonusAmount, recipients: supergroupId, }, workflow_definition_id: workflowDefinitionId, }); }); } return new FunctionResponse({ statusCode: 200, body: { supergroupId: supergroupId, offerStatus: offerCompletion.payload.status, signedDocumentId: offerCompletion.payload.signedDocumentId, completedAt: offerCompletion.payload.completedAt, signingBonusScheduled: signingBonusAmount > 0, }, }); }