Edge Functions
Run your own TypeScript/Deno code in your Wok, next to your data. Use functions for webhooks, third-party integrations, or any logic the database and REST API don't cover.
Deploy (shipped)
Write your function and ship it. index.ts can import local helper modules from the same function directory; TellWang deploys and persists the complete module tree. The cp's deploy_function step accepts the entrypoint as code and optional helpers as a relative-path files map. Git pushes and Wang's project deploy collect those files automatically.
Deploy notify-slack as a function on my Wok.Your function runs in your Wok, with secure access to its database and secrets — no servers to manage.
Invoke (shipped)
const { data } = await tw.functions.invoke("notify-slack", {
body: { message: "New signup 🎉" },
});Trigger on new rows (shipped)
Wire a function to run automatically when a row is written to a table. cp installs a Postgres trigger that fires pg_notify; a per-Wok listener inside cp picks the notify up and POSTs the row payload ({op, table, old, new}) to your function. The whole loop runs over the wok-local docker network — no public ingress, no extra latency.
// "run notify-slack on every INSERT into orders"
await tw.functions.triggers.create({
table: "public.orders",
event: "insert", // or "update" | "delete" | "*"
function_name: "notify-slack",
});Your function's request body looks like {trigger, fn, op, table, old?, new?}. new is the inserted/updated row; old is the deleted/pre-update row. Use the wok's in-network SUPABASE_URL (http://rest:3000) inside the function if you need to write back via PostgREST without hitting a public port.
Redis + BullMQ (shipped)
Every Wok ships a dedicated Redis 7 container, with process.env.REDIS_URL wired into every edge function — no setup. Reach for it for caching, rate limits, and sessions.
For work that has to run reliably — payroll runs, print batches, billing, invoice generation — BullMQ gives you durable job queues: a job that fails is retried with backoff instead of lost, jobs run in order, and a dropped worker picks up where it left off. That's the difference between "fire an HTTP call and hope" and a queue you can trust with money and paper.
import { Queue, Worker } from "bullmq";
import Redis from "ioredis";
const redis = new Redis(process.env.REDIS_URL!);
const emails = new Queue("emails", { connection: redis });
// in your function — enqueue from a webhook or API call
await emails.add("welcome", { userId: "u_123" });
// in another function — process
new Worker("emails", async (job) => {
await sendWelcomeEmail(job.data.userId);
}, { connection: redis });Redis runs inside the wok's docker network — only your functions and database can reach it. Persisted across restarts (AOF), 200 MiB memory cap with LRU eviction. For caching: any Redis client (ioredis, redis, etc) works against the same URL.
Roadmap
- Filtered + conditional triggers — WHEN clauses + column-list filters so "only when orders.total > 100" is one call.
- External Redis access — opt-in TLS proxy so apps outside the Wok can reach Redis with auth (today Redis is internal-only by design; proxy via an edge function if you need external ops).