Skip to content

Commit d2f33b0

Browse files
authored
Merge pull request #19 from mojisdev/improve-local-dx
chore: improve local dx
2 parents d2b1082 + 7a0fcde commit d2f33b0

File tree

6 files changed

+129
-21
lines changed

6 files changed

+129
-21
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,38 @@
11
# api.mojis.dev
2+
3+
A RESTful API for accessing emoji data.
4+
5+
## 📦 Installation
6+
7+
```sh
8+
git clone https://github.com/mojis-dev/api.mojis.dev.git
9+
cd api.mojis.dev
10+
pnpm install
11+
```
12+
13+
## 🚀 Usage
14+
15+
```sh
16+
pnpm run dev
17+
```
18+
19+
> [!NOTE]
20+
> This will copy the emoji data from [mojis/emoji-data](https://github.com/mojis-dev/emoji-data) to the `node_modules/.emoji-data` directory.
21+
> If you want to update this, you can run `pnpm run copy:emoji-data`.
22+
23+
## 📖 API Documentation
24+
25+
The API documentation is available at [api.mojis.dev](https://api.mojis.dev) using Scalar.
26+
27+
## 🔧 Development
28+
29+
The project uses:
30+
31+
- [Hono](https://hono.dev/) for the web framework
32+
- [Cloudflare Workers](https://workers.cloudflare.com/) for deployment
33+
- [Vitest](https://vitest.dev/) for testing
34+
- [Scalar](https://scalar.com/) for API documentation
35+
36+
## 📄 License
37+
38+
Published under [MIT License](./LICENSE).

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
"dev": "wrangler dev",
88
"build": "wrangler deploy --dry-run --outdir=dist",
99
"build:openapi": "tsx ./scripts/build-openapi",
10-
"predev": "tsx ./scripts/copy-emoji-data",
10+
"predev": "pnpm run copy:emoji-data && pnpm run setup:emoji-data",
11+
"setup:emoji-data": "tsx ./scripts/setup-dev/setup.ts",
12+
"copy:emoji-data": "tsx ./scripts/copy-emoji-data",
1113
"deploy": "wrangler deploy",
1214
"test": "pnpm vitest --run",
1315
"test:watch": "pnpm vitest",

scripts/copy-emoji-data.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
import { existsSync } from "node:fs";
2+
import { mkdir, writeFile } from "node:fs/promises";
13
import path from "node:path";
24
import process from "node:process";
3-
import { unstable_startWorker } from "wrangler";
5+
import { parseTarGzip } from "nanotar";
46

57
const root = path.resolve(import.meta.dirname, "../");
68

79
async function run() {
10+
if (!existsSync(path.join(root.toString(), "./node_modules/.emoji-data"))) {
11+
await mkdir(path.join(root.toString(), "./node_modules/.emoji-data"), { recursive: true });
12+
}
13+
814
const res = await fetch("https://github.com/mojisdev/emoji-data/archive/refs/heads/main.tar.gz");
915

1016
if (!res.ok) {
@@ -13,21 +19,28 @@ async function run() {
1319

1420
const blob = await res.blob();
1521

16-
const worker = await unstable_startWorker({
17-
config: path.join(root.toString(), "./wrangler.jsonc"),
18-
entrypoint: path.join(root.toString(), "./scripts/emoji-data-setup-app.ts"),
19-
});
22+
const filePrefix = "emoji-data-main/data/";
2023

21-
const formData = new FormData();
22-
formData.append("file", blob, "emoji-data.tar.gz");
24+
const tar = await parseTarGzip(await blob.arrayBuffer(), {
25+
filter(file) {
26+
if (!file.name.startsWith(filePrefix) || !file.name.endsWith(".json")) {
27+
return false;
28+
}
2329

24-
await worker.fetch("https://api.mojis.dev/upload", {
25-
method: "POST",
26-
// @ts-expect-error hmmm
27-
body: formData,
30+
// remove the file prefix
31+
file.name = file.name.slice(filePrefix.length);
32+
33+
return true;
34+
},
2835
});
2936

30-
await worker.dispose();
37+
for await (const file of tar) {
38+
const filePath = path.join(root.toString(), "./node_modules/.emoji-data", file.name);
39+
await mkdir(path.dirname(filePath), { recursive: true });
40+
await writeFile(filePath, file.text);
41+
}
42+
43+
console.log("emoji data copied");
3144
}
3245

3346
run().catch((err) => {

scripts/emoji-data-setup-app.ts renamed to scripts/setup-dev/setup-worker.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ app.post(
5151
promises.push(c.env.EMOJI_DATA.put(normalizedEntryName, entry.text));
5252
}
5353

54-
c.executionCtx.waitUntil(
55-
Promise.all(promises),
56-
);
57-
58-
return c.json({
59-
message: "Files uploaded",
60-
});
54+
try {
55+
await Promise.all(promises);
56+
return c.json({
57+
message: "Files uploaded",
58+
});
59+
} catch (err) {
60+
console.error(err);
61+
return c.json({
62+
message: "Failed to upload files",
63+
}, 500);
64+
}
6165
},
6266
);
6367

scripts/setup-dev/setup.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { readFile } from "node:fs/promises";
2+
import path from "node:path";
3+
import process from "node:process";
4+
import { unstable_startWorker } from "wrangler";
5+
6+
const root = path.resolve(import.meta.dirname, "../..");
7+
8+
async function run() {
9+
const worker = await unstable_startWorker({
10+
config: path.join(root.toString(), "./wrangler.jsonc"),
11+
entrypoint: path.join(root.toString(), "./scripts/setup-dev/setup-worker.ts"),
12+
});
13+
14+
const file = await readFile(path.join(root.toString(), "./node_modules/.emoji-data/emoji-data.tar.gz"));
15+
const blob = new Blob([file]);
16+
17+
const formData = new FormData();
18+
formData.append("file", blob, "emoji-data.tar.gz");
19+
20+
console.log("sending request to worker");
21+
const res = await worker.fetch("https://api.mojis.dev/upload", {
22+
method: "POST",
23+
// @ts-expect-error hmmm
24+
body: formData,
25+
});
26+
27+
const json = await res.json();
28+
29+
console.log("received response from worker");
30+
console.log(json);
31+
32+
await worker.dispose();
33+
}
34+
35+
run().catch((err) => {
36+
console.error(err);
37+
process.exit(1);
38+
});

worker-configuration.d.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Generated by Wrangler by running `wrangler types --env-interface CloudflareBindings` (hash: c476c03844aa0429b0aacf2d2d7c8815)
2-
// Runtime types generated with workerd@1.20250317.0 2025-03-13
2+
// Runtime types generated with workerd@1.20250319.0 2025-03-13
33
declare namespace Cloudflare {
44
interface Env {
55
API_VERSION: "x.y.z";
@@ -4613,6 +4613,20 @@ interface D1Meta {
46134613
last_row_id: number;
46144614
changed_db: boolean;
46154615
changes: number;
4616+
/**
4617+
* The region of the database instance that executed the query.
4618+
*/
4619+
served_by_region?: string;
4620+
/**
4621+
* True if-and-only-if the database instance that executed the query was the primary.
4622+
*/
4623+
served_by_primary?: boolean;
4624+
timings?: {
4625+
/**
4626+
* The duration of the SQL query execution by the database instance. It doesn't include any network time.
4627+
*/
4628+
sql_duration_ms: number;
4629+
};
46164630
}
46174631
interface D1Response {
46184632
success: true;

0 commit comments

Comments
 (0)