11Here are 2 different ways to add the "Code on Val Town" ribbon:
12
13### 1. Wrap your fetch handler (recommended)
14
15```ts
16import { modifyFetchHandler } from "https://esm.town/v/andreterron/codeOnValTown?v=45";
17import { html } from "https://esm.town/v/stevekrouse/html?v=5";
18
19export default modifyFetchHandler(async (req: Request): Promise<Response> => {
20 return html(`<h2>Hello world!</h2>`);
21});
51These functions infer the val using the call stack or the request URL. If the inference isn't working, or if you want to ensure it links to a specific val, pass the `val` argument:
52
53- `modifyFetchHandler(handler, {val: { handle: "andre", name: "foo" }})`
54- `modifyHtmlString("<html>...", {val: { handle: "andre", name: "foo" }})`
55
58You can set the style parameter to a css string to customize the ribbon. Check out [github-fork-ribbon-css](https://github.com/simonwhitaker/github-fork-ribbon-css?tab=readme-ov-file#styling) to learn more about how to style the element.
59
60- `modifyFetchHandler(handler, {style: ".github-fork-ribbon:before { background-color: #333; }"})`
61- `modifyHtmlString("<html>...", {style: ".github-fork-ribbon:before { background-color: #333; }"})`
62
64
65```ts
66modifyFetchHandler(handler, {style: `@media (max-width: 768px) {
67 .github-fork-ribbon {
68 display: none !important;
1import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON";
2
3export default async function fetchBrightDataBalance(
4 token: string,
5): Promise<number> {
6 try {
7 const result = await fetchJSON(
8 "https://api.brightdata.com/customer/balance",
9 {
14 return result.balance - result.pending_costs;
15 } catch (e) {
16 throw new Error(`Could not fetch balance (${e}).`);
17 }
18}
52});
53
54export default app.fetch;
55
56async function createPage(c: Context<HonoEnvOptional>) {
21 const req = c.req.raw;
22 console.log(c.req.path);
23 return fetch(`https://api.val.town${c.req.path}`, {
24 method: req.method,
25 body: req.body,
34const ENDPOINT = getValEndpointFromUrl(import.meta.url);
35export function api(path: string, token: string, init: RequestInit = {}) {
36 return fetch(`${ENDPOINT}/${path.replace(/^\/+/, "")}`, {
37 ...init,
38 headers: {
43}
44
45export default app.fetch;
65 const url = getValEndpointFromName(`@${author}/jwks`);
66 const method = createVerifyMethod(() => {
67 return fetch(url)
68 .then(res => res.json())
69 .then(({ keys }) => keys);
1/** @jsxImportSource https://esm.sh/hono@latest/jsx **/
2import { modifyFetchHandler } from "https://esm.town/v/andreterron/codeOnValTown?v=50";
3import { resetStyle } from "https://esm.town/v/nbbaier/resetStyle";
4import { sqlToCSV, sqlToJSON } from "https://esm.town/v/nbbaier/sqliteExportHelpers";
147});
148
149export default modifyFetchHandler(passwordAuth(app.fetch));
146});
147
148export default passwordAuth(app.fetch);
60}
61
62async function fetchUser(token: string): Promise<{ id: string }> {
63 const resp = await fetch("https://api.val.town/v1/me", {
64 headers: {
65 Authorization: `Bearer ${token}`,
68
69 if (resp.status !== 200) {
70 throw new Error("Could not fetch user");
71 }
72
76async function verifyApiToken(token: string) {
77 try {
78 const [currentUser, requestUser] = await Promise.all([fetchUser(Deno.env.get("valtown")), fetchUser(token)]);
79 return currentUser.id == requestUser.id;
80 } catch (_) {
13app.get("/", (c) => c.html(Layout`${userActionsDisplay(c.get("auth"))}` as string));
14
15export default app.fetch;
5app.get("/", (c) => c.text("Hello Val!!!"));
6
7export default app.fetch;