@canonical/react-ssr 0.27.1-experimental.0 → 0.28.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 (64) hide show
  1. package/README.md +74 -27
  2. package/dist/esm/bin/serve-bun.js +77 -0
  3. package/dist/esm/bin/serve-bun.js.map +1 -0
  4. package/dist/esm/bin/serve-express.js +19 -36
  5. package/dist/esm/bin/serve-express.js.map +1 -1
  6. package/dist/esm/lib/adapter/index.js +1 -1
  7. package/dist/esm/lib/adapter/index.js.map +1 -1
  8. package/dist/esm/lib/adapter/mime.js +7 -0
  9. package/dist/esm/lib/adapter/mime.js.map +1 -1
  10. package/dist/esm/lib/renderer/JSXRenderer.js +2 -0
  11. package/dist/esm/lib/renderer/JSXRenderer.js.map +1 -1
  12. package/dist/esm/lib/renderer/SitemapRenderer.js +2 -0
  13. package/dist/esm/lib/renderer/SitemapRenderer.js.map +1 -1
  14. package/dist/esm/lib/server/StaticMount.js +2 -0
  15. package/dist/esm/lib/server/StaticMount.js.map +1 -0
  16. package/dist/esm/lib/server/getRequestUrl.js +41 -0
  17. package/dist/esm/lib/server/getRequestUrl.js.map +1 -0
  18. package/dist/esm/lib/server/index.js +6 -0
  19. package/dist/esm/lib/server/index.js.map +1 -1
  20. package/dist/esm/lib/server/matchStaticRoute.js +14 -0
  21. package/dist/esm/lib/server/matchStaticRoute.js.map +1 -0
  22. package/dist/esm/lib/server/parseStaticPair.js +20 -0
  23. package/dist/esm/lib/server/parseStaticPair.js.map +1 -0
  24. package/dist/esm/lib/server/resolvePort.js +29 -0
  25. package/dist/esm/lib/server/resolvePort.js.map +1 -0
  26. package/dist/esm/lib/server/resolveStaticFile.js +61 -0
  27. package/dist/esm/lib/server/resolveStaticFile.js.map +1 -0
  28. package/dist/esm/lib/server/serveStream.js +1 -1
  29. package/dist/esm/lib/server/serveStream.js.map +1 -1
  30. package/dist/esm/lib/server/viteFetchMiddleware.js +152 -0
  31. package/dist/esm/lib/server/viteFetchMiddleware.js.map +1 -0
  32. package/dist/types/bin/serve-bun.d.ts +25 -0
  33. package/dist/types/bin/serve-bun.d.ts.map +1 -0
  34. package/dist/types/bin/serve-express.d.ts +6 -3
  35. package/dist/types/bin/serve-express.d.ts.map +1 -1
  36. package/dist/types/lib/adapter/index.d.ts +1 -1
  37. package/dist/types/lib/adapter/index.d.ts.map +1 -1
  38. package/dist/types/lib/adapter/mime.d.ts +7 -0
  39. package/dist/types/lib/adapter/mime.d.ts.map +1 -1
  40. package/dist/types/lib/adapter/types.d.ts +8 -10
  41. package/dist/types/lib/adapter/types.d.ts.map +1 -1
  42. package/dist/types/lib/renderer/JSXRenderer.d.ts +2 -0
  43. package/dist/types/lib/renderer/JSXRenderer.d.ts.map +1 -1
  44. package/dist/types/lib/renderer/SitemapRenderer.d.ts +2 -0
  45. package/dist/types/lib/renderer/SitemapRenderer.d.ts.map +1 -1
  46. package/dist/types/lib/server/StaticMount.d.ts +11 -0
  47. package/dist/types/lib/server/StaticMount.d.ts.map +1 -0
  48. package/dist/types/lib/server/getRequestUrl.d.ts +29 -0
  49. package/dist/types/lib/server/getRequestUrl.d.ts.map +1 -0
  50. package/dist/types/lib/server/index.d.ts +7 -0
  51. package/dist/types/lib/server/index.d.ts.map +1 -1
  52. package/dist/types/lib/server/matchStaticRoute.d.ts +12 -0
  53. package/dist/types/lib/server/matchStaticRoute.d.ts.map +1 -0
  54. package/dist/types/lib/server/parseStaticPair.d.ts +12 -0
  55. package/dist/types/lib/server/parseStaticPair.d.ts.map +1 -0
  56. package/dist/types/lib/server/resolvePort.d.ts +20 -0
  57. package/dist/types/lib/server/resolvePort.d.ts.map +1 -0
  58. package/dist/types/lib/server/resolveStaticFile.d.ts +20 -0
  59. package/dist/types/lib/server/resolveStaticFile.d.ts.map +1 -0
  60. package/dist/types/lib/server/serveStream.d.ts +1 -0
  61. package/dist/types/lib/server/serveStream.d.ts.map +1 -1
  62. package/dist/types/lib/server/viteFetchMiddleware.d.ts +81 -0
  63. package/dist/types/lib/server/viteFetchMiddleware.d.ts.map +1 -0
  64. package/package.json +11 -7
@@ -0,0 +1,81 @@
1
+ import { IncomingMessage, ServerResponse } from "node:http";
2
+ /**
3
+ * Minimal structural type for the parts of Vite's dev server this helper uses.
4
+ *
5
+ * `vite` is an optional peer dependency of this package (it is only needed by
6
+ * consumers running a Vite-backed dev server). Typing structurally avoids a
7
+ * hard dependency on Vite's types while still describing the contract: a
8
+ * connect-style middleware stack `(req, res, next) => void`.
9
+ */
10
+ export interface ViteMiddlewareServer {
11
+ middlewares: (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void;
12
+ }
13
+ /**
14
+ * Bridge Vite's connect-style middleware into a `fetch`-style handler.
15
+ *
16
+ * Runtime SSR dev servers built on `Bun.serve` (or any Web `fetch` server)
17
+ * cannot mount Vite's `(req, res, next)` middleware directly: that stack
18
+ * expects Node's `http.IncomingMessage` / `ServerResponse`, while `fetch`
19
+ * deals in Web `Request` / `Response`. Without delegating to Vite, every
20
+ * request — including `/@vite/client`, `/src/**`, `/@id/**`, `/@fs/**`,
21
+ * `/@react-refresh`, and `/node_modules/.vite/**` — would have to be
22
+ * server-rendered, so client modules and HMR assets would be returned as the
23
+ * SSR HTML page with the wrong `Content-Type` (browsers then block them as
24
+ * modules and the page never hydrates).
25
+ *
26
+ * This helper adapts a Web `Request` into a Node `req`/`res` pair, runs Vite's
27
+ * middleware against it, and returns a Web `Response` if the middleware handled
28
+ * the request — or `null` if the stack called `next()` (a page route the
29
+ * caller should server-render).
30
+ *
31
+ * The bridge is **runtime-agnostic**: it depends only on `node:http` /
32
+ * `node:net` and Web globals (`Request`, `Response`), so it works under Bun,
33
+ * Node's own `fetch` servers, Deno, and Workers — not just Bun. The `vite`
34
+ * instance is injected, not imported, keeping this module free of a runtime
35
+ * Vite dependency.
36
+ *
37
+ * The response body is **buffered**: chunks written by the middleware are
38
+ * collected and the `Response` resolves on `end`, with `status` and `headers`
39
+ * read from the (by-then-final) `ServerResponse`. This is correct and robust
40
+ * for dev assets — transformed JS/CSS modules and source maps, which are small
41
+ * and already in memory when Vite writes them. Streaming would buy near-zero
42
+ * latency here (SSR render streaming goes through the renderer's
43
+ * `renderToReadableStream`, never this bridge) while introducing header-timing
44
+ * and backpressure hazards, so it is deliberately avoided.
45
+ *
46
+ * Headers set via `res.writeHead(status, headers)` are captured in addition to
47
+ * `res.getHeaders()` (Vite's static-file middleware sets `Content-Type` etc.
48
+ * that way for non-JS assets), and multi-value headers such as `set-cookie` are
49
+ * preserved as separate entries rather than comma-folded.
50
+ *
51
+ * Only `GET`/`HEAD` requests are bridged. A bare `IncomingMessage` carries no
52
+ * request body, so any middleware that reads one would hang; requests with a
53
+ * body (and other methods) return `null` so the caller handles them. This
54
+ * matches Vite's asset/module/HMR surface, which is entirely `GET`/`HEAD`.
55
+ *
56
+ * @param vite - A Vite dev server created with `middlewareMode: true`.
57
+ * @returns A function mapping a Web `Request` to a `Response` (Vite handled it)
58
+ * or `null` (a page route, a non-`GET`/`HEAD` request — pass through to SSR).
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * import { createServer as createViteServer } from "vite";
63
+ * import { viteFetchMiddleware } from "@canonical/react-ssr/server";
64
+ *
65
+ * const vite = await createViteServer({
66
+ * server: { middlewareMode: true },
67
+ * appType: "custom",
68
+ * });
69
+ * const handleAsset = viteFetchMiddleware(vite);
70
+ *
71
+ * Bun.serve({
72
+ * async fetch(req) {
73
+ * const asset = await handleAsset(req);
74
+ * if (asset) return asset; // /@vite/client, /src/**, CSS, HMR …
75
+ * return ssrRender(req); // page route
76
+ * },
77
+ * });
78
+ * ```
79
+ */
80
+ export declare function viteFetchMiddleware(vite: ViteMiddlewareServer): (request: Request) => Promise<Response | null>;
81
+ //# sourceMappingURL=viteFetchMiddleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viteFetchMiddleware.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/viteFetchMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG5D;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,CACX,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,KAC1B,IAAI,CAAC;CACX;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,oBAAoB,GACzB,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAsGhD"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@canonical/react-ssr",
3
3
  "description": "TBD",
4
- "version": "0.27.1-experimental.0",
4
+ "version": "0.28.0",
5
5
  "type": "module",
6
6
  "module": "dist/esm/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -70,9 +70,9 @@
70
70
  },
71
71
  "devDependencies": {
72
72
  "@biomejs/biome": "2.4.9",
73
- "@canonical/biome-config": "^0.27.1-experimental.0",
74
- "@canonical/typescript-config-react": "^0.27.1-experimental.0",
75
- "@canonical/webarchitect": "^0.27.1-experimental.0",
73
+ "@canonical/biome-config": "^0.28.0",
74
+ "@canonical/typescript-config-react": "^0.28.0",
75
+ "@canonical/webarchitect": "^0.28.0",
76
76
  "@types/express": "^5.0.6",
77
77
  "@types/node": "^24.12.0",
78
78
  "@types/react": "^19.2.14",
@@ -82,18 +82,22 @@
82
82
  "vitest": "^4.0.18"
83
83
  },
84
84
  "dependencies": {
85
- "@canonical/utils": "^0.27.1-experimental.0",
85
+ "@canonical/utils": "^0.28.0",
86
86
  "htmlparser2": "^10.1.0",
87
87
  "react": "^19.2.4",
88
88
  "react-dom": "^19.2.4"
89
89
  },
90
90
  "peerDependencies": {
91
- "express": "^5.2.1"
91
+ "express": "^5.2.1",
92
+ "vite": "^8.0.0"
92
93
  },
93
94
  "peerDependenciesMeta": {
94
95
  "express": {
95
96
  "optional": true
97
+ },
98
+ "vite": {
99
+ "optional": true
96
100
  }
97
101
  },
98
- "gitHead": "d3f5b9aab7bec07fce40a12b45097d28d3cf0201"
102
+ "gitHead": "8297d72122bcba903f7e8833cb23ccbaa164ed56"
99
103
  }