Likes
13
![saolsen avatar](https://images.clerk.dev/oauth_github/img_2QtXHzN3gDPhKsBOvKsst8LTxC5.png)
prune_val
@saolsen
Script
Prune a val's versions. Useful if you want to delete a bunch of versions. All versions before keep_since that aren't in keep_versions will be deleted !!! You can run it without passing commit to see a preview of what will happen. Example await prune_val("abcdefg", [3,6,8], 12, true); Could output Val: untitled_peachTakin, Current Version: 15
Deleting Versions: [ 1, 2, 4, 5, 7, 8, 9, 10, 11 ]
Deleting Version 1
Deleted
Deleting Version 2
Deleted
Deleting Version 4
Deleted
Deleting Version 5
Deleted
Deleting Version 6
Deleted
Deleting Version 7
Version already deleted, skipping
Deleting Version 8
Deleted
Deleting Version 9
Deleted
Deleting Version 10
Deleted
Deleting Version 11
Deleted
![pomdtr avatar](https://images.clerk.dev/oauth_github/img_2RCoAITJZH1QencEgtVjh4Qirj4.jpeg)
sql
@pomdtr
Script
SQL Template Tag Port of blakeembrey/sql-template-tag for usage in val.town. Usage import { sqlite } from "https://esm.town/v/std/sqlite"
import { sql, zip } from "https://esm.town/v/pomdtr/sql"
const query = sql`SELECT * FROM books WHERE author = ${author}`;
console.log(query.sql) // => "SELECT * FROM books WHERE author = ?"
console.log(query.args) // => [author]
const res = await sqlite.execute(query)
console.table(zip(res)) For advanced usage (ex: nesting queries), refer to the project readme .
![saolsen avatar](https://images.clerk.dev/oauth_github/img_2QtXHzN3gDPhKsBOvKsst8LTxC5.png)
tracing
@saolsen
Script
Opentelemetry Tracing for Vals! Enables Opentelemetry tracing for vals.
Exports two functions, init and traced_handler .
init will set up opentelemetry. For how to use it see this example val . By default, traces log to the console but if you set HONEYCOMB_API_KEY it'll also push the traces to honeycomb.
In the future we can add more export targets for other services. I'm also thinking about making a val to display them. traced_handler is a wrapper for your handler you can use on an HTTP val. Just pass it your HTTP function and export it as the default and it'll trace every request. Here's a screenshot of what the honeycomb view of a trace from my connect playing val looks like.
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
ntfy
@xkonti
Script
Allows to publish a ntfy notification using a fluent builder configuration. Usage example import { ntfy } from "https://esm.town/v/xkonti/ntfy";
await ntfy()
.toServer(Deno.env.get("ntfyServer"))
.asUser(Deno.env.get("ntfyUser"), Deno.env.get("ntfyPassword"))
.toTopic("testing")
.withMessage("Hello there!")
.withTitle("First test")
.withViewAction("My website", "https://xkonti.tech")
.withTags("package", "val-town")
.withPriority("high")
.publish(); ⚠️ For the notification to be sent it needs to be published ( publish function). Use helper Executes specified functions that can modify the notification. Can be used to streamline authentication, apply common operations, etc. import { ntfy } from "https://esm.town/v/xkonti/ntfy";
const toMyNtfyServer = (builder: ReturnType<typeof ntfy>) => {
builder
.toServer(Deno.env.get("ntfyServer"))
.asUser(Deno.env.get("ntfyUser"), Deno.env.get("ntfyPassword"));
};
await ntfy()
.use(toMyNtfyServer)
.toTopic('home-automation')
.withMessage('You left the front door open')
.publish(); You can pass it multiple functions. Functions toServer(url) - optional Specifies a server that the notification will be sent do. By default it's https://ntfy.sh . asUser(user, password) - optional Authenticates with the user and password. Please use ValTown's secrets for this. await ntfy()
.asUser('user123', '12345')
... usingToken(token) - optional Authenticates using the provided token. Please use ValTown's secrets for this. await ntfy()
.usingToken('some-token')
... toTopic(topic) - required Specifies which topic to publish the message to. await ntfy()
.toTopic('home-automation')
... withMessage(message, markdown) - required Specifies the main message of the notification. You can also flag it as markdown by passing true as a second argument. By default markdown is false . await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
... await ntfy()
.toTopic('home-automation')
.withMessage('Your garage is **flooding**!', true)
... withTitle(title) - optional Sets the title of the notification. await ntfy()
.toTopic('home-automation')
.withTitle('Garage')
.withMessage('You left the front door open')
... withPriority(priority) - optional Sets the priority of the notification. Possible from lowest to highest priority: min , low , default , high , max await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withPriority('high')
... Alternatively you can use dedicated functions: .withMinPriority() , .withLowPriority() , .withDefaultPriority() , .withHighPriority() , .withMaxPriority() await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withHighPriority()
... withTags(...tags) - optional Sets tags of the notification. This overrides any previously existing tags. await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withTags('door', 'safety')
... withDelay(delay) - optional Sets the delay for notification delivery. Read ntfy docs for more info. await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withDelay('tomorrow, 10am')
... withViewAction(label, url, clear?) - optional Adds an action button that opens a website or app when tapped. label - Label of the action button in the notification url - URL to open when action is tapped clear - Clear notification after action button is tapped (defaults to false ) await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withViewAction('View Val', 'https://www.val.town/v/xkonti/ntfy')
... withBroadcastAction(label, intent?, extras?, clear?) - optional Adds an action button that sends an Android broadcast intent when tapped. label - Label of the action button in the notification intent - Android intent name, default is io.heckel.ntfy.USER_ACTION extras - Android intent extras. clear - Clear notification after action button is tapped (defaults to false ) await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withBroadcastAction('Selfie', 'Take picture', { 'cmd': 'pic' })
... withHtmlAction(label, url, method?, headers?, body?, clear?) - optional Adds an action button that sends a HTTP request when tapped. label - Label of the action button in the notification url - URL to which the HTTP request will be sent method - HTTP method to use for request, default is POST headers - HTTP headers to pass in request. body - HTTP body as a string clear - Clear notification after action button is tapped (defaults to false ) await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withHtmlAction(
'Self-destruct',
'https://self.destruct/initiate',
'POST',
{ 'Authentication': 'Bearer 123' },
'{"countdown":60}'
)
... withClickUrl(url) - optional Makes the notification open the specified URL when clicked (tapped). withRawAttachment(filename, filedata) - optional Attached a file to the notification. Only one file can be attached. await ntfy()
.toTopic('home-automation')
.withMessage('You left the front door open')
.withRawAttachment('todo.txt', 'Nothing!')
... withUrlAttachment(url) - optional Attaches a file that is hosted elsewhere (URL). withIcon(url) - optional Sets an icon for the notification. viaEmail(email) - optional Sends the notification via email instead. viaPhoneCall(number) - optional Sends the notification via a phone call . The number defaults to yes , which makes it use the first phone number defined on your ntfy account. withoutCache() - optional Disables the cache for the notification. Read the docs on caching for more info. withoutFirebase() - optional Disables Firebase forwarding for the notification. Read the docs on Firebase for more info. withUnifiedPush() - optional Indicates intent of using the Unified Push for the notification. Read the docs on Unified Push for more info.
gpt3
@patrickjm
RPC
* OpenAI text completion. https://platform.openai.com/docs/api-reference/completions
*
* val.town has generously provided a free daily quota. Until the quota is met, no need to provide an API key.
* To see if the quota has been met, you can run @patrickjm.openAiFreeQuotaExceeded()
*
* For full REST API access, see @patrickjm.openAiTextCompletion