@janit/fu 0.0.2 → 0.1.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/README.md CHANGED
@@ -8,9 +8,10 @@ No Vite, no Babel, no esbuild. The bundler, JSX transform and CSS engine are
8
8
  all Rust.
9
9
 
10
10
  ```
11
- core ~300 lines router + render + client + hmr runtime
12
- drivers ~400 lines build + dev + shared rolldown plugins
11
+ core ~560 lines router + render + client + hmr runtime
12
+ drivers ~490 lines build + dev + shared driver glue + rolldown plugins
13
13
  ```
14
+ (code lines, comments and blanks excluded)
14
15
 
15
16
  ## What this is
16
17
 
@@ -47,14 +48,19 @@ deno task todo:dev # the fu-todo example app
47
48
  deno task todo:build
48
49
  deno task todo:start # serve its build on :1337
49
50
 
50
- deno task test # 41 unit tests
51
- deno task check # types + tests + jsr publish dry-run
51
+ deno task test # 59 unit tests
52
+ deno task check # format, lint, types (framework and both apps), tests, jsr dry-run
53
+ deno task check:pkg # build, serve and dev-serve a real app from the packed npm artefact
52
54
  ```
53
55
 
54
56
  Both example apps build against **this checkout's `src/`**, never a published
55
57
  package, so the framework and the apps can be changed and tested together
56
- before anything is released. `npm install` at the root is the only setup step;
57
- it serves the whole repo.
58
+ before anything is released. The drivers make that hold: they alias the
59
+ framework's own package name to the runtime copy they are running from, so an
60
+ app's `import { App } from "@janit/fu"` cannot drift to a stale
61
+ `dist/` through Node's package self-reference. The apps are Deno workspace
62
+ members, so `deno check` sees the same mapping. `npm install` at the root is
63
+ the only setup step; it serves the whole repo.
58
64
 
59
65
  Then run the build on whichever runtime you like — one artifact, three runtimes:
60
66
 
@@ -231,9 +237,17 @@ type RouteManifest = Record<string, () => Promise<RouteModule>>;
231
237
  type Assets = { js: { href: string }[]; css: { href: string }[] };
232
238
  ```
233
239
 
234
- Everything bundler-specific lives in the drivers (`src/build.ts`, `src/dev.ts`)
235
- and the shared plugins (`src/plugins.ts`). The same core ran unchanged under a
236
- Vite driver during prototyping, so swapping the build layer stays cheap.
240
+ Everything bundler-specific lives in the drivers (`src/build.ts`, `src/dev.ts`),
241
+ the glue they share (`src/driver.ts`: locating the runtime modules, scanning a
242
+ project, the rolldown and nitro option sets) and the rolldown plugins
243
+ (`src/plugins.ts`). The same core ran unchanged under a Vite driver during
244
+ prototyping, so swapping the build layer stays cheap.
245
+
246
+ Routing is on `URLPattern`, but `exec` costs microseconds per route on Deno,
247
+ so it only runs when it can matter: a route with no pattern syntax is matched
248
+ by string equality against its canonical pathname, and a pattern whose
249
+ segment count cannot fit the path is skipped. A static hit is ~65 ns and a
250
+ dynamic one ~1.6 µs with 16 routes, down from 28 µs and 57 µs.
237
251
 
238
252
  See [the design doc](docs/design.md) for
239
253
  the full rationale and the nine undocumented traps this implementation encodes.
@@ -249,11 +263,12 @@ failure modes this framework actually hit, so each one guards a real regression:
249
263
 
250
264
  | area | what it pins down |
251
265
  |---|---|
252
- | router | static beats dynamic beats wildcard; wildcards span segments; params decode |
266
+ | router | static beats dynamic beats wildcard; wildcards span segments and match their own base path; params decode; a non-ASCII static route matches its percent-encoded request |
253
267
  | middleware | outer unwinds last and decorates inner short-circuits; `next()` twice rejects; throws propagate |
254
268
  | render | head escaping; JSON-LD cannot close its own `<script>`; 404 vs 405; islands get a marker |
255
269
  | errors | a 500 never leaks its message; error responses are uncacheable; a broken error page falls back |
256
- | plugins | `composes` keeps every class name; CSS output changes with content; the JSX transform never touches rolldown's runtime; the H3Event unwrap |
270
+ | plugins | `composes` keeps every class name; CSS output changes with content; the JSX transform never touches rolldown's runtime; the package self-alias |
271
+ | driver | the server entry imports only the optional files that exist; the H3Event unwrap |
257
272
 
258
273
  Two of these were found by writing the suite, not before it: `ctx.next()` called
259
274
  twice resumed at the wrong depth, and a middleware throwing synchronously
@@ -273,8 +288,11 @@ private history leaks:
273
288
  the privacy boundary, a staged-tree backstop that refuses the push if anything
274
289
  private reaches the index anyway, semver tagging derived from the public repo's
275
290
  existing tags, and version stamping so the git tag and `deno.json` cannot drift.
276
- `fu-todo/` is stripped from `janit/fu`; the framework specifier is rewritten
277
- from `../src/mod.ts` on the way into `janit/fu-todo`.
291
+ `fu-todo/` is stripped from `janit/fu`, and from its Deno workspace; the
292
+ framework specifier is rewritten from `../src/mod.ts` on the way into
293
+ `janit/fu-todo`, which also gets its own `nodeModulesDir` since it is no
294
+ longer a workspace member there. Both flows can be rehearsed against a local
295
+ bare repository by overriding `PUBLIC_REPO`.
278
296
 
279
297
  ## Known gaps
280
298
 
package/dist/app.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Ctx, Middleware } from "./types.ts";
1
+ import type { Ctx, Middleware } from "./types.js";
2
2
  export declare function compose<S>(middleware: readonly Middleware<S>[], terminal: (ctx: Ctx<S>) => Response | Promise<Response>): (ctx: Ctx<S>) => Promise<Response>;
3
3
  /**
4
4
  * The application: an ordered middleware chain.
@@ -20,6 +20,4 @@ export declare class App<S = Record<string, unknown>> {
20
20
  use(middleware: Middleware<S>): this;
21
21
  /** The registered chain, in registration order. */
22
22
  get middleware(): readonly Middleware<S>[];
23
- /** Wrap a terminal handler in this app's chain. */
24
- compose(terminal: (ctx: Ctx<S>) => Response | Promise<Response>): (ctx: Ctx<S>) => Promise<Response>;
25
23
  }
package/dist/app.js CHANGED
@@ -72,9 +72,5 @@ export class App {
72
72
  get middleware() {
73
73
  return this.#middleware;
74
74
  }
75
- /** Wrap a terminal handler in this app's chain. */
76
- compose(terminal) {
77
- return compose(this.#middleware, terminal);
78
- }
79
75
  }
80
76
  //# sourceMappingURL=app.js.map
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,SAAS,MAAM,CAAC,EAAsC;IACpD,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,UAAoC,EACpC,QAAuD;IAEvD,OAAO,CAAC,IAAY,EAAqB,EAAE;QACzC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,IAAY,EAAqB,EAAE;YAC9D,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YACzB,oEAAoE;YACpE,sEAAsE;YACtE,uCAAuC;YACvC,IAAI,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAE7C,qEAAqE;YACrE,yEAAyE;YACzE,qEAAqE;YACrE,yDAAyD;YACzD,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,MAAM,GAAG,GAAW;gBAClB,GAAG,IAAI;gBACP,IAAI,EAAE,GAAG,EAAE;oBACT,IAAI,MAAM,EAAE,CAAC;wBACX,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,wDAAwD,CAAC,CACpE,CAAC;oBACJ,CAAC;oBACD,MAAM,GAAG,IAAI,CAAC;oBACd,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC9B,CAAC;aACF,CAAC;YACF,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC;QACF,OAAO,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,GAAG;IACL,WAAW,GAAoB,EAAE,CAAC;IAE3C,gEAAgE;IAChE,GAAG,CAAC,UAAyB;QAC3B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,mDAAmD;IACnD,OAAO,CACL,QAAuD;QAEvD,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;CACF"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,SAAS,MAAM,CAAC,EAAsC;IACpD,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,UAAoC,EACpC,QAAuD;IAEvD,OAAO,CAAC,IAAY,EAAqB,EAAE;QACzC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,IAAY,EAAqB,EAAE;YAC9D,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YACzB,oEAAoE;YACpE,sEAAsE;YACtE,uCAAuC;YACvC,IAAI,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAE7C,qEAAqE;YACrE,yEAAyE;YACzE,qEAAqE;YACrE,yDAAyD;YACzD,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,MAAM,GAAG,GAAW;gBAClB,GAAG,IAAI;gBACP,IAAI,EAAE,GAAG,EAAE;oBACT,IAAI,MAAM,EAAE,CAAC;wBACX,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CAAC,wDAAwD,CAAC,CACpE,CAAC;oBACJ,CAAC;oBACD,MAAM,GAAG,IAAI,CAAC;oBACd,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC9B,CAAC;aACF,CAAC;YACF,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC;QACF,OAAO,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,GAAG;IACL,WAAW,GAAoB,EAAE,CAAC;IAE3C,gEAAgE;IAChE,GAAG,CAAC,UAAyB;QAC3B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF"}
package/dist/build.d.ts CHANGED
@@ -1,4 +1,2 @@
1
- import type { FuOptions } from "./types.ts";
1
+ import type { FuOptions } from "./types.js";
2
2
  export declare function build(opts: FuOptions): Promise<void>;
3
- /** Concatenate collected stylesheets into one hashed file. Returns its name. */
4
- export declare function writeSheets(dir: string, sheets: Map<string, string>): string | null;
package/dist/build.js CHANGED
@@ -1,52 +1,17 @@
1
1
  // Production driver: rolldown builds the client, nitro builds the server.
2
2
  import { rolldown } from "rolldown";
3
3
  import { build as nitroBuild, copyPublicAssets, createNitro } from "nitro/builder";
4
- import * as fs from "node:fs";
5
4
  import * as path from "node:path";
6
- import { bootModule, css, jsx, optional, ssrModule, virtual, walk } from "./plugins.js";
7
- /**
8
- * Directory holding the framework's own runtime modules, whose paths are handed
9
- * to rolldown. `import.meta.dirname` is undefined when this module is loaded
10
- * from a remote URL, and a bundler cannot fetch `https:` modules anyway — so
11
- * fail with the reason rather than a TypeError three frames later.
12
- */
13
- const HERE = import.meta.dirname ?? remoteFrameworkError();
14
- /**
15
- * Extension of the framework's own runtime modules: `.ts` when running from
16
- * source (this repo, or JSR), `.js` when running from the compiled npm build.
17
- */
18
- const EXT = import.meta.url.endsWith(".js") ? ".js" : ".ts";
19
- function remoteFrameworkError() {
20
- throw new Error("fu: the framework is loaded from a remote URL (" + import.meta.url + "), " +
21
- "so its runtime modules cannot be handed to the bundler. Install it " +
22
- "instead — `npm:@janit/fu` in a Deno import map, or `npm i @janit/fu` — " +
23
- "so it resolves to a real directory.");
24
- }
5
+ import { clientInput, emptyDir, nitroOptions, scanProject, writeSheets, writeSsrEntry, } from "./driver.js";
25
6
  export async function build(opts) {
26
- const root = path.resolve(opts.root);
27
- const outDir = opts.outDir ? path.resolve(opts.outDir) : path.join(root, ".output");
28
- const clientDir = path.join(root, "dist/client");
29
- const genDir = path.join(root, ".fu");
30
- const routeFiles = walk(root, path.join(root, "routes"));
31
- const islandFiles = walk(root, path.join(root, "islands"));
7
+ const project = scanProject(opts.root);
8
+ const outDir = opts.outDir ? path.resolve(opts.outDir) : path.join(project.root, ".output");
32
9
  // ---- client ----
33
- fs.rmSync(clientDir, { recursive: true, force: true });
34
- fs.mkdirSync(clientDir, { recursive: true });
10
+ emptyDir(project.clientDir);
35
11
  const sheets = new Map();
36
- const bundle = await rolldown({
37
- input: { boot: "fu:boot" },
38
- plugins: [
39
- virtual({ "fu:boot": bootModule(path.join(HERE, `client${EXT}`), islandFiles, root) }),
40
- css(sheets),
41
- jsx(),
42
- ],
43
- platform: "browser",
44
- // rolldown types modules by extension and refuses to bundle CSS; css()
45
- // has already replaced their contents with JS.
46
- moduleTypes: { ".css": "js" },
47
- });
12
+ const bundle = await rolldown(clientInput(project, sheets));
48
13
  const result = await bundle.write({
49
- dir: clientDir,
14
+ dir: project.clientDir,
50
15
  format: "esm",
51
16
  entryFileNames: "[name]-[hash].js",
52
17
  chunkFileNames: "[name]-[hash].js",
@@ -55,54 +20,14 @@ export async function build(opts) {
55
20
  const entry = result.output.find((o) => o.type === "chunk" && o.isEntry);
56
21
  if (!entry)
57
22
  throw new Error("fu: client build produced no entry chunk");
58
- const cssHref = writeSheets(clientDir, sheets);
23
+ const cssFile = writeSheets(project.clientDir, sheets);
59
24
  // ---- server ----
60
- fs.rmSync(genDir, { recursive: true, force: true });
61
- fs.mkdirSync(genDir, { recursive: true });
62
- const assets = {
25
+ const ssrEntry = writeSsrEntry(project, {
63
26
  js: [{ href: "/" + entry.fileName }],
64
- css: cssHref ? [{ href: "/" + cssHref }] : [],
65
- };
66
- // nitro path-resolves `handlers[].handler`, so a virtual id would not survive
67
- // its routing codegen — generate a real file.
68
- const ssrEntry = path.join(genDir, "ssr.ts");
69
- fs.writeFileSync(ssrEntry, ssrModule({
70
- renderPath: path.join(HERE, `render${EXT}`),
71
- routeFiles,
72
- root,
73
- assets: JSON.stringify(assets),
74
- appPath: optional(root, "app.ts", "app.tsx"),
75
- shellPath: optional(root, "routes/_app.tsx"),
76
- errorPath: optional(root, "routes/_error.tsx"),
77
- }));
78
- const nitro = await createNitro({
79
- rootDir: root,
80
- // Point nitro's scanner at the generated dir, never the project root, or it
81
- // claims `routes/` as its own server routes and shadows our catch-all.
82
- serverDir: genDir,
83
- scanDirs: [],
84
- output: { dir: outDir },
85
- publicAssets: [{ dir: clientDir, baseURL: "/" }],
86
- handlers: [{ route: "/**", handler: ssrEntry, format: "web", lazy: false }],
87
- rollupConfig: {
88
- // Islands are imported on the server too, so SSR needs the same handling.
89
- plugins: [css(new Map()), jsx({ stampIslands: true })],
90
- moduleTypes: { ".css": "js" },
91
- },
27
+ css: cssFile ? [{ href: "/" + cssFile }] : [],
92
28
  });
29
+ const nitro = await createNitro({ ...nitroOptions(project, ssrEntry), output: { dir: outDir } });
93
30
  await copyPublicAssets(nitro);
94
31
  await nitroBuild(nitro);
95
32
  }
96
- /** Concatenate collected stylesheets into one hashed file. Returns its name. */
97
- export function writeSheets(dir, sheets) {
98
- if (sheets.size === 0)
99
- return null;
100
- const merged = [...sheets.values()].join("\n");
101
- let h = 7;
102
- for (let i = 0; i < merged.length; i++)
103
- h = (Math.imul(h, 31) + merged.charCodeAt(i)) >>> 0;
104
- const name = `style-${h.toString(36)}.css`;
105
- fs.writeFileSync(path.join(dir, name), merged);
106
- return name;
107
- }
108
33
  //# sourceMappingURL=build.js.map
package/dist/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EACL,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,GACd,MAAM,aAAa,CAAC;AAGrB,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAe;IACzC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAE5F,mBAAmB;IACnB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAChC,GAAG,EAAE,OAAO,CAAC,SAAS;QACtB,MAAM,EAAE,KAAK;QACb,cAAc,EAAE,kBAAkB;QAClC,cAAc,EAAE,kBAAkB;KACnC,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEvD,mBAAmB;IACnB,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE;QACtC,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;KAC9C,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACjG,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC"}
package/dist/cli.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env -S deno run -A
2
+ import process from "node:process";
2
3
  import { build } from "./build.js";
3
4
  import { dev } from "./dev.js";
4
5
  export async function main(argv) {
5
6
  const [cmd = "dev", ...rest] = argv;
6
- const portArg = rest.find((a) => a.startsWith("--port="));
7
- const hostArg = rest.find((a) => a.startsWith("--host="));
8
- const rootArg = rest.find((a) => !a.startsWith("-"));
7
+ const flag = (name) => rest.find((a) => a.startsWith(`--${name}=`))?.slice(name.length + 3);
8
+ const port = flag("port");
9
9
  const opts = {
10
- root: rootArg ?? Deno?.cwd?.() ?? process.cwd(),
11
- port: portArg ? Number(portArg.slice("--port=".length)) : undefined,
12
- hostname: hostArg ? hostArg.slice("--host=".length) : undefined,
10
+ root: rest.find((a) => !a.startsWith("-")) ?? process.cwd(),
11
+ port: port ? Number(port) : undefined,
12
+ hostname: flag("host"),
13
13
  };
14
14
  if (cmd === "build")
15
15
  await build(opts);
@@ -21,5 +21,5 @@ export async function main(argv) {
21
21
  }
22
22
  }
23
23
  if (import.meta.main)
24
- await main(globalThis.process?.argv.slice(2) ?? []);
24
+ await main(process.argv.slice(2));
25
25
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,MAAM,CAAC,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,GAAG,EAAE,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE;QAC/C,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QACnE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;KAChE,CAAC;IACF,IAAI,GAAG,KAAK,OAAO;QAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC,IAAI,GAAG,KAAK,KAAK;QAAE,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;SACnC,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,wBAAwB,CAAC,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAID,IAAI,OAAO,IAAI,CAAC,IAAI;IAAE,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,MAAM,CAAC,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE,CAC5B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE;QAC3D,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QACrC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC;KACvB,CAAC;IACF,IAAI,GAAG,KAAK,OAAO;QAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC,IAAI,GAAG,KAAK,KAAK;QAAE,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;SACnC,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,wBAAwB,CAAC,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,IAAI,OAAO,IAAI,CAAC,IAAI;IAAE,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
package/dist/client.d.ts CHANGED
@@ -1,6 +1,12 @@
1
1
  import { type FunctionComponent } from "preact";
2
2
  type Props = Record<string, unknown>;
3
- /** Hydrate every `[data-island]` marker the server rendered. */
3
+ /**
4
+ * Hydrate every `[data-island]` marker the server rendered.
5
+ *
6
+ * Every distinct island module is fetched at once, then the markers are
7
+ * hydrated in document order; awaiting each in turn would serialise one
8
+ * network round-trip per island.
9
+ */
4
10
  export declare function hydrateIslands(manifest: Record<string, () => Promise<{
5
11
  default: FunctionComponent<Props>;
6
12
  }>>): Promise<void>;
package/dist/client.js CHANGED
@@ -25,18 +25,29 @@ function proxyFor(key, impl) {
25
25
  proxies.set(key, entry);
26
26
  return entry;
27
27
  }
28
- /** Hydrate every `[data-island]` marker the server rendered. */
28
+ /**
29
+ * Hydrate every `[data-island]` marker the server rendered.
30
+ *
31
+ * Every distinct island module is fetched at once, then the markers are
32
+ * hydrated in document order; awaiting each in turn would serialise one
33
+ * network round-trip per island.
34
+ */
29
35
  export async function hydrateIslands(manifest) {
30
- for (const el of document.querySelectorAll("[data-island]")) {
31
- const key = el.dataset.island;
36
+ const els = [...document.querySelectorAll("[data-island]")];
37
+ const keys = [...new Set(els.map((el) => el.dataset.island))];
38
+ const loaded = new Map(await Promise.all(keys.map(async (key) => {
32
39
  const loader = manifest[key];
33
- if (!loader) {
40
+ if (!loader)
34
41
  console.warn("[fu] no island module for", key);
42
+ return [key, loader ? (await loader()).default : null];
43
+ })));
44
+ for (const el of els) {
45
+ const key = el.dataset.island;
46
+ const impl = loaded.get(key);
47
+ if (!impl)
35
48
  continue;
36
- }
37
- const mod = await loader();
38
49
  const props = JSON.parse(el.dataset.props || "{}");
39
- hydrate(h(proxyFor(key, mod.default).Component, props), el);
50
+ hydrate(h(proxyFor(key, impl).Component, props), el);
40
51
  const list = mounted.get(key) ?? [];
41
52
  list.push({ el, props });
42
53
  mounted.set(key, list);
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/dev.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import type { FuOptions } from "./types.ts";
1
+ import type { FuOptions } from "./types.js";
2
2
  export declare function dev(opts: FuOptions): Promise<void>;
package/dist/dev.js CHANGED
@@ -5,71 +5,38 @@ import { serve } from "crossws/server";
5
5
  import { build as nitroBuild, createDevServer, createNitro, prepare } from "nitro/builder";
6
6
  import * as fs from "node:fs";
7
7
  import * as path from "node:path";
8
- import { bootModule, css, jsx, optional, ssrModule, virtual, walk } from "./plugins.js";
9
- /**
10
- * Directory holding the framework's own runtime modules, whose paths are handed
11
- * to rolldown. `import.meta.dirname` is undefined when this module is loaded
12
- * from a remote URL, and a bundler cannot fetch `https:` modules anyway — so
13
- * fail with the reason rather than a TypeError three frames later.
14
- */
15
- const HERE = import.meta.dirname ?? remoteFrameworkError();
16
- /**
17
- * Extension of the framework's own runtime modules: `.ts` when running from
18
- * source (this repo, or JSR), `.js` when running from the compiled npm build.
19
- */
20
- const EXT = import.meta.url.endsWith(".js") ? ".js" : ".ts";
21
- function remoteFrameworkError() {
22
- throw new Error("fu: the framework is loaded from a remote URL (" + import.meta.url + "), " +
23
- "so its runtime modules cannot be handed to the bundler. Install it " +
24
- "instead — `npm:@janit/fu` in a Deno import map, or `npm i @janit/fu` — " +
25
- "so it resolves to a real directory.");
26
- }
8
+ import { clientInput, emptyDir, nitroOptions, runtime, scanProject, writeSheets, writeSsrEntry, } from "./driver.js";
27
9
  export async function dev(opts) {
28
- const root = path.resolve(opts.root);
10
+ const project = scanProject(opts.root);
11
+ const { clientDir } = project;
29
12
  const port = opts.port ?? 1337;
30
13
  // Bind all interfaces so the dev server is reachable from other machines
31
14
  // and from inside containers, not just loopback.
32
15
  const hostname = opts.hostname ?? "0.0.0.0";
33
16
  const hmrPort = port + 1;
34
- const clientDir = path.join(root, "dist/client");
35
- const genDir = path.join(root, ".fu");
36
- const routeFiles = walk(root, path.join(root, "routes"));
37
- const islandFiles = walk(root, path.join(root, "islands"));
38
- fs.rmSync(clientDir, { recursive: true, force: true });
39
- fs.mkdirSync(clientDir, { recursive: true });
17
+ emptyDir(clientDir);
40
18
  const sheets = new Map();
41
19
  const peers = new Map();
42
20
  let cssVersion = 0;
43
- const writeSheets = () => {
44
- if (sheets.size)
45
- fs.writeFileSync(path.join(clientDir, "style.css"), [...sheets.values()].join("\n"));
46
- };
21
+ const flushCss = () => writeSheets(clientDir, sheets, "style.css");
47
22
  // `implement` takes the runtime SOURCE, not a path — a path gets inlined
48
23
  // literally and parsed as a regex. `$ADDR` is only substituted in rolldown's
49
24
  // own default runtime, so do it here.
50
- const hmrRuntime = fs.readFileSync(path.join(HERE, "hmr-runtime.js"), "utf8")
51
- .replaceAll("$ADDR", `localhost:${hmrPort}`);
25
+ const hmrRuntime = fs.readFileSync(runtime.hmr, "utf8").replaceAll("$ADDR", `localhost:${hmrPort}`);
52
26
  const engine = await DevEngine.create({
53
- input: { boot: "fu:boot" },
54
- plugins: [
55
- virtual({ "fu:boot": bootModule(path.join(HERE, `client${EXT}`), islandFiles, root) }),
56
- css(sheets),
57
- jsx({ hmr: true }),
58
- ],
59
- platform: "browser",
60
- moduleTypes: { ".css": "js" },
27
+ ...clientInput(project, sheets, true),
61
28
  experimental: { devMode: { host: "localhost", port: hmrPort, implement: hmrRuntime } },
62
29
  }, { dir: clientDir, format: "esm", entryFileNames: "[name].js", chunkFileNames: "[name].js" }, {
63
30
  watch: { enabled: true },
64
31
  onOutput(o) {
65
32
  if (o instanceof Error)
66
33
  return console.error("[fu] client build failed:", o.message);
67
- writeSheets();
34
+ flushCss();
68
35
  },
69
36
  onHmrUpdates(r) {
70
37
  if (r instanceof Error)
71
38
  return console.error("[fu] hmr error:", r.message);
72
- writeSheets();
39
+ flushCss();
73
40
  for (const { clientId, update } of r.updates) {
74
41
  const peer = peers.get(clientId);
75
42
  if (!peer || update.type === "Noop")
@@ -132,31 +99,11 @@ export async function dev(opts) {
132
99
  },
133
100
  });
134
101
  // SSR.
135
- fs.rmSync(genDir, { recursive: true, force: true });
136
- fs.mkdirSync(genDir, { recursive: true });
137
- const ssrEntry = path.join(genDir, "ssr.ts");
138
- const assets = `{ js: [{ href: "/boot.js" }], css: [{ href: "/style.css" }] }`;
139
- fs.writeFileSync(ssrEntry, ssrModule({
140
- renderPath: path.join(HERE, `render${EXT}`),
141
- routeFiles,
142
- root,
143
- assets,
144
- appPath: optional(root, "app.ts", "app.tsx"),
145
- shellPath: optional(root, "routes/_app.tsx"),
146
- errorPath: optional(root, "routes/_error.tsx"),
147
- }));
148
- const nitro = await createNitro({
149
- dev: true,
150
- rootDir: root,
151
- serverDir: genDir,
152
- scanDirs: [],
153
- publicAssets: [{ dir: clientDir, baseURL: "/" }],
154
- handlers: [{ route: "/**", handler: ssrEntry, format: "web", lazy: false }],
155
- rollupConfig: {
156
- plugins: [css(new Map()), jsx({ stampIslands: true })],
157
- moduleTypes: { ".css": "js" },
158
- },
102
+ const ssrEntry = writeSsrEntry(project, {
103
+ js: [{ href: "/boot.js" }],
104
+ css: [{ href: "/style.css" }],
159
105
  });
106
+ const nitro = await createNitro({ ...nitroOptions(project, ssrEntry), dev: true });
160
107
  const server = createDevServer(nitro);
161
108
  server.listen({ port, hostname });
162
109
  // Order matters: listen -> prepare -> build. `build` starts the dev runner.
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { createNitro } from "nitro/builder";
2
+ import type { InputOptions } from "rolldown";
3
+ import type { Assets } from "./types.js";
4
+ /** Absolute paths of the runtime modules the generated code imports. */
5
+ export declare const runtime: {
6
+ client: string;
7
+ render: string;
8
+ hmr: string;
9
+ };
10
+ /** Everything a driver needs to know about a project, found once up front. */
11
+ export interface Project {
12
+ root: string;
13
+ /** Root-relative, e.g. "/routes/blog/[slug].tsx". */
14
+ routeFiles: string[];
15
+ islandFiles: string[];
16
+ /** Absolute path to `app.ts`, if the project has one. */
17
+ appPath: string | null;
18
+ /** Absolute path to `routes/_app.tsx`, if the project has one. */
19
+ shellPath: string | null;
20
+ /** Absolute path to `routes/_error.tsx`, if the project has one. */
21
+ errorPath: string | null;
22
+ /** Client bundle output, served as public assets. */
23
+ clientDir: string;
24
+ /** Generated server entry. */
25
+ genDir: string;
26
+ }
27
+ export declare function scanProject(root: string): Project;
28
+ /**
29
+ * Recursively list source files under `<root>/<sub>`, as root-relative
30
+ * "/sub/a/b.tsx". Underscore-prefixed files are skipped: they are framework
31
+ * files (`routes/_app.tsx`), not routes.
32
+ */
33
+ export declare function walk(root: string, sub: string): string[];
34
+ /** Absolute path to an optional project file, or null when absent. */
35
+ export declare function optional(root: string, ...names: string[]): string | null;
36
+ /** Recreate `dir` empty. */
37
+ export declare function emptyDir(dir: string): void;
38
+ /** Rolldown input for the client bundle. */
39
+ export declare function clientInput(project: Project, sheets: Map<string, string>, hmr?: boolean): InputOptions;
40
+ /**
41
+ * Nitro options both drivers share. `serverDir` is the generated dir, never the
42
+ * project root, or nitro claims `routes/` as its own server routes and shadows
43
+ * the catch-all. Islands are imported on the server too, so SSR needs the same
44
+ * CSS and JSX handling as the client.
45
+ */
46
+ export declare function nitroOptions(project: Project, ssrEntry: string): Parameters<typeof createNitro>[0];
47
+ /** Concatenate collected stylesheets into one file; hashed unless a name is given. */
48
+ export declare function writeSheets(dir: string, sheets: Map<string, string>, name?: string): string | null;
49
+ /** The client entry: hydrate every island the page carries. */
50
+ export declare function bootModule(project: Pick<Project, "root" | "islandFiles">): string;
51
+ /**
52
+ * The server entry: the route manifest, the optional app, shell and error
53
+ * page, and the handler wired to nitro.
54
+ *
55
+ * Nitro invokes the handler with an H3Event, not a Request. The event exposes
56
+ * `url`/`headers` directly — which is why routing worked long before anyone
57
+ * read a body — but has no json()/text()/formData(). The real Request is
58
+ * `event.req`.
59
+ */
60
+ export declare function ssrModule(project: Pick<Project, "root" | "routeFiles" | "appPath" | "shellPath" | "errorPath">, assets: Assets): string;
61
+ /**
62
+ * Write the generated server entry and return its path. It has to be a real
63
+ * file: nitro path-resolves `handlers[].handler`, so a virtual id would not
64
+ * survive its routing codegen.
65
+ */
66
+ export declare function writeSsrEntry(project: Project, assets: Assets): string;