@barefootjs/hono 0.30.6 → 0.31.0
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/dist/adapter/hono-adapter.d.ts +43 -6
- package/dist/adapter/hono-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +44 -8
- package/dist/app.d.ts +11 -55
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +1 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -8
- package/dist/preload.d.ts +10 -1
- package/dist/preload.d.ts.map +1 -1
- package/dist/render.d.ts +1 -1
- package/dist/scripts.d.ts +76 -0
- package/dist/scripts.d.ts.map +1 -1
- package/dist/scripts.js +81 -17
- package/dist/vite.d.ts +37 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +2749 -0
- package/package.json +19 -11
- package/src/__tests__/scaffold.test.ts +9 -2
- package/src/__tests__/script-assets.test.ts +228 -0
- package/src/__tests__/vite.test.ts +144 -0
- package/src/adapter/hono-adapter.ts +134 -15
- package/src/app.ts +12 -73
- package/src/index.ts +1 -1
- package/src/preload.tsx +15 -2
- package/src/render.ts +1 -1
- package/src/scripts.tsx +136 -0
- package/src/vite.ts +210 -0
- package/dist/build.d.ts +0 -65
- package/dist/build.d.ts.map +0 -1
- package/dist/build.js +0 -188137
- package/dist/dev.d.ts +0 -36
- package/dist/dev.d.ts.map +0 -1
- package/dist/dev.js +0 -508
- package/src/__tests__/build.test.ts +0 -299
- package/src/__tests__/dev.test.tsx +0 -123
- package/src/__tests__/import-map.test.ts +0 -98
- package/src/build.ts +0 -230
- package/src/dev.tsx +0 -154
package/src/vite.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@barefootjs/hono/vite` — a Hono-specific COMPOSITION of core
|
|
3
|
+
* `@barefootjs/vite`'s `barefoot()`, mirroring `@barefootjs/go-template/
|
|
4
|
+
* vite`'s shape and naming (`barefoot`, named AND default export; a user
|
|
5
|
+
* never passes `adapter`, this constructs `HonoAdapter` itself).
|
|
6
|
+
*
|
|
7
|
+
* import { barefoot } from '@barefootjs/hono/vite'
|
|
8
|
+
*
|
|
9
|
+
* export default defineConfig({
|
|
10
|
+
* base: '/static/components/',
|
|
11
|
+
* build: { outDir: 'dist/static/components' },
|
|
12
|
+
* plugins: barefoot({
|
|
13
|
+
* components: ['src/components'],
|
|
14
|
+
* templates: 'dist/components',
|
|
15
|
+
* }),
|
|
16
|
+
* })
|
|
17
|
+
*
|
|
18
|
+
* ## Why this needs no `afterEmit`-driven combination step (unlike Go)
|
|
19
|
+
*
|
|
20
|
+
* `@barefootjs/go-template/vite` exists mainly to combine every discovered
|
|
21
|
+
* file's `types` fragment into ONE compilable `components.go` — Go's
|
|
22
|
+
* per-file fragments assume a shared `randomID` helper and a single package
|
|
23
|
+
* header, so they are not independently valid Go source (see that module's
|
|
24
|
+
* docstring). Hono's SSR marked template has no such constraint: `generate()`
|
|
25
|
+
* already emits a complete, self-contained `.tsx` file (its own imports,
|
|
26
|
+
* its own types inlined via `sections.types`) that wrangler/bun's own
|
|
27
|
+
* bundler compiles directly — there is nothing across files that needs
|
|
28
|
+
* stitching together. So this composition's core job is just what core's
|
|
29
|
+
* `barefoot()` already does: construct `HonoAdapter` and hand it to core.
|
|
30
|
+
*
|
|
31
|
+
* ## `assets` — the one thing this DOES need, mirroring go-template/vite
|
|
32
|
+
*
|
|
33
|
+
* A hand-written, non-component client bootstrap (e.g. this integration's
|
|
34
|
+
* `client/router-entry.ts`, which boots `@barefootjs/router`) isn't a
|
|
35
|
+
* `.tsx` component, so core's own discovery/`scriptAssets` machinery never
|
|
36
|
+
* sees it — but a plain `.tsx` SSR file (e.g. a blog layout) still needs a
|
|
37
|
+
* `<script src>` for it, and that URL is only knowable after Vite bundles it
|
|
38
|
+
* (dev: origin-based; build: manifest-hashed). `assets` resolves exactly
|
|
39
|
+
* that, into a generated TS module the SSR file can `import` — the
|
|
40
|
+
* TypeScript analogue of `@barefootjs/go-template/vite`'s generated
|
|
41
|
+
* `bf_assets.go`. See that module's docstring for the full "why a
|
|
42
|
+
* companion config-capture plugin" rationale (`afterEmit`'s
|
|
43
|
+
* `AfterEmitContext` is deliberately narrow — no `ResolvedConfig`, no dev
|
|
44
|
+
* origin, no manifest — so a tiny second plugin captures those via its own
|
|
45
|
+
* `configResolved`/`configureServer` hooks for `afterEmit`, in the same
|
|
46
|
+
* closure, to read).
|
|
47
|
+
*/
|
|
48
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
49
|
+
import { dirname, resolve } from 'node:path'
|
|
50
|
+
import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'
|
|
51
|
+
import { barefoot as coreBarefoot } from '@barefootjs/vite'
|
|
52
|
+
import type { AfterEmitContext } from '@barefootjs/vite'
|
|
53
|
+
import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPosixRelative } from '@barefootjs/vite'
|
|
54
|
+
import { HonoAdapter } from './adapter/index.ts'
|
|
55
|
+
import type { HonoAdapterOptions } from './adapter/index.ts'
|
|
56
|
+
|
|
57
|
+
export interface HonoViteOptions {
|
|
58
|
+
/** Source directories to scan for `.tsx` components, relative to the
|
|
59
|
+
* Vite project root (or absolute). */
|
|
60
|
+
components: string[]
|
|
61
|
+
/** Where compiled SSR templates (and `ssrDefaults`) land — relative to
|
|
62
|
+
* the Vite project root (or absolute). This is a backend source
|
|
63
|
+
* directory wrangler/bun's own bundler reads, NOT `build.outDir` (Vite's
|
|
64
|
+
* client-asset output). */
|
|
65
|
+
templates: string
|
|
66
|
+
/** Adapter-specific options passed to `HonoAdapter` (e.g. `clientJsFilename`). */
|
|
67
|
+
adapterOptions?: HonoAdapterOptions
|
|
68
|
+
/**
|
|
69
|
+
* Extra, non-component script entries whose Vite-resolved URL (dev:
|
|
70
|
+
* origin-based; production: content-hashed manifest path) should be
|
|
71
|
+
* exposed to the SSR app as a generated `Assets` map — e.g. a
|
|
72
|
+
* hand-written client bootstrap script that isn't a `.tsx` component, so
|
|
73
|
+
* it never goes through core's discovery/`scriptAssets` machinery, but
|
|
74
|
+
* still needs a `<script src="...">` URL only knowable after bundling.
|
|
75
|
+
*
|
|
76
|
+
* Keyed by the identifier the resolved URL should appear under in the
|
|
77
|
+
* generated map; values are entry paths relative to the Vite project
|
|
78
|
+
* root. You must ALSO register the same path as a Rollup entry yourself
|
|
79
|
+
* via stock `build.rollupOptions.input` — this plugin never adds
|
|
80
|
+
* bundling configuration on your behalf; this option only resolves the
|
|
81
|
+
* URL Vite already bundled it to, it doesn't request the bundling.
|
|
82
|
+
*/
|
|
83
|
+
assets?: Record<string, string>
|
|
84
|
+
/** Output path for the generated asset-map TS module, relative to the
|
|
85
|
+
* Vite project root. Default: 'dist/bf-assets.ts'. Ignored when `assets`
|
|
86
|
+
* is empty. */
|
|
87
|
+
assetsOutputFile?: string
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** write-if-changed: writes `content` to `absPath` only if it differs from
|
|
91
|
+
* what's already there, logging `label` when it actually wrote. Avoids
|
|
92
|
+
* touching mtime (and so falsely tripping a file watcher, e.g. wrangler's
|
|
93
|
+
* own dev rebuild) on a pass that produced byte-identical output. */
|
|
94
|
+
async function writeIfChanged(absPath: string, content: string, label: string): Promise<void> {
|
|
95
|
+
const prev = await readFile(absPath, 'utf-8').catch(() => null)
|
|
96
|
+
if (prev === content) return
|
|
97
|
+
// Unlike `@barefootjs/go-template/vite`'s `bf_assets.go` (project root by
|
|
98
|
+
// default), this plugin's default `assetsOutputFile` lives under `dist/`
|
|
99
|
+
// — a directory `vite build` may not have created yet on a clean
|
|
100
|
+
// checkout (nothing else in this plugin writes there before `afterEmit`
|
|
101
|
+
// runs), so ensure it exists before writing.
|
|
102
|
+
await mkdir(dirname(absPath), { recursive: true })
|
|
103
|
+
await writeFile(absPath, content)
|
|
104
|
+
console.log(`Generated: ${label}`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Resolves ONE asset entry's URL for the current pass: manifest-hashed for
|
|
108
|
+
* `mode: 'build'`, dev-origin-based for `mode: 'dev'`. Throws with an
|
|
109
|
+
* actionable message when the entry isn't in the build manifest — almost
|
|
110
|
+
* always means the caller forgot to also add it to
|
|
111
|
+
* `build.rollupOptions.input`. */
|
|
112
|
+
function resolveAssetUrl(
|
|
113
|
+
ctx: AfterEmitContext,
|
|
114
|
+
config: ResolvedConfig,
|
|
115
|
+
devServer: ViteDevServer | undefined,
|
|
116
|
+
entryRelPath: string,
|
|
117
|
+
manifest: Record<string, { file: string }> | undefined,
|
|
118
|
+
): string {
|
|
119
|
+
const absPath = resolve(ctx.projectDir, entryRelPath)
|
|
120
|
+
if (ctx.mode === 'dev') {
|
|
121
|
+
if (!devServer) throw new Error(`[hono/vite] asset "${entryRelPath}": dev server not ready`)
|
|
122
|
+
return devModuleUrl(config, resolveDevOrigin(devServer), absPath)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const manifestKey = toPosixRelative(config.root, absPath)
|
|
126
|
+
const [url] = resolveScriptAssets(manifest ?? {}, manifestKey, config.base)
|
|
127
|
+
if (!url) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`[hono/vite] asset "${entryRelPath}" was not found in the build manifest. ` +
|
|
130
|
+
`Did you also add it to build.rollupOptions.input?`,
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
return url
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Builds and write-if-changed's the generated TS asset map. No-op when
|
|
137
|
+
* `assets` is empty. */
|
|
138
|
+
async function writeAssetMap(
|
|
139
|
+
ctx: AfterEmitContext,
|
|
140
|
+
config: ResolvedConfig,
|
|
141
|
+
devServer: ViteDevServer | undefined,
|
|
142
|
+
assets: Record<string, string>,
|
|
143
|
+
assetsOutputFile: string,
|
|
144
|
+
): Promise<void> {
|
|
145
|
+
const keys = Object.keys(assets)
|
|
146
|
+
if (keys.length === 0) return
|
|
147
|
+
|
|
148
|
+
const manifest = ctx.mode === 'build' ? await loadManifest(ctx.outDir, config.build.manifest) : undefined
|
|
149
|
+
|
|
150
|
+
const entries = keys
|
|
151
|
+
.map(name => ` ${JSON.stringify(name)}: ${JSON.stringify(resolveAssetUrl(ctx, config, devServer, assets[name]!, manifest))},`)
|
|
152
|
+
.join('\n')
|
|
153
|
+
|
|
154
|
+
const content = [
|
|
155
|
+
`// Code generated by BarefootJS. DO NOT EDIT.`,
|
|
156
|
+
'',
|
|
157
|
+
`/**`,
|
|
158
|
+
` * Maps a logical asset name (this map's key) to its resolved URL for`,
|
|
159
|
+
` * the current build: a Vite dev-server origin URL in dev, a`,
|
|
160
|
+
` * content-hashed manifest path in production. Regenerated by`,
|
|
161
|
+
` * @barefootjs/hono/vite's afterEmit hook every time templates are`,
|
|
162
|
+
` * (re)emitted.`,
|
|
163
|
+
` */`,
|
|
164
|
+
`export const Assets: Record<string, string> = {`,
|
|
165
|
+
entries,
|
|
166
|
+
`}`,
|
|
167
|
+
].join('\n') + '\n'
|
|
168
|
+
|
|
169
|
+
await writeIfChanged(resolve(ctx.projectDir, assetsOutputFile), content, assetsOutputFile)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function barefoot(options: HonoViteOptions): Plugin[] {
|
|
173
|
+
const assets = options.assets ?? {}
|
|
174
|
+
const assetsOutputFile = options.assetsOutputFile ?? 'dist/bf-assets.ts'
|
|
175
|
+
|
|
176
|
+
// Populated by `honoAssetsConfigCapture` below (only added to the
|
|
177
|
+
// returned array when `assets` is non-empty). Read by `afterEmit` — see
|
|
178
|
+
// `@barefootjs/go-template/vite`'s identical mechanism for the ordering
|
|
179
|
+
// guarantee (`configResolved`/`configureServer` always run before the
|
|
180
|
+
// eager pass that triggers `afterEmit`, for both build and dev).
|
|
181
|
+
let resolvedConfig: ResolvedConfig | undefined
|
|
182
|
+
let devServer: ViteDevServer | undefined
|
|
183
|
+
|
|
184
|
+
const core = coreBarefoot({
|
|
185
|
+
adapter: new HonoAdapter(options.adapterOptions),
|
|
186
|
+
components: options.components,
|
|
187
|
+
templates: options.templates,
|
|
188
|
+
async afterEmit(ctx) {
|
|
189
|
+
if (Object.keys(assets).length > 0 && resolvedConfig) {
|
|
190
|
+
await writeAssetMap(ctx, resolvedConfig, devServer, assets, assetsOutputFile)
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
if (Object.keys(assets).length === 0) return [core]
|
|
196
|
+
|
|
197
|
+
const honoAssetsConfigCapture: Plugin = {
|
|
198
|
+
name: 'barefoot-hono-assets-config-capture',
|
|
199
|
+
configResolved(config) {
|
|
200
|
+
resolvedConfig = config
|
|
201
|
+
},
|
|
202
|
+
configureServer(server) {
|
|
203
|
+
devServer = server
|
|
204
|
+
},
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return [core, honoAssetsConfigCapture]
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { barefoot as default }
|
package/dist/build.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { BuildOptions } from '@barefootjs/jsx';
|
|
2
|
-
import { HonoAdapter } from './adapter/index.ts';
|
|
3
|
-
import type { HonoAdapterOptions } from './adapter/index.ts';
|
|
4
|
-
export interface HonoBuildOptions extends BuildOptions {
|
|
5
|
-
/** Inject Hono script collection wrapper (default: true) */
|
|
6
|
-
scriptCollection?: boolean;
|
|
7
|
-
/** Base path for client JS script URLs (default: '/static/components/') */
|
|
8
|
-
scriptBasePath?: string;
|
|
9
|
-
/** Adapter-specific options passed to HonoAdapter */
|
|
10
|
-
adapterOptions?: HonoAdapterOptions;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Create a BarefootBuildConfig for Hono projects.
|
|
14
|
-
*
|
|
15
|
-
* Uses structural typing — does not import BarefootBuildConfig to avoid
|
|
16
|
-
* circular dependency between @barefootjs/hono and @barefootjs/cli.
|
|
17
|
-
*/
|
|
18
|
-
export declare function createConfig(options?: HonoBuildOptions): {
|
|
19
|
-
adapter: HonoAdapter;
|
|
20
|
-
paths: import("@barefootjs/jsx").BarefootPaths | undefined;
|
|
21
|
-
components: string[] | undefined;
|
|
22
|
-
outDir: string | undefined;
|
|
23
|
-
minify: boolean | undefined;
|
|
24
|
-
contentHash: boolean | undefined;
|
|
25
|
-
externals: Record<string, import("@barefootjs/jsx").ExternalSpec> | undefined;
|
|
26
|
-
externalsBasePath: string | undefined;
|
|
27
|
-
bundleEntries: import("@barefootjs/jsx").BundleEntry[] | undefined;
|
|
28
|
-
localImportPrefixes: string[] | undefined;
|
|
29
|
-
transformMarkedTemplate: ((content: string, componentId: string, clientJsPath: string) => string) | undefined;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Add Hono script collection wrapper to an SSR marked template.
|
|
33
|
-
* Injects imports, a helper function, and script collector into each
|
|
34
|
-
* exported component function.
|
|
35
|
-
*/
|
|
36
|
-
export declare function addScriptCollection(content: string, componentId: string, clientJsPath: string, scriptBasePath?: string): string;
|
|
37
|
-
/**
|
|
38
|
-
* Replace comment contents with spaces (preserving length and newlines
|
|
39
|
-
* so indices computed against the masked text are valid in the
|
|
40
|
-
* original). Used by `addScriptCollection` so its `function Foo(`
|
|
41
|
-
* regex ignores JSDoc / inline comments — a docstring example like
|
|
42
|
-
* `function MyNode(this: HTMLElement, props)` previously masqueraded
|
|
43
|
-
* as a real function declaration (#1236).
|
|
44
|
-
*
|
|
45
|
-
* Handles `//` line comments and `/* ... *\/` block comments (incl.
|
|
46
|
-
* JSDoc). String literals are intentionally NOT masked: JSX text
|
|
47
|
-
* content routinely contains unbalanced apostrophes (`How's`) that a
|
|
48
|
-
* string-aware masker would misread as an open quote, blanking the
|
|
49
|
-
* rest of the file and hiding later function declarations.
|
|
50
|
-
*
|
|
51
|
-
* Strings inside comments are handled implicitly: the whole comment
|
|
52
|
-
* (including any quotes it contains) is blanked.
|
|
53
|
-
*
|
|
54
|
-
* **Known limitation**: this function does NOT track string
|
|
55
|
-
* boundaries, so a `//` or `/*` appearing INSIDE a string literal is
|
|
56
|
-
* still treated as a comment delimiter. Example: in
|
|
57
|
-
* `const u = "https://x.y" ; export function Foo() {}` the `//` in
|
|
58
|
-
* `https://` is misread as a line comment and the rest of the line is
|
|
59
|
-
* blanked — a `function Foo()` on that same line would be hidden from
|
|
60
|
-
* the regex. SSR template output (the only caller) does not embed
|
|
61
|
-
* such cases in practice. If a future caller can produce them, swap
|
|
62
|
-
* in a real lexer rather than extending this helper.
|
|
63
|
-
*/
|
|
64
|
-
export declare function maskComments(s: string): string;
|
|
65
|
-
//# sourceMappingURL=build.d.ts.map
|
package/dist/build.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,qDAAqD;IACrD,cAAc,CAAC,EAAE,kBAAkB,CAAA;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB;IAIvD,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;IACT,iBAAiB;IACjB,aAAa;IACb,mBAAmB;IACnB,uBAAuB,aACT,MAAM,eAAe,MAAM,gBAAgB,MAAM;EAIlE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,GAAE,MAA8B,GAAG,MAAM,CAiItJ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAwB9C"}
|