@barefootjs/vite 0.30.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.
Files changed (61) hide show
  1. package/dist/child-marker.d.ts +62 -0
  2. package/dist/child-marker.d.ts.map +1 -0
  3. package/dist/compile-cache.d.ts +19 -0
  4. package/dist/compile-cache.d.ts.map +1 -0
  5. package/dist/component-manifest.d.ts +69 -0
  6. package/dist/component-manifest.d.ts.map +1 -0
  7. package/dist/corpus-program.d.ts +41 -0
  8. package/dist/corpus-program.d.ts.map +1 -0
  9. package/dist/debounced-serial-runner.d.ts +27 -0
  10. package/dist/debounced-serial-runner.d.ts.map +1 -0
  11. package/dist/dev-server.d.ts +99 -0
  12. package/dist/dev-server.d.ts.map +1 -0
  13. package/dist/discover.d.ts +117 -0
  14. package/dist/discover.d.ts.map +1 -0
  15. package/dist/emit.d.ts +9 -0
  16. package/dist/emit.d.ts.map +1 -0
  17. package/dist/index.d.ts +8 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +24626 -0
  20. package/dist/manifest.d.ts +39 -0
  21. package/dist/manifest.d.ts.map +1 -0
  22. package/dist/paths.d.ts +57 -0
  23. package/dist/paths.d.ts.map +1 -0
  24. package/dist/plugin.d.ts +5 -0
  25. package/dist/plugin.d.ts.map +1 -0
  26. package/dist/resolve-client-js.d.ts +6 -0
  27. package/dist/resolve-client-js.d.ts.map +1 -0
  28. package/dist/types.d.ts +141 -0
  29. package/dist/types.d.ts.map +1 -0
  30. package/package.json +55 -0
  31. package/src/__tests__/child-marker.test.ts +24 -0
  32. package/src/__tests__/compile-cache.test.ts +73 -0
  33. package/src/__tests__/component-dir-entry.test.ts +239 -0
  34. package/src/__tests__/component-manifest.test.ts +124 -0
  35. package/src/__tests__/corpus-program.test.ts +244 -0
  36. package/src/__tests__/debounced-serial-runner.test.ts +131 -0
  37. package/src/__tests__/dev-server.test.ts +138 -0
  38. package/src/__tests__/discover.test.ts +148 -0
  39. package/src/__tests__/e2e-vite-build.test.ts +191 -0
  40. package/src/__tests__/e2e-vite-dev.test.ts +478 -0
  41. package/src/__tests__/emit.test.ts +73 -0
  42. package/src/__tests__/manifest.test.ts +146 -0
  43. package/src/__tests__/paths.test.ts +93 -0
  44. package/src/__tests__/plugin.test.ts +417 -0
  45. package/src/__tests__/relative-import-rewrite.test.ts +79 -0
  46. package/src/__tests__/resolve-client-js.test.ts +55 -0
  47. package/src/__tests__/templates-optional.test.ts +139 -0
  48. package/src/child-marker.ts +67 -0
  49. package/src/compile-cache.ts +63 -0
  50. package/src/component-manifest.ts +139 -0
  51. package/src/corpus-program.ts +125 -0
  52. package/src/debounced-serial-runner.ts +67 -0
  53. package/src/dev-server.ts +184 -0
  54. package/src/discover.ts +230 -0
  55. package/src/emit.ts +66 -0
  56. package/src/index.ts +25 -0
  57. package/src/manifest.ts +89 -0
  58. package/src/paths.ts +114 -0
  59. package/src/plugin.ts +792 -0
  60. package/src/resolve-client-js.ts +34 -0
  61. package/src/types.ts +144 -0
@@ -0,0 +1,39 @@
1
+ import type { Manifest } from 'vite';
2
+ /** Read and parse the manifest Vite just wrote to `outDir`. `manifestOption`
3
+ * mirrors `build.manifest`: `true` → the default `.vite/manifest.json`
4
+ * path; a string → that custom path, relative to `outDir`. */
5
+ export declare function loadManifest(outDir: string, manifestOption: boolean | string): Promise<Manifest>;
6
+ /** Join a Vite `base` (may or may not have a trailing slash; may be a full
7
+ * URL, an absolute path, or `'./'`) with a manifest-relative file path
8
+ * (never starts with `/`) into the URL an adapter should register. */
9
+ export declare function joinBaseAndFile(base: string, file: string): string;
10
+ /**
11
+ * The ordered `scriptAssets` list for one component's entry, per the
12
+ * design: just the entry's own hashed file — shared chunks (including the
13
+ * `@barefootjs/client` runtime) arrive as ESM imports the browser follows
14
+ * on its own, so they need no separate registration. `[]` when the entry
15
+ * isn't in the manifest (e.g. a `'use client'` file whose compile produced
16
+ * no client JS at all, or a stale discovery/build mismatch).
17
+ */
18
+ export declare function resolveScriptAssets(manifest: Manifest, manifestKey: string, base: string): string[];
19
+ /**
20
+ * The ordered `preloadAssets` list for one component's entry: every chunk
21
+ * the entry pulls in **transitively** via static `imports`, excluding the
22
+ * entry's own file (that one is already covered by `resolveScriptAssets`).
23
+ *
24
+ * Walked **breadth-first** from the entry so the chunks most likely to be
25
+ * shared across components (the runtime chunk, common child islands) sort
26
+ * first, and deduped by manifest key — both needed to keep the returned
27
+ * order deterministic across builds; a rebuild that reshuffles this list
28
+ * for no reason would show up as a spurious template diff. A `seen` set
29
+ * keyed by manifest key also guards against import cycles.
30
+ *
31
+ * Deliberately does NOT follow `dynamicImports`: a dynamic import is by
32
+ * definition not needed for first paint — the app chose to defer it — and
33
+ * preloading it would pull that deferred work forward, defeating the
34
+ * point of having split it out.
35
+ *
36
+ * `[]` when the entry isn't in the manifest, same as `resolveScriptAssets`.
37
+ */
38
+ export declare function resolvePreloadAssets(manifest: Manifest, manifestKey: string, base: string): string[];
39
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAA;AAEpC;;8DAE8D;AAC9D,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAItG;AAED;;sEAEsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAIV;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CAmBV"}
@@ -0,0 +1,57 @@
1
+ /** Posix-normalized path of `absPath` relative to `root` (manifest keys and
2
+ * Rollup `input` specifiers both want forward slashes regardless of OS). */
3
+ export declare function toPosixRelative(root: string, absPath: string): string;
4
+ /**
5
+ * A `rollupOptions.input` OBJECT KEY safe for `absPath`, given the Vite
6
+ * project root — NOT the same thing as a manifest lookup key (Vite's own
7
+ * manifest is keyed by the source file's root-relative path regardless of
8
+ * what name you give an entry here; see `manifest.ts` / `writeBundle` in
9
+ * `plugin.ts`, which never call this and must not start).
10
+ *
11
+ * Rollup uses an object-form `input`'s key AS THE CHUNK NAME (the `[name]`
12
+ * substitution in `output.entryFileNames`), and REJECTS a name that is
13
+ * itself an absolute or parent-relative path outright
14
+ * (`Invalid substitution "…" for placeholder "[name]"`) — which
15
+ * `toPosixRelative(root, absPath)` produces whenever `absPath` is OUTSIDE
16
+ * `root`, exactly the common case this monorepo's real layouts hit (a
17
+ * `components` dir that's a SIBLING of, not a descendant of, the app's
18
+ * Vite root — see `plugin.ts`'s `configureServer` docstring for the same
19
+ * layout fact from the dev side). Falls back to `absPath`'s position under
20
+ * whichever configured `componentDirs` entry contains it (the same
21
+ * mirroring `relativeUnderComponentDir` already does for emitted template
22
+ * paths) — short and readable (`blog/LikeButton`), unlike falling all the
23
+ * way back to the bare filesystem-rooted absolute path, which would work
24
+ * (no `..` possible once `path.resolve()`-normalized) but bakes the
25
+ * building machine's own directory structure into every output filename.
26
+ */
27
+ export declare function safeRollupEntryName(root: string, absPath: string, componentDirs: readonly string[]): string;
28
+ /**
29
+ * `absPath`'s position relative to whichever `componentDirs` entry
30
+ * contains it (POSIX, WITH extension) — e.g. `ui/button/index.tsx` for
31
+ * `<componentDir>/ui/button/index.tsx`. Falls back to the bare basename
32
+ * when the file isn't under any configured dir (shouldn't happen for
33
+ * discovered files, but keeps this total).
34
+ */
35
+ export declare function relativeUnderComponentDir(absPath: string, componentDirs: readonly string[]): string;
36
+ /** Swap `.tsx`/`.ts` for `newExtension` (e.g. adapter.extension, or
37
+ * `.ssr-defaults.json`) on a POSIX relative path. */
38
+ export declare function withExtension(relPath: string, newExtension: string): string;
39
+ /**
40
+ * Output path (relative to `templatesDir`, still POSIX) for a
41
+ * `templatesPerComponent` adapter's per-component file — same directory as
42
+ * the source file's mirror, named after the exported component instead of
43
+ * the source basename (Mojolicious-style template lookup by component
44
+ * name).
45
+ */
46
+ export declare function perComponentRelPath(relUnderComponentDir: string, componentName: string, extension: string): string;
47
+ /**
48
+ * Build a `rewriteRelativeImport` function for `compileJSX` — re-anchors a
49
+ * relative specifier written in `sourcePath` so it still resolves once the
50
+ * template is emitted to `outputPath` under `templatesDir` instead of
51
+ * living beside its source. Implemented standalone for the reason in this
52
+ * file's header comment. Only exercised by adapters whose templates carry
53
+ * real `import` statements (Hono-shaped JS-runtime adapters) — Go/Mojo/etc.
54
+ * templates have no import syntax and never call this.
55
+ */
56
+ export declare function buildRelativeImportRewriter(sourcePath: string, outputPath: string, componentDirs: readonly string[], templatesDir: string): (importPath: string) => string;
57
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAUA;4EAC4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI3G;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAQnG;AAED;qDACqD;AACrD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGlH;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,YAAY,EAAE,MAAM,GACnB,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAmBhC"}
@@ -0,0 +1,5 @@
1
+ import type { Plugin } from 'vite';
2
+ import type { BarefootViteOptions } from './types.ts';
3
+ export declare const PLUGIN_NAME = "barefoot";
4
+ export declare function barefoot(options: BarefootViteOptions): Plugin;
5
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAkEA,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAA;AAMjE,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,YAAY,CAAA;AA+BxE,eAAO,MAAM,WAAW,aAAa,CAAA;AAuCrC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAyoB7D"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Resolve `source` (an import specifier seen by Vite's `resolveId`) to the
3
+ * real `.tsx` file it stands in for, or `null` if this shim doesn't apply.
4
+ */
5
+ export declare function resolveClientJsSpecifier(source: string, importer: string | undefined): string | null;
6
+ //# sourceMappingURL=resolve-client-js.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-client-js.d.ts","sourceRoot":"","sources":["../src/resolve-client-js.ts"],"names":[],"mappings":"AAqBA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQpG"}
@@ -0,0 +1,141 @@
1
+ import type { TemplateAdapter } from '@barefootjs/jsx';
2
+ /**
3
+ * Narrow context handed to `afterEmit` once per eager pass (`writeBundle`
4
+ * for `vite build`, the dev pass for `vite dev`) — AFTER every discovered
5
+ * component's template has already been written to `templatesDir`. This is
6
+ * the one escape hatch this plugin exposes, and its shape is deliberately
7
+ * minimal:
8
+ *
9
+ * - `types`: adapter-generated `types` fragments (e.g. Go Props structs)
10
+ * this pass produced, keyed by the source file's absolute path. Raw,
11
+ * per-file, uncombined — combining them into a single backend-native
12
+ * file (stripping headers, deduping, injecting shared helpers) is a
13
+ * real per-language operation an adapter's own `/vite` subpath performs
14
+ * (see `@barefootjs/go-template/vite`'s use of `combineGoTypes`), not
15
+ * something core knows how to do generically.
16
+ * - `projectDir` / `templatesDir` / `outDir`: the same absolute paths the
17
+ * plugin itself just used to write templates and (for `outDir`) that
18
+ * Vite wrote client assets to.
19
+ * - `mode`: which eager pass just ran. Go's `components.go` (and any other
20
+ * adapter-side derived file) has to exist for `go run .` to even compile
21
+ * in dev, which is why this fires from BOTH passes, not just the build
22
+ * one — a hook named `postBuild` would misleadingly suggest otherwise.
23
+ *
24
+ * What this deliberately does NOT carry: emitted client JS. That's the
25
+ * one thing a caller must never be handed to rewrite post-compile (see
26
+ * CLAUDE.md's "never add compiler options/hooks for tool-specific output
27
+ * rewriting") — closing that door by TYPE, not by convention, is the
28
+ * point of keeping this context this narrow.
29
+ */
30
+ export interface AfterEmitContext {
31
+ /** Per-source-file `types` output, keyed by that file's absolute path.
32
+ * Empty when no discovered file in this pass produced a `types` output. */
33
+ types: Map<string, string>;
34
+ /** Absolute path to the Vite project root. */
35
+ projectDir: string;
36
+ /** Absolute path to the configured `templates` output dir. */
37
+ templatesDir: string;
38
+ /** Absolute path to Vite's configured `build.outDir`. */
39
+ outDir: string;
40
+ /** Which eager pass just ran. */
41
+ mode: 'build' | 'dev';
42
+ }
43
+ /**
44
+ * One `components` entry with per-directory compile behavior. A plain
45
+ * string is exactly equivalent to `{ dir: string }` — see
46
+ * `BarefootViteOptions.components`.
47
+ */
48
+ export interface ComponentDirEntry {
49
+ /** Source directory to scan, relative to the Vite root (or absolute). */
50
+ dir: string;
51
+ /** `CompileOptions.cssLayerPrefix` for every component under `dir`:
52
+ * static class strings get `layer-{value}:` prefixes so a library's
53
+ * base classes land in a lower cascade layer than app overrides. Set
54
+ * it on library entries, leave it off app entries. */
55
+ cssLayerPrefix?: string;
56
+ /** Directory NAMES to skip anywhere under `dir` (e.g. `['shared']`). */
57
+ skipDirs?: string[];
58
+ }
59
+ /**
60
+ * Public options for the `barefoot()` Vite plugin. Exactly three
61
+ * BarefootJS-specific FIELDS — everything else (bundling, hashing,
62
+ * chunking, tree-shaking, minification, dev server, `base`, `outDir`) is
63
+ * stock Vite config. Do not add more fields here; see the design doc for
64
+ * the full list of options this deliberately drops in favor of Vite's own
65
+ * equivalents (`minify` → `build.minify`, `externals` → Rollup's automatic
66
+ * chunk splitting, `clientJsBasePath`/`barefootJsPath` → `base` + manifest
67
+ * resolution, etc).
68
+ *
69
+ * The cap is on FIELDS, not on per-directory expressiveness: whether a
70
+ * directory's classes need a CSS cascade layer, or which subdirectories to
71
+ * skip, is a function of WHICH `components` entry a file came from — so
72
+ * that behavior rides on the `components` entries themselves
73
+ * (`ComponentDirEntry`) rather than becoming a 4th/5th top-level option.
74
+ */
75
+ export interface BarefootViteOptions {
76
+ /** A constructed `TemplateAdapter` instance (e.g. `new
77
+ * GoTemplateAdapter({ packageName: 'main' })`). Not a factory function —
78
+ * the plugin never constructs adapters itself. */
79
+ adapter: TemplateAdapter;
80
+ /** Source directories to scan for `.tsx` components, relative to the
81
+ * Vite project root (or absolute). A plain string is exactly equivalent
82
+ * to `{ dir: string }` (a `ComponentDirEntry` with no `cssLayerPrefix`/
83
+ * `skipDirs`) — use the object form only when a directory needs one of
84
+ * those. Entries are processed in array order, and that order is also
85
+ * the precedence when the same file is reachable under more than one
86
+ * entry: the first entry wins. */
87
+ components: (string | ComponentDirEntry)[];
88
+ /**
89
+ * Where compiled templates, `ssrDefaults`, and adapter-generated types
90
+ * land — relative to the Vite project root (or absolute). This is a
91
+ * backend source directory the server-side app reads, NOT
92
+ * `build.outDir` (which is Vite's client-asset output).
93
+ *
94
+ * Optional for an adapter whose `generate()` output is ALWAYS empty
95
+ * (e.g. `CSRAdapter` — CSR has no template-language backend to point a
96
+ * `templates` dir at). When omitted, the eager pass still compiles every
97
+ * discovered component (client JS generation is unaffected) but writes
98
+ * nothing to disk on its behalf — no per-component template/ssrDefaults/
99
+ * types files, no `manifest.json`. If some discovered component turns
100
+ * out to produce a REAL (non-empty) template anyway, the eager pass
101
+ * refuses loudly instead of silently dropping it: omitting `templates`
102
+ * is a claim about the adapter's output that this plugin verifies rather
103
+ * than trusts. See `plugin.ts`'s `assertNoRealTemplateOutput`.
104
+ */
105
+ templates?: string;
106
+ /**
107
+ * Optional escape hatch called once per eager pass (build AND dev), after
108
+ * templates are written, with a narrow `AfterEmitContext`. NOT a
109
+ * user-facing 4th option in the design-doc sense — it exists so an
110
+ * adapter's own `/vite` subpath (e.g. `@barefootjs/go-template/vite`) can
111
+ * wire up its own per-language post-processing (e.g. combining `types`
112
+ * into a single `components.go`) while calling this core plugin
113
+ * underneath. See `AfterEmitContext`'s docstring for what it can and
114
+ * cannot see.
115
+ */
116
+ afterEmit?: (ctx: AfterEmitContext) => Promise<void> | void;
117
+ }
118
+ /**
119
+ * Shape exposed on the returned plugin's `.api` — Vite's own convention
120
+ * (a plugin may attach an `api` property "designed for other plugins or
121
+ * Vite-based tools to access") for exactly this: tooling that wants this
122
+ * plugin's resolved options without re-deriving them from `vite.config.ts`
123
+ * text. The `bf` CLI (`packages/cli/src/context.ts`) is the one consumer
124
+ * today — it uses Vite's own `loadConfigFromFile` to get the resolved
125
+ * config, finds the plugin by name (`PLUGIN_NAME`, exported from
126
+ * `plugin.ts`) in its `plugins` array, and reads `api.options.components`
127
+ * as `sourceDirs`.
128
+ *
129
+ * Populated synchronously the moment `barefoot(options)` is called —
130
+ * `options` needs no Vite lifecycle hook to have already run, deliberately:
131
+ * `loadConfigFromFile` never calls a plugin's hooks (`config`,
132
+ * `configResolved`, ...) at all, it just evaluates `vite.config.ts` and
133
+ * returns the resulting plugin instances, so anything gated behind
134
+ * `configResolved` (e.g. the plugin's own resolved absolute `componentDirs`)
135
+ * would never be visible to a caller going through that path.
136
+ */
137
+ export interface BarefootPluginApi {
138
+ /** The exact options object `barefoot()` was constructed with. */
139
+ options: BarefootViteOptions;
140
+ }
141
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,gBAAgB;IAC/B;+EAC2E;IAC3E,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1B,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAA;IACpB,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAA;IACd,iCAAiC;IACjC,IAAI,EAAE,OAAO,GAAG,KAAK,CAAA;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAA;IACX;;;2DAGuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,mBAAmB;IAClC;;sDAEkD;IAClD,OAAO,EAAE,eAAe,CAAA;IACxB;;;;;;sCAMkC;IAClC,UAAU,EAAE,CAAC,MAAM,GAAG,iBAAiB,CAAC,EAAE,CAAA;IAC1C;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC5D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,OAAO,EAAE,mBAAmB,CAAA;CAC7B"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@barefootjs/vite",
3
+ "version": "0.30.0",
4
+ "description": "Vite plugin for BarefootJS: Vite/Rollup owns bundling, hashing, chunking, tree-shaking and minification of client assets, BarefootJS keeps only the JSX to (template, client JS) compile",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src"
17
+ ],
18
+ "scripts": {
19
+ "build": "bun run build:js && bun run build:types",
20
+ "build:js": "bun build ./src/index.ts --outfile ./dist/index.js --format esm --target node --external vite --external typescript",
21
+ "build:types": "tsgo --emitDeclarationOnly --outDir ./dist",
22
+ "test": "bun test",
23
+ "clean": "rm -rf dist",
24
+ "prepack": "node ../../scripts/swap-publish-config.mjs pack",
25
+ "postpack": "node ../../scripts/swap-publish-config.mjs unpack"
26
+ },
27
+ "keywords": [
28
+ "vite",
29
+ "vite-plugin",
30
+ "barefoot",
31
+ "ssr"
32
+ ],
33
+ "author": "kobaken <kentafly88@gmail.com>",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/piconic-ai/barefootjs",
38
+ "directory": "packages/vite"
39
+ },
40
+ "dependencies": {
41
+ "@barefootjs/shared": "0.30.6"
42
+ },
43
+ "peerDependencies": {
44
+ "@barefootjs/jsx": ">=0.2.0",
45
+ "vite": "^6.0.0"
46
+ },
47
+ "devDependencies": {
48
+ "@barefootjs/client": "0.30.6",
49
+ "@barefootjs/go-template": "0.30.6",
50
+ "@barefootjs/hono": "0.30.6",
51
+ "@barefootjs/jsx": "0.30.6",
52
+ "typescript": "^5.0.0",
53
+ "vite": "^6.0.0"
54
+ }
55
+ }
@@ -0,0 +1,24 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+ import { bfChildMarkerName, BF_CHILD_NOOP_ID } from '../child-marker.ts'
3
+
4
+ describe('bfChildMarkerName', () => {
5
+ test('extracts the child name from a compiler-emitted marker', () => {
6
+ expect(bfChildMarkerName('/* @bf-child:TodoItem */')).toBe('TodoItem')
7
+ })
8
+
9
+ test('returns null for a normal specifier', () => {
10
+ expect(bfChildMarkerName('./TodoItem')).toBeNull()
11
+ expect(bfChildMarkerName('@barefootjs/client')).toBeNull()
12
+ })
13
+
14
+ test('returns null for a marker-shaped string with extra characters', () => {
15
+ expect(bfChildMarkerName('/* @bf-child:TodoItem */extra')).toBeNull()
16
+ expect(bfChildMarkerName('prefix/* @bf-child:TodoItem */')).toBeNull()
17
+ })
18
+ })
19
+
20
+ describe('BF_CHILD_NOOP_ID', () => {
21
+ test('is a virtual (null-byte-prefixed) module id', () => {
22
+ expect(BF_CHILD_NOOP_ID.startsWith('\0')).toBe(true)
23
+ })
24
+ })
@@ -0,0 +1,73 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+ import { CompileCache } from '../compile-cache.ts'
3
+ import type { CompileResult } from '@barefootjs/jsx'
4
+
5
+ function fakeResult(tag: string): CompileResult {
6
+ return { files: [{ path: tag, content: tag, type: 'clientJs' }], errors: [] }
7
+ }
8
+
9
+ describe('CompileCache', () => {
10
+ test('compiles once for the same (path, content) pair', () => {
11
+ const cache = new CompileCache()
12
+ let calls = 0
13
+ const compile = () => {
14
+ calls++
15
+ return fakeResult('a')
16
+ }
17
+
18
+ const first = cache.getOrCompile('/a.tsx', 'content', compile)
19
+ const second = cache.getOrCompile('/a.tsx', 'content', compile)
20
+
21
+ expect(calls).toBe(1)
22
+ expect(first).toBe(second)
23
+ })
24
+
25
+ test('recompiles when the content changes', () => {
26
+ const cache = new CompileCache()
27
+ let calls = 0
28
+ const compile = () => {
29
+ calls++
30
+ return fakeResult(`v${calls}`)
31
+ }
32
+
33
+ const first = cache.getOrCompile('/a.tsx', 'v1', compile)
34
+ const second = cache.getOrCompile('/a.tsx', 'v2', compile)
35
+
36
+ expect(calls).toBe(2)
37
+ expect(first).not.toBe(second)
38
+ })
39
+
40
+ test('tracks distinct paths independently', () => {
41
+ const cache = new CompileCache()
42
+ let calls = 0
43
+ const compile = () => {
44
+ calls++
45
+ return fakeResult(`n${calls}`)
46
+ }
47
+
48
+ cache.getOrCompile('/a.tsx', 'same', compile)
49
+ cache.getOrCompile('/b.tsx', 'same', compile)
50
+
51
+ expect(calls).toBe(2)
52
+ })
53
+
54
+ test('peek returns undefined before any compile and the cached result after', () => {
55
+ const cache = new CompileCache()
56
+ expect(cache.peek('/a.tsx')).toBeUndefined()
57
+ const result = cache.getOrCompile('/a.tsx', 'content', () => fakeResult('a'))
58
+ expect(cache.peek('/a.tsx')).toBe(result)
59
+ })
60
+
61
+ test('clear() forces a recompile', () => {
62
+ const cache = new CompileCache()
63
+ let calls = 0
64
+ const compile = () => {
65
+ calls++
66
+ return fakeResult('a')
67
+ }
68
+ cache.getOrCompile('/a.tsx', 'content', compile)
69
+ cache.clear()
70
+ cache.getOrCompile('/a.tsx', 'content', compile)
71
+ expect(calls).toBe(2)
72
+ })
73
+ })