Skip to content

Commit 4086338

Browse files
committed
feat: share backend
1 parent dfda652 commit 4086338

File tree

5 files changed

+101
-12
lines changed

5 files changed

+101
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ dist-ssr
2424
*.sw?
2525

2626
.vercel
27+
.env*.local

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@tailwindcss/typography": "^0.5.16",
2323
"@universal-middleware/core": "^0.4.7",
2424
"@universal-middleware/hono": "^0.4.12",
25+
"@vercel/blob": "^1.1.1",
2526
"class-variance-authority": "^0.7.1",
2627
"clsx": "^2.1.1",
2728
"hono": "^4.7.11",

pnpm-lock.yaml

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/server/api.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@ import * as v from "valibot";
22
import { vValidator } from "@hono/valibot-validator";
33
import { nanoid } from "nanoid";
44
import { Hono } from "hono";
5+
import { put, head } from "@vercel/blob";
56

6-
const sharedCode: Map<string, Uint8Array> = new Map();
7+
const BLOG_PATH = "parameters/share";
78

89
const parameters = new Hono()
9-
.get("/:id", (c) => {
10+
.get("/:id", async (c) => {
1011
const { id } = c.req.param();
11-
const bytes = sharedCode.get(id);
12-
13-
if (!bytes) {
14-
throw new Error("Foo");
12+
try {
13+
const { url } = await head(`${BLOG_PATH}/${id}.txt`);
14+
const res = await fetch(url);
15+
const code = new TextDecoder().decode(await res.arrayBuffer());
16+
17+
return c.json({ code });
18+
} catch (e) {
19+
console.error(`Failed to load playground with id ${id}: ${e}`);
20+
return c.notFound();
1521
}
16-
17-
const code = new TextDecoder().decode(bytes);
18-
19-
return c.json({ code });
2022
})
2123
.post(
2224
"/",
@@ -26,7 +28,7 @@ const parameters = new Hono()
2628
code: v.string(),
2729
}),
2830
),
29-
(c) => {
31+
async (c) => {
3032
const { code } = c.req.valid("json");
3133
const bytes = new TextEncoder().encode(code);
3234

@@ -35,7 +37,10 @@ const parameters = new Hono()
3537
}
3638

3739
const id = nanoid();
38-
sharedCode.set(id, bytes);
40+
await put(`${BLOG_PATH}/${id}.txt`, code, {
41+
addRandomSuffix: false,
42+
access: "public",
43+
});
3944

4045
return c.json({ id });
4146
},

vite.config.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,42 @@ import { defineConfig, mergeConfig, type Plugin } from "vite";
77

88
const OUT_DIR = ".vercel";
99

10+
/**
11+
* Load .env files in dev.
12+
* This is naive implementation but I wanted to avoid adding a dependency.
13+
*/
14+
const dotenv = (envFile?: string | string[]): Plugin => ({
15+
name: "dotenv",
16+
async buildStart() {
17+
const files = () => {
18+
if (!envFile) {
19+
return [".env.local"];
20+
}
21+
22+
if (typeof envFile === "string") {
23+
return [envFile];
24+
}
25+
26+
return envFile;
27+
};
28+
29+
const contents = await Promise.all(
30+
files().flatMap((path) => fs.readFile(path, "utf-8").catch(() => "")),
31+
);
32+
contents
33+
.flatMap((line) => line.split("\n"))
34+
.map((line) => line.trim())
35+
.filter((line) => !line.startsWith("#") && line !== "")
36+
.map((line) => line.split("="))
37+
.map(([key, value]) => {
38+
if (key.startsWith("VITE_")) {
39+
return;
40+
}
41+
process.env[key] = value.replaceAll('"', "");
42+
});
43+
},
44+
});
45+
1046
/**
1147
* Create the [config.json][1] and [vc-config.json][2] files required in the final output.
1248
*
@@ -180,6 +216,7 @@ export default defineConfig(({ mode, command }) => {
180216
allowedHosts: [".coder", ".ngrok"],
181217
},
182218
plugins: [
219+
dotenv(),
183220
react(),
184221
devServer({
185222
entry: "./src/server/index.tsx",

0 commit comments

Comments
 (0)