diff --git a/bun.lockb b/bun.lockb
index 06e3e32..043534e 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/mocks/app-alias-tsconfig-paths/SomeComponent.tsx b/mocks/app-alias-tsconfig-paths/SomeComponent.tsx
new file mode 100644
index 0000000..7a59658
--- /dev/null
+++ b/mocks/app-alias-tsconfig-paths/SomeComponent.tsx
@@ -0,0 +1,5 @@
+import Counter from './islands/Counter'
+
+export default function SomeComponent() {
+ return
+}
diff --git a/mocks/app-alias-tsconfig-paths/islands/Counter.tsx b/mocks/app-alias-tsconfig-paths/islands/Counter.tsx
new file mode 100644
index 0000000..9185146
--- /dev/null
+++ b/mocks/app-alias-tsconfig-paths/islands/Counter.tsx
@@ -0,0 +1,3 @@
+export default function Counter() {
+ return
Counter
+}
diff --git a/mocks/app-alias-tsconfig-paths/routes/_renderer.tsx b/mocks/app-alias-tsconfig-paths/routes/_renderer.tsx
new file mode 100644
index 0000000..32f0296
--- /dev/null
+++ b/mocks/app-alias-tsconfig-paths/routes/_renderer.tsx
@@ -0,0 +1,20 @@
+import { jsxRenderer } from 'hono/jsx-renderer'
+import { HasIslands } from '../../../src/server'
+
+export default jsxRenderer(
+ ({ children }) => {
+ return (
+
+
+ {children}
+
+
+
+
+
+ )
+ },
+ {
+ docType: false,
+ }
+)
diff --git a/mocks/app-alias-tsconfig-paths/routes/has-islands.tsx b/mocks/app-alias-tsconfig-paths/routes/has-islands.tsx
new file mode 100644
index 0000000..dd1d00c
--- /dev/null
+++ b/mocks/app-alias-tsconfig-paths/routes/has-islands.tsx
@@ -0,0 +1,5 @@
+import Counter from '@mocks/SomeComponent'
+
+export default function HasIslands() {
+ return
+}
diff --git a/mocks/app-alias-tsconfig-paths/routes/has-no-islands.tsx b/mocks/app-alias-tsconfig-paths/routes/has-no-islands.tsx
new file mode 100644
index 0000000..8b34c7d
--- /dev/null
+++ b/mocks/app-alias-tsconfig-paths/routes/has-no-islands.tsx
@@ -0,0 +1,3 @@
+export default function HasNoIslands() {
+ return No Islands
+}
diff --git a/mocks/tsconfig.json b/mocks/tsconfig.json
new file mode 100644
index 0000000..aabf0e3
--- /dev/null
+++ b/mocks/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../tsconfig.json",
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index bf6fbad..08fcdbb 100644
--- a/package.json
+++ b/package.json
@@ -136,6 +136,7 @@
"tsup": "^8.1.0",
"typescript": "^5.3.3",
"vite": "^5.2.8",
+ "vite-tsconfig-paths": "^5.0.1",
"vitest": "^1.4.0"
},
"engines": {
diff --git a/src/vite/inject-importing-islands.ts b/src/vite/inject-importing-islands.ts
index 916e944..476fb70 100644
--- a/src/vite/inject-importing-islands.ts
+++ b/src/vite/inject-importing-islands.ts
@@ -2,7 +2,7 @@ import _generate from '@babel/generator'
import { parse } from '@babel/parser'
import precinct from 'precinct'
import { normalizePath } from 'vite'
-import type { Plugin } from 'vite'
+import type { Plugin, ResolvedConfig } from 'vite'
import { readFile } from 'fs/promises'
import path from 'path'
import { IMPORTING_ISLANDS_ID } from '../constants.js'
@@ -27,6 +27,8 @@ export async function injectImportingIslands(
let appPath = ''
const islandDir = options?.islandDir ?? '/app/islands'
let root = ''
+ let config: ResolvedConfig
+ const resolvedCache = new Map()
const cache: Record = {}
const walkDependencyTree: (
@@ -66,7 +68,8 @@ export async function injectImportingIslands(
return {
name: 'inject-importing-islands',
- configResolved: async (config) => {
+ configResolved: async (resolveConfig) => {
+ config = resolveConfig
appPath = path.join(config.root, options?.appDir ?? '/app')
root = config.root
},
@@ -75,14 +78,22 @@ export async function injectImportingIslands(
return
}
+ const resolve = async (importee: string, importer?: string) => {
+ if (resolvedCache.has(importee)) {
+ return this.resolve(importee)
+ }
+ const resolvedId = await this.resolve(importee, importer)
+ // Cache to prevent infinite loops in recursive calls.
+ resolvedCache.set(importee, true)
+ return resolvedId
+ }
+
const hasIslandsImport = (
await Promise.all(
- (await walkDependencyTree(id, async (id: string) => await this.resolve(id)))
- .flat()
- .map(async (x) => {
- const rootPath = '/' + path.relative(root, normalizePath(x)).replace(/\\/g, '/')
- return matchIslandComponentId(rootPath, islandDir)
- })
+ (await walkDependencyTree(id, resolve)).flat().map(async (x) => {
+ const rootPath = '/' + path.relative(root, normalizePath(x)).replace(/\\/g, '/')
+ return matchIslandComponentId(rootPath, islandDir)
+ })
)
).some((matched) => matched)
diff --git a/test-integration/apps.test.ts b/test-integration/apps.test.ts
index 1aaaed0..049191f 100644
--- a/test-integration/apps.test.ts
+++ b/test-integration/apps.test.ts
@@ -583,6 +583,38 @@ describe(' Component with path aliases', () => {
})
})
+describe(' Component with path alias with vite-tsconfig-paths', () => {
+ const ROUES = import.meta.glob(
+ '../mocks/app-alias-tsconfig-paths/routes/**/[a-z[-][a-z-_[]*.(tsx|ts)',
+ {
+ eager: true,
+ }
+ )
+ const RENDERER = import.meta.glob('../mocks/app-alias-tsconfig-paths/routes/**/_renderer.tsx', {
+ eager: true,
+ })
+
+ const app = createApp({
+ root: '../mocks/app-alias-tsconfig-paths/routes',
+ ROUTES: ROUES as any,
+ RENDERER: RENDERER as any,
+ })
+
+ it('Should return a script tag with tagged HasIslands - /has-islands', async () => {
+ const res = await app.request('/has-islands')
+ expect(res.status).toBe(200)
+ expect(await res.text()).toBe(
+ 'Counter
'
+ )
+ })
+
+ it('Should no return a script tag - /has-no-islands', async () => {
+ const res = await app.request('/has-no-islands')
+ expect(res.status).toBe(200)
+ expect(await res.text()).toBe('No Islands
')
+ })
+})
+
describe('Island Components with Preserved Files', () => {
const ROUTES = import.meta.glob(
'../mocks/app-islands-in-preserved/routes/**/[a-z[-][a-z-_[]*.(tsx|ts|mdx)',
diff --git a/test-integration/vitest.config.ts b/test-integration/vitest.config.ts
index eb198bf..923bef4 100644
--- a/test-integration/vitest.config.ts
+++ b/test-integration/vitest.config.ts
@@ -1,4 +1,5 @@
import mdx from '@mdx-js/rollup'
+import tsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vitest/config'
import path from 'path'
import { injectImportingIslands } from '../src/vite/inject-importing-islands'
@@ -28,5 +29,6 @@ export default defineConfig({
mdx({
jsxImportSource: 'hono/jsx',
}),
+ tsconfigPaths(),
],
})
diff --git a/tsconfig.json b/tsconfig.json
index dc6122e..5dc8496 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -13,13 +13,19 @@
"vitest/globals"
],
"jsx": "react-jsx",
- "jsxImportSource": "hono/jsx"
+ "jsxImportSource": "hono/jsx",
+ "baseUrl": ".",
+ "paths": {
+ "@mocks/*": [
+ "./mocks/app-alias-tsconfig-paths/*"
+ ]
+ }
},
"include": [
"src",
"test-integration",
"test-e2e",
- "mocks",
+ "mocks"
],
"exclude": [
"mocks/app-alias"
diff --git a/yarn.lock b/yarn.lock
index 06e77c1..a3ee083 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1,6 +1,6 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
-# bun ./bun.lockb --hash: 01AE2360C20256F8-361f85d0cfaa2723-33B136C6C40B62C1-a2a2739cf72fa158
+# bun ./bun.lockb --hash: 543A293A66C80C95-f7ab18b32b9678e2-D7579C357F066BE3-94c80f775e73166d
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7":
@@ -1567,7 +1567,7 @@ debug@^3.2.7:
dependencies:
ms "^2.1.1"
-debug@^4.0.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5:
+debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5:
version "4.3.7"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz"
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
@@ -2461,6 +2461,11 @@ globby@^11.0.1, globby@^11.1.0:
fast-glob "^3.2.9"
array-union "^2.1.0"
+globrex@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz"
+ integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
+
gonzales-pe@^4.3.0:
version "4.3.0"
resolved "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz"
@@ -5183,6 +5188,11 @@ ts-interface-checker@^0.1.9:
resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+tsconfck@^3.0.3:
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz"
+ integrity sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==
+
tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
@@ -5441,6 +5451,15 @@ vite-node@1.6.0:
pathe "^1.1.1"
picocolors "^1.0.0"
+vite-tsconfig-paths@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz"
+ integrity sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==
+ dependencies:
+ debug "^4.1.1"
+ globrex "^0.1.2"
+ tsconfck "^3.0.3"
+
vitest@^1.4.0:
version "1.6.0"
resolved "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz"