From c4e8b3eec4aa780a5e0ff5f313621073a5425893 Mon Sep 17 00:00:00 2001 From: Yusuke Wada Date: Thu, 1 Feb 2024 18:53:51 +0900 Subject: [PATCH] feat: introduce `` (#27) --- bun.lockb | Bin 347299 -> 347299 bytes examples/basic/app/global.d.ts | 11 ++--- examples/basic/app/routes/_renderer.tsx | 40 ++++++++-------- examples/basic/bun.lockb | Bin 55077 -> 82080 bytes package.json | 2 +- src/constants.ts | 1 + src/server/components.tsx | 8 ++++ src/server/index.ts | 1 + src/server/server.ts | 21 ++++++++- src/vite/index.ts | 3 ++ src/vite/inject-importing-islands.ts | 60 ++++++++++++++++++++++++ test/hono-jsx/app/routes/_renderer.tsx | 5 +- test/hono-jsx/integration.test.ts | 54 +++++++++++++++++++-- test/hono-jsx/vitest.config.ts | 5 +- 14 files changed, 171 insertions(+), 40 deletions(-) create mode 100644 src/server/components.tsx create mode 100644 src/vite/inject-importing-islands.ts diff --git a/bun.lockb b/bun.lockb index b0038320652bd9dc9485a75b9fde555142dd2927..dfb7fda6b1719c11276cd1b85eb7f019e7ca1967 100755 GIT binary patch delta 33 pcmZ2HQ*`l6(S{br7N#xC)jQc4;|%mn^$gmZb~0~o+R36g834^83*P_$ delta 33 lcmZ2HQ*`l6(S{br7N#xC)jQdl7{H*tX(#jcrkyN`lL5OG3XuQ+ diff --git a/examples/basic/app/global.d.ts b/examples/basic/app/global.d.ts index e9536ef..216b135 100644 --- a/examples/basic/app/global.d.ts +++ b/examples/basic/app/global.d.ts @@ -1,16 +1,11 @@ -// eslint-disable-next-line node/no-extraneous-import -import 'hono' +import type {} from 'hono' -type Head = { +type Props = { title?: string } declare module 'hono' { - interface Env { - Variables: {} - Bindings: {} - } interface ContextRenderer { - (content: string | Promise, head?: Head): Response | Promise + (content: string | Promise, props?: Props): Response | Promise } } diff --git a/examples/basic/app/routes/_renderer.tsx b/examples/basic/app/routes/_renderer.tsx index df3dff7..344a047 100644 --- a/examples/basic/app/routes/_renderer.tsx +++ b/examples/basic/app/routes/_renderer.tsx @@ -1,24 +1,22 @@ import { jsxRenderer } from 'hono/jsx-renderer' +import { HasIslands } from 'honox/server' -export default jsxRenderer( - ({ children, title }) => { - return ( - - - - - {title ? {title} : <>} - {import.meta.env.PROD ? ( +export default jsxRenderer(({ children, title }) => { + return ( + + + + + {title ? {title} : <>} + {import.meta.env.PROD ? ( + - ) : ( - - )} - - {children} - - ) - }, - { - docType: true, - } -) + + ) : ( + + )} + + {children} + + ) +}) diff --git a/examples/basic/bun.lockb b/examples/basic/bun.lockb index fbd4567b18465c2ba3a9887678ddc07d0d69bcb5..36ec9f54e53b6da41c78b458b3b1738da3fc640f 100755 GIT binary patch delta 26657 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 S%)Bs>)STBSPN>+a{=WckI*;H0 delta 10425 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 awxBjO4r6%Fj|J7PPhb)IuJ>g7lz#>_rX&jh diff --git a/package.json b/package.json index f80583a..77f4414 100644 --- a/package.json +++ b/package.json @@ -117,4 +117,4 @@ "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.9.6" } -} \ No newline at end of file +} diff --git a/src/constants.ts b/src/constants.ts index 6c9e790..8cf2797 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,2 +1,3 @@ export const COMPONENT_NAME = 'component-name' export const DATA_SERIALIZED_PROPS = 'data-serialized-props' +export const IMPORTING_ISLANDS_ID = '__importing_islands' as const diff --git a/src/server/components.tsx b/src/server/components.tsx new file mode 100644 index 0000000..1d6983a --- /dev/null +++ b/src/server/components.tsx @@ -0,0 +1,8 @@ +import type { FC } from 'hono/jsx' +import { useRequestContext } from 'hono/jsx-renderer' +import { IMPORTING_ISLANDS_ID } from '../constants.js' + +export const HasIslands: FC = ({ children }) => { + const c = useRequestContext() + return <>{c.get(IMPORTING_ISLANDS_ID) ? children : <>} +} diff --git a/src/server/index.ts b/src/server/index.ts index cc14490..a6be94c 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,2 +1,3 @@ export { createApp } from './server.js' export type { ServerOptions } from './server.js' +export { HasIslands } from './components.js' diff --git a/src/server/server.ts b/src/server/server.ts index 296e0f9..793dd35 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,7 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Hono } from 'hono' import type { Env, NotFoundHandler, ErrorHandler, MiddlewareHandler } from 'hono' +import { createMiddleware } from 'hono/factory' import type { H } from 'hono/types' +import { IMPORTING_ISLANDS_ID } from '../constants.js' import { filePathToPath, groupByDirectory, @@ -15,12 +17,19 @@ const ERROR_FILENAME = '_error.tsx' const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'] as const type AppFile = { default: Hono } + +type InnerMeta = { + [key in typeof IMPORTING_ISLANDS_ID]?: boolean +} + type RouteFile = { default?: Function -} & { [M in (typeof METHODS)[number]]?: H[] } +} & { [M in (typeof METHODS)[number]]?: H[] } & InnerMeta + type RendererFile = { default: MiddlewareHandler } type NotFoundFile = { default: NotFoundHandler } type ErrorFile = { default: ErrorHandler } + type InitFunction = (app: Hono) => void export type ServerOptions = { @@ -114,6 +123,13 @@ export const createApp = (options?: ServerOptions): Hono => rootPath = filePathToPath(rootPath) for (const [filename, route] of Object.entries(content)) { + // @ts-expect-error route[IMPORTING_ISLANDS_ID] is not typed + const importingIslands = route[IMPORTING_ISLANDS_ID] as boolean + const setInnerMeta = createMiddleware(async function setInnerMeta(c, next) { + c.set(IMPORTING_ISLANDS_ID as any, importingIslands) + await next() + }) + const routeDefault = route.default const path = filePathToPath(filename) @@ -126,17 +142,20 @@ export const createApp = (options?: ServerOptions): Hono => for (const m of METHODS) { const handlers = (route as Record)[m] if (handlers) { + subApp.on(m, path, setInnerMeta) subApp.on(m, path, ...handlers) } } // export default factory.createHandlers(...) if (routeDefault && Array.isArray(routeDefault)) { + subApp.get(path, setInnerMeta) subApp.get(path, ...(routeDefault as H[])) } // export default function Helle() {} if (typeof routeDefault === 'function') { + subApp.get(path, setInnerMeta) subApp.get(path, (c) => { return c.render(routeDefault(), route as any) }) diff --git a/src/vite/index.ts b/src/vite/index.ts index 925022a..1eb5c2b 100644 --- a/src/vite/index.ts +++ b/src/vite/index.ts @@ -2,6 +2,7 @@ import path from 'path' import devServer, { defaultOptions as devServerDefaultOptions } from '@hono/vite-dev-server' import type { DevServerOptions } from '@hono/vite-dev-server' import type { PluginOption } from 'vite' +import { injectImportingIslands } from './inject-importing-islands.js' import { islandComponents } from './island-components.js' type HonoXOptions = { @@ -38,6 +39,8 @@ function honox(options?: HonoXOptions): PluginOption[] { plugins.push(islandComponents()) } + plugins.push(injectImportingIslands()) + return [ { name: 'honox-vite-config', diff --git a/src/vite/inject-importing-islands.ts b/src/vite/inject-importing-islands.ts new file mode 100644 index 0000000..02bae86 --- /dev/null +++ b/src/vite/inject-importing-islands.ts @@ -0,0 +1,60 @@ +import _generate from '@babel/generator' +import { parse } from '@babel/parser' +import _traverse from '@babel/traverse' +import type { Plugin } from 'vite' +import { IMPORTING_ISLANDS_ID } from '../constants.js' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const traverse = (_traverse.default as typeof _traverse) ?? _traverse +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const generate = (_generate.default as typeof _generate) ?? _generate + +export function injectImportingIslands(): Plugin { + return { + name: 'inject-importing-islands', + transform(code, id) { + if (id.endsWith('.tsx') || id.endsWith('.jsx')) { + let hasIslandsImport = false + const ast = parse(code, { + sourceType: 'module', + plugins: ['jsx'], + }) + + traverse(ast, { + ImportDeclaration(path) { + // We have to make a note that `../components/islands/foo.tsx` is also a target. + if (path.node.source.value.includes('islands/')) { + hasIslandsImport = true + } + }, + }) + + if (hasIslandsImport) { + const hasIslandsNode = { + type: 'ExportNamedDeclaration', + declaration: { + type: 'VariableDeclaration', + declarations: [ + { + type: 'VariableDeclarator', + id: { type: 'Identifier', name: IMPORTING_ISLANDS_ID }, + init: { type: 'BooleanLiteral', value: true }, + }, + ], + kind: 'const', + }, + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ast.program.body.push(hasIslandsNode as any) + } + + const output = generate(ast, {}, code) + return { + code: output.code, + map: output.map, + } + } + }, + } +} diff --git a/test/hono-jsx/app/routes/_renderer.tsx b/test/hono-jsx/app/routes/_renderer.tsx index ba8020b..067565b 100644 --- a/test/hono-jsx/app/routes/_renderer.tsx +++ b/test/hono-jsx/app/routes/_renderer.tsx @@ -1,11 +1,14 @@ import { jsxRenderer } from 'hono/jsx-renderer' +import { HasIslands } from '../../../../src/server' export default jsxRenderer(({ children, title }) => { return ( {title} - + + + {children} diff --git a/test/hono-jsx/integration.test.ts b/test/hono-jsx/integration.test.ts index b75a7d8..af2ffab 100644 --- a/test/hono-jsx/integration.test.ts +++ b/test/hono-jsx/integration.test.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { poweredBy } from 'hono/powered-by' +import { describe, it, expect, vi } from 'vitest' import { createApp } from '../../src/server' describe('Basic', () => { @@ -27,6 +28,21 @@ describe('Basic', () => { method: 'GET', handler: expect.any(Function), }, + { + path: '/about/:name/address', + method: 'GET', + handler: expect.any(Function), + }, + { + path: '/about/:name', + method: 'GET', + handler: expect.any(Function), + }, + { + path: '/about/:name', + method: 'GET', + handler: expect.any(Function), + }, { path: '/about/:name', method: 'POST', @@ -34,6 +50,11 @@ describe('Basic', () => { }, { path: '/about/:name', + method: 'POST', + handler: expect.any(Function), + }, + { + path: '/interaction', method: 'GET', handler: expect.any(Function), }, @@ -43,8 +64,16 @@ describe('Basic', () => { handler: expect.any(Function), }, { path: '/api', method: 'POST', handler: expect.any(Function) }, + { path: '/api', method: 'POST', handler: expect.any(Function) }, + { path: '/api', method: 'GET', handler: expect.any(Function) }, { path: '/api', method: 'GET', handler: expect.any(Function) }, { path: '/', method: 'GET', handler: expect.any(Function) }, + { path: '/', method: 'GET', handler: expect.any(Function) }, + { + path: '/post', + method: 'GET', + handler: expect.any(Function), + }, { path: '/post', method: 'GET', @@ -55,8 +84,14 @@ describe('Basic', () => { method: 'GET', handler: expect.any(Function), }, + { + path: '/throw_error', + method: 'GET', + handler: expect.any(Function), + }, ] - expect(app.routes).toEqual(routes) + expect(app.routes).toHaveLength(routes.length) + expect(app.routes).toEqual(expect.arrayContaining(routes)) }) it('Should return 200 response - / with a Powered By header', async () => { @@ -127,7 +162,7 @@ describe('Basic', () => { const res = await app.request('/') expect(res.status).toBe(200) expect(await res.text()).toBe( - 'This is a title

Hello

' + 'This is a title

Hello

' ) }) @@ -135,7 +170,7 @@ describe('Basic', () => { const res = await app.request('/foo') expect(res.status).toBe(404) expect(await res.text()).toBe( - 'Not Found

Not Found

' + 'Not Found

Not Found

' ) }) @@ -144,7 +179,7 @@ describe('Basic', () => { expect(res.status).toBe(200) // hono/jsx escape a single quote to ' expect(await res.text()).toBe( - 'me

It's me

My name is me' + 'me

It's me

My name is me' ) }) @@ -157,11 +192,20 @@ describe('Basic', () => { ) }) + it('Should return 200 response /interaction', async () => { + const res = await app.request('/interaction') + expect(res.status).toBe(200) + // hono/jsx escape a single quote to ' + expect(await res.text()).toBe( + '

Count: 5

' + ) + }) + it('Should return 500 response /throw_error', async () => { const res = await app.request('/throw_error') expect(res.status).toBe(500) expect(await res.text()).toBe( - 'Internal Server Error

Custom Error Message: Foo

' + 'Internal Server Error

Custom Error Message: Foo

' ) }) }) diff --git a/test/hono-jsx/vitest.config.ts b/test/hono-jsx/vitest.config.ts index 0903e10..f220ecb 100644 --- a/test/hono-jsx/vitest.config.ts +++ b/test/hono-jsx/vitest.config.ts @@ -1,13 +1,12 @@ import mdx from '@mdx-js/rollup' import { defineConfig } from 'vitest/config' +import { injectImportingIslands } from '../../src/vite/inject-importing-islands' import { islandComponents } from '../../src/vite/island-components' export default defineConfig({ - test: { - globals: true, - }, plugins: [ islandComponents(), + injectImportingIslands(), mdx({ jsxImportSource: 'hono/jsx', }),