GithubHelp home page GithubHelp logo

sor4chi / hono-do Goto Github PK

View Code? Open in Web Editor NEW
77.0 3.0 2.0 324 KB

A wrapper of Cloudflare Workers's Durable Object for Hono.

Home Page: https://www.npmjs.com/package/hono-do

License: MIT License

JavaScript 8.38% TypeScript 91.62%
cloudflare workers hono durable-objects

hono-do's Introduction

Hono for Durable Object

Hono DO is a wrapper of Cloudflare Workers ' Durable Object, designed for Hono.

Important

Cloudflare released RPC feature, which is a better way to communicate between Durable Objects. This library was developed to improve the developer experience for Durable Objects when RPC was not yet available. So, please consider it before using this library.

$ npm install hono-do

Usage

export const Counter = generateHonoObject("/counter", async (app, state) => {
  const { storage } = state;
  let value = (await storage.get<number>("value")) ?? 0;

  app.post("/increment", (c) => {
    storage.put("value", value++);
    return c.text(value.toString());
  });

  app.post("/decrement", (c) => {
    storage.put("value", value--);
    return c.text(value.toString());
  });

  app.get("/", (c) => {
    return c.text(value.toString());
  });
});

You want to find more? Check out the examples!

Support

License

MIT

Contributing

This project is open for contributions. Feel free to open an issue or a pull request! Contributing Guide for more information.

hono-do's People

Contributors

dependabot[bot] avatar github-actions[bot] avatar sor4chi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hono-do's Issues

Question: Is this project still maintained?

Hi @sor4chi! Thanks for creating this package. It is exciting.

I notice that it hasn't been maintained in some time. Are you still planning on keeping it?

I intend to help you maintain it; I guess my question is if you are interested in active work on it or if I should focus on my fork.

Best regard!

Durable Objects syntax idea

Durable Object is a very good representation in that it can store state and mutations as a single object.
However, if we could provide a third party, we would be able to ensure more flexibility and maintainability of notation.

ref: honojs/examples#86

For now, I implemented the simplest method I can think of at the moment to generate a HonoObject in main and a sample of it.

As far as I know, Durable Object works by exporting the class itself, not the class instance.
Therefore, we tried to use the Constructor Function to generate dynamic classes while keeping the Hono interface easy to use.

If you have any ideas for a better interface, we'd love to hear your opinions and suggestions!

WebSocket context

Hono does not have a WebSocket context function like c.ws() by default.
Because websocket implementations vary considerably from runtime to runtime.

Since Hono DO is a library specialized for cloudflare workers, we thought it would be easier to use if we extended context to provide a handler for websocket.

[BUG]: an error occur when Hono Object's basepath is dynamic path

Reproduce

const app = new Hono<{
  Bindings: {
    ROOM: DurableObjectNamespace;
  };
}>();

app.all("/room/:roomId/*", (c) => {
  const roomId = c.req.param("roomId");
  const id = c.env.ROOM.idFromName(roomId);
  const obj = c.env.ROOM.get(id);
  return obj.fetch(c.req.raw);
});

export const Room = generateHonoObject("/room/:roomId", (app) => {
  app.get("/", (c) => c.text(c.req.param("roomId")));
});

Error

Can not add a route since the matcher is already built.

Way to resolve

Currently, Hono is initialized only once outside the constructor of HonoObject.
Initialize Hono class in HonoObject's constructor.

Endpoint Integration Idea

I want to add new syntax for less code.

export const Counter = generateHonoObject("/counter", async (app, state) => {
  const { storage } = state;
  let value = (await storage.get<number>("value")) ?? 0;

  app.post("/increment", (c) => {
    storage.put("value", value++);
    return c.text(value.toString());
  });

  app.post("/decrement", (c) => {
    storage.put("value", value--);
    return c.text(value.toString());
  });

  app.get("/", (c) => {
    return c.text(value.toString());
  });
});

So far the code had to be written like this

app.all("/counter/*", (c) => {
  const id = c.env.COUNTER.idFromName("Counter");
  const obj = c.env.COUNTER.get(id);
  return obj.fetch(c.req.raw);
});

I plan to add a new syntax like

app.do(Counter, "Counter")

app.do() is extended by Hono. The first args is Hono Object, and The second args is the value of idFromName().

Having issues making messages persist

@sor4chi Thank you so much for making hono-do library. It makes it so easy to work with DO and websockets.

I am trying to use it to build a real-time quiz app where I want to use DO and web sockets for real-time results. I am trying to implement persistence in hibernate-chat example. But I am running into issues. Could you please help? I am not sure whether my approach is right or wrong or i am missing something.

import { generateHonoObject } from 'hono-do';
import { defineStorage } from 'hono-do/storage';

function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    const r = (Math.random() * 16) | 0,
      v = c == 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

declare module 'hono-do' {
  interface HonoObjectVars {
    messages: {
      timestamp: string;
      text: string;
    }[];
  }
}

export const Chat = generateHonoObject('/chat', async (app, state, vars) => {
  let { storage } = state;
  const [getValue] = await defineStorage(state.storage, 'value', {});

  // console.log(await state.storage.get('value'), 'aaa');

  vars.messages = [];

  app.get('/messages', async (c) => c.json(await getValue()));

  app.get('/websocket', async (c) => {
    if (c.req.header('Upgrade') === 'websocket') {
      return await handleWebSocketUpgrade();
    }
    return c.text('Not found', 404);
  });

  async function handleWebSocketUpgrade() {
    const [client, server] = Object.values(new WebSocketPair());
    const clientId = uuidv4();
    state.acceptWebSocket(server);
    server.serializeAttachment({ clientId });

    return new Response(null, { status: 101, webSocket: client });
  }
});

Chat.webSocketMessage(async (webSocket, msg, state, vars) => {
  const { clientId: senderClientId } = await webSocket.deserializeAttachment();
  const [getValue, setValue] = await defineStorage(state.storage, 'value', {});
  let oldMessages: any = await getValue();
  console.log('msg', msg, vars, state, webSocket);
  oldMessages.push(msg);
  // await state.storage.put('value', oldMessages);
  setValue(oldMessages);
  state.getWebSockets().forEach((ws) => {
    const { clientId } = ws.deserializeAttachment();
    if (clientId === senderClientId) {
      return;
    }
    try {
      vars.messages.push(JSON.parse(msg.toString()));
      ws.send(msg.toString());
    } catch (error) {
      ws.close();
    }
  });
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.