// slackNotify — post a message to a Slack incoming webhook, fire-and-forget. // // Demonstrates: `ctx.waitUntil(...)` — schedule work that OUTLIVES the // response. The caller gets `{ queued: true }` immediately; the actual // delivery runs in the background (on Cloudflare via the real // `ExecutionContext.waitUntil`, best-effort elsewhere). We use the global // `fetch` here because a detached background POST needs no HttpClient features. // // SLACK_WEBHOOK_URL=https://hooks.slack.com/... voltro serverless dev functions/slackNotify.serverless.ts // curl -X POST http://localhost:8910/ -d '{"text":"deploy finished"}' import { Effect, Schema } from 'effect' import { defineServerless, ServerlessHttpError } from '@voltro/serverless' export default defineServerless({ name: 'slack-notify', method: 'POST', input: Schema.Struct({ text: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(3000)) }), output: Schema.Struct({ queued: Schema.Boolean }), handler: ({ text }, ctx) => Effect.gen(function* () { const webhook = ctx.env.SLACK_WEBHOOK_URL if (!webhook) { return yield* Effect.fail( new ServerlessHttpError({ status: 503, message: 'slack-not-configured', detail: 'Set SLACK_WEBHOOK_URL.' }), ) } // Schedule the delivery in the background and respond NOW. ctx.waitUntil( fetch(webhook, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ text }), }).catch(() => { /* best-effort — a failed notification must not fail the request */ }), ) return { queued: true } }), })