Newsletter
TechAnV Blog
Get updates on security engineering, Rust, eBPF, and DevSecOps. No spam, unsubscribe anytime.
Check your inbox and click the confirmation link to complete your subscription.
Running a scheduled function on Val Town to import Atom feeds into Datasette Cloud#
Val Town is a neat service for hosting short server-side JavaScript programs online - reminiscent of a combination of Glitch and Observable Notebooks.
Today I figured out how to use it to run an hourly task (a “Val”) that fetches data from an Atom feed, parses it and then submits the resulting parsed data to a table running on Datasette Cloud via the Datasette JSON write API.
Configuring secrets in environment variables#
Because this Val needs to be able to call the Datasette Cloud API with an API token, I needed to figure out Val Town secrets. These are pretty straight-forward: you can set multiple environment variables for your account on this page:
https://www.val.town/settings/environment-variables
Those variables are then made available to your Vals through Deno.env.get("VARIABLE_NAME").
Scheduling a Val#
The Val Town logged in homepage looks like this:
Clicking “Scheduled function” creates a new private Val with a random name that looks like this:
The cog next to “Runs every 1hr” can be used to set a different interval.
Writing the code#
After some experimentation I landed on this as the content of my Val:
1export default async function(interval: Interval) {2 const { default: Parser } = await import("npm:rss-parser");3 let parser = new Parser();4 let feed = await parser.parseURL("https://simonwillison.net/atom/everything/");5 const token = Deno.env.get("DATASETTE_CLOUD_SIMON_FEED_WRITE");6 const url = "https://simon.datasette.cloud/data/feed/-/insert";7 const body = {8 "rows": feed.items,9 "replace": true,10 };11 const response = await fetch(url, {12 method: "POST",13 headers: {14 "Content-Type": "application/json",15 "Authorization": `Bearer ${token}`,16 },17 body: JSON.stringify(body),18 });19 if (response.ok) {20 const responseData = await response.json();21 console.log("Response data:", responseData);22 } else {23 console.error("Request failed:", response.statusText);24 }25}- Any NPM module can be imported directly into a Val using
await import("npm:name-of-package") - I used rss-parser to parse the feed - it was the first option I tried and provided exactly what I wanted
- As mentioned earlier,
Deno.env.get()provides access to configured environment variables - Deno’s fetch() function is modeled on the browser standard
console.log()andconsole.error()log to a dedicated log for that Val, visible beneath it
The blue “Run” button can be clicked any time to try out the Val. Once I got it working I left it running, and it’s been executing once an hour ever since.