honox 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -24
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +3 -1
- package/dist/server/components/has-islands.d.ts +5 -0
- package/dist/server/components/has-islands.js +10 -0
- package/dist/server/components/index.d.ts +4 -0
- package/dist/server/components/index.js +6 -0
- package/dist/server/components/script.d.ts +11 -0
- package/dist/server/components/script.js +31 -0
- package/dist/server/factory/factory.d.ts +19 -0
- package/dist/server/factory/factory.js +11 -0
- package/dist/server/factory/index.d.ts +3 -0
- package/dist/server/factory/index.js +5 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +1 -0
- package/dist/server/server.d.ts +5 -1
- package/dist/server/server.js +30 -23
- package/dist/vite/client.d.ts +10 -0
- package/dist/vite/client.js +28 -0
- package/dist/vite/index.d.ts +3 -3
- package/dist/vite/index.js +10 -1
- package/dist/vite/inject-importing-islands.d.ts +5 -0
- package/dist/vite/inject-importing-islands.js +52 -0
- package/dist/vite/island-components.js +2 -1
- package/package.json +22 -10
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# HonoX
|
|
2
2
|
|
|
3
|
-
**HonoX** is a simple and fast meta framework for creating websites
|
|
3
|
+
**HonoX** is a simple and fast - _supersonic_ - meta framework for creating full-stack websites or Web APIs - (formerly _[Sonik](https://github.com/sonikjs/sonik)_). It stands on the shoulders of giants; built on [Hono](https://hono.dev/), [Vite](https://hono.dev/), and UI libraries.
|
|
4
4
|
|
|
5
|
-
**Note**: _HonoX is currently in a "beta stage".
|
|
5
|
+
**Note**: _HonoX is currently in a "beta stage". Breaking changes are introduced without following semantic versioning._
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **File-based routing** - You can create a large
|
|
9
|
+
- **File-based routing** - You can create a large application like Next.js.
|
|
10
10
|
- **Fast SSR** - Rendering is ultra-fast thanks to Hono.
|
|
11
11
|
- **BYOR** - You can bring your own renderer, not only one using hono/jsx.
|
|
12
|
-
- **
|
|
12
|
+
- **Islands hydration** - If you want interactions, create an island. JavaScript is hydrated only for it.
|
|
13
13
|
- **Middleware** - It works as Hono, so you can use a lot of Hono's middleware.
|
|
14
14
|
|
|
15
15
|
## Get Started - Basic
|
|
@@ -154,7 +154,7 @@ Before writing `_renderer.tsx`, write the Renderer type definition in `global.d.
|
|
|
154
154
|
|
|
155
155
|
```ts
|
|
156
156
|
// app/global.d.ts
|
|
157
|
-
import 'hono'
|
|
157
|
+
import type {} from 'hono'
|
|
158
158
|
|
|
159
159
|
type Head = {
|
|
160
160
|
title?: string
|
|
@@ -179,7 +179,7 @@ export default jsxRenderer(({ children, title }) => {
|
|
|
179
179
|
<head>
|
|
180
180
|
<meta charset='UTF-8' />
|
|
181
181
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
|
182
|
-
{title ? <title>{title}</title> :
|
|
182
|
+
{title ? <title>{title}</title> : <></>}
|
|
183
183
|
</head>
|
|
184
184
|
<body>{children}</body>
|
|
185
185
|
</html>
|
|
@@ -245,7 +245,7 @@ The below is the project structure of a minimal application including a client s
|
|
|
245
245
|
|
|
246
246
|
### Renderer
|
|
247
247
|
|
|
248
|
-
This is a `_renderer.tsx
|
|
248
|
+
This is a `_renderer.tsx`, which will load the `/app/client.ts` entry file for the client. It will load the JavaScript file for the production according to the variable `import.meta.env.PROD`. And renders the inside of `HasIslands` if there are islands on that page.
|
|
249
249
|
|
|
250
250
|
```tsx
|
|
251
251
|
// app/routes/_renderer.tsx
|
|
@@ -258,7 +258,9 @@ export default jsxRenderer(({ children }) => {
|
|
|
258
258
|
<meta charset='UTF-8' />
|
|
259
259
|
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
|
260
260
|
{import.meta.env.PROD ? (
|
|
261
|
-
<
|
|
261
|
+
<HasIslands>
|
|
262
|
+
<script type='module' src='/static/client.js'></script>
|
|
263
|
+
</HasIslands>
|
|
262
264
|
) : (
|
|
263
265
|
<script type='module' src='/app/client.ts'></script>
|
|
264
266
|
)}
|
|
@@ -269,6 +271,27 @@ export default jsxRenderer(({ children }) => {
|
|
|
269
271
|
})
|
|
270
272
|
```
|
|
271
273
|
|
|
274
|
+
If you have a manifest file in `dist/.vite/manifest.json`, you can easily write it using `<Script />`.
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
// app/routes/_renderer.tsx
|
|
278
|
+
import { jsxRenderer } from 'hono/jsx-renderer'
|
|
279
|
+
import { Script } from 'honox/server'
|
|
280
|
+
|
|
281
|
+
export default jsxRenderer(({ children }) => {
|
|
282
|
+
return (
|
|
283
|
+
<html lang='en'>
|
|
284
|
+
<head>
|
|
285
|
+
<meta charset='UTF-8' />
|
|
286
|
+
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
|
287
|
+
<Script src='/app/client.ts' />
|
|
288
|
+
</head>
|
|
289
|
+
<body>{children}</body>
|
|
290
|
+
</html>
|
|
291
|
+
)
|
|
292
|
+
})
|
|
293
|
+
```
|
|
294
|
+
|
|
272
295
|
### Client Entry File
|
|
273
296
|
|
|
274
297
|
A client side entry file should be in `app/client.ts`. Simply, write `createClient()`.
|
|
@@ -320,7 +343,7 @@ export default createRoute((c) => {
|
|
|
320
343
|
|
|
321
344
|
You can bring your own renderer using a UI library like React, Preact, Solid, or others.
|
|
322
345
|
|
|
323
|
-
**Note**: We
|
|
346
|
+
**Note**: We may not provide supports for the renderer you bring.
|
|
324
347
|
|
|
325
348
|
### React case
|
|
326
349
|
|
|
@@ -389,6 +412,25 @@ createClient({
|
|
|
389
412
|
|
|
390
413
|
## Guides
|
|
391
414
|
|
|
415
|
+
### Nested Layouts
|
|
416
|
+
|
|
417
|
+
If you are using the JSX Renderer middleware, you can nest layouts using ` <Layout />`.
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
// app/routes/posts/_renderer.tsx
|
|
421
|
+
|
|
422
|
+
import { jsxRenderer } from 'hono/jsx-renderer'
|
|
423
|
+
|
|
424
|
+
export default jsxRenderer(({ children, Layout }) => {
|
|
425
|
+
return (
|
|
426
|
+
<Layout>
|
|
427
|
+
<nav>Posts Menu</nav>
|
|
428
|
+
<div>{children}</div>
|
|
429
|
+
</Layout>
|
|
430
|
+
)
|
|
431
|
+
})
|
|
432
|
+
```
|
|
433
|
+
|
|
392
434
|
### Using Middleware
|
|
393
435
|
|
|
394
436
|
You can use Hono's Middleware in each root file with the same syntax as Hono. For example, to validate a value with the [Zod Validator](https://github.com/honojs/middleware/tree/main/packages/zod-validator), do the following:
|
|
@@ -533,6 +575,7 @@ Since a HonoX instance is essentially a Hono instance, it can be deployed on any
|
|
|
533
575
|
Setup the `vite.config.ts`:
|
|
534
576
|
|
|
535
577
|
```ts
|
|
578
|
+
// vite.config.ts
|
|
536
579
|
import { defineConfig } from 'vite'
|
|
537
580
|
import honox from 'honox/vite'
|
|
538
581
|
import pages from '@hono/vite-cloudflare-pages'
|
|
@@ -546,25 +589,15 @@ If you want to include client side scripts and assets:
|
|
|
546
589
|
|
|
547
590
|
```ts
|
|
548
591
|
// vite.config.ts
|
|
549
|
-
import { defineConfig } from 'vite'
|
|
550
|
-
import honox from 'honox/vite'
|
|
551
592
|
import pages from '@hono/vite-cloudflare-pages'
|
|
593
|
+
import honox from 'honox/vite'
|
|
594
|
+
import client from 'honox/vite/client'
|
|
595
|
+
import { defineConfig } from 'vite'
|
|
552
596
|
|
|
553
597
|
export default defineConfig(({ mode }) => {
|
|
554
598
|
if (mode === 'client') {
|
|
555
599
|
return {
|
|
556
|
-
|
|
557
|
-
rollupOptions: {
|
|
558
|
-
input: ['./app/client.ts'],
|
|
559
|
-
output: {
|
|
560
|
-
entryFileNames: 'static/client.js',
|
|
561
|
-
chunkFileNames: 'static/assets/[name]-[hash].js',
|
|
562
|
-
assetFileNames: 'static/assets/[name].[ext]',
|
|
563
|
-
},
|
|
564
|
-
},
|
|
565
|
-
emptyOutDir: false,
|
|
566
|
-
copyPublicDir: false,
|
|
567
|
-
},
|
|
600
|
+
plugins: [client()],
|
|
568
601
|
}
|
|
569
602
|
} else {
|
|
570
603
|
return {
|
|
@@ -577,7 +610,7 @@ export default defineConfig(({ mode }) => {
|
|
|
577
610
|
Build command (including a client):
|
|
578
611
|
|
|
579
612
|
```txt
|
|
580
|
-
vite build && vite build
|
|
613
|
+
vite build --mode client && vite build
|
|
581
614
|
```
|
|
582
615
|
|
|
583
616
|
Deploy with the following commands after build. Ensure you have [Wrangler](https://developers.cloudflare.com/workers/wrangler/) installed:
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
declare const COMPONENT_NAME = "component-name";
|
|
2
2
|
declare const DATA_SERIALIZED_PROPS = "data-serialized-props";
|
|
3
|
+
declare const IMPORTING_ISLANDS_ID: "__importing_islands";
|
|
3
4
|
|
|
4
|
-
export { COMPONENT_NAME, DATA_SERIALIZED_PROPS };
|
|
5
|
+
export { COMPONENT_NAME, DATA_SERIALIZED_PROPS, IMPORTING_ISLANDS_ID };
|
package/dist/constants.js
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Fragment, jsx } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { useRequestContext } from "hono/jsx-renderer";
|
|
3
|
+
import { IMPORTING_ISLANDS_ID } from "../../constants.js";
|
|
4
|
+
const HasIslands = ({ children }) => {
|
|
5
|
+
const c = useRequestContext();
|
|
6
|
+
return /* @__PURE__ */ jsx(Fragment, { children: c.get(IMPORTING_ISLANDS_ID) ? children : /* @__PURE__ */ jsx(Fragment, {}) });
|
|
7
|
+
};
|
|
8
|
+
export {
|
|
9
|
+
HasIslands
|
|
10
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Fragment, jsx } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { HasIslands } from "./has-islands.js";
|
|
3
|
+
const Script = async (options) => {
|
|
4
|
+
const src = options.src;
|
|
5
|
+
if (options.prod ?? import.meta.env.PROD) {
|
|
6
|
+
let manifest = options.manifest;
|
|
7
|
+
if (!manifest) {
|
|
8
|
+
const MANIFEST = import.meta.glob("/dist/.vite/manifest.json", {
|
|
9
|
+
eager: true
|
|
10
|
+
});
|
|
11
|
+
for (const [, manifestFile] of Object.entries(MANIFEST)) {
|
|
12
|
+
if (manifestFile["default"]) {
|
|
13
|
+
manifest = manifestFile["default"];
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (manifest) {
|
|
19
|
+
const scriptInManifest = manifest[src.replace(/^\//, "")];
|
|
20
|
+
if (scriptInManifest) {
|
|
21
|
+
return /* @__PURE__ */ jsx(HasIslands, { children: /* @__PURE__ */ jsx("script", { type: "module", src: `/${scriptInManifest.file}` }) });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
25
|
+
} else {
|
|
26
|
+
return /* @__PURE__ */ jsx("script", { type: "module", src });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
Script
|
|
31
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as hono_types from 'hono/types';
|
|
2
|
+
import * as hono from 'hono';
|
|
3
|
+
import { Env, Hono } from 'hono';
|
|
4
|
+
|
|
5
|
+
declare const createRoute: {
|
|
6
|
+
<I extends hono.Input = {}>(handler1: hono_types.H<Env, any, I>): [hono_types.H<Env, any, I>];
|
|
7
|
+
<I_1 extends hono.Input = {}, I2 extends hono.Input = I_1, R extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_1, R>, handler2: hono_types.H<Env, any, I2, R>): [hono_types.H<Env, any, I_1, R>, hono_types.H<Env, any, I2, R>];
|
|
8
|
+
<I_2 extends hono.Input = {}, I2_1 extends hono.Input = I_2, I3 extends hono.Input = I_2 & I2_1, R_1 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_2, R_1>, handler2: hono_types.H<Env, any, I2_1, R_1>, handler3: hono_types.H<Env, any, I3, R_1>): [hono_types.H<Env, any, I_2, R_1>, hono_types.H<Env, any, I2_1, R_1>, hono_types.H<Env, any, I3, R_1>];
|
|
9
|
+
<I_3 extends hono.Input = {}, I2_2 extends hono.Input = I_3, I3_1 extends hono.Input = I_3 & I2_2, I4 extends hono.Input = I_3 & I2_2 & I3_1, R_2 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_3, R_2>, handler2: hono_types.H<Env, any, I2_2, R_2>, handler3: hono_types.H<Env, any, I3_1, R_2>, handler4: hono_types.H<Env, any, I4, R_2>): [hono_types.H<Env, any, I_3, R_2>, hono_types.H<Env, any, I2_2, R_2>, hono_types.H<Env, any, I3_1, R_2>, hono_types.H<Env, any, I4, R_2>];
|
|
10
|
+
<I_4 extends hono.Input = {}, I2_3 extends hono.Input = I_4, I3_2 extends hono.Input = I_4 & I2_3, I4_1 extends hono.Input = I_4 & I2_3 & I3_2, I5 extends hono.Input = I_4 & I2_3 & I3_2 & I4_1, R_3 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_4, R_3>, handler2: hono_types.H<Env, any, I2_3, R_3>, handler3: hono_types.H<Env, any, I3_2, R_3>, handler4: hono_types.H<Env, any, I4_1, R_3>, handler5: hono_types.H<Env, any, I5, R_3>): [hono_types.H<Env, any, I_4, R_3>, hono_types.H<Env, any, I2_3, R_3>, hono_types.H<Env, any, I3_2, R_3>, hono_types.H<Env, any, I4_1, R_3>, hono_types.H<Env, any, I5, R_3>];
|
|
11
|
+
<I_5 extends hono.Input = {}, I2_4 extends hono.Input = I_5, I3_3 extends hono.Input = I_5 & I2_4, I4_2 extends hono.Input = I_5 & I2_4 & I3_3, I5_1 extends hono.Input = I_5 & I2_4 & I3_3 & I4_2, I6 extends hono.Input = I_5 & I2_4 & I3_3 & I4_2 & I5_1, R_4 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_5, R_4>, handler2: hono_types.H<Env, any, I2_4, R_4>, handler3: hono_types.H<Env, any, I3_3, R_4>, handler4: hono_types.H<Env, any, I4_2, R_4>, handler5: hono_types.H<Env, any, I5_1, R_4>, handler6: hono_types.H<Env, any, I6, R_4>): [hono_types.H<Env, any, I_5, R_4>, hono_types.H<Env, any, I2_4, R_4>, hono_types.H<Env, any, I3_3, R_4>, hono_types.H<Env, any, I4_2, R_4>, hono_types.H<Env, any, I5_1, R_4>, hono_types.H<Env, any, I6, R_4>];
|
|
12
|
+
<I_6 extends hono.Input = {}, I2_5 extends hono.Input = I_6, I3_4 extends hono.Input = I_6 & I2_5, I4_3 extends hono.Input = I_6 & I2_5 & I3_4, I5_2 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3, I6_1 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3 & I5_2, I7 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3 & I5_2 & I6_1, R_5 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_6, R_5>, handler2: hono_types.H<Env, any, I2_5, R_5>, handler3: hono_types.H<Env, any, I3_4, R_5>, handler4: hono_types.H<Env, any, I4_3, R_5>, handler5: hono_types.H<Env, any, I5_2, R_5>, handler6: hono_types.H<Env, any, I6_1, R_5>, handler7: hono_types.H<Env, any, I7, R_5>): [hono_types.H<Env, any, I_6, R_5>, hono_types.H<Env, any, I2_5, R_5>, hono_types.H<Env, any, I3_4, R_5>, hono_types.H<Env, any, I4_3, R_5>, hono_types.H<Env, any, I5_2, R_5>, hono_types.H<Env, any, I6_1, R_5>, hono_types.H<Env, any, I7, R_5>];
|
|
13
|
+
<I_7 extends hono.Input = {}, I2_6 extends hono.Input = I_7, I3_5 extends hono.Input = I_7 & I2_6, I4_4 extends hono.Input = I_7 & I2_6 & I3_5, I5_3 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4, I6_2 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3, I7_1 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3 & I6_2, I8 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3 & I6_2 & I7_1, R_6 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_7, R_6>, handler2: hono_types.H<Env, any, I2_6, R_6>, handler3: hono_types.H<Env, any, I3_5, R_6>, handler4: hono_types.H<Env, any, I4_4, R_6>, handler5: hono_types.H<Env, any, I5_3, R_6>, handler6: hono_types.H<Env, any, I6_2, R_6>, handler7: hono_types.H<Env, any, I7_1, R_6>, handler8: hono_types.H<Env, any, I8, R_6>): [hono_types.H<Env, any, I_7, R_6>, hono_types.H<Env, any, I2_6, R_6>, hono_types.H<Env, any, I3_5, R_6>, hono_types.H<Env, any, I4_4, R_6>, hono_types.H<Env, any, I5_3, R_6>, hono_types.H<Env, any, I6_2, R_6>, hono_types.H<Env, any, I7_1, R_6>, hono_types.H<Env, any, I8, R_6>];
|
|
14
|
+
<I_8 extends hono.Input = {}, I2_7 extends hono.Input = I_8, I3_6 extends hono.Input = I_8 & I2_7, I4_5 extends hono.Input = I_8 & I2_7 & I3_6, I5_4 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5, I6_3 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4, I7_2 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3, I8_1 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3 & I7_2, I9 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3 & I7_2 & I8_1, R_7 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_8, R_7>, handler2: hono_types.H<Env, any, I2_7, R_7>, handler3: hono_types.H<Env, any, I3_6, R_7>, handler4: hono_types.H<Env, any, I4_5, R_7>, handler5: hono_types.H<Env, any, I5_4, R_7>, handler6: hono_types.H<Env, any, I6_3, R_7>, handler7: hono_types.H<Env, any, I7_2, R_7>, handler8: hono_types.H<Env, any, I8_1, R_7>, handler9: hono_types.H<Env, any, I9, R_7>): [hono_types.H<Env, any, I_8, R_7>, hono_types.H<Env, any, I2_7, R_7>, hono_types.H<Env, any, I3_6, R_7>, hono_types.H<Env, any, I4_5, R_7>, hono_types.H<Env, any, I5_4, R_7>, hono_types.H<Env, any, I6_3, R_7>, hono_types.H<Env, any, I7_2, R_7>, hono_types.H<Env, any, I8_1, R_7>, hono_types.H<Env, any, I9, R_7>];
|
|
15
|
+
<I_9 extends hono.Input = {}, I2_8 extends hono.Input = I_9, I3_7 extends hono.Input = I_9 & I2_8, I4_6 extends hono.Input = I_9 & I2_8 & I3_7, I5_5 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6, I6_4 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5, I7_3 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4, I8_2 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3, I9_1 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3 & I8_2, I10 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3 & I8_2 & I9_1, R_8 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_9, R_8>, handler2: hono_types.H<Env, any, I2_8, R_8>, handler3: hono_types.H<Env, any, I3_7, R_8>, handler4: hono_types.H<Env, any, I4_6, R_8>, handler5: hono_types.H<Env, any, I5_5, R_8>, handler6: hono_types.H<Env, any, I6_4, R_8>, handler7: hono_types.H<Env, any, I7_3, R_8>, handler8: hono_types.H<Env, any, I8_2, R_8>, handler9: hono_types.H<Env, any, I9_1, R_8>, handler10: hono_types.H<Env, any, I10, R_8>): [hono_types.H<Env, any, I_9, R_8>, hono_types.H<Env, any, I2_8, R_8>, hono_types.H<Env, any, I3_7, R_8>, hono_types.H<Env, any, I4_6, R_8>, hono_types.H<Env, any, I5_5, R_8>, hono_types.H<Env, any, I6_4, R_8>, hono_types.H<Env, any, I7_3, R_8>, hono_types.H<Env, any, I8_2, R_8>, hono_types.H<Env, any, I9_1, R_8>, hono_types.H<Env, any, I10, R_8>];
|
|
16
|
+
};
|
|
17
|
+
declare const createHono: () => Hono<Env, hono_types.BlankSchema, "/">;
|
|
18
|
+
|
|
19
|
+
export { createHono, createRoute };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export { ServerOptions, createApp } from './server.js';
|
|
2
|
+
export { HasIslands } from './components/has-islands.js';
|
|
3
|
+
export { Script } from './components/script.js';
|
|
2
4
|
import 'hono/types';
|
|
3
5
|
import 'hono';
|
|
6
|
+
import '../constants.js';
|
|
7
|
+
import 'hono/jsx';
|
|
8
|
+
import 'vite';
|
package/dist/server/index.js
CHANGED
package/dist/server/server.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import { H } from 'hono/types';
|
|
3
3
|
import { Env, Hono, MiddlewareHandler, NotFoundHandler, ErrorHandler } from 'hono';
|
|
4
|
+
import { IMPORTING_ISLANDS_ID } from '../constants.js';
|
|
4
5
|
|
|
5
6
|
declare const METHODS: readonly ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"];
|
|
7
|
+
type InnerMeta = {
|
|
8
|
+
[key in typeof IMPORTING_ISLANDS_ID]?: boolean;
|
|
9
|
+
};
|
|
6
10
|
type RouteFile = {
|
|
7
11
|
default?: Function;
|
|
8
12
|
} & {
|
|
9
13
|
[M in (typeof METHODS)[number]]?: H[];
|
|
10
|
-
};
|
|
14
|
+
} & InnerMeta;
|
|
11
15
|
type RendererFile = {
|
|
12
16
|
default: MiddlewareHandler;
|
|
13
17
|
};
|
package/dist/server/server.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
+
import { createMiddleware } from "hono/factory";
|
|
3
|
+
import { IMPORTING_ISLANDS_ID } from "../constants.js";
|
|
2
4
|
import {
|
|
3
5
|
filePathToPath,
|
|
4
6
|
groupByDirectory,
|
|
5
7
|
listByDirectory,
|
|
6
|
-
pathToDirectoryPath,
|
|
7
8
|
sortDirectoriesByDepth
|
|
8
9
|
} from "../utils/file.js";
|
|
9
10
|
const NOTFOUND_FILENAME = "_404.tsx";
|
|
@@ -28,10 +29,12 @@ const createApp = (options) => {
|
|
|
28
29
|
eager: true
|
|
29
30
|
});
|
|
30
31
|
const rendererList = listByDirectory(RENDERER_FILE);
|
|
31
|
-
const applyRenderer = (rendererFile) => {
|
|
32
|
+
const applyRenderer = (app2, rendererFile) => {
|
|
32
33
|
const renderer = RENDERER_FILE[rendererFile];
|
|
33
|
-
const
|
|
34
|
-
|
|
34
|
+
const rendererDefault = renderer["default"];
|
|
35
|
+
if (rendererDefault) {
|
|
36
|
+
app2.all("*", rendererDefault);
|
|
37
|
+
}
|
|
35
38
|
};
|
|
36
39
|
const ROUTES_FILE = options?.ROUTES ?? import.meta.glob("/app/routes/**/[!_]*.(ts|tsx|mdx)", {
|
|
37
40
|
eager: true
|
|
@@ -40,30 +43,31 @@ const createApp = (options) => {
|
|
|
40
43
|
for (const map of routesMap) {
|
|
41
44
|
for (const [dir, content] of Object.entries(map)) {
|
|
42
45
|
const subApp = new Hono();
|
|
43
|
-
let
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
rendererFiles = rendererList[paths.join("/")];
|
|
51
|
-
if (!rendererFiles) {
|
|
52
|
-
paths.pop();
|
|
53
|
-
if (paths.length) {
|
|
54
|
-
getRendererPaths(paths);
|
|
55
|
-
}
|
|
46
|
+
let rendererPaths = rendererList[dir] ?? [];
|
|
47
|
+
const getRendererPaths = (paths) => {
|
|
48
|
+
rendererPaths = rendererList[paths.join("/")];
|
|
49
|
+
if (!rendererPaths) {
|
|
50
|
+
paths.pop();
|
|
51
|
+
if (paths.length) {
|
|
52
|
+
getRendererPaths(paths);
|
|
56
53
|
}
|
|
57
|
-
return rendererFiles;
|
|
58
|
-
};
|
|
59
|
-
rendererFiles = getRendererPaths(dirPaths);
|
|
60
|
-
if (rendererFiles) {
|
|
61
|
-
applyRenderer(rendererFiles[0]);
|
|
62
54
|
}
|
|
63
|
-
|
|
55
|
+
return rendererPaths ?? [];
|
|
56
|
+
};
|
|
57
|
+
const dirPaths = dir.split("/");
|
|
58
|
+
rendererPaths = getRendererPaths(dirPaths);
|
|
59
|
+
rendererPaths.sort((a, b) => a.split("/").length - b.split("/").length);
|
|
60
|
+
rendererPaths.map((path) => {
|
|
61
|
+
applyRenderer(subApp, path);
|
|
62
|
+
});
|
|
64
63
|
let rootPath = dir.replace(rootRegExp, "");
|
|
65
64
|
rootPath = filePathToPath(rootPath);
|
|
66
65
|
for (const [filename, route] of Object.entries(content)) {
|
|
66
|
+
const importingIslands = route[IMPORTING_ISLANDS_ID];
|
|
67
|
+
const setInnerMeta = createMiddleware(async function innerMeta(c, next) {
|
|
68
|
+
c.set(IMPORTING_ISLANDS_ID, importingIslands);
|
|
69
|
+
await next();
|
|
70
|
+
});
|
|
67
71
|
const routeDefault = route.default;
|
|
68
72
|
const path = filePathToPath(filename);
|
|
69
73
|
if (routeDefault && "fetch" in routeDefault) {
|
|
@@ -72,13 +76,16 @@ const createApp = (options) => {
|
|
|
72
76
|
for (const m of METHODS) {
|
|
73
77
|
const handlers = route[m];
|
|
74
78
|
if (handlers) {
|
|
79
|
+
subApp.on(m, path, setInnerMeta);
|
|
75
80
|
subApp.on(m, path, ...handlers);
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
if (routeDefault && Array.isArray(routeDefault)) {
|
|
84
|
+
subApp.get(path, setInnerMeta);
|
|
79
85
|
subApp.get(path, ...routeDefault);
|
|
80
86
|
}
|
|
81
87
|
if (typeof routeDefault === "function") {
|
|
88
|
+
subApp.get(path, setInnerMeta);
|
|
82
89
|
subApp.get(path, (c) => {
|
|
83
90
|
return c.render(routeDefault(), route);
|
|
84
91
|
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const defaultOptions = {
|
|
2
|
+
jsxImportSource: "hono/jsx/dom",
|
|
3
|
+
assetsDir: "static"
|
|
4
|
+
};
|
|
5
|
+
function client(options) {
|
|
6
|
+
return {
|
|
7
|
+
name: "honox-vite-client",
|
|
8
|
+
config: () => {
|
|
9
|
+
return {
|
|
10
|
+
build: {
|
|
11
|
+
rollupOptions: {
|
|
12
|
+
input: ["/app/client.ts"]
|
|
13
|
+
},
|
|
14
|
+
assetsDir: options?.assetsDir ?? defaultOptions.assetsDir,
|
|
15
|
+
manifest: true
|
|
16
|
+
},
|
|
17
|
+
esbuild: {
|
|
18
|
+
jsxImportSource: options?.jsxImportSource ?? defaultOptions.jsxImportSource
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
var client_default = client;
|
|
25
|
+
export {
|
|
26
|
+
client_default as default,
|
|
27
|
+
defaultOptions
|
|
28
|
+
};
|
package/dist/vite/index.d.ts
CHANGED
|
@@ -3,13 +3,13 @@ export { defaultOptions as devServerDefaultOptions } from '@hono/vite-dev-server
|
|
|
3
3
|
import { PluginOption } from 'vite';
|
|
4
4
|
export { islandComponents } from './island-components.js';
|
|
5
5
|
|
|
6
|
-
type
|
|
6
|
+
type Options = {
|
|
7
7
|
islands?: boolean;
|
|
8
8
|
entry?: string;
|
|
9
9
|
devServer?: DevServerOptions;
|
|
10
10
|
external?: string[];
|
|
11
11
|
};
|
|
12
|
-
declare const defaultOptions:
|
|
13
|
-
declare function honox(options?:
|
|
12
|
+
declare const defaultOptions: Options;
|
|
13
|
+
declare function honox(options?: Options): PluginOption[];
|
|
14
14
|
|
|
15
15
|
export { honox as default, defaultOptions };
|
package/dist/vite/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import devServer, { defaultOptions as devServerDefaultOptions } from "@hono/vite-dev-server";
|
|
3
|
+
import { injectImportingIslands } from "./inject-importing-islands.js";
|
|
3
4
|
import { islandComponents } from "./island-components.js";
|
|
4
5
|
const defaultOptions = {
|
|
5
6
|
islands: true,
|
|
@@ -23,9 +24,17 @@ function honox(options) {
|
|
|
23
24
|
if (options?.islands !== false) {
|
|
24
25
|
plugins.push(islandComponents());
|
|
25
26
|
}
|
|
27
|
+
plugins.push(injectImportingIslands());
|
|
26
28
|
return [
|
|
27
29
|
{
|
|
28
|
-
name: "honox-vite-config"
|
|
30
|
+
name: "honox-vite-config",
|
|
31
|
+
config: () => {
|
|
32
|
+
return {
|
|
33
|
+
ssr: {
|
|
34
|
+
noExternal: true
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
29
38
|
},
|
|
30
39
|
...plugins
|
|
31
40
|
];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import _generate from "@babel/generator";
|
|
2
|
+
import { parse } from "@babel/parser";
|
|
3
|
+
import _traverse from "@babel/traverse";
|
|
4
|
+
import { IMPORTING_ISLANDS_ID } from "../constants.js";
|
|
5
|
+
const traverse = _traverse.default ?? _traverse;
|
|
6
|
+
const generate = _generate.default ?? _generate;
|
|
7
|
+
function injectImportingIslands() {
|
|
8
|
+
return {
|
|
9
|
+
name: "inject-importing-islands",
|
|
10
|
+
transform(code, id) {
|
|
11
|
+
if (id.endsWith(".tsx") || id.endsWith(".jsx")) {
|
|
12
|
+
let hasIslandsImport = false;
|
|
13
|
+
const ast = parse(code, {
|
|
14
|
+
sourceType: "module",
|
|
15
|
+
plugins: ["jsx"]
|
|
16
|
+
});
|
|
17
|
+
traverse(ast, {
|
|
18
|
+
ImportDeclaration(path) {
|
|
19
|
+
if (path.node.source.value.includes("islands/")) {
|
|
20
|
+
hasIslandsImport = true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
if (hasIslandsImport) {
|
|
25
|
+
const hasIslandsNode = {
|
|
26
|
+
type: "ExportNamedDeclaration",
|
|
27
|
+
declaration: {
|
|
28
|
+
type: "VariableDeclaration",
|
|
29
|
+
declarations: [
|
|
30
|
+
{
|
|
31
|
+
type: "VariableDeclarator",
|
|
32
|
+
id: { type: "Identifier", name: IMPORTING_ISLANDS_ID },
|
|
33
|
+
init: { type: "BooleanLiteral", value: true }
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
kind: "const"
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
ast.program.body.push(hasIslandsNode);
|
|
40
|
+
}
|
|
41
|
+
const output = generate(ast, {}, code);
|
|
42
|
+
return {
|
|
43
|
+
code: output.code,
|
|
44
|
+
map: output.map
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
injectImportingIslands
|
|
52
|
+
};
|
|
@@ -75,8 +75,9 @@ const transformJsxTags = (contents, componentName) => {
|
|
|
75
75
|
ExportDefaultDeclaration(path) {
|
|
76
76
|
if (path.node.declaration.type === "FunctionDeclaration") {
|
|
77
77
|
const functionId = path.node.declaration.id;
|
|
78
|
-
if (!functionId)
|
|
78
|
+
if (!functionId) {
|
|
79
79
|
return;
|
|
80
|
+
}
|
|
80
81
|
const isAsync = path.node.declaration.async;
|
|
81
82
|
const originalFunctionId = identifier(functionId.name + "Original");
|
|
82
83
|
const originalFunction = functionExpression(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honox",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -8,15 +8,18 @@
|
|
|
8
8
|
"test:unit": "vitest --run test/unit",
|
|
9
9
|
"test:integration": "bun test:integration:api && bun test:integration:hono-jsx",
|
|
10
10
|
"test:integration:hono-jsx": "vitest run -c ./test/hono-jsx/vitest.config.ts ./test/hono-jsx/integration.test.ts",
|
|
11
|
+
"test:integration:hono-jsx:watch": "vitest -c ./test/hono-jsx/vitest.config.ts ./test/hono-jsx/integration.test.ts",
|
|
11
12
|
"test:integration:api": "vitest run -c ./test/api/vitest.config.ts ./test/api/integration.test.ts",
|
|
12
13
|
"test:e2e": "playwright test -c ./test/hono-jsx/playwright.config.ts ./test/hono-jsx/e2e.test.ts",
|
|
13
14
|
"typecheck": "tsc --noEmit",
|
|
14
15
|
"build": "tsup && publint",
|
|
15
16
|
"watch": "tsup --watch",
|
|
16
|
-
"lint": "eslint src
|
|
17
|
-
"lint:fix": "eslint
|
|
18
|
-
"
|
|
19
|
-
"
|
|
17
|
+
"lint": "eslint --ext js,ts src test",
|
|
18
|
+
"lint:fix": "eslint --ext js,ts src test --fix",
|
|
19
|
+
"format": "prettier --check \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
|
|
20
|
+
"format:fix": "prettier --write \"src/**/*.{js,ts}\" \"test/**/*.{js,ts}\"",
|
|
21
|
+
"prerelease": "bun run test && bun run build",
|
|
22
|
+
"release": "np"
|
|
20
23
|
},
|
|
21
24
|
"files": [
|
|
22
25
|
"dist"
|
|
@@ -49,6 +52,10 @@
|
|
|
49
52
|
"./vite": {
|
|
50
53
|
"types": "./dist/vite/index.d.ts",
|
|
51
54
|
"import": "./dist/vite/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./vite/client": {
|
|
57
|
+
"types": "./dist/vite/client.d.ts",
|
|
58
|
+
"import": "./dist/vite/client.js"
|
|
52
59
|
}
|
|
53
60
|
},
|
|
54
61
|
"typesVersions": {
|
|
@@ -70,6 +77,9 @@
|
|
|
70
77
|
],
|
|
71
78
|
"vite": [
|
|
72
79
|
"./dist/vite"
|
|
80
|
+
],
|
|
81
|
+
"vite/client": [
|
|
82
|
+
"./dist/vite/client"
|
|
73
83
|
]
|
|
74
84
|
}
|
|
75
85
|
},
|
|
@@ -89,10 +99,10 @@
|
|
|
89
99
|
"@babel/parser": "^7.23.6",
|
|
90
100
|
"@babel/traverse": "^7.23.6",
|
|
91
101
|
"@babel/types": "^7.23.6",
|
|
92
|
-
"@hono/vite-dev-server": "^0.
|
|
102
|
+
"@hono/vite-dev-server": "^0.5.0"
|
|
93
103
|
},
|
|
94
104
|
"devDependencies": {
|
|
95
|
-
"@hono/eslint-config": "^0.0.
|
|
105
|
+
"@hono/eslint-config": "^0.0.4",
|
|
96
106
|
"@mdx-js/rollup": "^3.0.0",
|
|
97
107
|
"@playwright/test": "^1.41.0",
|
|
98
108
|
"@types/babel__generator": "^7",
|
|
@@ -100,8 +110,8 @@
|
|
|
100
110
|
"@types/node": "^20.10.5",
|
|
101
111
|
"eslint": "^8.56.0",
|
|
102
112
|
"glob": "^10.3.10",
|
|
103
|
-
"hono": "4.0.0-rc.
|
|
104
|
-
"np": "
|
|
113
|
+
"hono": "4.0.0-rc.4",
|
|
114
|
+
"np": "7.7.0",
|
|
105
115
|
"prettier": "^3.1.1",
|
|
106
116
|
"publint": "^0.2.7",
|
|
107
117
|
"tsup": "^8.0.1",
|
|
@@ -109,8 +119,10 @@
|
|
|
109
119
|
"vite": "^5.0.12",
|
|
110
120
|
"vitest": "^1.2.1"
|
|
111
121
|
},
|
|
112
|
-
"packageManager": "yarn@4.0.2",
|
|
113
122
|
"engines": {
|
|
114
123
|
"node": ">=18.14.1"
|
|
124
|
+
},
|
|
125
|
+
"optionalDependencies": {
|
|
126
|
+
"@rollup/rollup-linux-x64-gnu": "^4.9.6"
|
|
115
127
|
}
|
|
116
128
|
}
|