Readme

Sync local <-> remote vals

TODO

  • Separate the logic in two steps:
    1. Detect changes
    2. Apply changes
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
98
99
100
import * as dotenv from "jsr:@std/dotenv";
import { encodeHex } from "jsr:@std/encoding/hex";
import { existsSync } from "jsr:@std/fs/exists";
import * as path from "jsr:@std/path";
const valtownToken = Deno.env.get("VALTOWN_TOKEN");
if (!valtownToken) {
console.error("VALTOWN_TOKEN is required");
Deno.exit(1);
}
export async function fetchEnv() {
const { data: res, error } = await fetchValTown("/v1/eval", {
method: "POST",
body: JSON.stringify({
code: "JSON.stringify(Deno.env.toObject())",
args: [],
}),
});
if (error) {
throw error;
}
const env = JSON.parse(res);
delete env["VALTOWN_API_URL"];
return env;
}
export async function fetchValTown<T = any>(
path: string,
options?: RequestInit & {
paginate?: boolean;
},
): Promise<{ data: T; error?: Error }> {
const apiURL = Deno.env.get("API_URL") || "https://api.val.town";
const headers = {
...options?.headers,
Authorization: `Bearer ${valtownToken}`,
};
if (options?.paginate) {
const data = [];
let url = new URL(`${apiURL}${path}`);
url.searchParams.set("limit", "100");
while (true) {
const resp = await fetch(url, {
headers,
});
if (!resp.ok) {
throw new Error(await resp.text());
}
const res = (await resp.json()) as {
data: unknown[];
links: { next?: string };
};
data.push(...res.data);
if (!res.links.next) {
break;
}
url = new URL(res.links.next);
}
return { data } as { data: T };
}
const resp = await fetch(`${apiURL}${path}`, {
...options,
headers,
});
if (!resp.ok) {
const text = await resp.text();
return { data: text as T, error: new Error(text) };
}
if (resp.headers.get("content-type")?.startsWith("application/json")) {
const data = (await resp.json()) as T;
return { data };
}
const text = await resp.text();
return { data: text } as { data: T };
}
type Meta = {
id: string;
name: string;
hash: string;
};
const lock: Record<string, Meta> = existsSync("vt.lock")
? JSON.parse(Deno.readTextFileSync("vt.lock"))
: {};
const { data: me } = await fetchValTown("/v1/me");
const valDir = path.join(Deno.cwd(), me.username);
if (!existsSync(valDir)) {
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
May 7, 2024