honojs / honox

HonoX - Hono based meta framework
https://hono.dev
MIT License
1.4k stars 38 forks source link

Considering supporting RPC-mode #24

Closed yusukebe closed 6 months ago

sor4chi commented 7 months ago

Hi, @yusukebe.

In Nuxt.js、

.nuxt
├── app.config.mjs
├── components.d.ts
├── imports.d.ts
├── nuxt.d.ts
├── schema
│  ├── nuxt.schema.d.ts
│  └── nuxt.schema.json
├── tsconfig.json
├── tsconfig.server.json
├── types
│  ├── app.config.d.ts
│  ├── imports.d.ts
│  ├── nitro-config.d.ts
│  ├── nitro-imports.d.ts
│  ├── nitro-nuxt.d.ts
│  ├── nitro-routes.d.ts
│  ├── nitro.d.ts
│  ├── plugins.d.ts
│  ├── schema.d.ts
│  └── vue-shim.d.ts
└── vue-router-stub.d.ts

Generate an aggregated .d.ts file under the .nuxt folder.

This is a group of files that are dynamically generated during watch and build, but you can create a folder like .honox in such a system, hoist the Type of each route in it, and globally declare it as AppType, so that the RPC is split into separate I think it is possible to make the RPC type-safe even for divided routes.

How about this way?

nakasyou commented 7 months ago

honojs/hono#2192 was linked this pr by auto. You should reopen this PR.

nakasyou commented 7 months ago

I think generating type files is good idea, but I have other ideas. In QwikCity, you can use server$. This is realized by changing AST. My ideas is inspired by this.

1. Transform AST using Babel

This idea is using babel.

// app/islands/submit.tsx
import typeof submit from '../routes/submit'
import { rpc } from 'honox/rpc'

export default function () {
  const client = rpc<typeof submit>()
  ...
}

to

import { rpc } from 'honox/rpc'

export default function () {
  const client = rpc('/submit')
  ...
}

Babel is included in HonoX's dependencies. This idea isn't impossible.

2. Replace import contents using load(Vite plugin API)

It idea is converting the import from app/islands to app/routes in Vite.

For example:

// app/islands/submit.tsx
/**
 * Through Vite, convert to `export default <fetch script>`
 */
import submit from '../routes/submit'

export default function () {
  submit().then(res => ...)
  ...
}

3. Replace import using Babel

This idea is similar of Replace import contents using `load`(Vite plugin API). Replacing import content when only import sequence is matched.

For example, transform

// app/islands/submit.tsx
/**
 * Through Vite, convert to `export default <fetch script>`
 */
import $submit from '../routes/submit'
/**
 * This import content is raw, not replaced.
 */
import submit from '../routes/submit'

export default function () {
  $submit().then(res => ...)
}

to

import $submit from './node_modules/.honox/tmp/rpc/routes/submit'
import submit from '../routes/submit'

export default function () {
  $submit().then(res => ...)
}

How about this idea?

yusukebe commented 7 months ago

Hi @nakasyou

Thanks for the proposal! But I think there is nothing to do to support RPC-mode because we can use hc as the same as normal Hono app:

https://github.com/yusukebe/honox-playground/tree/main/projects/rpc/app

Screenshot 2024-02-14 at 13 51 25
nakasyou commented 7 months ago

Hi @yusukebe, thank you for your comment!

Thanks for the proposal! But I think there is nothing to do to support RPC-mode because we can use hc as the same as normal Hono app:

I see. But I have a con.

I think hc<AppType>('/api') is long code. When you import AppType, the path /api is decided. So if we can write code without writing '/api', it is more smart.

Do you have more idea or opinion?

yusukebe commented 7 months ago

@nakasyou

Hmmm. I understand what you are saying, but I can't think of a smart way to do it right now. I don't want to add anything if it will complicate the code to solve it.

Since the philosophy of HonoX is to utilize Hono's own assets as much as possible, it makes sense to use hc.

yusukebe commented 7 months ago

Or, just an idea, maybe we can improve hc. A way to avoid giving the base path /api for example.

nakasyou commented 7 months ago

@yusukebe

I don't want to add anything if it will complicate the code to solve it. Since the philosophy of HonoX is to utilize Hono's own assets as much as possible, it makes sense to use hc.

I understood. And I think so.

maybe we can improve hc. A way to avoid giving the base path /api for example.

If we able it, it is very cool. I hope realize it.

Or, like @sor4chi's https://github.com/honojs/honox/issues/24#issuecomment-1935673899, generating type safe path is smart.

For example, generate file like this:

interface Hc {
  hc<T extends Api1AppType>(base: '/api1'): ...
  hc<T extends Api2AppType>(base: '/api2'): ...
}
declare module 'hono/client' {
  export const hc: Hc['hc']
}

If we can implement it, we can probably write type safe path.

sor4chi commented 6 months ago

Is there any way to dynamically infer the type of a default-exported object from a filepath?

yusukebe commented 6 months ago

@sor4chi

That matter is related to #53

sor4chi commented 6 months ago

@yusukebe Thank you! I'm personally trying out the dynamic type generation and declare I suggested above and was wondering how to infer the type from a file in the node.js environment that is the runtime of the vite-plugin.

yusukebe commented 6 months ago

This Issue using the term RPC is closed because it can be misleading.

If you want to use RPC-mode, please use this method.

https://github.com/honojs/honox/issues/24#issuecomment-1943077708