pomdtr
I mainly enjoy tinkering with the val.town api:
- VS Code integration: https://github.com/pomdtr/valtown-vscode
- CLI: https://github.com/pomdtr/vt
Likes
108
runGist
@pomdtr
HTTP (deprecated)
Run a Github Gist Usage Fork this val Create a Gist on Github, containing a javascript module the module must have either exactly one export or a default export the export must be a function that accept a request and return a response In the gist url, replace gist.github.com/<username> by <username>-rungist.web.val.run For security reasons, only gists with a github username matching your val username are allowed to run on your account. Example Github Gist: https://gist.github.com/pomdtr/0b9bc664b48b1ad4316ba6324564885e Http Server: https://pomdtr-rungist.web.val.run/0b9bc664b48b1ad4316ba6324564885e
blog
@pomdtr
HTTP (deprecated)
Val Town Blog A blog written, developed and hosted on val.town. How ? Each article on this blog is contained single val, with a #blog tag. See this example article . // #blog
// title: Example Post
import { article } from "https://esm.town/v/pomdtr/article";
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import { html } from "https://esm.town/v/stevekrouse/html?v=5";
export async function examplePost(req: Request) {
const { author, name } = extractValInfo(import.meta.url);
return html(await article(author, name));
} Each of these post work on it's own . This val is able to: list them with the /v1/search api (with a #blog query) post with different author than the owner of this val will be filtered out only public vals will be listed render the readme of those vals using remark (with github styling) This process run each time a user visit the web endpoint , so the blog is always up to date. You can get your own instance of the blog by just forking this val .
blob
@std
Script
Blob Storage - Docs ↗ Val Town comes with blob storage built-in. It allows for storing any data, like text, JSON, or images. You can access it via std/blob . Blob storage is scoped globally to your account. If you set a blob in one val, you can retrieve it by the same key in another val. It's backed by Cloudflare R2. You may find this admin viewer helpful for viewing and editing your blobs. Get JSON import { blob } from "https://esm.town/v/std/blob";
let blobDemo = await blob.getJSON("myKey");
console.log(blobDemo); // returns `undefined` if not found Set JSON import { blob } from "https://esm.town/v/std/blob";
await blob.setJSON("myKey", { hello: "world" }); List keys import { blob } from "https://esm.town/v/std/blob";
let allKeys = await blob.list();
console.log(allKeys);
const appKeys = await blob.list("app_");
console.log(appKeys); // all keys that begin with `app_` Delete by key import { blob } from "https://esm.town/v/std/blob";
await blob.delete("myKey"); Examples Counter RSS Notifications (saving the last run time) Picture: Save & Read Error Handling blob.get can throw ValTownBlobNotFoundError Any method can throw ValTownBlobError for unexpected errors. Utilities Our Blob SDK also includes some utility functions to make working with blobs easier. Copy import { blob } from "https://esm.town/v/std/blob";
await blob.copy("myKey", "myKeyCopy"); Move import { blob } from "https://esm.town/v/std/blob";
await blob.move("myKey", "myKeyNew"); Lower-level API We provide access to the lower-level getter and setters,
which are useful if you are storing non-JSON or binary data,
need to stream in your response or request data, or do anything else lower-level. async get(key: string) : Retrieves a blob for a given key. async set(key: string, value: string | BodyInit) : Sets the blob value for a given key. See BodyInit . Limitations Blob-stored data counts towards your total Val Town storage – 10mb on the free plan and 1gb on pro. Check our pricing page to learn more. Keys for blobs can be up to 512 characters long. 📝 Edit docs
sunbeamValTownFn
@pomdtr
HTTP (deprecated)
Sunbeam integration for Val Town Installation First, install sunbeam . Then create a new val referencing this val. const sunbeamValtown = @pomdtr.sunbeamValTownFn(@me.secrets.valtown) then switch it's visibility to unlisted. You can then install your val in sunbeam # install the extension
sunbeam extension install --alias valtown val:<username>/sunbeamValtown Usage sunbeam valtown # list your vals
sunbeam valtown --help # list available commands Demo
minizod
@zackoverflow
Script
minizod Tiny Zod implementation. Why Zod is a dense library, and its module structure (or lack thereof) makes it difficult for bundlers to tree-shake unused modules . Additionally, using Zod in vals requires the await import syntax which means having to wrap every schema in a Promise and awaiting it. This is extremely annoying. So this is a lil-tiny-smol Zod meant for use in vals. A noteworthy use-case is using minizod to generate tyep-safe API calls to run vals outside of Val Town (such as client-side). Type-safe API call example We can use minizod to create type safe HTTP handlers and generate the corresponding code to call them using Val Town's API, all in a type-safe manner. First, create a schema for a function. The following example defines a schema for a function that takes a { name: string } parameter and returns a Promise<{ text: string }> . const minizodExampleSchema = () =>
@zackoverflow.minizod().chain((z) =>
z
.func()
.args(z.tuple().item(z.object({ name: z.string() })))
.ret(z.promise().return(z.object({ text: z.string() })))
); With a function schema, you can then create an implementation and export it as a val: const minizodExample = @me.minizodExampleSchema().impl(async (
{ name },
) => ({ text: `Hello, ${name}!` })).json() In the above example, we call .impl() on a function schema and pass in a closure which implements the actual body of the function. Here, we simply return a greeting to the name passed in. We can call this val, and it will automatically parse and validate the args we give it: // Errors at compile time and runtime for us!
const response = @me.minizodExample({ name: 420 }) Alternatively, we can use the .json() function to use it as a JSON HTTP handler: const minizodExample = @me.minizodExampleSchema().impl(async (
{ name },
) => ({ text: `Hello, ${name}!` })).json() // <-- this part We can now call minizodExample through Val Town's API. Since we defined a schema for it, we know exactly the types of its arguments and return, which means we can generate type-safe code to call the API: let generatedApiCode =
@zackoverflow.minizodFunctionGenerateTypescript(
// put your username here
"zackoverflow",
"minizodExample",
// put your auth token here
"my auth token",
@me.minizodExampleSchema(),
); This generates the following the code: export const fetchMinizodExample = async (
...args: [{ name: string }]
): Promise<Awaited<Promise<{ text: string }>>> =>
await fetch(`https://api.val.town/v1/run/zackoverflow.minizodExample`, {
method: "POST",
body: JSON.stringify({
args: [...args],
}),
headers: {
Authorization: "Bearer ksafajslfkjal;kjf;laksjl;fajsdf",
},
}).then((res) => res.json());