Skip to content

Commit

Permalink
Merge pull request #31 from sor4chi/feat/env-getter
Browse files Browse the repository at this point in the history
feat: enable to get bindings env from vars
  • Loading branch information
sor4chi authored Dec 3, 2023
2 parents 1476881 + 44c46e2 commit cdf0f9e
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 44 deletions.
19 changes: 19 additions & 0 deletions .changeset/clean-seals-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"hono-do": minor
---

feat: enable to get bindings env from vars

```ts
import { generateHonoObject } from "hono-do";

type Env = {
Bindings: {
KV: KVNamespace
};
}

export const Batcher = generateHonoObject<Env>("/", async (app, state, vars) => {
vars.env.KV // KVNamespace
})
```
21 changes: 20 additions & 1 deletion examples/batcher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@ The code is based on [Cloudflare's Alarm example](https://developers.cloudflare.

```
pnpm install
pnpm dev
```

Setup the database:

```
pnpm create-db
```

Copy the outputted database configuration.
Add the database configuration to the `wrangler.toml` file.

Add the following to the `wrangler.toml` file's `[[d1_databases]]` section:

```
preview_database_id = "DB"
```

Run the following to start the batcher:

```
pnpm dev
```
3 changes: 2 additions & 1 deletion examples/batcher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
"dev": "wrangler dev src/index.ts",
"deploy": "wrangler deploy --minify src/index.ts"
"deploy": "wrangler deploy --minify src/index.ts",
"create-db": "wrangler d1 create batch-db"
},
"dependencies": {
"hono": "^3.6.0",
Expand Down
59 changes: 37 additions & 22 deletions examples/batcher/src/batcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import { generateHonoObject } from "hono-do";

import { Env } from ".";

const SECONDS = 1000;

declare module "hono-do" {
Expand All @@ -10,29 +12,42 @@ declare module "hono-do" {
}
}

export const Batcher = generateHonoObject(
"/batcher",
async (app, state, vars) => {
const { storage } = state;
const vals = await storage.list({ reverse: true, limit: 1 });
vars.count = vals.size === 0 ? 0 : parseInt(vals.keys().next().value);

app.post("/", async (c) => {
vars.count++;

const currentAlarm = await storage.getAlarm();
if (currentAlarm == null) {
await storage.setAlarm(Date.now() + 10 * SECONDS);
}

await storage.put(vars.count.toString(), await c.req.text());
return c.json({ queued: vars.count });
});
},
).alarm(async (state, vars) => {
export const Batcher = generateHonoObject<
Env,
Record<string, never>,
"/batcher"
>("/batcher", async (app, state, vars) => {
await vars.env.DB.prepare(
"CREATE TABLE IF NOT EXISTS batcher (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)",
).run();

const { storage } = state;
const vals = await storage.list();
console.log(Array.from(vals.values())); // eg: POST other upstream service
const vals = await storage.list<string>({ reverse: true, limit: 1 });
vars.count = vals.size === 0 ? 0 : parseInt(vals.keys().next().value);

app.post("/", async (c) => {
vars.count++;

const currentAlarm = await storage.getAlarm();
if (currentAlarm == null) {
await storage.setAlarm(Date.now() + 10 * SECONDS);
}

await storage.put(vars.count.toString(), await c.req.text());
return c.json({ queued: vars.count });
});
}).alarm(async ({ storage }, vars) => {
const vals = await storage.list<string>();
let query = "INSERT INTO batcher (data) VALUES ";
const params: string[] = [];
for (const value of vals.values()) {
query += "(?),";
params.push(value);
}
query = query.slice(0, -1);
await vars.env.DB.prepare(query)
.bind(...params)
.run();
await storage.deleteAll();
vars.count = 0;
});
7 changes: 5 additions & 2 deletions examples/batcher/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Hono } from "hono";

const app = new Hono<{
export interface Env {
Bindings: {
BATCHER: DurableObjectNamespace;
DB: D1Database;
};
}>();
}

const app = new Hono<Env>();

app.all("/batcher/*", (c) => {
const id = c.env.BATCHER.idFromName("Batcher");
Expand Down
6 changes: 6 additions & 0 deletions examples/batcher/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ bindings = [{ name = "BATCHER", class_name = "Batcher" }]
[[migrations]]
tag = "v1"
new_classes = ["Batcher"]

[[d1_databases]]
binding = "DB"
database_name = "batch-db"
database_id = "ae9d3bb9-d843-4fab-9387-7aed0ad5b92b"
preview_database_id = "DB"
8 changes: 5 additions & 3 deletions packages/hono-do/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ export function generateHonoObject<
cb: (
app: Hono<E, S, BasePath>,
state: DurableObjectState,
vars: HonoObjectVars,
vars: HonoObjectVars & { env: E["Bindings"] },
) => void | Promise<void>,
handlers: HonoObjectHandlers = {},
) {
const _handlers: HonoObjectHandlers = {
...handlers,
};

const honoObject = function (this, state) {
const honoObject = function (this, state, env) {
const app = new Hono<E, S, BasePath>().basePath(basePath);
this.app = app;
this.state = state;
this.vars = {};
this.vars = {
env,
};
state.blockConcurrencyWhile(async () => {
await cb(app, state, this.vars);
});
Expand Down
34 changes: 20 additions & 14 deletions packages/hono-do/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,52 +11,58 @@ interface HonoObjectState<
> {
app: Hono<E, S, BasePath>;
state: DurableObjectState;
vars: HonoObjectVars;
vars: HonoObjectVars & {
env: E["Bindings"];
};
}

export interface HonoObject<
E extends Env = Env,
S extends Schema = Record<string, never>,
BasePath extends string = "/",
> extends HonoObjectState<E, S, BasePath> {
(this: HonoObject<E, S, BasePath>, state: DurableObjectState): void;
alarm: (handler: AlarmHandler) => HonoObject<E, S, BasePath>;
(
this: HonoObject<E, S, BasePath>,
state: DurableObjectState,
env: E["Bindings"],
): void;
alarm: (handler: AlarmHandler<E>) => HonoObject<E, S, BasePath>;
webSocketMessage: (
handler: WebSocketMessageHandler,
handler: WebSocketMessageHandler<E>,
) => HonoObject<E, S, BasePath>;
webSocketClose: (
handler: WebSocketCloseHandler,
handler: WebSocketCloseHandler<E>,
) => HonoObject<E, S, BasePath>;
webSocketError: (
handler: WebSocketErrorHandler,
handler: WebSocketErrorHandler<E>,
) => HonoObject<E, S, BasePath>;
}

export type AlarmHandler = (
export type AlarmHandler<E extends Env = Env> = (
...args: MergeArray<
Parameters<NonNullable<DurableObject["alarm"]>>,
[state: DurableObjectState, vars: HonoObjectVars]
[state: DurableObjectState, vars: HonoObjectVars & { env: E["Bindings"] }]
>
) => ReturnType<NonNullable<DurableObject["alarm"]>>;

export type WebSocketMessageHandler = (
export type WebSocketMessageHandler<E extends Env = Env> = (
...args: MergeArray<
Parameters<NonNullable<DurableObject["webSocketMessage"]>>,
[state: DurableObjectState, vars: HonoObjectVars]
[state: DurableObjectState, vars: HonoObjectVars & { env: E["Bindings"] }]
>
) => ReturnType<NonNullable<DurableObject["webSocketMessage"]>>;

export type WebSocketCloseHandler = (
export type WebSocketCloseHandler<E extends Env = Env> = (
...args: MergeArray<
Parameters<NonNullable<DurableObject["webSocketClose"]>>,
[state: DurableObjectState, vars: HonoObjectVars]
[state: DurableObjectState, vars: HonoObjectVars & { env: E["Bindings"] }]
>
) => ReturnType<NonNullable<DurableObject["webSocketClose"]>>;

export type WebSocketErrorHandler = (
export type WebSocketErrorHandler<E extends Env = Env> = (
...args: MergeArray<
Parameters<NonNullable<DurableObject["webSocketError"]>>,
[state: DurableObjectState, vars: HonoObjectVars]
[state: DurableObjectState, vars: HonoObjectVars & { env: E["Bindings"] }]
>
) => ReturnType<NonNullable<DurableObject["webSocketError"]>>;

Expand Down
3 changes: 2 additions & 1 deletion packages/hono-do/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ describe("generateHonoObject", () => {
Bindings: {
HOGE_DB: D1Database;
};
}>("/", (app) => {
}>("/", (app, _, vars) => {
expectTypeOf(vars.env.HOGE_DB).toEqualTypeOf<D1Database>();
app.get("/hoge", async (c) => {
expectTypeOf(c.var.HOGE_VAR).toEqualTypeOf<string>();
expectTypeOf(c.env.HOGE_DB).toEqualTypeOf<D1Database>();
Expand Down

0 comments on commit cdf0f9e

Please sign in to comment.