The AppMap Deno recorder core, extracted from a pilot instrumenting one
Supabase edge function (waitlist-submit) in a real production app.
No business logic beyond that one example — this is the generic
tooling, not the app it came from.
appmap/appmap.ts—withAppMap(handler, options), a per-request session driver forDeno.serve/ Supabase edge functions. Records only requests carrying a W3Ctraceparentheader, one AppMap per request, to a local directory or POSTed to a collector if the runtime doesn't allow file writes.appmap/recorder/— the recorder core (Recording,startRecording,autoInstrument, event serialization to AppMap v1.2 JSON).examples/waitlist-submit.instrumented.ts— the actual pilot output: a real edge function (public waitlist signup, layered anti-spam checks) run through the build-time transform and manually wired towithAppMap.
This is the pilot as it was actually run and verified: Deno.serve(handler)
rewritten by hand to Deno.serve(withAppMap(handler, {...})), with a
hand-added import. That's real overhead on application code.
A cleaner version exists: getappmap/appmap-react
has a zero-touch Deno runner (appmap-deno, using deno run --preload)
that gets the same recording with no source changes at all — the
entry file stays completely untouched. That work came after this
pilot; this repo is kept as-is because it's what was actually verified
against the app it targets, not a claim that the wiring style here is
the final answer.
One caveat that matters if you adopt either version for Supabase
specifically: Supabase Edge Runtime is a custom Rust server
embedding Deno core, not the deno CLI — it has no --preload or
equivalent hook. The zero-touch runner in appmap-react only reaches
plain deno run / self-hosted Deno. For Supabase, the manual wiring
here (or its equivalent) is still the only way in.
deno run -A --node-modules-dir=none --unstable-sloppy-imports \
examples/waitlist-submit.instrumented.ts--node-modules-dir=none is a local-CLI-only requirement — it's
needed because a root package.json elsewhere in a real checkout
makes Deno expect a local node_modules/ for the npm:supabase-js
import; Supabase's actual edge runtime doesn't have this problem.
Needs SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY set (fake values
are fine for the honeypot and GET config-endpoint branches, which
never touch the database).
A stamped request through the honeypot branch:
curl 'http://localhost:8000/' \
-X POST -H 'Content-Type: application/json' \
-H 'traceparent: 00-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-1111111111111111-01' \
-d '{"first_name":"Bot","email":"bot@example.com","website":"http://spam.example"}'
ls tmp/appmap/requests/ # one file, showing handleWaitlistRequest -> getClientIp -> json