Avatar

@neverstew

9 likes105 public vals
Joined January 12, 2023
Twice called wise. 🧐 Building a better world at https://equalcare.coop.

This Val URL

Returns the URL of the val that calls this function.

See https://www.val.town/v/neverstew.thisValUrlExample

Readme
1
2
3
4
5
6
import { parentReference } from "https://esm.town/v/stevekrouse/parentReference?v=3";
export let thisValUrl = () => {
let { userHandle, valName } = parentReference();
return `https://val.town/v/${userHandle}.${valName}`;
};

This val allows you to send me an email at a certain datetime. Fun!

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { emailServiceCreate } from "https://esm.town/v/neverstew/emailServiceCreate";
export let scheduleEmail = async (req: express.Request, res: express.Response) => {
const z = await import("npm:zod");
const params = z.object({
sendAt: z.string().datetime(),
content: z.string(),
});
const sendAt = req.query.sendAt;
const content = req.query.content;
const parsedParams = params.safeParse({ sendAt, content });
if (parsedParams.success) {
await emailServiceCreate(parsedParams.data);
res.send(`Scheduled for ${sendAt}`);
}
else {
res.send(JSON.stringify(parsedParams.error.format()));
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { email } from "https://esm.town/v/std/email?v=9";
import { PDFDocument } from "npm:pdf-lib";
export let sendPDF = (async () => {
// PDF Creation
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage();
page.drawText("You can create PDFs!");
const content = await pdfDoc.saveAsBase64();
return email({
text: "here's a pdf",
attachments: [
{
content,
filename: "test.pdf",
type: "application/pdf",
disposition: "attachment",
},
],
});
})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { set } from "https://esm.town/v/std/set?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
let { submittedEmailAddresses } = await import("https://esm.town/v/neverstew/submittedEmailAddresses");
export const renderFormAndSaveData = async (req: Request) => {
// A visit from a web browser? Serve a HTML page with a form
if (req.method === "GET") {
return new Response(
`
<!DOCTYPE html>
<html>
<head>
<title>Email Form</title>
</head>
<body>
<!-- Change the action here to THIS val's Express endpoint! -->
<form action="https://neverstew-renderFormAndSaveData.web.val.run" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
`,
{ headers: { "Content-Type": "text/html" } },
);
}
// Otherwise, someone has submitted a form so let's handle that
if (submittedEmailAddresses === undefined) {
submittedEmailAddresses = [];
}
const formData = await req.formData();
const emailAddress = formData.get("email") as string;
if (submittedEmailAddresses.includes(emailAddress)) {
return new Response("you're already signed up!");
}
await email({
text: `${emailAddress} just signed up!`,
subject: "new sign up",
});
submittedEmailAddresses.push(emailAddress);
await set(
"submittedEmailAddresses",
submittedEmailAddresses,
);
return new Response("thanks! you're signed up!");
};
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let { submittedEmailAddresses } = await import("https://esm.town/v/neverstew/submittedEmailAddresses");
export const saveFormData = async (req: Request) => {
// Create somewhere to store data if it doesn't already exist
if (submittedEmailAddresses === undefined) {
submittedEmailAddresses = [];
}
// Pick out the form data
const formData = await req.formData();
const emailAddress = formData.get("email");
if (submittedEmailAddresses.includes(emailAddress)) {
return new Response("you're already signed up!");
}
console.email(`${emailAddress} just signed up!`, "new sign up");
// Store form data
submittedEmailAddresses.push(emailAddress);
return new Response("thanks! you're signed up!");
};
1
2
3
4
5
6
7
8
9
import { toGeojsonPoint } from "https://esm.town/v/neverstew/toGeojsonPoint";
import { manchesterBerylStations } from "https://esm.town/v/neverstew/manchesterBerylStations";
import { geojsonFeatureCollection } from "https://esm.town/v/neverstew/geojsonFeatureCollection";
export let manchesterBerylStationsGeojson = geojsonFeatureCollection(
manchesterBerylStations.map(
toGeojsonPoint,
),
);

Readable

Make any website instantly readable!

Readme
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import basicCss from "https://esm.town/v/neverstew/basicCss";
import { Readability } from "npm:@mozilla/readability";
// @ts-ignore
import { JSDOM } from "npm:jsdom";
export default async function(req: Request) {
let resp = await fetch(`https://${new URL(req.url).pathname}`, req);
let body = await resp.text();
let doc = new JSDOM(body);
let reader = new Readability(doc.window.document.cloneNode(true));
let article = reader.parse();
console.log(article.content);
return new Response(
`
<html>
<head>
<style>${basicCss}</style>
</head>
<body>
<main>
<article>
${article.content}
</article>
</main>
</body>
</html>
`,
{
headers: {
"Content-Type": "text/html",
},
},
);
}

githubRestClient

Does what it says! Defaults to using GITHUB_TOKEN env var if none is passed to the function.

Readme
1
2
3
4
5
import { Octokit } from "npm:@octokit/rest";
export async function githubRestClient(ghToken: string | undefined) {
return new Octokit({ auth: ghToken || Deno.env.get("GITHUB_TOKEN") }).rest;
}
1
2
3
export function sleep(milliseconds: number) {
return new Promise(res => setTimeout(res, 3000));
}

inTheBackground

With the addition of the "early return" feature of web handlers, you can now process short background tasks in vals. This can be really useful for occasions where an immediate response is required, with a subsequent update a few seconds later

e.g. a Discord bot that calls ChatGPT needs to respond within a few seconds, which can be too fast for the AI to generate a response. We can instead reply immediately and then update that message later, inTheBackground

Simply wrap something in inTheBackground and it will do just that! In this example, we log something a few seconds later than the web response is sent back.

Readme
Fork
1
2
3
4
5
6
7
8
9
10
import { inTheBackground } from "https://esm.town/v/neverstew/inTheBackground";
import { sleep } from "https://esm.town/v/neverstew/sleep";
export default async function(req: Request): Promise<Response> {
inTheBackground(async () => {
await sleep(3000);
console.info(new Date());
});
return Response.json({ time: new Date() });
}