Avatar

vladimyr

Joined August 5, 2023
Likes
94
pomdtr avatar
pomdtr
pipes
Script
An interactive, runnable TypeScript val by pomdtr
1
jxnblk avatar
jxnblk
caviar
Script
Simple CSS Vars library import { caviar } from "https://esm.town/v/jxnblk/caviar"; const vars = caviar({ dark: { text: "#000", bg: "#fff", }, light: { text: "#fff", bg: "#000", }, }); // JSX example <div style={vars.style.light}> <h1 style={{ color: vars.text, backgroundColor: vars.bg, }}> Hello </h1> </div> Can also be used for non-dynamic CSS vars import { caviar } from "https://esm.town/v/jxnblk/caviar"; const vars = caviar({ blue: "#0cf", }); // <div style={vars.style} /> Tests: https://www.val.town/v/jxnblk/caviar_tests TODO [ ] Fallback for missing mode keys
2
jxnblk avatar
jxnblk
tuna
Script
🐟 Simple CSS library for Val Town import { css } from "https://esm.town/v/jxnblk/tuna"; const styles = css({ body: { // special keyword for <body> element fontFamily: "system-ui, sans-serif", margin: 0, backgroundColor: "#f5f5f5", }, container: { padding: 32, // numbers are converted to pixel units margin: "0 auto", maxWidth: 1024, }, input: { fontFamily: "inherit", fontSize: "inherit", lineHeight: "1.5", padding: "2px 8px", border: "1px solid #ccc", borderRadius: "4px", }, }); // JSX example const html = render( <div className={styles.container}> <style {...styles.tag} /> <h1>Tuna Example</h1> <input type="text" defaultValue="hi" className={styles.input} /> </div> ); // get raw CSS string styles.css Nested selectors and pseudoselectors const styles = css({ button: { background-color: "tomato", "&:hover": { background-color: "magenta", }, "& > svg": { fill: "currentColor", }, }, }); Media queries const styles = css({ box: { padding: 16, "@media screen and (min-width: 768px)": { padding: 32, "&:hover": { color: "tomato", }, }, } }); Limitations Does not support HTML element selectors (other than body ) Tests: https://www.val.town/v/jxnblk/tuna_tests
3
pomdtr avatar
pomdtr
deno_server
Script
An interactive, runnable TypeScript val by pomdtr
1
saolsen avatar
saolsen
gameplay_agent
Script
gameplay_agent This is a val.town mirror of gameplay/games/agent . Click the link to see docs.
1
pomdtr avatar
pomdtr
cmdk_v1
Script
An interactive, runnable TypeScript val by pomdtr
1
pomdtr avatar
pomdtr
serve_blobs
HTTP
Serve prefixed blobs. Usage import { serveBlobs } from "https://esm.town/v/pomdtr/serve_blobs" export default serveBlobs({ root: "public/" }) All your blobs prefixed by public/ will be publicly accessible. Ex: Go to https://pomdtr-public.web.val.run/example.json to view the blob public/example.json from my account.
3
ramkarthik avatar
ramkarthik
bookmark
HTTP
A minimal bookmarking tool This allows you to bookmark links and view them later. Completely powered by ValTown and SQLite. To set this up for yourself Fork the val From your ValTown settings page, add an environment variable named bookmarks_client_id and give it a value (you will be using this for saving) Add another environment variable named bookmarks_client_secret and give it a value (you will also be using this for saving) At first, the "bookmarks" table will not exist, so we need to save an article first, which will create the "bookmarks" table To do this, add a bookmarklet to your browser with this value (replace BOOKMARKS-CLIENT-ID and BOOKMARKS-CLIENT-SECRET with the values you added to the environment variables, and replace BOOKMARKS-URL with your VAL's URL): javascript:void(open('BOOKMARKS-URL/save?u='+encodeURIComponent(location.href)+'&t='+encodeURIComponent(document.title)+'&id=BOOKMARKS-CLIENT-ID&secret=BOOKMARKS-CLIENT-SECRET', 'Bookmark a link', 'width=400,height=450')) Click this bookmarklet to bookmark the URL of the current active tab Go to your VAL URL homepage to see the bookmark Demo Here are my bookmarks: https://ramkarthik-bookmark.web.val.run/ Note Make sure you don't share bookmarks_client_id and bookmarks_client_secret . It is used for authentication before saving a bookmark.
7
nbbaier avatar
nbbaier
declarativeMigrations
Script
The beginnings of a val town implementation of the approach to declarative sqlite migrations laid out in this post: Simple declarative schema migration for SQLite
1
stevekrouse avatar
stevekrouse
sqlite_clone_migrate_table
Script
SQLite Migrate Table via cloning it into a new table example There are a lot of migrations that SQLite doesn't allow, such as adding a primary key on a table. The way to accomplish this is by creating a new table with the schema you desire and then copying the rows of the old table into it. This example shows how to: Get the schema for the existing table Create the new table Copy all rows from old to new Rename the old table to an archive (just in case) Rename the new table to the original table name This script shows me adding a primary key constraint to the Profile column of my DateMeDocs database. I would console and comment out various parts of it as I went. You can see everything I did in the version history. The main tricky part for me was removing the duplicate primary key entries before doing the migration step, which is a useful thing anyways, from a data cleaning perspective.
3
stevekrouse avatar
stevekrouse
insecureFetch
Script
Insecure SSL Cert Fetch This will be useful if you're getting a invalid peer certificate: UnknownIssuer error . If you need to make a fetch request to a website with a dubious or non-standard SSL certificate, you can use this proxy we made on Cloudflare workers (which doesn't verify SSL certs): https://unsecure-fetch.val-town.workers.dev/ import { insecureFetch } from "https://esm.town/v/stevekrouse/insecureFetch"; const url = "https://assignment-api.uspto.gov/patent/basicSearch?query=1234567&fields=main&rows=20"; const data = await insecureFetch(url) const text = await data.text(); console.log(text)
1
maxm avatar
maxm
ittyExample
HTTP
An interactive, runnable TypeScript val by maxm
1
pomdtr avatar
pomdtr
valtownByExample
HTTP
Val town by example Usage Simple Example To add an example, just create a val. The val should start with a JSDoc style multi line comment that describes the example: /** * @title HTTP server: Hello World * @description An example of a HTTP server that serves a "Hello World" message. */ // this comment will be displayed on the left export const server = () => new Response("Hello world!") The title is required. Then, you can write the code. Code can be prefixed with a comment that describes the code. The comment will be rendered next to the code in the example page. Make sure your val is public, then go to https://pomdtr-val_town_by_example.web.val.run/v/<your-username>/<your-val> Using multiple vals You can add another val to your example by adding an @include directive /** * @title HTTP server: Hello World * @description An example of a HTTP server that serves a "Hello World" message. * @include pomdtr/secondary_val */ See @pomdtr/react_example Adding external resources to your example You can attach an external link to your val by using the @resource directive. External resources are specified using a markdown link. /** * @title HTTP server: Hello World * @description An example of a HTTP server that serves a "Hello World" message. * @resource [Val Town Docs](https://docs.val.town) **/ Adding examples to the homepage Just add your val in @pomdtr/val_town_by_example_toc
3
pomdtr avatar
pomdtr
awesome
HTTP
Awesome Val Town An curated list of useful community vals. Feel free to create your own awesome list! Apps @pomdtr/blob_editor @nbbaier/sqliteExplorerApp View and interact with your Val Town SQLite data. @pomdtr/http_client Attach a postman-like http client to your vals VS Code Extension vt Chrome Extension Tooling Authentication @pomdtr/basicAuth @pomdtr/email_auth @pomdtr/password_auth Sqlite @sqlite/db @pomdtr/sql @pomdtr/kv @postpostscript/sqliteUniverse Blob @stevekrouse/blobAdmin @pomdtr/lowdb Middleware @andreterron/codeOnValTown Testing @pomdtr/test_explorer Api @pomdtr/api @pomdtr/trpc Other @vladimyr/valshot @pomdtr/mdx @pomdtr/serve_readme OpenAI @pomdtr/ask_ai Web Components Val Town Playground CodeMirror
6
pomdtr avatar
pomdtr
love_letter
HTTP
<3 Val Town Val Town is my new favourite thing. Never heard of it ? Well, according to it's homepage, Val Town is a social website to write and deploy TypeScript. It's often introduced as zappier for developers , or twitter for code . The 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: execute a function on a cron schedule host a small websites (this article hosted on Val Town ) send yourself emails ... But there is more to Val Town than this. If you take a look at the trending vals , you will quickly notice a pattern: most of the vals are about Val Town itself. People are using Val Town to extend Val Town, and it's fascinating to see what they come up with. I've built a few of these extensions myself, and this article is about one of them. Fixing the Val Town Search Val.town is built around the http import feature of Deno. Each val is a standalone module, that you can import in other vals. It works both for your own vals, and for the vals of other users. All of this is great, but there is one big issue: the search feature is terrible . It only works for exact text matches, and there is no way to set any filters based on username , creation_date , or anything else. This makes it really hard to find a val you are looking for, even if you are the one who wrote it. In any other platform, I would have just given up and moved on. But Val Town is different. I was confident that I could address this issue in userspace, without having to wait for the platform to implement it. Val Town allows you to run a val on a cron schedule, so I wrote a val that would fetch all the vals from the API, and store them as a sqlite table (did I mention that every user get it's own sqlite database ?). const createQuery = `CREATE TABLE IF NOT EXISTS vals ( ... );`; // run every hour export default function(interval: Interval) { // create the val table await options.sqlite.execute(createQuery); let url = "https://api.val.town/v1/search/vals?query=%20&limit=100"; // fetch all vals, and store them in the sqlite table while (true) { const resp = await fetch(url); if (!resp.ok) { throw new Error(await resp.text()); } const res = await resp.json(); const rows = res.data.map(valToRow); await insertRows(rows, options); if (!res.links.next) { break; } url = res.links.next; } } Once the val had finished running, I had a table with all the vals from the platform. I could now run queries on this table to find the vals I was looking for. import { sqlite } from "https://esm.town/v/std/sqlite" const res = await sqlite.execute(`SELECT * FROM vals WHERE author = 'pomdtr' && code LIKE '%search%'`); Of course I could have stopped there, but I wanted to go further. I wanted to share this table with other users, so they could run their own queries on it. Isolating the Vals Table There was still a challenge to overcome: the table was part of my account database, and I didn't want to give everyone access to it (there are some sensitive tables in there). One way to solve this issue would be to publish a stripped-down api that only allows a few predefined queries. But that would be boring, and I wanted to give users the full power of SQL. So I decided to isolate the val table in a separate account. There is a neat trick to achieve this on val.town: each val get's it own email address, and email sent to vals can be forwarded to your own email address. import { email as sendEmail } from "https://esm.town/v/std/email?v=11"; // triggered each time an email is sent to pomdtr.sqlite_email@valtown.email export default async function(email: Email) { // forward the email to my own email address await sendEmail({ subject: email.subject, html: email.html, text: email.text, }); } Since val.town account can be created with a val.email address, you can create an infinite number of accounts (and thus sqlite databases) using this trick. So say hello to the sqlite account , which is a separate account that only contains the vals table. After creating the account, I just needed to fork the cron val from my main account to get a copy of the vals table in the sqlite account. Publishing the Table The 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. import { rpc } from "https://esm.town/v/std/rpc?v=5"; import { InStatement, sqlite } from "https://esm.town/v/std/sqlite?v=4"; // rpc create an server, exposed on the val http endpoint export default rpc(async (statement: InStatement) => { try { // run the query, then return the result as json return await sqlite.execute(statement); } catch (e) { throw new Response(e.message, { status: 500, }); } }); Everyone can now run queries on the table thanks a publically accessible endpoint (you even have write access to it, but I trust you to not mess with it). You can test it locally using curl and jq : echo "SELECT * FROM vals WHERE lower(name) LIKE '%feed%' and lower(name) like '%email%' LIMIT 100" | jq -R '{args: [.]} ' | xargs -0 -I {} curl -X POST "https://sqlite-execute.web.val.run" -H "Content-Type: application/json" -d {} | jq Of course I don't expect the average val.town user to use shell commands to run queries, so I also built an helper val to interact with the API, allowing users to run queries from their own vals. // only the import changed from the previous example import { db } from "https://esm.town/v/sqlite/db"; // this query will run on the `sqlite` account const res = await db.execute(`SELECT * FROM vals WHERE author = 'pomdtr' && code LIKE '%search%'`); I've seen some really cool vals built on top of this API. Someone even wrote down a guide to help users interact with it from the command-line! I hope that someone will build an search UI to interact with it at some point, but in the meantime, you can use a community-contributed sqlite web interface to run queries on top of the vals table. Val.town as a code-taking app As I've tried to show, having both a runtime, an editor and an API on the same platform is quite a magic formula. It's probably why val.town resonates so much with me. Using CodeSandbox, Stackblitz, Repl.it, Gitpod, Github Codespaces or Gitpod feels pretty much the same, everything still revolves around the same concept of a project/repository. They feel uninspired somehow, trying to replicate the desktop IDE experience in the browser, instead of embracing the new possibilities that the web platform offers. Val.town breaks this mold. I see it as a code-taking app, a place where I can just dump my ideas without worrying about the usual frictions of writing and deploying code.
1
easrng avatar
easrng
kyselyVtDemo
Script
Kysely on val.town Uses @easrng/kyselyVtDialect as a Kysely Dialect and @easrng/kyselyVtTypes for type autogeneration.
1