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
import { getMermaidDependencyGraph } from "https://esm.town/v/rlesser/getDependencyGraph?v=91";
import { getReverseDependencies } from "https://esm.town/v/rlesser/getReverseDependencies";
import { gfm } from "https://esm.town/v/rlesser/gfm";
import { Hono } from "npm:hono@3.9.2";
const app = new Hono();
const homePageMarkdown = `
# ValTown Dependency Graph Viewer
### What is this
This tool lets you view dependency graph for any public val on [valtown](www.val.town).
Add a valtown slug (\`author/name\`) to this url to see the dependency graph for that val.
Some big dependency graphs - let me know if you find any bigger ones!
* [stevekrouse/sqlite_admin](stevekrouse/sqlite_admin)
* [nbbaier/vtIdeaAggregator](nbbaier/vtIdeaAggregator)
* [rodrigotello/hnFollow](rodrigotello/hnFollow)
* [rlesser/dependency_graph](rlesser/dependency_graph) (a bit meta...)
### TODO
Some ideas for how to expand this site:
* **show the upstream dependencies** - no public API for this yet, but could probably make it work with the search api
* **search for vals** - let people search for vals right from here, using the search api and debouncing
* **toggle graph complexity** - let people choose to see all dependencies or only valtown dependencies (thru the browser)
* **cache graphs in DB** - we should be kind to valtown's API by caching graph data as exploring the
graph involves a lot of calls. maybe only update it when the val version number changes?
* **handle more module sources** - currently we only group npm, esm.sh, and valtown modules. we could add more or make
this a dynamic grouping mechanism?
* **author pages?** - a page to show all the public vals by a person. not sure if needed and dont want to just end up
wrapping every val.town page here.
* **val readme** - show the val readme at the top of each val page
`;
const valPageMarkdown = (author: string, name: string, mermaid: string, reverseDeps: string) => `
[Home](/)
# ${author}/${name}
### Dependency Graph
\`\`\`mermaid
${mermaid}
\`\`\`
### Reverse Dependencies
${reverseDeps || "*None found*"}
`;
const footerMarkdown = `
---
*Website created by [rlesser/dependency_graph](https://www.val.town/v/rlesser/dependency_graph)*
`;
async function makePage(markdown: string, title: string) {
return await gfm(markdown + footerMarkdown, { title, favicon: "๐Ÿ–‡๏ธ" });
}
app.get("/", async (c) => {
return c.html(await makePage(homePageMarkdown, "ValTown Dependency Graph"));
});
app.get("/:author/:name", async (c) => {
const author = c.req.param("author");
const name = c.req.param("name");
try {
const mermaid = await getMermaidDependencyGraph(`${author}/${name}`);
const reverseDeps = (await getReverseDependencies(`${author}/${name}`))
.map(d => `* [${d.slug}](/${d.slug})`)
.join("\n");
return c.html(
await makePage(
valPageMarkdown(author, name, mermaid, reverseDeps),
`${author}/${name} | ValTown Dependency Graph`,
),
);
} catch (e) {
return c.html("Error!<br>" + e);
}
});
export default app.fetch;
๐Ÿ‘† This is a val. Vals are TypeScript snippets of code, written in the browser and run on our servers. Create scheduled functions, email yourself, and persist small pieces of data โ€” all from the browser.