7The idea is simple: you write down a javascript snippet (named vals) in your browser, and it's instantly executed on a server. You can use it to:
8
9- execute a function on a cron schedule
10- host a small websites (this article [hosted on Val Town](https://www.val.town/v/pomdtr/love_letter))
11- send yourself emails
32
33// run every hour
34export default function(interval: Interval) {
35 // create the val table
36 await options.sqlite.execute(createQuery);
78
79// triggered each time an email is sent to pomdtr.sqlite_email@valtown.email
80export default async function(email: Email) {
81 // forward the email to my own email address
82 await sendEmail({
96## Publishing the Table
97
98The val.town stdlib provides a neat `rpc` function that provides a simple way to expose a function as an API. So I decided to write a simple val that would run a query on the table, and return the result.
99
100```ts
3// Send a pushover message.
4// token, user, and other opts are as specified at https://pushover.net/api
5export default async function pushover({
6 token,
7 user,
3const NEWSLETTER_URL = "https://bytes.dev/archives";
4
5function normalizeURL(url: string) {
6 return url.startsWith("http://") || url.startsWith("https://")
7 ? url
9}
10
11async function fetchText(url: string, options?: any) {
12 const response = await fetch(normalizeURL(url), {
13 redirect: "follow",
2
3// Fetches a random joke.
4async function fetchRandomJoke() {
5 const response = await fetch(
6 "https://official-joke-api.appspot.com/random_joke",
9};
10
11export function authMiddleware(
12 handler: (Request) => Promise<Response>,
13 options: Options,
56}
57
58export default async function(req: Request): Promise<Response> {
59 return new Response("This is middleware only");
60}
15 */
16
17export default async function(req: Request): Promise<Response> {
18 // HANDLE GET REQUEST FOR 'VERIFICATION REQUESTS'
19 if (req.method === "GET") {
10export const blobStore = createStore();
11
12export function createStore<T>(options?: KeyvBlobOptions): Store<T> {
13 const key = options?.key ?? "keyv";
14 return new KeyvLow<T>({
5import ky from "npm:ky";
6
7export default async function(req: Request, options?: {
8 transformReadme: HtmlProcessor;
9}): Promise<Response> {
39}
40
41async function fetchValtownExample(scope: string, name: string, version: string) {
42 const pkgConfig = await getConfig(scope, name, version);
43 version = pkgConfig.version;
8export type HtmlProcessor = (html: string, author: string, name: string) => Promise<string>;
9
10export function serveReadme(
11 valUrl: string | URL,
12 transformHtml: HtmlProcessor = decorateHtml,
25
26export { decorateHtml as transformHtml };
27async function decorateHtml(html: string, author: string, name: string) {
28 html = await appendCodeOnValTownRibbon(html, author, name);
29 html = await appendPersonalizedFooter(html);
31}
32
33export async function appendCodeOnValTownRibbon(html: string, author: string, name: string) {
34 const { ribbonElement } = await import("https://esm.town/v/andreterron/codeOnVT_ribbonElement?v=7");
35 const fragment = ribbonElement({ val: { handle: author, name } });
37}
38
39export async function appendPersonalizedFooter(html: string) {
40 const { MyFooter: createMyFooter } = await import("https://esm.town/v/vladimyr/MyFooter");
41 const style = `<style>
54}
55
56async function readmeToHtml(readme: string, author: string, name: string) {
57 return linkifyReadme(
58 await gfm(readme, {
15export const sqliteStore = createStore();
16
17export function createStore<T>(options?: KeyvSqliteOptions): Store<T> {
18 return new KeyvSql({
19 ...options,
23}
24
25async function connect() {
26 return async function query(sql: string): Promise<Record<string, any>[]> {
27 const { columns, rows } = await sqlite.execute(sql);
28 return rows.map(row => {