void-plugin-hono-jsx 0.1.0-alpha.2 → 0.1.0-alpha.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0-alpha.3](https://github.com/ts-76/void-plugin-hono-jsx/compare/v0.1.0-alpha.2...v0.1.0-alpha.3) (2026-10-12)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * support scaffold and current framework versions ([#46](https://github.com/ts-76/void-plugin-hono-jsx/issues/46)) ([4748044](https://github.com/ts-76/void-plugin-hono-jsx/commit/4748044cea8af423a77a6e51f0494c9b6d5a9a34))
9
+
3
10
  ## [0.1.0-alpha.2](https://github.com/ts-76/void-plugin-hono-jsx/compare/v0.1.0-alpha.1...v0.1.0-alpha.2) (2026-10-12)
4
11
 
5
12
 
package/README.md CHANGED
@@ -4,14 +4,16 @@ This experimental package integrates Hono JSX with Void Pages. The package name
4
4
 
5
5
  ## Supported versions
6
6
 
7
- | Dependency | Verified version |
8
- | --- | --- |
9
- | Node.js | 24.21.0 or newer |
10
- | Void | 0.26.1 |
11
- | Hono | 4.13.13 |
12
- | Vite | 8.3.3 |
7
+ | Component | Accepted stable range | Full consumer fixtures |
8
+ | --- | --- | --- |
9
+ | Node.js | >=24.21.0 | 24.21.0 |
10
+ | Void | >=0.26.1 <0.28.0 | 0.26.1, 0.27.0 |
11
+ | Hono | >=4.13.13 <5.0.0 | 4.13.13 |
12
+ | Vite | >=8.0.16 <9.0.0 | 8.0.16 (Vite Plus), 8.3.3, 8.3.4 |
13
+ | Vite Plus | Host Vite must satisfy the Vite range | 0.1.24 (scaffold), 1.1.0 (latest) |
14
+ | TypeScript | Project tooling | 7.0.2 |
13
15
 
14
- Framework packages are exact peer dependencies. Other versions have not been validated; configuration fails with an install command when Void, Hono or Vite differs from this baseline.
16
+ The next release after alpha.2 broadens these peer ranges. Published alpha.1 and staged alpha.2 retain their exact-version gate; install a local candidate to test this change before its release. Stable Vite/Hono updates within the current major are admitted by compatibility policy; Void is pre-1.0, so the next minor (0.28) requires explicit validation. Prereleases are excluded. The fixture versions above were exercised individually; admitting a range does not mean every future version has already been tested. New upstream releases require refreshed fixtures, full checks and dependency audit review.
15
17
 
16
18
  ## Install
17
19
 
@@ -19,14 +21,14 @@ Use Node 24.21.0 or newer:
19
21
 
20
22
  ```sh
21
23
  npm install void-plugin-hono-jsx@next hono@4.13.13
22
- npm install --save-dev void@0.26.1 vite@8.3.3 typescript@7.0.2
24
+ npm install --save-dev void@0.27.0 vite@8.3.4 typescript@7.0.2
23
25
  ```
24
26
 
25
27
  For a local validation tarball, in the repository, run `npm ci`, `npm run build:package`, then `npm pack ./packages/hono-pages`. Install the resulting tarball in your project alongside the supported peer versions:
26
28
 
27
29
  ```sh
28
30
  npm install ./void-plugin-hono-jsx-<version>.tgz hono@4.13.13
29
- npm install --save-dev void@0.26.1 vite@8.3.3 typescript@7.0.2
31
+ npm install --save-dev void@0.27.0 vite@8.3.4 typescript@7.0.2
30
32
  ```
31
33
 
32
34
  ## Configure
@@ -44,6 +46,26 @@ Configure project settings in `void.config.ts` using `defineConfig` from `void/c
44
46
 
45
47
  Use `jsx: "react-jsx"` and `jsxImportSource: "hono/jsx"` in TypeScript. The plugin chooses the server or DOM factory for application JSX; the plugin resolves package runtime exports using Vite's actual consumer environment. Cloudflare worker environments may enable the browser condition, so that condition alone cannot select the renderer.
46
48
 
49
+ ## Running Vite and launcher diagnostics
50
+
51
+ The config hook reads `this.meta.viteVersion` from the Vite instance executing the hook. Resolving `vite/package.json` from the adapter or project is not evidence of the running host. The adapter also checks the actual Vite helper module it imports. Errors include the host version, helper version, and absolute adapter/project package.json paths; different pnpm peer copies therefore remain visible.
52
+
53
+ Bundled launchers such as `vp dev` can execute another Vite even when the project has a direct `vite` dependency. The Void 0.27.0 scaffold requests `vite-plus: ^0.1.21`, resolving to 0.1.24 with host Vite 8.0.16. Latest Vite Plus 1.1.0 runs host Vite 8.3.3. The scaffold fixture retains direct npm Vite 8.3.4. Latest Vite Plus requires its official aligned toolchain: `vite` aliases `npm:@voidzero-dev/vite-plus-core@1.1.0`, and the fixture follows its documented consumer-only Vite/Vitest overrides (Vitest 5.0.3). Both are exercised in independent locked consumers, including dev, build and preview. These settings align the toolchain; they do not replace vulnerable transitive dependencies. Standard Vite 8.3.3/8.3.4 is also covered. Installing project Vite alone does not change a bundled host; unsupported host errors identify the launcher action separately from stale helper peer resolution.
54
+
55
+ If the project version is already correct, inspect the paths in the diagnostic and refresh stale adapter peer resolutions/lockfiles. Do not infer the host identity from the project dependency alone. Missing hook version information fails closed. [Vite plugin context metadata](https://vite.dev/guide/api-plugin.html#plugin-context-meta)
56
+
57
+ ## Adapting a Void scaffold
58
+
59
+ Void's init wizard currently offers React, Vue, Svelte and Solid adapters rather than Hono JSX. A React scaffold can be adapted without replacing its Vite Plus scripts:
60
+
61
+ 1. Install this adapter and `hono`; use a candidate/new release with the support policy above.
62
+ 2. Replace `voidReact()` / `@void/react/plugin` in `vite.config.ts` with `voidHonoPages()` / `void-plugin-hono-jsx/plugin`, keeping `voidPlugin()`.
63
+ 3. Set TypeScript `jsx` to `react-jsx` and `jsxImportSource` to `hono/jsx`. Change page/component React imports and hooks to Hono JSX APIs.
64
+ 4. Once React code is removed, uninstall `@void/react`, `react`, `react-dom`, `@types/react`, `@types/react-dom` and `oxc-transform-react` if they are otherwise unused. The Hono plugin supplies its own JSX transform.
65
+ 5. Keep `vp dev`, `vp build`, `vp preview`, or use the plain Vite scaffold. Verify the app's loaders/actions and database migrations locally.
66
+
67
+ The latest consumer fixtures also install React scaffold dependencies (React/DOM/types 19.3.0, `@void/react` 0.27.0 and `oxc-transform-react` 0.153.0), showing that their presence does not block the Hono adapter. This is not a React-to-Hono source conversion or a claim that other UI frameworks run through this adapter.
68
+
47
69
  ## Source and debugging files
48
70
 
49
71
  The next alpha candidate includes the original `src/plugins/*.ts` and `src/runtime/*.{ts,tsx}` alongside compiled `dist` entries. Every JavaScript file has a `.js.map` with embedded original source; every declaration has a `.d.ts.map` pointing to the same packaged TypeScript files. Build-time import rewriting composes its map with the compiler map, so generated locations still refer to the original source. These additions require a new release; alpha.0 and alpha.1 remain unchanged.
@@ -130,6 +152,8 @@ The advisory concerns esbuild's own development server. The adapter uses Vite/Ox
130
152
 
131
153
  The package adds no overrides and does not force changes to Void's internal dependencies. Consumers install the framework peers and their dependencies even though this archive contains no dependency implementation. Follow compatible upstream fixes; a peer upgrade requires renewed validation. New unreviewed advisories continue to block release preparation policy.
132
154
 
155
+ The scaffold Vite Plus 0.1.24 additionally brings `oxfmt 0.52.0 → tinypool 2.1.0`. On 2026-10-12 its consumer audit reported three propagated Critical package entries from [GHSA-5gmw-xhrv-c9v3](https://github.com/advisories/GHSA-5gmw-xhrv-c9v3) and [GHSA-85c8-ppgw-ccpr](https://github.com/advisories/GHSA-85c8-ppgw-ccpr). These require prototype pollution followed by pool worker creation/run options; `oxfmt/dist/cli.js` imports Tinypool. Dev/build/preview worked, but that does not prove formatter paths safe. These advisories are unapproved and continue to block that stack's release plan. Prefer latest Vite Plus 1.1.0 with its aligned alias or plain Vite; both retain only the existing esbuild advisory in reviewed audits. No tinypool override or security exception was added. See the repository `docs/scaffold-compatibility.md` for the complete matrix and audit assessment.
156
+
133
157
  ## Verification
134
158
 
135
159
  `npm run check:consumer` packs the package, audits its file list, copies a fixture into a temporary directory, installs locked peer dependencies and the tarball, and checks types, development rendering, production build, preview rendering and browser interaction. The consumer uses only the documented package exports and does not import repository source files.
@@ -142,7 +166,7 @@ Page and companion-loader edits reload the document and reset page/layout state.
142
166
 
143
167
  In development, the SSR renderer eagerly imports server-rendered page and layout modules with their providers. This keeps in-flight requests within the same module generation during a reload. Server-side module initialization therefore happens when the renderer loads, including pages not yet visited. Browser-only page components are excluded from this server graph. Production keeps lazy component imports. The packed-consumer regression also sends parallel SSR requests during six simultaneous page/loader revisions and requires every response to succeed.
144
168
 
145
- The packed-consumer check edits a page, changes its loader value, adds and removes a route, checks counter interaction after reloading, and asserts that the server stays running. It also verifies actionable diagnostics for unverified Void, Hono and Vite versions. Development and production preview are exercised on the exact baseline above; no additional framework versions are claimed. The active CI workflow covers that baseline on Node 24.21.0. It also runs `npm run check:source` for navigation, persistent layouts, action forms and head metadata in development and production preview. Inspect the GitHub Actions result on the commit being reviewed.
169
+ The packed-consumer check edits a page, changes its loader value, adds and removes a route, checks counter interaction after reloading, and asserts that the server stays running. It also verifies resolved dependency paths and rejection of an unsupported running Vite even when a supported npm Vite is installed. Five locked consumers cover the original baseline, the Vite patch update, latest Void with plain Vite, the scaffold Vite Plus, and latest Vite Plus on Node 24.21.0. The existing required baseline context aggregates all five results. It also runs `npm run check:source` for navigation, persistent layouts, action forms and head metadata in development and production preview. Inspect the GitHub Actions result on the commit being reviewed.
146
170
 
147
171
  ## Local ISR
148
172
 
@@ -1,2 +1,13 @@
1
- export declare function assertSupportedFrameworks(): void;
1
+ export declare const supportedFrameworkRanges: {
2
+ void: string;
3
+ hono: string;
4
+ vite: string;
5
+ };
6
+ export declare const supportedViteRange: string;
7
+ export declare function supportsFramework(name: keyof typeof supportedFrameworkRanges, version: unknown): boolean;
8
+ export declare const supportsVite: (version: unknown) => boolean;
9
+ export declare function assertSupportedFrameworks({ root, viteVersion }: {
10
+ root: string;
11
+ viteVersion: unknown;
12
+ }): void;
2
13
  //# sourceMappingURL=compatibility.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAKA,wBAAgB,yBAAyB,SAqBxC"}
1
+ {"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wBAAwB;IACnC,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC;AACF,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAIhE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,OAAO,wBAAwB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CASxG;AACD,eAAO,MAAM,YAAY,YAAa,OAAO,KAAG,OAA6C,CAAC;AAwB9F,wBAAgB,yBAAyB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,QAetG"}
@@ -1,30 +1,73 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
- const supported = { void: '0.26.1', hono: '4.13.13', vite: '8.3.3' };
5
- export function assertSupportedFrameworks() {
6
- const require = createRequire(import.meta.url);
7
- for (const [name, expected] of Object.entries(supported)) {
8
- let directory = dirname(require.resolve(name));
9
- let version;
10
- while (true) {
11
- const path = join(directory, 'package.json');
12
- if (existsSync(path)) {
13
- const metadata = JSON.parse(readFileSync(path, 'utf8'));
14
- if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && metadata.name === name) {
15
- if (!('version' in metadata) || typeof metadata.version !== 'string')
16
- throw new Error(`Hono Pages: ${name} package version is missing.`);
17
- version = metadata.version;
18
- break;
19
- }
4
+ import { version as helperViteVersion } from 'vite';
5
+ export const supportedFrameworkRanges = {
6
+ void: '>=0.26.1 <0.28.0',
7
+ hono: '>=4.13.13 <5.0.0',
8
+ vite: '>=8.0.16 <9.0.0',
9
+ };
10
+ export const supportedViteRange = supportedFrameworkRanges.vite;
11
+ // Only stable releases are admitted. Void is pre-1.0, so its next minor
12
+ // requires explicit validation; Hono and Vite use their current major lines.
13
+ export function supportsFramework(name, version) {
14
+ if (typeof version !== 'string')
15
+ return false;
16
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version);
17
+ if (!match)
18
+ return false;
19
+ const [major, minor, patch] = match.slice(1).map(Number);
20
+ if (![major, minor, patch].every(Number.isSafeInteger))
21
+ return false;
22
+ if (name === 'void')
23
+ return major === 0 && ((minor === 26 && patch >= 1) || minor === 27);
24
+ if (name === 'hono')
25
+ return major === 4 && (minor > 13 || (minor === 13 && patch >= 13));
26
+ return major === 8 && (minor > 0 || patch >= 16);
27
+ }
28
+ export const supportsVite = (version) => supportsFramework('vite', version);
29
+ function packageInfo(name, require) {
30
+ let directory = dirname(require.resolve(name));
31
+ while (true) {
32
+ const path = join(directory, 'package.json');
33
+ if (existsSync(path)) {
34
+ const metadata = JSON.parse(readFileSync(path, 'utf8'));
35
+ if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && (metadata.name === name || (name === 'vite' && metadata.name === '@voidzero-dev/vite-plus-core'))) {
36
+ if (!('version' in metadata) || typeof metadata.version !== 'string')
37
+ throw new Error(`Hono Pages: ${name} package version is missing (${path}).`);
38
+ return { version: metadata.version, path };
20
39
  }
21
- const parent = dirname(directory);
22
- if (parent === directory)
23
- throw new Error(`Hono Pages: cannot locate ${name} package metadata.`);
24
- directory = parent;
25
40
  }
26
- if (version !== expected)
27
- throw new Error(`Hono Pages: ${name} ${version} is unverified; install ${name}@${expected}. The adapter requires void@0.26.1, hono@4.13.13 and vite@8.3.3.`);
41
+ const parent = dirname(directory);
42
+ if (parent === directory)
43
+ throw new Error(`Hono Pages: cannot locate ${name} package metadata from ${require.resolve(name)}.`);
44
+ directory = parent;
45
+ }
46
+ }
47
+ function describe(name, require) {
48
+ try {
49
+ const info = packageInfo(name, require);
50
+ return `${info.path} (metadata ${info.version})`;
51
+ }
52
+ catch {
53
+ return `not resolved from ${require.resolve.paths(name)?.join(', ') ?? 'this context'}`;
54
+ }
55
+ }
56
+ export function assertSupportedFrameworks({ root, viteVersion }) {
57
+ const adapter = createRequire(import.meta.url);
58
+ const project = createRequire(join(root, 'package.json'));
59
+ const diagnostic = () => `Running Vite from hook context: ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'}. Adapter helper Vite: ${helperViteVersion}; package.json: ${describe('vite', adapter)}. Project Vite package.json: ${describe('vite', project)}. Package paths are diagnostics, not the running Vite identity.`;
60
+ if (!supportsVite(viteVersion)) {
61
+ throw new Error(`Hono Pages: running Vite ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Update the CLI/launcher that executes Vite. For bundled launchers such as vp, installing project vite alone does not update the running Vite. For standard Vite, install vite@^8.3.4 and run vite directly.`);
62
+ }
63
+ if (!supportsVite(helperViteVersion)) {
64
+ throw new Error(`Hono Pages: adapter helper Vite ${helperViteVersion} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Inspect the adapter's resolved peer copy; install vite@^8.3.4 and refresh the adapter's peer resolution/lockfile if a stale copy remains.`);
65
+ }
66
+ for (const name of ['void', 'hono']) {
67
+ const expected = supportedFrameworkRanges[name];
68
+ const info = packageInfo(name, adapter);
69
+ if (!supportsFramework(name, info.version))
70
+ throw new Error(`Hono Pages: ${name} ${info.version} is unsupported; install ${name}@"${expected}". Resolved package.json: ${info.path}. Project package.json: ${describe(name, project)}. ${diagnostic()}`);
28
71
  }
29
72
  }
30
73
  //# sourceMappingURL=compatibility.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACrE,MAAM,UAAU,yBAAyB;IACvC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,IAAI,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,IAAI,OAA2B,CAAC;QAChC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBACtG,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ;wBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,8BAA8B,CAAC,CAAC;oBACzI,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;oBAC3B,MAAM;gBACR,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,oBAAoB,CAAC,CAAC;YACjG,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,OAAO,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,IAAI,OAAO,2BAA2B,IAAI,IAAI,QAAQ,kEAAkE,CAAC,CAAC;IACzL,CAAC;AACH,CAAC","sourcesContent":["import { createRequire } from 'node:module';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst supported = { void: '0.26.1', hono: '4.13.13', vite: '8.3.3' };\nexport function assertSupportedFrameworks() {\n const require = createRequire(import.meta.url);\n for (const [name, expected] of Object.entries(supported)) {\n let directory = dirname(require.resolve(name));\n let version: string | undefined;\n while (true) {\n const path = join(directory, 'package.json');\n if (existsSync(path)) {\n const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && metadata.name === name) {\n if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing.`);\n version = metadata.version;\n break;\n }\n }\n const parent = dirname(directory);\n if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata.`);\n directory = parent;\n }\n if (version !== expected) throw new Error(`Hono Pages: ${name} ${version} is unverified; install ${name}@${expected}. The adapter requires void@0.26.1, hono@4.13.13 and vite@8.3.3.`);\n }\n}\n"]}
1
+ {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from 'node:module';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { version as helperViteVersion } from 'vite';\n\nexport const supportedFrameworkRanges = {\n void: '>=0.26.1 <0.28.0',\n hono: '>=4.13.13 <5.0.0',\n vite: '>=8.0.16 <9.0.0',\n};\nexport const supportedViteRange = supportedFrameworkRanges.vite;\n\n// Only stable releases are admitted. Void is pre-1.0, so its next minor\n// requires explicit validation; Hono and Vite use their current major lines.\nexport function supportsFramework(name: keyof typeof supportedFrameworkRanges, version: unknown): boolean {\n if (typeof version !== 'string') return false;\n const match = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$/.exec(version);\n if (!match) return false;\n const [major, minor, patch] = match.slice(1).map(Number);\n if (![major, minor, patch].every(Number.isSafeInteger)) return false;\n if (name === 'void') return major === 0 && ((minor === 26 && patch >= 1) || minor === 27);\n if (name === 'hono') return major === 4 && (minor > 13 || (minor === 13 && patch >= 13));\n return major === 8 && (minor > 0 || patch >= 16);\n}\nexport const supportsVite = (version: unknown): boolean => supportsFramework('vite', version);\n\ntype PackageInfo = { version: string; path: string };\nfunction packageInfo(name: string, require: NodeRequire): PackageInfo {\n let directory = dirname(require.resolve(name));\n while (true) {\n const path = join(directory, 'package.json');\n if (existsSync(path)) {\n const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && (metadata.name === name || (name === 'vite' && metadata.name === '@voidzero-dev/vite-plus-core'))) {\n if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing (${path}).`);\n return { version: metadata.version, path };\n }\n }\n const parent = dirname(directory);\n if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata from ${require.resolve(name)}.`);\n directory = parent;\n }\n}\nfunction describe(name: string, require: NodeRequire): string {\n try { const info = packageInfo(name, require); return `${info.path} (metadata ${info.version})`; }\n catch { return `not resolved from ${require.resolve.paths(name)?.join(', ') ?? 'this context'}`; }\n}\n\nexport function assertSupportedFrameworks({ root, viteVersion }: { root: string; viteVersion: unknown }) {\n const adapter = createRequire(import.meta.url);\n const project = createRequire(join(root, 'package.json'));\n const diagnostic = () => `Running Vite from hook context: ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'}. Adapter helper Vite: ${helperViteVersion}; package.json: ${describe('vite', adapter)}. Project Vite package.json: ${describe('vite', project)}. Package paths are diagnostics, not the running Vite identity.`;\n if (!supportsVite(viteVersion)) {\n throw new Error(`Hono Pages: running Vite ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Update the CLI/launcher that executes Vite. For bundled launchers such as vp, installing project vite alone does not update the running Vite. For standard Vite, install vite@^8.3.4 and run vite directly.`);\n }\n if (!supportsVite(helperViteVersion)) {\n throw new Error(`Hono Pages: adapter helper Vite ${helperViteVersion} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Inspect the adapter's resolved peer copy; install vite@^8.3.4 and refresh the adapter's peer resolution/lockfile if a stale copy remains.`);\n }\n for (const name of ['void', 'hono'] as const) {\n const expected = supportedFrameworkRanges[name];\n const info = packageInfo(name, adapter);\n if (!supportsFramework(name, info.version)) throw new Error(`Hono Pages: ${name} ${info.version} is unsupported; install ${name}@\"${expected}\". Resolved package.json: ${info.path}. Project package.json: ${describe(name, project)}. ${diagnostic()}`);\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  import type { Plugin } from 'vite';
2
- /** Experimental Pages contract verified against Void 0.26.1. */
2
+ /** Experimental Pages contract verified against Void 0.26.1 and 0.27.0. */
3
3
  export declare function voidHonoPages(): Plugin[];
4
4
  //# sourceMappingURL=hono-pages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono-pages.d.ts","sourceRoot":"","sources":["../../src/plugins/hono-pages.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAQnC,gEAAgE;AAChE,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAgIxC"}
1
+ {"version":3,"file":"hono-pages.d.ts","sourceRoot":"","sources":["../../src/plugins/hono-pages.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAQnC,2EAA2E;AAC3E,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAgIxC"}
@@ -1,4 +1,5 @@
1
1
  import { realpathSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
2
3
  import { normalizePath } from 'vite';
3
4
  import { pagesRuntimePath, clientRuntimePath, publicRuntimeModules } from './runtime-paths.js';
4
5
  import { generateComponentManifest, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages } from 'void/pages';
@@ -7,7 +8,7 @@ import { honoIslands } from './hono-islands.js';
7
8
  import { assertSupportedFrameworks } from './compatibility.js';
8
9
  const rendererId = 'virtual:void-pages-renderer';
9
10
  const clientId = 'virtual:void-pages-client';
10
- /** Experimental Pages contract verified against Void 0.26.1. */
11
+ /** Experimental Pages contract verified against Void 0.26.1 and 0.27.0. */
11
12
  export function voidHonoPages() {
12
13
  const root = process.cwd();
13
14
  const pagesDir = resolvePagesDir(root);
@@ -32,8 +33,8 @@ export function voidHonoPages() {
32
33
  return [honoIslands(), honoJsx(), {
33
34
  name: 'void-hono:pages',
34
35
  enforce: 'pre',
35
- config() {
36
- assertSupportedFrameworks();
36
+ config(config) {
37
+ assertSupportedFrameworks({ root: resolve(config.root ?? root), viteVersion: this?.meta?.viteVersion });
37
38
  return {
38
39
  resolve: { dedupe: ['hono'] },
39
40
  build: { manifest: true, rollupOptions: { input: { 'pages-client': clientId } } },
@@ -1 +1 @@
1
- {"version":3,"file":"hono-pages.js","sourceRoot":"","sources":["../../src/plugins/hono-pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,iCAAiC,EAAE,SAAS,EAAuB,MAAM,YAAY,CAAC;AAE3I,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,MAAM,UAAU,GAAG,6BAA6B,CAAC;AACjD,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAE7C,gEAAgE;AAChE,MAAM,UAAU,aAAa;IAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,iCAAiC,CAAC,IAAI,CAAC,CAAC;IAC3D,IAAI,IAAgC,CAAC;IAErC,KAAK,UAAU,MAAM;QACnB,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7D,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;QACvI,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,0DAA0D,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACnG,CAAC;YACD,IAAI,UAAU,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;gBACrG,MAAM,IAAI,KAAK,CAAC,+EAA+E,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACxH,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE;YAChC,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,KAAK;YACd,MAAM;gBACJ,yBAAyB,EAAE,CAAC;gBAC5B,OAAO;oBACL,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE;oBAC7B,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,EAAE;iBAClF,CAAC;YACJ,CAAC;YACD,iBAAiB;gBACf,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAClD,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrF,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC;YAC7G,CAAC;YACD,KAAK,CAAC,UAAU;gBACd,MAAM,MAAM,EAAE,CAAC;YACjB,CAAC;YACD,eAAe,CAAC,MAAM;gBACpB,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE;oBAC7B,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;wBAAE,IAAI,GAAG,SAAS,CAAC;gBACtF,CAAC,CAAC;gBACF,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAChC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACnC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrH,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE;gBAChD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;oBAAE,OAAO;gBAC3E,MAAM,MAAM,EAAE,CAAC;gBACf,IAAI,IAAI,KAAK,QAAQ;oBAAE,OAAO,EAAE,CAAC;gBACjC,MAAM,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;gBACxD,KAAK,MAAM,MAAM,IAAI,OAAO;oBAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;gBAClH,KAAK,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;oBACxC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACrE,IAAI,MAAM;wBAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;gBAClG,CAAC;gBACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;gBACnD,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,SAAS,CAAC,EAAE;gBACV,IAAI,EAAE,KAAK,UAAU,IAAI,EAAE,KAAK,QAAQ;oBAAE,OAAO,KAAK,EAAE,EAAE,CAAC;gBAC3D,IAAI,EAAE,KAAK,gBAAgB,IAAI,EAAE,KAAK,iBAAiB;oBAAE,OAAO,EAAE,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;gBAC1G,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;gBACzC,IAAI,OAAO;oBAAE,OAAO,EAAE,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7I,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,KAAK,KAAK,UAAU,EAAE,IAAI,EAAE,KAAK,KAAK,QAAQ,EAAE;oBAAE,OAAO;gBAC/D,MAAM,WAAW,GAAG,IAAI,IAAI,MAAM,MAAM,EAAE,CAAC;gBAC3C,MAAM,cAAc,GAAG,EAAE,KAAK,KAAK,UAAU,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,KAAK,CAAC;gBACnF,MAAM,YAAY,GAAG,EAAE,KAAK,KAAK,QAAQ,EAAE;oBACzC,CAAC,CAAC,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAC7E,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;gBAC/H,IAAI,QAAQ,GAAG,yBAAyB,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;gBACjE,IAAI,cAAc,EAAE,CAAC;oBACnB,uEAAuE;oBACvE,sEAAsE;oBACtE,uEAAuE;oBACvE,gEAAgE;oBAChE,MAAM,OAAO,GAAa,EAAE,CAAC;oBAC7B,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,wCAAwC,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE;wBACxF,MAAM,IAAI,GAAG,qBAAqB,OAAO,CAAC,MAAM,EAAE,CAAC;wBACnD,OAAO,CAAC,IAAI,CAAC,eAAe,IAAI,SAAS,IAAI,GAAG,CAAC,CAAC;wBAClD,OAAO,SAAS,IAAI,EAAE,CAAC;oBACzB,CAAC,CAAC,CAAC;oBACH,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,QAAQ,CAAC;gBAClD,CAAC;gBACD,IAAI,EAAE,KAAK,KAAK,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;oBAAE,OAAO,YAAY,CAAC;gBACnG,IAAI,EAAE,KAAK,KAAK,UAAU,EAAE,EAAE,CAAC;oBAC7B,OAAO;;;6CAG8B,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;EAG3E,QAAQ;;QAEF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;CAqBzC,CAAC;gBACI,CAAC;gBACD,OAAO;iCACoB,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;EAChE,QAAQ;wFAC8E,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC;CACzL,CAAC;YACE,CAAC;SACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { realpathSync } from 'node:fs';\nimport { normalizePath } from 'vite';\nimport { pagesRuntimePath, clientRuntimePath, publicRuntimeModules } from './runtime-paths.ts';\nimport { generateComponentManifest, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages, type PageScanResult } from 'void/pages';\nimport type { Plugin } from 'vite';\nimport { honoJsx } from './hono-jsx.ts';\nimport { honoIslands } from './hono-islands.ts';\nimport { assertSupportedFrameworks } from './compatibility.ts';\n\nconst rendererId = 'virtual:void-pages-renderer';\nconst clientId = 'virtual:void-pages-client';\n\n/** Experimental Pages contract verified against Void 0.26.1. */\nexport function voidHonoPages(): Plugin[] {\n const root = process.cwd();\n const pagesDir = resolvePagesDir(root);\n const staticData = resolveStaticPageDataBuildOptions(root);\n let scan: PageScanResult | undefined;\n\n async function rescan() {\n scan = await scanPages(root, { pagesDir });\n for (const layout of [...scan.layouts, ...scan.namedLayouts]) {\n if (layout.island || !/\\.[jt]sx$/.test(layout.filePath)) throw new Error('Hono Pages: only standard TSX/JSX layouts are supported.');\n }\n for (const page of scan.pages) {\n if (!/\\.[jt]sx$/.test(page.componentPath)) {\n throw new Error(`Hono Pages: only standard TSX/JSX pages are supported: ${page.componentPath}.`);\n }\n if (staticData.enabled && page.methods.some((method) => method === 'action' || method === 'actions')) {\n throw new Error(`Hono Pages: actions require a server and cannot be used with static output: ${page.componentPath}.`);\n }\n }\n return scan;\n }\n\n return [honoIslands(), honoJsx(), {\n name: 'void-hono:pages',\n enforce: 'pre',\n config() {\n assertSupportedFrameworks();\n return {\n resolve: { dedupe: ['hono'] },\n build: { manifest: true, rollupOptions: { input: { 'pages-client': clientId } } },\n };\n },\n configEnvironment() {\n const modules = Object.keys(publicRuntimeModules);\n const packages = [...new Set(modules.map((id) => id.slice(0, id.lastIndexOf('/'))))];\n return { optimizeDeps: { exclude: ['hono', ...modules] }, resolve: { noExternal: ['hono', ...packages] } };\n },\n async buildStart() {\n await rescan();\n },\n configureServer(server) {\n const clear = (file: string) => {\n if (normalizePath(file).startsWith(normalizePath(pagesDir) + '/')) scan = undefined;\n };\n server.watcher.on('add', clear);\n server.watcher.on('unlink', clear);\n server.httpServer?.once('close', () => { server.watcher.off('add', clear); server.watcher.off('unlink', clear); });\n },\n async hotUpdate({ file, type, modules, timestamp }) {\n if (!normalizePath(file).startsWith(normalizePath(pagesDir) + '/')) return;\n await rescan();\n if (type !== 'update') return [];\n const invalidated = new Set<(typeof modules)[number]>();\n for (const module of modules) this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);\n for (const id of [rendererId, clientId]) {\n const module = this.environment.moduleGraph.getModuleById(`\\0${id}`);\n if (module) this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);\n }\n this.environment.hot.send({ type: 'full-reload' });\n return [];\n },\n resolveId(id) {\n if (id === rendererId || id === clientId) return `\\0${id}`;\n if (id === pagesRuntimePath || id === clientRuntimePath) return { id: realpathSync(id), external: false };\n const runtime = publicRuntimeModules[id];\n if (runtime) return { id: realpathSync(this.environment.config.consumer === 'client' ? runtime.client : runtime.server), external: false };\n },\n async load(id) {\n if (id !== `\\0${rendererId}` && id !== `\\0${clientId}`) return;\n const currentScan = scan ?? await rescan();\n const serverSnapshot = id === `\\0${rendererId}` && this.environment.mode === 'dev';\n const manifestScan = id === `\\0${clientId}`\n ? { ...currentScan, pages: currentScan.pages.filter((page) => !page.island) }\n : serverSnapshot ? { ...currentScan, pages: currentScan.pages.filter((page) => page.renderMode !== 'client') } : currentScan;\n let manifest = generateComponentManifest(manifestScan, pagesDir);\n if (serverSnapshot) {\n // A request can retain the old renderer while the worker module runner\n // reloads. Capture components with its providers instead of importing\n // a new generation into an in-flight render. Browser-only pages remain\n // absent from this server graph; production keeps lazy imports.\n const imports: string[] = [];\n manifest = manifest.replace(/\\(\\) => import\\((\"(?:[^\"\\\\]|\\\\.)*\")\\)/g, (_, path: string) => {\n const name = `__honoPageSnapshot${imports.length}`;\n imports.push(`import * as ${name} from ${path};`);\n return `() => ${name}`;\n });\n manifest = imports.join('\\n') + '\\n' + manifest;\n }\n if (id === `\\0${clientId}` && !currentScan.pages.some((page) => !page.island)) return 'export {};';\n if (id === `\\0${rendererId}`) {\n return `\nimport { jsx } from 'hono/jsx';\nimport { createSsrRouter } from 'void/pages-client';\nimport { PageContext, RouterContext } from ${JSON.stringify(pagesRuntimePath)};\nimport { serializePageData } from 'void/pages-server';\nimport { renderHeadToString, renderHtmlAttrs, renderBodyAttrs } from 'void/pages-head';\n${manifest}\nexport async function renderPage(pageObj, assetTags) {\n if (${JSON.stringify(staticData.enabled)} && pageObj.deferredKeys) throw new Error('Hono Pages: deferred props cannot be statically prerendered; remove defer().');\n const load = components[pageObj.component];\n if (!load) throw new Error('Hono Pages: unknown page component ' + pageObj.component);\n const { default: Page } = await load();\n if (typeof Page !== 'function') throw new Error('Hono Pages: a page must export a component function.');\n let content = jsx(Page, pageObj.props);\n const ids = layoutTree[pageObj.component] ?? [];\n const layouts = await Promise.all(ids.map(async (id) => (await components[id]()).default));\n for (const Layout of layouts.reverse()) {\n if (typeof Layout !== 'function') throw new Error('Hono Pages: a layout must export a component function.');\n content = jsx(Layout, { children: content });\n }\n const markup = await jsx(RouterContext.Provider, { value: createSsrRouter(pageObj.url, pageObj.params), children: jsx(PageContext.Provider, { value: pageObj, children: content }) }).toString();\n const head = pageObj.head;\n const body = pageObj.deferredKeys ? assetTags.body.replaceAll('<script type=\"module\"', '<script async type=\"module\"') : assetTags.body;\n return '<!doctype html><html' + (head ? renderHtmlAttrs(head) : '') + '><head>'\n + (head ? renderHeadToString(head) : '') + assetTags.css + assetTags.preloads\n + '</head><body' + (head ? renderBodyAttrs(head) : '') + '>'\n + '<script id=\"__VOID_PAGE_DATA__\" type=\"application/json\">' + serializePageData(pageObj) + '</script>'\n + '<div id=\"app\">' + markup + '</div>' + body + '</body></html>';\n}\n`;\n }\n return `\nimport { startHonoPages } from ${JSON.stringify(clientRuntimePath)};\n${manifest}\nawait startHonoPages({ components, layoutTree, routeMeta, matchRoute, staticPageData: ${JSON.stringify(staticData.enabled)}, staticPageDataFastPath: ${JSON.stringify(staticData.fastPath)} });\n`;\n },\n }];\n}\n"]}
1
+ {"version":3,"file":"hono-pages.js","sourceRoot":"","sources":["../../src/plugins/hono-pages.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { normalizePath } from 'vite';\nimport { pagesRuntimePath, clientRuntimePath, publicRuntimeModules } from './runtime-paths.ts';\nimport { generateComponentManifest, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages, type PageScanResult } from 'void/pages';\nimport type { Plugin } from 'vite';\nimport { honoJsx } from './hono-jsx.ts';\nimport { honoIslands } from './hono-islands.ts';\nimport { assertSupportedFrameworks } from './compatibility.ts';\n\nconst rendererId = 'virtual:void-pages-renderer';\nconst clientId = 'virtual:void-pages-client';\n\n/** Experimental Pages contract verified against Void 0.26.1 and 0.27.0. */\nexport function voidHonoPages(): Plugin[] {\n const root = process.cwd();\n const pagesDir = resolvePagesDir(root);\n const staticData = resolveStaticPageDataBuildOptions(root);\n let scan: PageScanResult | undefined;\n\n async function rescan() {\n scan = await scanPages(root, { pagesDir });\n for (const layout of [...scan.layouts, ...scan.namedLayouts]) {\n if (layout.island || !/\\.[jt]sx$/.test(layout.filePath)) throw new Error('Hono Pages: only standard TSX/JSX layouts are supported.');\n }\n for (const page of scan.pages) {\n if (!/\\.[jt]sx$/.test(page.componentPath)) {\n throw new Error(`Hono Pages: only standard TSX/JSX pages are supported: ${page.componentPath}.`);\n }\n if (staticData.enabled && page.methods.some((method) => method === 'action' || method === 'actions')) {\n throw new Error(`Hono Pages: actions require a server and cannot be used with static output: ${page.componentPath}.`);\n }\n }\n return scan;\n }\n\n return [honoIslands(), honoJsx(), {\n name: 'void-hono:pages',\n enforce: 'pre',\n config(config) {\n assertSupportedFrameworks({ root: resolve(config.root ?? root), viteVersion: this?.meta?.viteVersion });\n return {\n resolve: { dedupe: ['hono'] },\n build: { manifest: true, rollupOptions: { input: { 'pages-client': clientId } } },\n };\n },\n configEnvironment() {\n const modules = Object.keys(publicRuntimeModules);\n const packages = [...new Set(modules.map((id) => id.slice(0, id.lastIndexOf('/'))))];\n return { optimizeDeps: { exclude: ['hono', ...modules] }, resolve: { noExternal: ['hono', ...packages] } };\n },\n async buildStart() {\n await rescan();\n },\n configureServer(server) {\n const clear = (file: string) => {\n if (normalizePath(file).startsWith(normalizePath(pagesDir) + '/')) scan = undefined;\n };\n server.watcher.on('add', clear);\n server.watcher.on('unlink', clear);\n server.httpServer?.once('close', () => { server.watcher.off('add', clear); server.watcher.off('unlink', clear); });\n },\n async hotUpdate({ file, type, modules, timestamp }) {\n if (!normalizePath(file).startsWith(normalizePath(pagesDir) + '/')) return;\n await rescan();\n if (type !== 'update') return [];\n const invalidated = new Set<(typeof modules)[number]>();\n for (const module of modules) this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);\n for (const id of [rendererId, clientId]) {\n const module = this.environment.moduleGraph.getModuleById(`\\0${id}`);\n if (module) this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);\n }\n this.environment.hot.send({ type: 'full-reload' });\n return [];\n },\n resolveId(id) {\n if (id === rendererId || id === clientId) return `\\0${id}`;\n if (id === pagesRuntimePath || id === clientRuntimePath) return { id: realpathSync(id), external: false };\n const runtime = publicRuntimeModules[id];\n if (runtime) return { id: realpathSync(this.environment.config.consumer === 'client' ? runtime.client : runtime.server), external: false };\n },\n async load(id) {\n if (id !== `\\0${rendererId}` && id !== `\\0${clientId}`) return;\n const currentScan = scan ?? await rescan();\n const serverSnapshot = id === `\\0${rendererId}` && this.environment.mode === 'dev';\n const manifestScan = id === `\\0${clientId}`\n ? { ...currentScan, pages: currentScan.pages.filter((page) => !page.island) }\n : serverSnapshot ? { ...currentScan, pages: currentScan.pages.filter((page) => page.renderMode !== 'client') } : currentScan;\n let manifest = generateComponentManifest(manifestScan, pagesDir);\n if (serverSnapshot) {\n // A request can retain the old renderer while the worker module runner\n // reloads. Capture components with its providers instead of importing\n // a new generation into an in-flight render. Browser-only pages remain\n // absent from this server graph; production keeps lazy imports.\n const imports: string[] = [];\n manifest = manifest.replace(/\\(\\) => import\\((\"(?:[^\"\\\\]|\\\\.)*\")\\)/g, (_, path: string) => {\n const name = `__honoPageSnapshot${imports.length}`;\n imports.push(`import * as ${name} from ${path};`);\n return `() => ${name}`;\n });\n manifest = imports.join('\\n') + '\\n' + manifest;\n }\n if (id === `\\0${clientId}` && !currentScan.pages.some((page) => !page.island)) return 'export {};';\n if (id === `\\0${rendererId}`) {\n return `\nimport { jsx } from 'hono/jsx';\nimport { createSsrRouter } from 'void/pages-client';\nimport { PageContext, RouterContext } from ${JSON.stringify(pagesRuntimePath)};\nimport { serializePageData } from 'void/pages-server';\nimport { renderHeadToString, renderHtmlAttrs, renderBodyAttrs } from 'void/pages-head';\n${manifest}\nexport async function renderPage(pageObj, assetTags) {\n if (${JSON.stringify(staticData.enabled)} && pageObj.deferredKeys) throw new Error('Hono Pages: deferred props cannot be statically prerendered; remove defer().');\n const load = components[pageObj.component];\n if (!load) throw new Error('Hono Pages: unknown page component ' + pageObj.component);\n const { default: Page } = await load();\n if (typeof Page !== 'function') throw new Error('Hono Pages: a page must export a component function.');\n let content = jsx(Page, pageObj.props);\n const ids = layoutTree[pageObj.component] ?? [];\n const layouts = await Promise.all(ids.map(async (id) => (await components[id]()).default));\n for (const Layout of layouts.reverse()) {\n if (typeof Layout !== 'function') throw new Error('Hono Pages: a layout must export a component function.');\n content = jsx(Layout, { children: content });\n }\n const markup = await jsx(RouterContext.Provider, { value: createSsrRouter(pageObj.url, pageObj.params), children: jsx(PageContext.Provider, { value: pageObj, children: content }) }).toString();\n const head = pageObj.head;\n const body = pageObj.deferredKeys ? assetTags.body.replaceAll('<script type=\"module\"', '<script async type=\"module\"') : assetTags.body;\n return '<!doctype html><html' + (head ? renderHtmlAttrs(head) : '') + '><head>'\n + (head ? renderHeadToString(head) : '') + assetTags.css + assetTags.preloads\n + '</head><body' + (head ? renderBodyAttrs(head) : '') + '>'\n + '<script id=\"__VOID_PAGE_DATA__\" type=\"application/json\">' + serializePageData(pageObj) + '</script>'\n + '<div id=\"app\">' + markup + '</div>' + body + '</body></html>';\n}\n`;\n }\n return `\nimport { startHonoPages } from ${JSON.stringify(clientRuntimePath)};\n${manifest}\nawait startHonoPages({ components, layoutTree, routeMeta, matchRoute, staticPageData: ${JSON.stringify(staticData.enabled)}, staticPageDataFastPath: ${JSON.stringify(staticData.fastPath)} });\n`;\n },\n }];\n}\n"]}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "void-plugin-hono-jsx",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "private": false,
5
- "description": "Experimental Hono JSX Pages adapter for Void 0.26.1",
5
+ "description": "Experimental Hono JSX Pages adapter for Void",
6
6
  "type": "module",
7
7
  "license": "MIT",
8
8
  "engines": {
@@ -31,9 +31,9 @@
31
31
  }
32
32
  },
33
33
  "peerDependencies": {
34
- "hono": "4.13.13",
35
- "void": "0.26.1",
36
- "vite": "8.3.3"
34
+ "hono": ">=4.13.13 <5.0.0",
35
+ "void": ">=0.26.1 <0.28.0",
36
+ "vite": ">=8.0.16 <9.0.0"
37
37
  },
38
38
  "repository": {
39
39
  "type": "git",
@@ -1,27 +1,64 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
+ import { version as helperViteVersion } from 'vite';
4
5
 
5
- const supported = { void: '0.26.1', hono: '4.13.13', vite: '8.3.3' };
6
- export function assertSupportedFrameworks() {
7
- const require = createRequire(import.meta.url);
8
- for (const [name, expected] of Object.entries(supported)) {
9
- let directory = dirname(require.resolve(name));
10
- let version: string | undefined;
11
- while (true) {
12
- const path = join(directory, 'package.json');
13
- if (existsSync(path)) {
14
- const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));
15
- if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && metadata.name === name) {
16
- if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing.`);
17
- version = metadata.version;
18
- break;
19
- }
6
+ export const supportedFrameworkRanges = {
7
+ void: '>=0.26.1 <0.28.0',
8
+ hono: '>=4.13.13 <5.0.0',
9
+ vite: '>=8.0.16 <9.0.0',
10
+ };
11
+ export const supportedViteRange = supportedFrameworkRanges.vite;
12
+
13
+ // Only stable releases are admitted. Void is pre-1.0, so its next minor
14
+ // requires explicit validation; Hono and Vite use their current major lines.
15
+ export function supportsFramework(name: keyof typeof supportedFrameworkRanges, version: unknown): boolean {
16
+ if (typeof version !== 'string') return false;
17
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version);
18
+ if (!match) return false;
19
+ const [major, minor, patch] = match.slice(1).map(Number);
20
+ if (![major, minor, patch].every(Number.isSafeInteger)) return false;
21
+ if (name === 'void') return major === 0 && ((minor === 26 && patch >= 1) || minor === 27);
22
+ if (name === 'hono') return major === 4 && (minor > 13 || (minor === 13 && patch >= 13));
23
+ return major === 8 && (minor > 0 || patch >= 16);
24
+ }
25
+ export const supportsVite = (version: unknown): boolean => supportsFramework('vite', version);
26
+
27
+ type PackageInfo = { version: string; path: string };
28
+ function packageInfo(name: string, require: NodeRequire): PackageInfo {
29
+ let directory = dirname(require.resolve(name));
30
+ while (true) {
31
+ const path = join(directory, 'package.json');
32
+ if (existsSync(path)) {
33
+ const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));
34
+ if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && (metadata.name === name || (name === 'vite' && metadata.name === '@voidzero-dev/vite-plus-core'))) {
35
+ if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing (${path}).`);
36
+ return { version: metadata.version, path };
20
37
  }
21
- const parent = dirname(directory);
22
- if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata.`);
23
- directory = parent;
24
38
  }
25
- if (version !== expected) throw new Error(`Hono Pages: ${name} ${version} is unverified; install ${name}@${expected}. The adapter requires void@0.26.1, hono@4.13.13 and vite@8.3.3.`);
39
+ const parent = dirname(directory);
40
+ if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata from ${require.resolve(name)}.`);
41
+ directory = parent;
42
+ }
43
+ }
44
+ function describe(name: string, require: NodeRequire): string {
45
+ try { const info = packageInfo(name, require); return `${info.path} (metadata ${info.version})`; }
46
+ catch { return `not resolved from ${require.resolve.paths(name)?.join(', ') ?? 'this context'}`; }
47
+ }
48
+
49
+ export function assertSupportedFrameworks({ root, viteVersion }: { root: string; viteVersion: unknown }) {
50
+ const adapter = createRequire(import.meta.url);
51
+ const project = createRequire(join(root, 'package.json'));
52
+ const diagnostic = () => `Running Vite from hook context: ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'}. Adapter helper Vite: ${helperViteVersion}; package.json: ${describe('vite', adapter)}. Project Vite package.json: ${describe('vite', project)}. Package paths are diagnostics, not the running Vite identity.`;
53
+ if (!supportsVite(viteVersion)) {
54
+ throw new Error(`Hono Pages: running Vite ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Update the CLI/launcher that executes Vite. For bundled launchers such as vp, installing project vite alone does not update the running Vite. For standard Vite, install vite@^8.3.4 and run vite directly.`);
55
+ }
56
+ if (!supportsVite(helperViteVersion)) {
57
+ throw new Error(`Hono Pages: adapter helper Vite ${helperViteVersion} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Inspect the adapter's resolved peer copy; install vite@^8.3.4 and refresh the adapter's peer resolution/lockfile if a stale copy remains.`);
58
+ }
59
+ for (const name of ['void', 'hono'] as const) {
60
+ const expected = supportedFrameworkRanges[name];
61
+ const info = packageInfo(name, adapter);
62
+ if (!supportsFramework(name, info.version)) throw new Error(`Hono Pages: ${name} ${info.version} is unsupported; install ${name}@"${expected}". Resolved package.json: ${info.path}. Project package.json: ${describe(name, project)}. ${diagnostic()}`);
26
63
  }
27
64
  }
@@ -1,4 +1,5 @@
1
1
  import { realpathSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
2
3
  import { normalizePath } from 'vite';
3
4
  import { pagesRuntimePath, clientRuntimePath, publicRuntimeModules } from './runtime-paths.ts';
4
5
  import { generateComponentManifest, resolvePagesDir, resolveStaticPageDataBuildOptions, scanPages, type PageScanResult } from 'void/pages';
@@ -10,7 +11,7 @@ import { assertSupportedFrameworks } from './compatibility.ts';
10
11
  const rendererId = 'virtual:void-pages-renderer';
11
12
  const clientId = 'virtual:void-pages-client';
12
13
 
13
- /** Experimental Pages contract verified against Void 0.26.1. */
14
+ /** Experimental Pages contract verified against Void 0.26.1 and 0.27.0. */
14
15
  export function voidHonoPages(): Plugin[] {
15
16
  const root = process.cwd();
16
17
  const pagesDir = resolvePagesDir(root);
@@ -36,8 +37,8 @@ export function voidHonoPages(): Plugin[] {
36
37
  return [honoIslands(), honoJsx(), {
37
38
  name: 'void-hono:pages',
38
39
  enforce: 'pre',
39
- config() {
40
- assertSupportedFrameworks();
40
+ config(config) {
41
+ assertSupportedFrameworks({ root: resolve(config.root ?? root), viteVersion: this?.meta?.viteVersion });
41
42
  return {
42
43
  resolve: { dedupe: ['hono'] },
43
44
  build: { manifest: true, rollupOptions: { input: { 'pages-client': clientId } } },