Readme

Blob Storage - Docs β†—

Val Town comes with blob storage built-in. It allows for storing any data: text, JSON, 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
Create valimport { blob } from "https://esm.town/v/std/blob"; let blobDemo = await blob.getJSON("myKey"); console.log(blobDemo); // returns `undefined` if not found
Set JSON
Create valimport { blob } from "https://esm.town/v/std/blob"; await blob.setJSON("myKey", { hello: "world" });
List keys
Create valimport { blob } from "https://esm.town/v/std/blob"; let allKeys = await blob.listKeys(); console.log(allKeys); const appKeys = await blob.listKeys("app_"); console.log(appKeys); // all keys that begin with `app_`
Delete by key
Create valimport { blob } from "https://esm.town/v/std/blob"; await blob.delete("myKey");

Examples

Error Handling

Utilities

Our Blob SDK also includes some utility functions to make working with blobs easier.

Copy
Create valimport { blob } from "https://esm.town/v/std/blob"; await blob.copy("myKey", "myKeyCopy");
Move
Create valimport { blob } from "https://esm.town/v/std/blob"; await blob.move("myKey", "myKeyNew");

Lower-level API

We do 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

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { API_URL } from "https://esm.town/v/std/API_URL";
import { ValTownBlobError } from "https://esm.town/v/std/ValTownBlobError";
import { ValTownBlobNotFoundError } from "https://esm.town/v/std/ValTownBlobNotFoundError";
export const blob = {
get: get,
set: set,
copy: copy,
move: move,
list: list,
delete: delete_,
getJSON: getJSON,
setJSON: setJSON,
};
async function list(prefix?: string): Promise<{ key: string; size: number; lastModified: string }[]> {
let querystring = prefix ? `?prefix=${encodeURIComponent(prefix)}` : "";
const res = await fetch(`${API_URL}/v1/blob${querystring}`, {
headers: {
Authorization: `Bearer ${Deno.env.get("valtown")}`,
},
});
if (!res.ok) {
const body = await res.text();
throw new ValTownBlobError(body ? body : "Error listing blobs");
}
return res.json();
}
async function delete_(key: string) {
const res = await fetch(`${API_URL}/v1/blob/${encodeURIComponent(key)}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${Deno.env.get("valtown")}`,
},
});
if (!res.ok) {
const body = await res.text();
throw new ValTownBlobError(body ? body : "Error deleting blob");
}
}
async function get(key: string) {
const res = await fetch(`${API_URL}/v1/blob/${encodeURIComponent(key)}`, {
headers: {
Authorization: `Bearer ${Deno.env.get("valtown")}`,
},
});
if (res.status === 404) {
throw new ValTownBlobNotFoundError();
}
if (!res.ok) {
const body = await res.text();
throw new ValTownBlobError(body ? body : "Error getting blob data");
}
return res;
}
async function set(key: string, value: BodyInit) {
const res = await fetch(`${API_URL}/v1/blob/${encodeURIComponent(key)}`, {
method: "POST",
headers: {
Authorization: `Bearer ${Deno.env.get("valtown")}`,
},
body: value,
});
if (!res.ok) {
const body = await res.text();
throw new ValTownBlobError(body ? body : "Error setting blob data");
}
}
async function copy(previous: string, next: string) {
const res = await get(previous);
await set(next, res.body);
}
async function move(previous: string, next: string) {
await copy(previous, next);
await delete_(previous);
}
async function getJSON(key: string) {
try {
const res = await get(key);
return res.json();
} catch (e) {
if (e instanceof ValTownBlobNotFoundError) {
return undefined;
}
throw e;
}
}
async function setJSON(key: string, value: any) {
return set(key, JSON.stringify(value));
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
v11 was merged from the PR "add copy and move methods" by pomdtr