Public
std
blob
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. Blob Admin Panels Blob Storage in Settings – built-into Val Town - list, download, delete blobs Blob Admin – search, view, edit, upload blobs – built in a val – easy to customize in Val Town! Usage 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
9
rozek
InvocationTracker
Script
If you make a val public, you may probably also want to see how often that val is used - perhaps even including some statistics which show how often that val was called in a given time span. This is exactly what the "InvocationTracker" was written for. Simply include a call to the "InvocationTracker" in your val, and from then on any invocations will be tracked in an sqlite table allowing you to easily calculate how often the val was used in total or get the time course of calls. Usage Example Using an InvocationTracker (within the val that should be monitored) is quite simple: import { InvocationTracker } from 'https://esm.town/v/rozek/InvocationTracker'
const TrackingTable = 'xxx' // enter name of sqlite table that can be used
const Granularity = 15*60*1000 // how precisely should be logged?
;(async () => {
const Tracker = await InvocationTracker.new(TrackingTable,Granularity)
await Tracker.increment() // logs this invocation
... now continue as usual
})() Later, you may then use the "InvocationTracker" to provide you with some statistics: import { InvocationTracker } from 'https://esm.town/v/rozek/InvocationTracker'
const TrackingTable = 'xxx' // enter name of sqlite table that can be used
;(async () => {
const Tracker = await InvocationTracker.new(TrackingTable,Granularity)
/**** define the time span that interests you ****/
const from = new Date('xxx').getTime() // enter start date of your time span
const to = Date.now() // here we are interested in all invocations until now
/**** get the total number of invocations in the given time span ****/
const totalInvocations = await Tracker.totalInvocationsInSpan(from,to)
/**** get more information about when your val was called over time ****/
const Invocations = await Tracker.InvocationsInSpan(from,to)
// format: [{ Time,Invocations },...] with the given granularity
// only times with actual invocations are listed, idle times are skipped
})() The "InvocationTracker" is designed to be accessed simultaneously from multiple concurrently running vals without interfering with each other. API Reference static async new (Name:string, Granularity:number = 15*60*1000):Promise<InvocationTracker>
creates a new "InvocationTracker" instance. Name must match /^[a-z_][0-9a-z_]+$/i , Granularity is the time resolution in milliseconds async Granularity ():Promise<number>
returns the current time resolution in milliseconds async setGranularity (newGranularity:number):Promise<void>
sets a new time resolution (in milliseconds). newGranularity must be an integer >= 1 async reset ():Promise<void>
clears all recorded invocations async increment ():Promise<void>
increments the invocation count for the current time period async InvocationsInSpan (from:number, to:number):Promise<{ Time:number, Invocations:number }[]>
returns a list of invocation counts within the specified time span. from and to are Unix timestamps in milliseconds async totalInvocationsInSpan (from:number, to:number):Promise<number>
returns the total number of invocations within the specified time span. from and to are Unix timestamps in milliseconds Tests Some tests can be found in val InvocationTracker_Test
0
rozek-openrouter_test.web.val.run
Updated: February 1, 2025