@elurjs/kit 2.4.4

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 (255) hide show
  1. package/CHANGELOG.md +874 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1330 -0
  4. package/bin/elur-kit.js +54 -0
  5. package/dist/lib/action/define.d.cts +72 -0
  6. package/dist/lib/action/define.d.ts +72 -0
  7. package/dist/lib/action/error-store.d.cts +29 -0
  8. package/dist/lib/action/error-store.d.ts +29 -0
  9. package/dist/lib/action/index.cjs +1 -0
  10. package/dist/lib/action/index.d.cts +64 -0
  11. package/dist/lib/action/index.d.ts +64 -0
  12. package/dist/lib/action/index.js +2 -0
  13. package/dist/lib/action/origin.d.cts +20 -0
  14. package/dist/lib/action/origin.d.ts +20 -0
  15. package/dist/lib/action/scan.d.cts +28 -0
  16. package/dist/lib/action/scan.d.ts +28 -0
  17. package/dist/lib/action/server.d.cts +30 -0
  18. package/dist/lib/action/server.d.ts +30 -0
  19. package/dist/lib/action-BB6N5yD-.js +111 -0
  20. package/dist/lib/action-BB6N5yD-.js.map +1 -0
  21. package/dist/lib/action-DZHihU3Z.cjs +2 -0
  22. package/dist/lib/action-DZHihU3Z.cjs.map +1 -0
  23. package/dist/lib/adapters/bun.cjs +30 -0
  24. package/dist/lib/adapters/bun.cjs.map +1 -0
  25. package/dist/lib/adapters/bun.d.cts +13 -0
  26. package/dist/lib/adapters/bun.d.ts +13 -0
  27. package/dist/lib/adapters/bun.js +65 -0
  28. package/dist/lib/adapters/bun.js.map +1 -0
  29. package/dist/lib/adapters/index.cjs +0 -0
  30. package/dist/lib/adapters/index.d.cts +30 -0
  31. package/dist/lib/adapters/index.d.ts +30 -0
  32. package/dist/lib/adapters/index.js +0 -0
  33. package/dist/lib/adapters/netlify.cjs +10 -0
  34. package/dist/lib/adapters/netlify.cjs.map +1 -0
  35. package/dist/lib/adapters/netlify.d.cts +13 -0
  36. package/dist/lib/adapters/netlify.d.ts +13 -0
  37. package/dist/lib/adapters/netlify.js +51 -0
  38. package/dist/lib/adapters/netlify.js.map +1 -0
  39. package/dist/lib/adapters/node.cjs +46 -0
  40. package/dist/lib/adapters/node.cjs.map +1 -0
  41. package/dist/lib/adapters/node.d.cts +13 -0
  42. package/dist/lib/adapters/node.d.ts +13 -0
  43. package/dist/lib/adapters/node.js +105 -0
  44. package/dist/lib/adapters/node.js.map +1 -0
  45. package/dist/lib/adapters/shared.d.cts +17 -0
  46. package/dist/lib/adapters/shared.d.ts +17 -0
  47. package/dist/lib/adapters/vercel.cjs +2 -0
  48. package/dist/lib/adapters/vercel.cjs.map +1 -0
  49. package/dist/lib/adapters/vercel.d.cts +9 -0
  50. package/dist/lib/adapters/vercel.d.ts +9 -0
  51. package/dist/lib/adapters/vercel.js +62 -0
  52. package/dist/lib/adapters/vercel.js.map +1 -0
  53. package/dist/lib/build/build.d.cts +83 -0
  54. package/dist/lib/build/build.d.ts +83 -0
  55. package/dist/lib/build/document-shell.d.cts +48 -0
  56. package/dist/lib/build/document-shell.d.ts +48 -0
  57. package/dist/lib/build/transform-source.d.cts +26 -0
  58. package/dist/lib/build/transform-source.d.ts +26 -0
  59. package/dist/lib/build/vite-build.d.cts +78 -0
  60. package/dist/lib/build/vite-build.d.ts +78 -0
  61. package/dist/lib/cache/policy.d.cts +25 -0
  62. package/dist/lib/cache/policy.d.ts +25 -0
  63. package/dist/lib/cache.d.cts +13 -0
  64. package/dist/lib/cache.d.ts +13 -0
  65. package/dist/lib/capabilities-C0TDQoMY.cjs +2 -0
  66. package/dist/lib/capabilities-C0TDQoMY.cjs.map +1 -0
  67. package/dist/lib/capabilities-C7txofmY.js +45 -0
  68. package/dist/lib/capabilities-C7txofmY.js.map +1 -0
  69. package/dist/lib/cli/commands.d.cts +15 -0
  70. package/dist/lib/cli/commands.d.ts +15 -0
  71. package/dist/lib/cli.cjs +5132 -0
  72. package/dist/lib/cli.cjs.map +1 -0
  73. package/dist/lib/cli.d.cts +30 -0
  74. package/dist/lib/cli.d.ts +30 -0
  75. package/dist/lib/cli.js +5131 -0
  76. package/dist/lib/cli.js.map +1 -0
  77. package/dist/lib/collections-Dbc8aRLf.js +233 -0
  78. package/dist/lib/collections-Dbc8aRLf.js.map +1 -0
  79. package/dist/lib/collections-VDy5g9p8.cjs +13 -0
  80. package/dist/lib/collections-VDy5g9p8.cjs.map +1 -0
  81. package/dist/lib/config/index.cjs +2 -0
  82. package/dist/lib/config/index.cjs.map +1 -0
  83. package/dist/lib/config/index.d.cts +100 -0
  84. package/dist/lib/config/index.d.ts +100 -0
  85. package/dist/lib/config/index.js +122 -0
  86. package/dist/lib/config/index.js.map +1 -0
  87. package/dist/lib/content/collections.d.cts +69 -0
  88. package/dist/lib/content/collections.d.ts +69 -0
  89. package/dist/lib/content/frontmatter.d.cts +20 -0
  90. package/dist/lib/content/frontmatter.d.ts +20 -0
  91. package/dist/lib/content/index.cjs +2 -0
  92. package/dist/lib/content/index.cjs.map +1 -0
  93. package/dist/lib/content/index.d.cts +5 -0
  94. package/dist/lib/content/index.d.ts +5 -0
  95. package/dist/lib/content/index.js +28 -0
  96. package/dist/lib/content/index.js.map +1 -0
  97. package/dist/lib/content/markdown.d.cts +6 -0
  98. package/dist/lib/content/markdown.d.ts +6 -0
  99. package/dist/lib/content/raw.d.cts +9 -0
  100. package/dist/lib/content/raw.d.ts +9 -0
  101. package/dist/lib/content/schema.d.cts +14 -0
  102. package/dist/lib/content/schema.d.ts +14 -0
  103. package/dist/lib/errors-0X7pCFNU.cjs +2 -0
  104. package/dist/lib/errors-0X7pCFNU.cjs.map +1 -0
  105. package/dist/lib/errors-ePYxDlhU.js +70 -0
  106. package/dist/lib/errors-ePYxDlhU.js.map +1 -0
  107. package/dist/lib/errors.d.cts +84 -0
  108. package/dist/lib/errors.d.ts +84 -0
  109. package/dist/lib/hydrate-8a3TbQbs.cjs +2 -0
  110. package/dist/lib/hydrate-8a3TbQbs.cjs.map +1 -0
  111. package/dist/lib/hydrate-CgZGrTxF.js +126 -0
  112. package/dist/lib/hydrate-CgZGrTxF.js.map +1 -0
  113. package/dist/lib/image/index.cjs +2 -0
  114. package/dist/lib/image/index.cjs.map +1 -0
  115. package/dist/lib/image/index.d.cts +37 -0
  116. package/dist/lib/image/index.d.ts +37 -0
  117. package/dist/lib/image/index.js +49 -0
  118. package/dist/lib/image/index.js.map +1 -0
  119. package/dist/lib/image/pipeline.d.cts +37 -0
  120. package/dist/lib/image/pipeline.d.ts +37 -0
  121. package/dist/lib/image/registry.cjs +2 -0
  122. package/dist/lib/image/registry.cjs.map +1 -0
  123. package/dist/lib/image/registry.d.cts +26 -0
  124. package/dist/lib/image/registry.d.ts +26 -0
  125. package/dist/lib/image/registry.js +23 -0
  126. package/dist/lib/image/registry.js.map +1 -0
  127. package/dist/lib/image/service.cjs +2 -0
  128. package/dist/lib/image/service.cjs.map +1 -0
  129. package/dist/lib/image/service.d.cts +164 -0
  130. package/dist/lib/image/service.d.ts +164 -0
  131. package/dist/lib/image/service.js +308 -0
  132. package/dist/lib/image/service.js.map +1 -0
  133. package/dist/lib/index.cjs +1 -0
  134. package/dist/lib/index.cjs.map +1 -0
  135. package/dist/lib/index.d.cts +38 -0
  136. package/dist/lib/index.d.ts +38 -0
  137. package/dist/lib/index.js +1 -0
  138. package/dist/lib/index.js.map +1 -0
  139. package/dist/lib/integrations/hooks.d.cts +58 -0
  140. package/dist/lib/integrations/hooks.d.ts +58 -0
  141. package/dist/lib/integrations/index.cjs +1 -0
  142. package/dist/lib/integrations/index.d.cts +18 -0
  143. package/dist/lib/integrations/index.d.ts +18 -0
  144. package/dist/lib/integrations/index.js +2 -0
  145. package/dist/lib/integrations-7dpN1RYB.js +35 -0
  146. package/dist/lib/integrations-7dpN1RYB.js.map +1 -0
  147. package/dist/lib/integrations-DDqfWjvH.cjs +2 -0
  148. package/dist/lib/integrations-DDqfWjvH.cjs.map +1 -0
  149. package/dist/lib/interpolation-plugin-Bt-KRKVY.js +365 -0
  150. package/dist/lib/interpolation-plugin-Bt-KRKVY.js.map +1 -0
  151. package/dist/lib/interpolation-plugin-CMPCDlVJ.cjs +31 -0
  152. package/dist/lib/interpolation-plugin-CMPCDlVJ.cjs.map +1 -0
  153. package/dist/lib/island/generate-entry.d.cts +27 -0
  154. package/dist/lib/island/generate-entry.d.ts +27 -0
  155. package/dist/lib/island/hydrate.d.cts +33 -0
  156. package/dist/lib/island/hydrate.d.ts +33 -0
  157. package/dist/lib/island/index.cjs +1 -0
  158. package/dist/lib/island/index.d.cts +2 -0
  159. package/dist/lib/island/index.d.ts +2 -0
  160. package/dist/lib/island/index.js +1 -0
  161. package/dist/lib/island/island.d.cts +32 -0
  162. package/dist/lib/island/island.d.ts +32 -0
  163. package/dist/lib/island/scan.d.cts +14 -0
  164. package/dist/lib/island/scan.d.ts +14 -0
  165. package/dist/lib/manifest/index.cjs +3 -0
  166. package/dist/lib/manifest/index.cjs.map +1 -0
  167. package/dist/lib/manifest/index.d.cts +18 -0
  168. package/dist/lib/manifest/index.d.ts +18 -0
  169. package/dist/lib/manifest/index.js +110 -0
  170. package/dist/lib/manifest/index.js.map +1 -0
  171. package/dist/lib/middleware/index.d.cts +56 -0
  172. package/dist/lib/middleware/index.d.ts +56 -0
  173. package/dist/lib/middleware/stream-boundary.d.cts +53 -0
  174. package/dist/lib/middleware/stream-boundary.d.ts +53 -0
  175. package/dist/lib/node-http-DRAUhO0c.js +617 -0
  176. package/dist/lib/node-http-DRAUhO0c.js.map +1 -0
  177. package/dist/lib/node-http-DhxguYyz.cjs +13 -0
  178. package/dist/lib/node-http-DhxguYyz.cjs.map +1 -0
  179. package/dist/lib/render/render-to-string.d.cts +12 -0
  180. package/dist/lib/render/render-to-string.d.ts +12 -0
  181. package/dist/lib/render/ssr-flag.d.cts +4 -0
  182. package/dist/lib/render/ssr-flag.d.ts +4 -0
  183. package/dist/lib/route-scanner-JY6YrNH5.cjs +2 -0
  184. package/dist/lib/route-scanner-JY6YrNH5.cjs.map +1 -0
  185. package/dist/lib/route-scanner-XcLId7lK.js +100 -0
  186. package/dist/lib/route-scanner-XcLId7lK.js.map +1 -0
  187. package/dist/lib/router/client.cjs +2 -0
  188. package/dist/lib/router/client.cjs.map +1 -0
  189. package/dist/lib/router/client.d.cts +47 -0
  190. package/dist/lib/router/client.d.ts +47 -0
  191. package/dist/lib/router/client.js +298 -0
  192. package/dist/lib/router/client.js.map +1 -0
  193. package/dist/lib/router/route-scanner.d.cts +50 -0
  194. package/dist/lib/router/route-scanner.d.ts +50 -0
  195. package/dist/lib/runtime/capabilities.d.cts +47 -0
  196. package/dist/lib/runtime/capabilities.d.ts +47 -0
  197. package/dist/lib/runtime/context.d.cts +140 -0
  198. package/dist/lib/runtime/context.d.ts +140 -0
  199. package/dist/lib/runtime/handler.d.cts +39 -0
  200. package/dist/lib/runtime/handler.d.ts +39 -0
  201. package/dist/lib/runtime/index.cjs +1 -0
  202. package/dist/lib/runtime/index.d.cts +6 -0
  203. package/dist/lib/runtime/index.d.ts +6 -0
  204. package/dist/lib/runtime/index.js +4 -0
  205. package/dist/lib/runtime/node-http.d.cts +2 -0
  206. package/dist/lib/runtime/node-http.d.ts +2 -0
  207. package/dist/lib/runtime/security-headers.d.cts +13 -0
  208. package/dist/lib/runtime/security-headers.d.ts +13 -0
  209. package/dist/lib/runtime/static.d.cts +1 -0
  210. package/dist/lib/runtime/static.d.ts +1 -0
  211. package/dist/lib/runtime-CrH5X-Es.cjs +2 -0
  212. package/dist/lib/runtime-CrH5X-Es.cjs.map +1 -0
  213. package/dist/lib/runtime-Ds2-wH6P.js +520 -0
  214. package/dist/lib/runtime-Ds2-wH6P.js.map +1 -0
  215. package/dist/lib/scan-CY2O9ty6.cjs +2 -0
  216. package/dist/lib/scan-CY2O9ty6.cjs.map +1 -0
  217. package/dist/lib/scan-CjMUgnsd.js +22 -0
  218. package/dist/lib/scan-CjMUgnsd.js.map +1 -0
  219. package/dist/lib/scan-DXzYtmRQ.cjs +2 -0
  220. package/dist/lib/scan-DXzYtmRQ.cjs.map +1 -0
  221. package/dist/lib/scan-Dn93ycXG.js +33 -0
  222. package/dist/lib/scan-Dn93ycXG.js.map +1 -0
  223. package/dist/lib/seo/index.cjs +10 -0
  224. package/dist/lib/seo/index.cjs.map +1 -0
  225. package/dist/lib/seo/index.d.cts +99 -0
  226. package/dist/lib/seo/index.d.ts +99 -0
  227. package/dist/lib/seo/index.js +41 -0
  228. package/dist/lib/seo/index.js.map +1 -0
  229. package/dist/lib/shared-CfqOLsKj.cjs +183 -0
  230. package/dist/lib/shared-CfqOLsKj.cjs.map +1 -0
  231. package/dist/lib/shared-DU3iQgr7.js +236 -0
  232. package/dist/lib/shared-DU3iQgr7.js.map +1 -0
  233. package/dist/lib/ssr/match.d.cts +25 -0
  234. package/dist/lib/ssr/match.d.ts +25 -0
  235. package/dist/lib/ssr/render.d.cts +62 -0
  236. package/dist/lib/ssr/render.d.ts +62 -0
  237. package/dist/lib/ssr/server.d.cts +41 -0
  238. package/dist/lib/ssr/server.d.ts +41 -0
  239. package/dist/lib/ssr/stream.d.cts +48 -0
  240. package/dist/lib/ssr/stream.d.ts +48 -0
  241. package/dist/lib/stream-CpOG052V.js +104 -0
  242. package/dist/lib/stream-CpOG052V.js.map +1 -0
  243. package/dist/lib/stream-DmZjYqHm.cjs +17 -0
  244. package/dist/lib/stream-DmZjYqHm.cjs.map +1 -0
  245. package/dist/lib/types.d.cts +97 -0
  246. package/dist/lib/types.d.ts +97 -0
  247. package/dist/lib/vite/index.cjs +2 -0
  248. package/dist/lib/vite/index.cjs.map +1 -0
  249. package/dist/lib/vite/index.d.cts +41 -0
  250. package/dist/lib/vite/index.d.ts +41 -0
  251. package/dist/lib/vite/index.js +229 -0
  252. package/dist/lib/vite/index.js.map +1 -0
  253. package/dist/lib/vite/interpolation-plugin.d.cts +64 -0
  254. package/dist/lib/vite/interpolation-plugin.d.ts +64 -0
  255. package/package.json +292 -0
@@ -0,0 +1,104 @@
1
+ import { u as e } from "./errors-ePYxDlhU.js";
2
+ import { _ as t, l as n, o as r, v as i } from "./node-http-DRAUhO0c.js";
3
+ //#region src/ssr/stream.ts
4
+ var a = /* @__PURE__ */ e({
5
+ RouteNotFoundError: () => u,
6
+ renderPageBody: () => d,
7
+ renderStreamingPage: () => l
8
+ }), o = (e) => import(e);
9
+ function s(e, t) {
10
+ return e.replace(/:([a-zA-Z0-9_]+)(\*)?/g, (e, n, r) => {
11
+ let i = t[n];
12
+ return i == null ? "" : r && Array.isArray(i) ? i.join("/") : String(i);
13
+ });
14
+ }
15
+ function c(e, t) {
16
+ return `<script type="module">${`
17
+ async function __elurJsStreamRender() {
18
+ try {
19
+ const url = "/__elur-js/render?page=" + encodeURIComponent(${JSON.stringify(e)}) + "&search=" + encodeURIComponent(${JSON.stringify(t)});
20
+ const res = await fetch(url);
21
+ if (!res.ok) throw new Error("Streaming render failed: " + res.status);
22
+ const html = await res.text();
23
+ const app = document.getElementById("app");
24
+ if (app) app.innerHTML = html;
25
+ document.dispatchEvent(new CustomEvent("elur:rendered"));
26
+ } catch (err) {
27
+ console.error("[elur-kit] streaming render failed", err);
28
+ }
29
+ }
30
+ __elurJsStreamRender();
31
+ `}<\/script>`;
32
+ }
33
+ async function l(e) {
34
+ let { route: n, params: r, searchParams: a, config: l, importer: u = o, actions: d } = e;
35
+ if (!n.loadingPath) throw Error("Cannot stream a page without a loading.ts boundary");
36
+ let { default: f } = await u(n.loadingPath), p = `<div id="elur-loading">${await i(() => f())}</div>${c(s(n.path, r), a.toString())}`, m = {}, h = [], g = [];
37
+ if (n.layouts.length > 0) {
38
+ let t = n.layouts[0], i = t.replace(/layout\.ts$/, "layout.data.ts");
39
+ if (i !== t) try {
40
+ let t = await u(i), n = t.load ? await t.load({
41
+ params: r,
42
+ searchParams: a,
43
+ request: e.request
44
+ }) : void 0;
45
+ if (n && typeof n == "object") {
46
+ let e = n.htmlAttributes;
47
+ e && Object.assign(m, e);
48
+ let t = n.headScripts;
49
+ Array.isArray(t) && h.push(...t);
50
+ let r = n.headLinks;
51
+ Array.isArray(r) && g.push(...r);
52
+ }
53
+ } catch {}
54
+ }
55
+ return t({
56
+ title: "Loading...",
57
+ lang: l.lang,
58
+ body: p,
59
+ data: {
60
+ __elur_js_streaming: !0,
61
+ page: n.path
62
+ },
63
+ actions: d,
64
+ htmlAttributes: m,
65
+ headScripts: h,
66
+ headLinks: g,
67
+ clientEntry: l.clientEntry
68
+ });
69
+ }
70
+ var u = class extends Error {
71
+ constructor(e) {
72
+ super(`No route found for ${e}`), this.name = "RouteNotFoundError";
73
+ }
74
+ };
75
+ async function d(e) {
76
+ let { routes: t, pathname: i, searchParams: a, config: s, actions: c, importer: l = o, request: d } = e, f = r(i, t.pages);
77
+ if (!f) throw new u(i);
78
+ let p = await n({
79
+ route: f.route,
80
+ params: f.params,
81
+ searchParams: a,
82
+ config: s,
83
+ actions: c,
84
+ importer: l,
85
+ request: d
86
+ });
87
+ if (p.response) return {
88
+ body: "",
89
+ title: "",
90
+ response: p.response
91
+ };
92
+ let m = p.html.match(/<div id="app">([\s\S]*)<\/div>\s*(<script|$)/), h = m ? m[1].trim() : p.html, g = p.html.match(/<title[^>]*>([^<]*)<\/title>/);
93
+ return {
94
+ body: h,
95
+ title: g ? g[1] : p.resolvedTitle ?? "",
96
+ fullHtml: p.html,
97
+ clearActionErrorCookie: p.clearActionErrorCookie,
98
+ head: p.head
99
+ };
100
+ }
101
+ //#endregion
102
+ export { a as i, d as n, l as r, u as t };
103
+
104
+ //# sourceMappingURL=stream-CpOG052V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-CpOG052V.js","names":[],"sources":["../../src/ssr/stream.ts"],"sourcesContent":["import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell } from \"../build/document-shell.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad } from \"../types.js\";\nimport { matchRoute } from \"./match.js\";\nimport { renderPage } from \"./render.js\";\n\nexport interface StreamingPageOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n importer?: (path: string) => Promise<unknown>;\n actions?: Record<string, string[]>;\n request?: Request;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/** Builds the concrete URL path for a route pattern given matched params. */\nfunction buildConcretePath(\n routePath: string,\n params: Record<string, string | string[]>,\n): string {\n return routePath.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_m, name: string, catchAll?: string) => {\n const value = params[name];\n if (value === undefined || value === null) return \"\";\n return catchAll ? (Array.isArray(value) ? value.join(\"/\") : String(value)) : String(value);\n });\n}\n\nfunction streamingScript(page: string, search: string): string {\n const src = `\n async function __elurJsStreamRender() {\n try {\n const url = \"/__elur-js/render?page=\" + encodeURIComponent(${JSON.stringify(page)}) + \"&search=\" + encodeURIComponent(${JSON.stringify(search)});\n const res = await fetch(url);\n if (!res.ok) throw new Error(\"Streaming render failed: \" + res.status);\n const html = await res.text();\n const app = document.getElementById(\"app\");\n if (app) app.innerHTML = html;\n document.dispatchEvent(new CustomEvent(\"elur:rendered\"));\n } catch (err) {\n console.error(\"[elur-kit] streaming render failed\", err);\n }\n }\n __elurJsStreamRender();\n `;\n return `<script type=\"module\">${src}</script>`;\n}\n\n/**\n * Render a page shell that shows the loading boundary while the real content\n * is fetched and injected by the client.\n */\nexport async function renderStreamingPage(options: StreamingPageOptions): Promise<string> {\n const { route, params, searchParams, config, importer = defaultImport, actions } = options;\n if (!route.loadingPath) {\n throw new Error(\"Cannot stream a page without a loading.ts boundary\");\n }\n\n const { default: Loading } = (await importer(route.loadingPath)) as {\n default: () => ElurTemplate;\n };\n\n const loadingBody = await renderToString(() => Loading());\n const concretePath = buildConcretePath(route.path, params);\n const body = `<div id=\"elur-loading\">${loadingBody}</div>${streamingScript(concretePath, searchParams.toString())}`;\n\n // Apply <html> attributes and head scripts (e.g. data-theme and the no-flash\n // theme script) from the root layout loader so the shell paints correctly\n // before the real content arrives.\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n if (route.layouts.length > 0) {\n const rootLayout = route.layouts[0];\n const dataPath = rootLayout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (dataPath !== rootLayout) {\n try {\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n const layoutData = mod.load ? await mod.load({ params, searchParams, request: options.request }) : undefined;\n if (layoutData && typeof layoutData === \"object\") {\n const attrs = (layoutData as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (layoutData as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (layoutData as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n }\n } catch {\n // The root layout loader is optional; ignore failures here.\n }\n }\n }\n\n return documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n clientEntry: config.clientEntry,\n });\n}\n\nexport interface RenderPageBodyOptions {\n routes: ScannedRoutes;\n pathname: string;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n}\n\nexport interface RenderPageBodyResult {\n /** Inner HTML body for the page (without the document shell). */\n body: string;\n /** Page title extracted from the rendered shell. */\n title: string;\n /** Full rendered document shell (used for ISR caching). */\n fullHtml?: string;\n /** `Set-Cookie` value that clears a consumed action error cookie. */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /** First-class Response when a loader threw one (A-22). */\n response?: Response;\n}\n\n/** Thrown by `renderPageBody` when the requested path has no matching route. */\nexport class RouteNotFoundError extends Error {\n constructor(pathname: string) {\n super(`No route found for ${pathname}`);\n this.name = \"RouteNotFoundError\";\n }\n}\n\n/**\n * Render only the inner HTML body for a page. Used by the streaming endpoint\n * to inject the real content into the shell.\n */\nexport async function renderPageBody(options: RenderPageBodyOptions): Promise<RenderPageBodyResult> {\n const { routes, pathname, searchParams, config, actions, importer = defaultImport, request } = options;\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n throw new RouteNotFoundError(pathname);\n }\n\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), propagate it (A-22).\n if (result.response) {\n return {\n body: \"\",\n title: \"\",\n response: result.response,\n };\n }\n\n const bodyMatch = result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n const body = bodyMatch ? bodyMatch[1].trim() : result.html;\n const titleMatch = result.html.match(/<title[^>]*>([^<]*)<\\/title>/);\n return {\n body,\n title: titleMatch ? titleMatch[1] : result.resolvedTitle ?? \"\",\n fullHtml: result.html,\n clearActionErrorCookie: result.clearActionErrorCookie,\n head: result.head,\n };\n}\n"],"mappings":";;;;;;;IAmBM,KAAiB,MAAiB,OAAO;AAG/C,SAAS,EACP,GACA,GACQ;CACR,OAAO,EAAU,QAAQ,2BAA2B,GAAI,GAAc,MAAsB;EAC1F,IAAM,IAAQ,EAAO;EAErB,OADI,KAAiC,OAAa,KAC3C,KAAY,MAAM,QAAQ,CAAK,IAAI,EAAM,KAAK,GAAG,IAAI,OAAO,CAAK;CAC1E,CAAC;AACH;AAEA,SAAS,EAAgB,GAAc,GAAwB;CAiB7D,OAAO,yBAAyB;;;qEAbmC,KAAK,UAAU,CAAI,EAAE,sCAAsC,KAAK,UAAU,CAAM,EAAE;;;;;;;;;;;;IAajH;AACtC;AAMA,eAAsB,EAAoB,GAAgD;CACxF,IAAM,EAAE,UAAO,WAAQ,iBAAc,WAAQ,cAAW,GAAe,eAAY;CACnF,IAAI,CAAC,EAAM,aACT,MAAU,MAAM,oDAAoD;CAGtE,IAAM,EAAE,SAAS,MAAa,MAAM,EAAS,EAAM,WAAW,GAMxD,IAAO,0BAA0B,MAFb,QAAqB,EAAQ,CAAC,EAEL,QAAQ,EADtC,EAAkB,EAAM,MAAM,CACwB,GAAc,EAAa,SAAS,CAAC,KAK1G,IAAyC,CAAC,GAC1C,IAAwB,CAAC,GACzB,IAAsB,CAAC;CAC7B,IAAI,EAAM,QAAQ,SAAS,GAAG;EAC5B,IAAM,IAAa,EAAM,QAAQ,IAC3B,IAAW,EAAW,QAAQ,eAAe,gBAAgB;EACnE,IAAI,MAAa,GACf,IAAI;GACF,IAAM,IAAO,MAAM,EAAS,CAAQ,GAC9B,IAAa,EAAI,OAAO,MAAM,EAAI,KAAK;IAAE;IAAQ;IAAc,SAAS,EAAQ;GAAQ,CAAC,IAAI,KAAA;GACnG,IAAI,KAAc,OAAO,KAAe,UAAU;IAChD,IAAM,IAAS,EAA2D;IAC1E,AAAI,KAAO,OAAO,OAAO,GAAgB,CAAK;IAC9C,IAAM,IAAW,EAA0C;IAC3D,AAAI,MAAM,QAAQ,CAAO,KAAG,EAAY,KAAK,GAAG,CAAO;IACvD,IAAM,IAAS,EAAwC;IACvD,AAAI,MAAM,QAAQ,CAAK,KAAG,EAAU,KAAK,GAAG,CAAK;GACnD;EACF,QAAQ,CAER;CAEJ;CAEA,OAAO,EAAc;EACnB,OAAO;EACP,MAAM,EAAO;EACb;EACA,MAAM;GAAE,qBAAqB;GAAM,MAAM,EAAM;EAAK;EACpD;EACA;EACA;EACA;EACA,aAAa,EAAO;CACtB,CAAC;AACH;AA4BA,IAAa,IAAb,cAAwC,MAAM;CAC5C,YAAY,GAAkB;EAE5B,AADA,MAAM,sBAAsB,GAAU,GACtC,KAAK,OAAO;CACd;AACF;AAMA,eAAsB,EAAe,GAA+D;CAClG,IAAM,EAAE,WAAQ,aAAU,iBAAc,WAAQ,YAAS,cAAW,GAAe,eAAY,GACzF,IAAQ,EAAW,GAAU,EAAO,KAAK;CAC/C,IAAI,CAAC,GACH,MAAM,IAAI,EAAmB,CAAQ;CAGvC,IAAM,IAAS,MAAM,EAAW;EAC9B,OAAO,EAAM;EACb,QAAQ,EAAM;EACd;EACA;EACA;EACA;EACA;CACF,CAAC;CAGD,IAAI,EAAO,UACT,OAAO;EACL,MAAM;EACN,OAAO;EACP,UAAU,EAAO;CACnB;CAGF,IAAM,IAAY,EAAO,KAAK,MAAM,8CAA8C,GAC5E,IAAO,IAAY,EAAU,EAAE,CAAC,KAAK,IAAI,EAAO,MAChD,IAAa,EAAO,KAAK,MAAM,8BAA8B;CACnE,OAAO;EACL;EACA,OAAO,IAAa,EAAW,KAAK,EAAO,iBAAiB;EAC5D,UAAU,EAAO;EACjB,wBAAwB,EAAO;EAC/B,MAAM,EAAO;CACf;AACF"}
@@ -0,0 +1,17 @@
1
+ const e=require("./errors-0X7pCFNU.cjs"),t=require("./node-http-DhxguYyz.cjs");var n=e.u({RouteNotFoundError:()=>s,renderPageBody:()=>c,renderStreamingPage:()=>o}),r=e=>import(e);function i(e,t){return e.replace(/:([a-zA-Z0-9_]+)(\*)?/g,(e,n,r)=>{let i=t[n];return i==null?``:r&&Array.isArray(i)?i.join(`/`):String(i)})}function a(e,t){return`<script type="module">${`
2
+ async function __elurJsStreamRender() {
3
+ try {
4
+ const url = "/__elur-js/render?page=" + encodeURIComponent(${JSON.stringify(e)}) + "&search=" + encodeURIComponent(${JSON.stringify(t)});
5
+ const res = await fetch(url);
6
+ if (!res.ok) throw new Error("Streaming render failed: " + res.status);
7
+ const html = await res.text();
8
+ const app = document.getElementById("app");
9
+ if (app) app.innerHTML = html;
10
+ document.dispatchEvent(new CustomEvent("elur:rendered"));
11
+ } catch (err) {
12
+ console.error("[elur-kit] streaming render failed", err);
13
+ }
14
+ }
15
+ __elurJsStreamRender();
16
+ `}<\/script>`}async function o(e){let{route:n,params:o,searchParams:s,config:c,importer:l=r,actions:u}=e;if(!n.loadingPath)throw Error(`Cannot stream a page without a loading.ts boundary`);let{default:d}=await l(n.loadingPath),f=`<div id="elur-loading">${await t.v(()=>d())}</div>${a(i(n.path,o),s.toString())}`,p={},m=[],h=[];if(n.layouts.length>0){let t=n.layouts[0],r=t.replace(/layout\.ts$/,`layout.data.ts`);if(r!==t)try{let t=await l(r),n=t.load?await t.load({params:o,searchParams:s,request:e.request}):void 0;if(n&&typeof n==`object`){let e=n.htmlAttributes;e&&Object.assign(p,e);let t=n.headScripts;Array.isArray(t)&&m.push(...t);let r=n.headLinks;Array.isArray(r)&&h.push(...r)}}catch{}}return t._({title:`Loading...`,lang:c.lang,body:f,data:{__elur_js_streaming:!0,page:n.path},actions:u,htmlAttributes:p,headScripts:m,headLinks:h,clientEntry:c.clientEntry})}var s=class extends Error{constructor(e){super(`No route found for ${e}`),this.name=`RouteNotFoundError`}};async function c(e){let{routes:n,pathname:i,searchParams:a,config:o,actions:c,importer:l=r,request:u}=e,d=t.o(i,n.pages);if(!d)throw new s(i);let f=await t.l({route:d.route,params:d.params,searchParams:a,config:o,actions:c,importer:l,request:u});if(f.response)return{body:``,title:``,response:f.response};let p=f.html.match(/<div id="app">([\s\S]*)<\/div>\s*(<script|$)/),m=p?p[1].trim():f.html,h=f.html.match(/<title[^>]*>([^<]*)<\/title>/);return{body:m,title:h?h[1]:f.resolvedTitle??``,fullHtml:f.html,clearActionErrorCookie:f.clearActionErrorCookie,head:f.head}}Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return s}});
17
+ //# sourceMappingURL=stream-DmZjYqHm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-DmZjYqHm.cjs","names":[],"sources":["../../src/ssr/stream.ts"],"sourcesContent":["import type { ElurTemplate } from \"@elurjs/core\";\nimport { renderToString } from \"../render/render-to-string.js\";\nimport { documentShell } from \"../build/document-shell.js\";\nimport type { PageRoute, ScannedRoutes } from \"../router/route-scanner.js\";\nimport type { BuildConfig } from \"../build/build.js\";\nimport type { PageDataLoad } from \"../types.js\";\nimport { matchRoute } from \"./match.js\";\nimport { renderPage } from \"./render.js\";\n\nexport interface StreamingPageOptions {\n route: PageRoute;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n importer?: (path: string) => Promise<unknown>;\n actions?: Record<string, string[]>;\n request?: Request;\n}\n\nconst defaultImport = (path: string) => import(path);\n\n/** Builds the concrete URL path for a route pattern given matched params. */\nfunction buildConcretePath(\n routePath: string,\n params: Record<string, string | string[]>,\n): string {\n return routePath.replace(/:([a-zA-Z0-9_]+)(\\*)?/g, (_m, name: string, catchAll?: string) => {\n const value = params[name];\n if (value === undefined || value === null) return \"\";\n return catchAll ? (Array.isArray(value) ? value.join(\"/\") : String(value)) : String(value);\n });\n}\n\nfunction streamingScript(page: string, search: string): string {\n const src = `\n async function __elurJsStreamRender() {\n try {\n const url = \"/__elur-js/render?page=\" + encodeURIComponent(${JSON.stringify(page)}) + \"&search=\" + encodeURIComponent(${JSON.stringify(search)});\n const res = await fetch(url);\n if (!res.ok) throw new Error(\"Streaming render failed: \" + res.status);\n const html = await res.text();\n const app = document.getElementById(\"app\");\n if (app) app.innerHTML = html;\n document.dispatchEvent(new CustomEvent(\"elur:rendered\"));\n } catch (err) {\n console.error(\"[elur-kit] streaming render failed\", err);\n }\n }\n __elurJsStreamRender();\n `;\n return `<script type=\"module\">${src}</script>`;\n}\n\n/**\n * Render a page shell that shows the loading boundary while the real content\n * is fetched and injected by the client.\n */\nexport async function renderStreamingPage(options: StreamingPageOptions): Promise<string> {\n const { route, params, searchParams, config, importer = defaultImport, actions } = options;\n if (!route.loadingPath) {\n throw new Error(\"Cannot stream a page without a loading.ts boundary\");\n }\n\n const { default: Loading } = (await importer(route.loadingPath)) as {\n default: () => ElurTemplate;\n };\n\n const loadingBody = await renderToString(() => Loading());\n const concretePath = buildConcretePath(route.path, params);\n const body = `<div id=\"elur-loading\">${loadingBody}</div>${streamingScript(concretePath, searchParams.toString())}`;\n\n // Apply <html> attributes and head scripts (e.g. data-theme and the no-flash\n // theme script) from the root layout loader so the shell paints correctly\n // before the real content arrives.\n const htmlAttributes: Record<string, string> = {};\n const headScripts: string[] = [];\n const headLinks: string[] = [];\n if (route.layouts.length > 0) {\n const rootLayout = route.layouts[0];\n const dataPath = rootLayout.replace(/layout\\.ts$/, \"layout.data.ts\");\n if (dataPath !== rootLayout) {\n try {\n const mod = (await importer(dataPath)) as { load?: PageDataLoad };\n const layoutData = mod.load ? await mod.load({ params, searchParams, request: options.request }) : undefined;\n if (layoutData && typeof layoutData === \"object\") {\n const attrs = (layoutData as { htmlAttributes?: Record<string, string> }).htmlAttributes;\n if (attrs) Object.assign(htmlAttributes, attrs);\n const scripts = (layoutData as { headScripts?: string[] }).headScripts;\n if (Array.isArray(scripts)) headScripts.push(...scripts);\n const links = (layoutData as { headLinks?: string[] }).headLinks;\n if (Array.isArray(links)) headLinks.push(...links);\n }\n } catch {\n // The root layout loader is optional; ignore failures here.\n }\n }\n }\n\n return documentShell({\n title: \"Loading...\",\n lang: config.lang,\n body,\n data: { __elur_js_streaming: true, page: route.path },\n actions,\n htmlAttributes,\n headScripts,\n headLinks,\n clientEntry: config.clientEntry,\n });\n}\n\nexport interface RenderPageBodyOptions {\n routes: ScannedRoutes;\n pathname: string;\n searchParams: URLSearchParams;\n config: Pick<BuildConfig, \"lang\" | \"clientEntry\">;\n actions?: Record<string, string[]>;\n importer?: (path: string) => Promise<unknown>;\n request?: Request;\n}\n\nexport interface RenderPageBodyResult {\n /** Inner HTML body for the page (without the document shell). */\n body: string;\n /** Page title extracted from the rendered shell. */\n title: string;\n /** Full rendered document shell (used for ISR caching). */\n fullHtml?: string;\n /** `Set-Cookie` value that clears a consumed action error cookie. */\n clearActionErrorCookie?: string;\n /** `<head>` tags (title, meta, OG, twitter) for the SPA router to merge. */\n head?: string;\n /** First-class Response when a loader threw one (A-22). */\n response?: Response;\n}\n\n/** Thrown by `renderPageBody` when the requested path has no matching route. */\nexport class RouteNotFoundError extends Error {\n constructor(pathname: string) {\n super(`No route found for ${pathname}`);\n this.name = \"RouteNotFoundError\";\n }\n}\n\n/**\n * Render only the inner HTML body for a page. Used by the streaming endpoint\n * to inject the real content into the shell.\n */\nexport async function renderPageBody(options: RenderPageBodyOptions): Promise<RenderPageBodyResult> {\n const { routes, pathname, searchParams, config, actions, importer = defaultImport, request } = options;\n const match = matchRoute(pathname, routes.pages);\n if (!match) {\n throw new RouteNotFoundError(pathname);\n }\n\n const result = await renderPage({\n route: match.route,\n params: match.params,\n searchParams,\n config,\n actions,\n importer,\n request,\n });\n\n // If a loader threw a Response (redirect, 404, etc.), propagate it (A-22).\n if (result.response) {\n return {\n body: \"\",\n title: \"\",\n response: result.response,\n };\n }\n\n const bodyMatch = result.html.match(/<div id=\"app\">([\\s\\S]*)<\\/div>\\s*(<script|$)/);\n const body = bodyMatch ? bodyMatch[1].trim() : result.html;\n const titleMatch = result.html.match(/<title[^>]*>([^<]*)<\\/title>/);\n return {\n body,\n title: titleMatch ? titleMatch[1] : result.resolvedTitle ?? \"\",\n fullHtml: result.html,\n clearActionErrorCookie: result.clearActionErrorCookie,\n head: result.head,\n };\n}\n"],"mappings":"oKAmBM,EAAiB,GAAiB,OAAO,GAG/C,SAAS,EACP,EACA,EACQ,CACR,OAAO,EAAU,QAAQ,0BAA2B,EAAI,EAAc,IAAsB,CAC1F,IAAM,EAAQ,EAAO,GAErB,OADI,GAAiC,KAAa,GAC3C,GAAY,MAAM,QAAQ,CAAK,EAAI,EAAM,KAAK,GAAG,EAAI,OAAO,CAAK,CAC1E,CAAC,CACH,CAEA,SAAS,EAAgB,EAAc,EAAwB,CAiB7D,MAAO,yBAAyB;;;qEAbmC,KAAK,UAAU,CAAI,EAAE,sCAAsC,KAAK,UAAU,CAAM,EAAE;;;;;;;;;;;;IAajH,WACtC,CAMA,eAAsB,EAAoB,EAAgD,CACxF,GAAM,CAAE,QAAO,SAAQ,eAAc,SAAQ,WAAW,EAAe,WAAY,EACnF,GAAI,CAAC,EAAM,YACT,MAAU,MAAM,oDAAoD,EAGtE,GAAM,CAAE,QAAS,GAAa,MAAM,EAAS,EAAM,WAAW,EAMxD,EAAO,0BAA0B,MAFb,EAAA,MAAqB,EAAQ,CAAC,EAEL,QAAQ,EADtC,EAAkB,EAAM,KAAM,CACwB,EAAc,EAAa,SAAS,CAAC,IAK1G,EAAyC,CAAC,EAC1C,EAAwB,CAAC,EACzB,EAAsB,CAAC,EAC7B,GAAI,EAAM,QAAQ,OAAS,EAAG,CAC5B,IAAM,EAAa,EAAM,QAAQ,GAC3B,EAAW,EAAW,QAAQ,cAAe,gBAAgB,EACnE,GAAI,IAAa,EACf,GAAI,CACF,IAAM,EAAO,MAAM,EAAS,CAAQ,EAC9B,EAAa,EAAI,KAAO,MAAM,EAAI,KAAK,CAAE,SAAQ,eAAc,QAAS,EAAQ,OAAQ,CAAC,EAAI,IAAA,GACnG,GAAI,GAAc,OAAO,GAAe,SAAU,CAChD,IAAM,EAAS,EAA2D,eACtE,GAAO,OAAO,OAAO,EAAgB,CAAK,EAC9C,IAAM,EAAW,EAA0C,YACvD,MAAM,QAAQ,CAAO,GAAG,EAAY,KAAK,GAAG,CAAO,EACvD,IAAM,EAAS,EAAwC,UACnD,MAAM,QAAQ,CAAK,GAAG,EAAU,KAAK,GAAG,CAAK,CACnD,CACF,MAAQ,CAER,CAEJ,CAEA,OAAO,EAAA,EAAc,CACnB,MAAO,aACP,KAAM,EAAO,KACb,OACA,KAAM,CAAE,oBAAqB,GAAM,KAAM,EAAM,IAAK,EACpD,UACA,iBACA,cACA,YACA,YAAa,EAAO,WACtB,CAAC,CACH,CA4BA,IAAa,EAAb,cAAwC,KAAM,CAC5C,YAAY,EAAkB,CAC5B,MAAM,sBAAsB,GAAU,EACtC,KAAK,KAAO,oBACd,CACF,EAMA,eAAsB,EAAe,EAA+D,CAClG,GAAM,CAAE,SAAQ,WAAU,eAAc,SAAQ,UAAS,WAAW,EAAe,WAAY,EACzF,EAAQ,EAAA,EAAW,EAAU,EAAO,KAAK,EAC/C,GAAI,CAAC,EACH,MAAM,IAAI,EAAmB,CAAQ,EAGvC,IAAM,EAAS,MAAM,EAAA,EAAW,CAC9B,MAAO,EAAM,MACb,OAAQ,EAAM,OACd,eACA,SACA,UACA,WACA,SACF,CAAC,EAGD,GAAI,EAAO,SACT,MAAO,CACL,KAAM,GACN,MAAO,GACP,SAAU,EAAO,QACnB,EAGF,IAAM,EAAY,EAAO,KAAK,MAAM,8CAA8C,EAC5E,EAAO,EAAY,EAAU,EAAE,CAAC,KAAK,EAAI,EAAO,KAChD,EAAa,EAAO,KAAK,MAAM,8BAA8B,EACnE,MAAO,CACL,OACA,MAAO,EAAa,EAAW,GAAK,EAAO,eAAiB,GAC5D,SAAU,EAAO,KACjB,uBAAwB,EAAO,uBAC/B,KAAM,EAAO,IACf,CACF"}
@@ -0,0 +1,97 @@
1
+ /** Route params: `[slug]` -> string, `[...slug]` -> string[]. */
2
+ export type RouteParams = Record<string, string | string[]>;
3
+ /** Infer the data type from a loader type, supporting both plain types and functions. */
4
+ type InferLoaderData<T> = T extends (...args: any[]) => infer R ? Awaited<R> : T;
5
+ /** Props received by a `page.ts` component's default export. */
6
+ export type PageProps<TData = unknown, TLayout = unknown> = {
7
+ /** Return value of the route's `page.data.ts` loader. */
8
+ data: InferLoaderData<TData>;
9
+ /** Return value of the nearest `layout.data.ts` loader, if any. */
10
+ layoutData?: InferLoaderData<TLayout>;
11
+ /** Dynamic segment values. */
12
+ params: RouteParams;
13
+ /** Parsed query string. */
14
+ searchParams: URLSearchParams;
15
+ /** Return value of the last executed action (POST). */
16
+ form?: unknown;
17
+ };
18
+ /** Props received by a `layout.ts` component's default export. */
19
+ export type LayoutProps<TData = unknown> = {
20
+ /** Slot where the child page/layout is rendered. */
21
+ children: unknown;
22
+ /** Return value of this layout's `layout.data.ts`, if any. */
23
+ data?: InferLoaderData<TData>;
24
+ };
25
+ /** Context passed to a `load` function. */
26
+ export interface LoadContext {
27
+ params: RouteParams;
28
+ searchParams: URLSearchParams;
29
+ request?: Request;
30
+ }
31
+ /** Signature for `page.data.ts` / `layout.data.ts` `load` export. */
32
+ export type PageDataLoad<TData = unknown> = (ctx: LoadContext) => Promise<TData> | TData;
33
+ /** Signature for `generateStaticParams` in dynamic page modules. */
34
+ export type GenerateStaticParams = () => Promise<RouteParams[]> | RouteParams[];
35
+ /** OpenGraph metadata for a page. */
36
+ export interface OpenGraphMetadata {
37
+ /** OG type: website, article, profile, etc. */
38
+ type?: string;
39
+ /** OG title (falls back to the page title). */
40
+ title?: string;
41
+ /** OG description (falls back to the page description). */
42
+ description?: string;
43
+ /** Absolute or relative URL to the canonical page. */
44
+ url?: string;
45
+ /** Image URL for social sharing previews. */
46
+ image?: string;
47
+ /** Image alternative text. Emitted as `og:image:alt`. */
48
+ imageAlt?: string;
49
+ /** Image width in pixels. Emitted as `og:image:width`. */
50
+ imageWidth?: number;
51
+ /** Image height in pixels. Emitted as `og:image:height`. */
52
+ imageHeight?: number;
53
+ /** Image MIME type (e.g. "image/png"). Emitted as `og:image:type`. */
54
+ imageType?: string;
55
+ /** Site name shown in social cards. */
56
+ siteName?: string;
57
+ /** Locale, e.g. "es_ES". */
58
+ locale?: string;
59
+ }
60
+ /** Twitter card metadata for a page. */
61
+ export interface TwitterMetadata {
62
+ /** Card type: summary, summary_large_image, player, app. */
63
+ card?: "summary" | "summary_large_image" | "player" | "app";
64
+ /** Title (falls back to the page title). */
65
+ title?: string;
66
+ /** Description (falls back to the page description). */
67
+ description?: string;
68
+ /** Image URL for the card. */
69
+ image?: string;
70
+ /** Image alternative text. Emitted as `twitter:image:alt`. */
71
+ imageAlt?: string;
72
+ }
73
+ /** Page-level metadata emitted into the `<head>` by the document shell. */
74
+ export interface PageMetadata {
75
+ /** Page title (also used as `<title>` and as fallback for OG/Twitter). */
76
+ title?: string;
77
+ /** Meta description. */
78
+ description?: string;
79
+ /** Canonical URL. */
80
+ canonical?: string;
81
+ /** Robots directive, e.g. "index, follow" or "noindex". */
82
+ robots?: string;
83
+ /** OpenGraph metadata for social sharing. */
84
+ openGraph?: OpenGraphMetadata;
85
+ /** Twitter card metadata. */
86
+ twitter?: TwitterMetadata;
87
+ /** Additional `<meta>` tags as key/value pairs. */
88
+ other?: Record<string, string>;
89
+ }
90
+ /** Context passed to a `generateMetadata` function. */
91
+ export interface MetadataContext extends LoadContext {
92
+ /** Loader data resolved for the current page, if a loader exists. */
93
+ data?: unknown;
94
+ }
95
+ /** Signature for `generateMetadata` exported by `page.ts` modules. */
96
+ export type GenerateMetadata = (ctx: MetadataContext) => Promise<PageMetadata> | PageMetadata;
97
+ export {};
@@ -0,0 +1,97 @@
1
+ /** Route params: `[slug]` -> string, `[...slug]` -> string[]. */
2
+ export type RouteParams = Record<string, string | string[]>;
3
+ /** Infer the data type from a loader type, supporting both plain types and functions. */
4
+ type InferLoaderData<T> = T extends (...args: any[]) => infer R ? Awaited<R> : T;
5
+ /** Props received by a `page.ts` component's default export. */
6
+ export type PageProps<TData = unknown, TLayout = unknown> = {
7
+ /** Return value of the route's `page.data.ts` loader. */
8
+ data: InferLoaderData<TData>;
9
+ /** Return value of the nearest `layout.data.ts` loader, if any. */
10
+ layoutData?: InferLoaderData<TLayout>;
11
+ /** Dynamic segment values. */
12
+ params: RouteParams;
13
+ /** Parsed query string. */
14
+ searchParams: URLSearchParams;
15
+ /** Return value of the last executed action (POST). */
16
+ form?: unknown;
17
+ };
18
+ /** Props received by a `layout.ts` component's default export. */
19
+ export type LayoutProps<TData = unknown> = {
20
+ /** Slot where the child page/layout is rendered. */
21
+ children: unknown;
22
+ /** Return value of this layout's `layout.data.ts`, if any. */
23
+ data?: InferLoaderData<TData>;
24
+ };
25
+ /** Context passed to a `load` function. */
26
+ export interface LoadContext {
27
+ params: RouteParams;
28
+ searchParams: URLSearchParams;
29
+ request?: Request;
30
+ }
31
+ /** Signature for `page.data.ts` / `layout.data.ts` `load` export. */
32
+ export type PageDataLoad<TData = unknown> = (ctx: LoadContext) => Promise<TData> | TData;
33
+ /** Signature for `generateStaticParams` in dynamic page modules. */
34
+ export type GenerateStaticParams = () => Promise<RouteParams[]> | RouteParams[];
35
+ /** OpenGraph metadata for a page. */
36
+ export interface OpenGraphMetadata {
37
+ /** OG type: website, article, profile, etc. */
38
+ type?: string;
39
+ /** OG title (falls back to the page title). */
40
+ title?: string;
41
+ /** OG description (falls back to the page description). */
42
+ description?: string;
43
+ /** Absolute or relative URL to the canonical page. */
44
+ url?: string;
45
+ /** Image URL for social sharing previews. */
46
+ image?: string;
47
+ /** Image alternative text. Emitted as `og:image:alt`. */
48
+ imageAlt?: string;
49
+ /** Image width in pixels. Emitted as `og:image:width`. */
50
+ imageWidth?: number;
51
+ /** Image height in pixels. Emitted as `og:image:height`. */
52
+ imageHeight?: number;
53
+ /** Image MIME type (e.g. "image/png"). Emitted as `og:image:type`. */
54
+ imageType?: string;
55
+ /** Site name shown in social cards. */
56
+ siteName?: string;
57
+ /** Locale, e.g. "es_ES". */
58
+ locale?: string;
59
+ }
60
+ /** Twitter card metadata for a page. */
61
+ export interface TwitterMetadata {
62
+ /** Card type: summary, summary_large_image, player, app. */
63
+ card?: "summary" | "summary_large_image" | "player" | "app";
64
+ /** Title (falls back to the page title). */
65
+ title?: string;
66
+ /** Description (falls back to the page description). */
67
+ description?: string;
68
+ /** Image URL for the card. */
69
+ image?: string;
70
+ /** Image alternative text. Emitted as `twitter:image:alt`. */
71
+ imageAlt?: string;
72
+ }
73
+ /** Page-level metadata emitted into the `<head>` by the document shell. */
74
+ export interface PageMetadata {
75
+ /** Page title (also used as `<title>` and as fallback for OG/Twitter). */
76
+ title?: string;
77
+ /** Meta description. */
78
+ description?: string;
79
+ /** Canonical URL. */
80
+ canonical?: string;
81
+ /** Robots directive, e.g. "index, follow" or "noindex". */
82
+ robots?: string;
83
+ /** OpenGraph metadata for social sharing. */
84
+ openGraph?: OpenGraphMetadata;
85
+ /** Twitter card metadata. */
86
+ twitter?: TwitterMetadata;
87
+ /** Additional `<meta>` tags as key/value pairs. */
88
+ other?: Record<string, string>;
89
+ }
90
+ /** Context passed to a `generateMetadata` function. */
91
+ export interface MetadataContext extends LoadContext {
92
+ /** Loader data resolved for the current page, if a loader exists. */
93
+ data?: unknown;
94
+ }
95
+ /** Signature for `generateMetadata` exported by `page.ts` modules. */
96
+ export type GenerateMetadata = (ctx: MetadataContext) => Promise<PageMetadata> | PageMetadata;
97
+ export {};
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../node-http-DhxguYyz.cjs"),t=require("../route-scanner-JY6YrNH5.cjs"),n=require("../scan-CY2O9ty6.cjs"),r=require("../interpolation-plugin-CMPCDlVJ.cjs"),i=require("../scan-DXzYtmRQ.cjs"),a=require("../collections-VDy5g9p8.cjs");let o=require("node:fs/promises"),s=require("node:path");function c(c={}){let m=c.appDir??`src/app`,h=c.islandsDir??`src/islands`,g=c.contentDir??`src/content`,_=c.generatedEntry??`.elur/entry-client.ts`,v=c.clientEntry??`/_elur/entry-client.js`,y=c.lang??`es`,b=c.hydrateImport??`@elurjs/kit/island`,x=c.routerImport??`@elurjs/kit/router`,S=null,C={},w=`.`,T=null,E={name:`elur-kit`,enforce:`pre`,async configResolved(e){w=e.root;let c=(0,s.resolve)(w,_),l=await n.t((0,s.resolve)(w,h)),u=r.s(l,c,b,x);await(0,o.mkdir)((0,s.dirname)(c),{recursive:!0}),await(0,o.writeFile)(c,u,`utf8`);let d=(0,s.resolve)(w,m);S=await t.t(d),C=await i.n(d),a.s((0,s.resolve)(w,g)),T=await r.i(w)},configureServer(n){let o=u(n,w),E=d(()=>C,()=>S,o),D=(0,s.resolve)(w,m);l(n,D,(0,s.resolve)(w,h),(0,s.resolve)(w,g),w,_,b,x,()=>{S=null,C={},a.t()}),n.middlewares.use(async(a,s,l)=>{let u=new URL(a.url??`/`,`http://${a.headers.host??`localhost`}`),d=u.pathname;if(d===`/__elur-js/actions`&&a.method===`POST`){try{let t=await f(a),n=e.t(a,t),r=await e.n(n,E,c.actionSecurity);s.writeHead(r.status,Object.fromEntries(r.headers.entries())),s.end(await r.text())}catch(e){console.error(`[elur-kit] action error:`,e),s.writeHead(500,{"Content-Type":`text/plain; charset=utf-8`}),s.end(String(e))}return}if(d.startsWith(`/_elur/entry-client.js`)){let e=await n.transformRequest(`/.elur/entry-client.ts`);if(e){s.writeHead(200,{"Content-Type":`application/javascript; charset=utf-8`,"Cache-Control":`no-store, must-revalidate`}),s.end(e.code);return}}let m=S??=await t.t(D),h=Object.keys(C).length?C:C=await i.n(D);if(d===`/__elur-js/render`){let{renderPageBody:t,RouteNotFoundError:n}=await Promise.resolve().then(()=>require("../stream-DmZjYqHm.cjs")).then(e=>e.i);try{let n=u.searchParams.get(`page`)??`/`,r=u.searchParams.get(`search`)??``,c=(a.headers.accept??``).includes(`application/json`),l=e.t(a),{body:d,title:f,head:p,clearActionErrorCookie:g}=await t({routes:m,pathname:n,searchParams:new URLSearchParams(r),config:{lang:y,clientEntry:v},actions:i.t(h),importer:o,request:l});if(c){let e={"Content-Type":`application/json; charset=utf-8`};g&&(e[`X-Elur-Action-Clear-Cookie`]=g),s.writeHead(200,e),s.end(JSON.stringify({title:f,body:d,head:p,clearActionErrorCookie:g}))}else{let e={"Content-Type":`text/html; charset=utf-8`};g&&(e[`Set-Cookie`]=g),s.writeHead(200,e),s.end(d)}return}catch(e){if(e instanceof n){s.writeHead(404,{"Content-Type":`text/plain; charset=utf-8`}),s.end(`Not Found`);return}console.error(`[elur-kit] render endpoint error:`,e),s.writeHead(500,{"Content-Type":`text/plain; charset=utf-8`}),s.end(String(e));return}}if(!d.startsWith(`/@`)&&!d.startsWith(`/node_modules/`)&&!d.includes(`.`)){let t=e.a(d,m.api);if(t){try{let n=(await o(t.route.routePath))[a.method??`GET`];if(typeof n!=`function`){s.writeHead(405,{"Content-Type":`text/plain`}),s.end(`Method not allowed: ${a.method}`);return}let r=a.method&&a.method!==`GET`&&a.method!==`HEAD`?await f(a):void 0,i=await n(e.t(a,r),{params:t.params});s.writeHead(i.status,Object.fromEntries(i.headers.entries())),s.end(Buffer.from(await i.arrayBuffer()))}catch(e){console.error(`[elur-kit] API route error:`,e),s.writeHead(500,{"Content-Type":`text/plain; charset=utf-8`}),s.end(String(e))}return}}let g;if(T&&r.a(d,T.config)){let t=await r.o(T,e.t(a));if(t.kind===`response`){s.writeHead(t.response.status,Object.fromEntries(t.response.headers.entries())),s.end(Buffer.from(await t.response.arrayBuffer()));return}g=t.headers}await p(a,s,l,{routes:m,actions:h,clientEntry:v,lang:y,ssrLoad:o,middlewareHeaders:g})||l()})}};return r.r(c.interpolation??`auto`)?[E,r.n({appDir:m,islandsDir:h})]:[E]}function l(e,t,i,a,c,l,u,d,f){let p=e=>e.startsWith(t)||e.startsWith(i)||e.startsWith(a);async function m(){let t=await n.t(i),a=(0,s.resolve)(c,l),f=r.s(t,a,u,d);await(0,o.mkdir)((0,s.dirname)(a),{recursive:!0}),await(0,o.writeFile)(a,f,`utf8`);let p=e.moduleGraph.getModuleById(a);p&&e.moduleGraph.invalidateModule(p)}e.watcher.on(`change`,async t=>{if(!p(t))return;f();let n=e.moduleGraph.getModuleById(t);n&&e.moduleGraph.invalidateModule(n),t.startsWith(i)?(await m(),console.log(`[elur-kit] HMR reload islands after change:`,t)):t.startsWith(a)&&t.endsWith(`.md`)?console.log(`[elur-kit] HMR content changed:`,t):(t.includes(`.action.ts`)||t.includes(`.data.ts`)||t.includes(`page.ts`)||t.includes(`layout.ts`))&&console.log(`[elur-kit] HMR reload routes/actions after change:`,t)}),e.watcher.on(`add`,async e=>{p(e)&&(f(),e.startsWith(i)&&await m(),console.log(`[elur-kit] HMR new file detected:`,e))}),e.watcher.on(`unlink`,async t=>{if(!p(t))return;f();let n=e.moduleGraph.getModuleById(t);n&&e.moduleGraph.invalidateModule(n),t.startsWith(i)&&await m(),console.log(`[elur-kit] HMR file removed:`,t)})}function u(e,t){return n=>{let r=`/`+(0,s.relative)(t,n).split(`\\`).join(`/`);return e.ssrLoadModule(r)}}function d(t,n,r){return async(i,a)=>{let o=t(),s=n(),c;a&&s&&(c=s.pages.some(e=>e.path===a)?a:e.o(a,s.pages)?.route.path??a);let l=c?o[c]:Object.values(o).find(e=>e[i])??void 0,u=l?l[i]:void 0;if(!u)return;let d=(await r(u))[i];if(typeof d==`function`)return d}}function f(e){return new Promise((t,n)=>{let r=``;e.setEncoding(`utf8`),e.on(`data`,e=>{r+=e}),e.on(`end`,()=>t(r)),e.on(`error`,n)})}async function p(t,n,r,a){if(!a.routes)return!1;let o=i.t(a.actions),s=t.url??`/`;if(s.includes(`?`)&&(s=s.split(`?`)[0]),s.startsWith(`/@`)||s.startsWith(`/node_modules/`)||s.includes(`.`))return!1;let c={lang:a.lang,clientEntry:a.clientEntry},l=e.o(s,a.routes.pages);if(l)try{let r=e.t(t);if(a.middlewareHeaders)for(let[e,t]of Object.entries(a.middlewareHeaders))r.headers.set(e,t);let{html:i,clearActionErrorCookie:s}=await e.l({route:l.route,params:l.params,searchParams:new URLSearchParams(t.url?.split(`?`)[1]??``),config:c,importer:a.ssrLoad,actions:o,request:r}),u={"Content-Type":`text/html; charset=utf-8`,"Cache-Control":`no-store, must-revalidate`};return s&&(u[`Set-Cookie`]=s),n.writeHead(200,u),n.end(i),!0}catch(t){console.error(`[elur-kit] SSR render error:`,t);let r=await e.c({routes:a.routes,status:500,error:t,config:c,actions:o,importer:a.ssrLoad});return r?(n.writeHead(r.status,{"Content-Type":`text/html; charset=utf-8`,"Cache-Control":`no-store, must-revalidate`}),n.end(r.html)):(n.writeHead(500,{"Content-Type":`text/plain; charset=utf-8`,"Cache-Control":`no-store, must-revalidate`}),n.end(String(t))),!0}let u=await e.c({routes:a.routes,status:404,config:c,actions:o,importer:a.ssrLoad});return u?(n.writeHead(u.status,{"Content-Type":`text/html; charset=utf-8`,"Cache-Control":`no-store, must-revalidate`}),n.end(u.html),!0):!1}exports.coreSupportsPartialInterpolation=r.t,exports.elurJsInterpolationPlugin=r.n,exports.elurJsKit=c,exports.shouldUseLegacyInterpolation=r.r;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/vite/index.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { Plugin, Connect, ViteDevServer } from \"vite\";\nimport { scanRoutes } from \"../router/route-scanner.js\";\nimport { scanActions, actionNames, type ActionRegistry } from \"../action/scan.js\";\nimport { handleActionRequest, type ActionSecurityOptions } from \"../action/server.js\";\nimport { scanIslands } from \"../island/scan.js\";\nimport { buildEntrySource } from \"../island/generate-entry.js\";\nimport { matchApiRoute, matchRoute } from \"../ssr/match.js\";\nimport { renderPage, renderErrorPage } from \"../ssr/render.js\";\nimport { setContentRoot, clearContentCache } from \"../content/collections.js\";\nimport { loadMiddleware, matchesMiddleware, runMiddleware, type LoadedMiddleware } from \"../middleware/index.js\";\nimport { elurJsInterpolationPlugin, shouldUseLegacyInterpolation, type InterpolationMode } from \"./interpolation-plugin.js\";\nimport { incomingMessageToRequest } from \"../runtime/node-http.js\";\n\nexport interface ElurJsKitViteOptions {\n /** App directory relative to Vite root (default: src/app). */\n appDir?: string;\n /** Islands directory relative to Vite root (default: src/islands). */\n islandsDir?: string;\n /** Content directory relative to Vite root (default: src/content). */\n contentDir?: string;\n /** Where to write the generated client entry (default: .elur/entry-client.ts). */\n generatedEntry?: string;\n /** Public path for the client entry module (default: /_elur/entry-client.js). */\n clientEntry?: string;\n /** HTML lang attribute (default: es). */\n lang?: string;\n /** Import specifier for hydrateIslands in the generated entry. */\n hydrateImport?: string;\n /** Import specifier for startClientRouter in the generated entry. */\n routerImport?: string;\n /** CSRF / origin policy applied to the server actions endpoint in dev. */\n actionSecurity?: ActionSecurityOptions;\n /**\n * How the legacy interpolation transform is handled (default: \"auto\").\n * With a Elur core that supports partial attribute interpolation natively\n * the transform is not applied; use \"legacy\" for migrations against older\n * cores and \"off\" to never transform.\n */\n interpolation?: InterpolationMode;\n}\n\n/**\n * Official Vite plugin for elur-kit.\n *\n * In dev mode it generates the islands entry and renders every page via SSR.\n * In production builds it can be combined with `elur-kit build` to generate\n * static HTML files.\n */\nexport function elurJsKit(options: ElurJsKitViteOptions = {}): Plugin[] {\n const appDir = options.appDir ?? \"src/app\";\n const islandsDir = options.islandsDir ?? \"src/islands\";\n const contentDir = options.contentDir ?? \"src/content\";\n const generatedEntry = options.generatedEntry ?? \".elur/entry-client.ts\";\n const clientEntry = options.clientEntry ?? \"/_elur/entry-client.js\";\n const lang = options.lang ?? \"es\";\n const hydrateImport = options.hydrateImport ?? \"@elurjs/kit/island\";\n const routerImport = options.routerImport ?? \"@elurjs/kit/router\";\n\n let routes: Awaited<ReturnType<typeof scanRoutes>> | null = null;\n let actions: ActionRegistry = {};\n let root: string = \".\";\n let middleware: LoadedMiddleware | null = null;\n\n const mainPlugin: Plugin = {\n name: \"elur-kit\",\n enforce: \"pre\",\n\n async configResolved(config) {\n root = config.root;\n const entryPath = resolve(root, generatedEntry);\n const islands = await scanIslands(resolve(root, islandsDir));\n const source = buildEntrySource(islands, entryPath, hydrateImport, routerImport);\n await mkdir(dirname(entryPath), { recursive: true });\n await writeFile(entryPath, source, \"utf8\");\n\n const appDirPath = resolve(root, appDir);\n routes = await scanRoutes(appDirPath);\n actions = await scanActions(appDirPath);\n\n // Wire up the content layer root so getCollection/getEntry resolve\n // from the user's src/content directory.\n setContentRoot(resolve(root, contentDir));\n\n // Load user middleware (src/middleware.ts) if it exists.\n middleware = await loadMiddleware(root);\n },\n\n configureServer(server) {\n const ssrLoad = createSsrLoader(server, root);\n const resolveAction = createActionResolver(() => actions, () => routes, ssrLoad);\n\n const appDirPath = resolve(root, appDir);\n const islandsDirPath = resolve(root, islandsDir);\n const contentDirPath = resolve(root, contentDir);\n setupHmr(server, appDirPath, islandsDirPath, contentDirPath, root, generatedEntry, hydrateImport, routerImport, () => {\n routes = null;\n actions = {};\n clearContentCache();\n });\n\n server.middlewares.use(async (req, res, next) => {\n const requestUrl = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`);\n const urlPath = requestUrl.pathname;\n\n // Server actions endpoint.\n if (urlPath === \"/__elur-js/actions\" && req.method === \"POST\") {\n try {\n const body = await readRequestBody(req);\n const request = incomingMessageToRequest(req, body);\n const response = await handleActionRequest(request, resolveAction, options.actionSecurity);\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(await response.text());\n } catch (err) {\n console.error(\"[elur-kit] action error:\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(String(err));\n }\n return;\n }\n\n if (urlPath.startsWith(\"/_elur/entry-client.js\")) {\n const transformed = await server.transformRequest(\n \"/.elur/entry-client.ts\",\n );\n if (transformed) {\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n });\n res.end(transformed.code);\n return;\n }\n }\n\n const currentRoutes = routes ?? (routes = await scanRoutes(appDirPath));\n const currentActions = Object.keys(actions).length ? actions : (actions = await scanActions(appDirPath));\n\n // Render endpoint used by the SPA router and streaming boundaries.\n if (urlPath === \"/__elur-js/render\") {\n const { renderPageBody, RouteNotFoundError } = await import(\"../ssr/stream.js\");\n try {\n const page = requestUrl.searchParams.get(\"page\") ?? \"/\";\n const search = requestUrl.searchParams.get(\"search\") ?? \"\";\n const wantsJson = (req.headers[\"accept\"] ?? \"\").includes(\"application/json\");\n const request = incomingMessageToRequest(req);\n const { body, title, head, clearActionErrorCookie } = await renderPageBody({\n routes: currentRoutes,\n pathname: page,\n searchParams: new URLSearchParams(search),\n config: { lang, clientEntry },\n actions: actionNames(currentActions),\n importer: ssrLoad,\n request,\n });\n if (wantsJson) {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"X-Elur-Action-Clear-Cookie\"] = clearActionErrorCookie;\n res.writeHead(200, headers);\n res.end(JSON.stringify({ title, body, head, clearActionErrorCookie }));\n } else {\n const headers: Record<string, string> = { \"Content-Type\": \"text/html; charset=utf-8\" };\n if (clearActionErrorCookie) headers[\"Set-Cookie\"] = clearActionErrorCookie;\n res.writeHead(200, headers);\n res.end(body);\n }\n return;\n } catch (err) {\n if (err instanceof RouteNotFoundError) {\n res.writeHead(404, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(\"Not Found\");\n return;\n }\n console.error(\"[elur-kit] render endpoint error:\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(String(err));\n return;\n }\n }\n\n if (!urlPath.startsWith(\"/@\") && !urlPath.startsWith(\"/node_modules/\") && !urlPath.includes(\".\")) {\n const apiMatch = matchApiRoute(urlPath, currentRoutes.api);\n if (apiMatch) {\n try {\n const mod = (await ssrLoad(apiMatch.route.routePath)) as Record<\n string,\n (request: Request, context?: { params: Record<string, string | string[]> }) => unknown\n >;\n const handler = mod[req.method ?? \"GET\"];\n if (typeof handler !== \"function\") {\n res.writeHead(405, { \"Content-Type\": \"text/plain\" });\n res.end(`Method not allowed: ${req.method}`);\n return;\n }\n const body = req.method && req.method !== \"GET\" && req.method !== \"HEAD\" ? await readRequestBody(req) : undefined;\n const request = incomingMessageToRequest(req, body);\n const response = (await handler(request, { params: apiMatch.params })) as Response;\n res.writeHead(response.status, Object.fromEntries(response.headers.entries()));\n res.end(Buffer.from(await response.arrayBuffer()));\n } catch (err) {\n console.error(\"[elur-kit] API route error:\", err);\n res.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n res.end(String(err));\n }\n return;\n }\n }\n\n // Run middleware before SSR rendering.\n let middlewareHeaders: Record<string, string> | undefined;\n if (middleware && matchesMiddleware(urlPath, middleware.config)) {\n const mwResult = await runMiddleware(middleware, incomingMessageToRequest(req));\n if (mwResult.kind === \"response\") {\n res.writeHead(mwResult.response.status, Object.fromEntries(mwResult.response.headers.entries()));\n res.end(Buffer.from(await mwResult.response.arrayBuffer()));\n return;\n }\n middlewareHeaders = mwResult.headers;\n }\n\n const handled = await handleSsrRequest(req, res, next, {\n routes: currentRoutes,\n actions: currentActions,\n clientEntry,\n lang,\n ssrLoad,\n middlewareHeaders,\n });\n if (!handled) next();\n });\n },\n };\n\n return shouldUseLegacyInterpolation(options.interpolation ?? \"auto\")\n ? [mainPlugin, elurJsInterpolationPlugin({ appDir, islandsDir })]\n : [mainPlugin];\n}\n\nexport { elurJsInterpolationPlugin, type InterpolationPluginOptions } from \"./interpolation-plugin.js\";\nexport type { InterpolationMode } from \"./interpolation-plugin.js\";\nexport { coreSupportsPartialInterpolation, shouldUseLegacyInterpolation } from \"./interpolation-plugin.js\";\n\nfunction setupHmr(\n server: ViteDevServer,\n appDirPath: string,\n islandsDirPath: string,\n contentDirPath: string,\n root: string,\n generatedEntry: string,\n hydrateImport: string,\n routerImport: string,\n invalidate: () => void,\n) {\n const isRelevant = (path: string) =>\n path.startsWith(appDirPath) || path.startsWith(islandsDirPath) || path.startsWith(contentDirPath);\n\n async function regenerateIslandEntry() {\n const islands = await scanIslands(islandsDirPath);\n const entryPath = resolve(root, generatedEntry);\n const source = buildEntrySource(islands, entryPath, hydrateImport, routerImport);\n await mkdir(dirname(entryPath), { recursive: true });\n await writeFile(entryPath, source, \"utf8\");\n const entryMod = server.moduleGraph.getModuleById(entryPath);\n if (entryMod) server.moduleGraph.invalidateModule(entryMod);\n }\n\n server.watcher.on(\"change\", async (path) => {\n if (!isRelevant(path)) return;\n invalidate();\n const mod = server.moduleGraph.getModuleById(path);\n if (mod) server.moduleGraph.invalidateModule(mod);\n if (path.startsWith(islandsDirPath)) {\n await regenerateIslandEntry();\n console.log(\"[elur-kit] HMR reload islands after change:\", path);\n } else if (path.startsWith(contentDirPath) && path.endsWith(\".md\")) {\n console.log(\"[elur-kit] HMR content changed:\", path);\n } else if (path.includes(\".action.ts\") || path.includes(\".data.ts\") || path.includes(\"page.ts\") || path.includes(\"layout.ts\")) {\n console.log(\"[elur-kit] HMR reload routes/actions after change:\", path);\n }\n });\n\n server.watcher.on(\"add\", async (path) => {\n if (!isRelevant(path)) return;\n invalidate();\n if (path.startsWith(islandsDirPath)) {\n await regenerateIslandEntry();\n }\n console.log(\"[elur-kit] HMR new file detected:\", path);\n });\n\n server.watcher.on(\"unlink\", async (path) => {\n if (!isRelevant(path)) return;\n invalidate();\n const mod = server.moduleGraph.getModuleById(path);\n if (mod) server.moduleGraph.invalidateModule(mod);\n if (path.startsWith(islandsDirPath)) {\n await regenerateIslandEntry();\n }\n console.log(\"[elur-kit] HMR file removed:\", path);\n });\n}\n\nfunction createSsrLoader(server: ViteDevServer, root: string) {\n return (filePath: string) => {\n const rel = relative(root, filePath);\n const url = \"/\" + rel.split(\"\\\\\").join(\"/\");\n return server.ssrLoadModule(url);\n };\n}\n\nfunction createActionResolver(\n getActions: () => import(\"../action/scan.js\").ActionRegistry,\n getRoutes: () => Awaited<ReturnType<typeof scanRoutes>> | null,\n ssrLoad: (path: string) => Promise<unknown>,\n) {\n return async (name: string, page?: string) => {\n const actions = getActions();\n const routes = getRoutes();\n let pageKey: string | undefined;\n if (page && routes) {\n pageKey = routes.pages.some((route) => route.path === page)\n ? page\n : (matchRoute(page, routes.pages)?.route.path ?? page);\n }\n const pageActions = pageKey ? actions[pageKey] : Object.values(actions).find((p) => p[name]) ?? undefined;\n const actionPath = pageActions ? pageActions[name] : undefined;\n if (!actionPath) return undefined;\n const mod = (await ssrLoad(actionPath)) as Record<string, unknown>;\n const action = mod[name];\n if (typeof action === \"function\") {\n return action as (...args: unknown[]) => unknown;\n }\n return undefined;\n };\n}\n\nfunction readRequestBody(req: Connect.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let body = \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk) => {\n body += chunk;\n });\n req.on(\"end\", () => resolve(body));\n req.on(\"error\", reject);\n });\n}\n\ninterface SsrHandlerOptions {\n routes: Awaited<ReturnType<typeof scanRoutes>> | null;\n actions: ActionRegistry;\n clientEntry: string;\n lang: string;\n ssrLoad: (path: string) => Promise<unknown>;\n middlewareHeaders?: Record<string, string>;\n}\n\nasync function handleSsrRequest(\n req: Connect.IncomingMessage,\n res: import(\"node:http\").ServerResponse,\n _next: Connect.NextFunction,\n options: SsrHandlerOptions,\n): Promise<boolean> {\n if (!options.routes) return false;\n const publicActions = actionNames(options.actions);\n\n let urlPath = req.url ?? \"/\";\n if (urlPath.includes(\"?\")) urlPath = urlPath.split(\"?\")[0];\n\n // Let Vite handle its own internals and assets.\n if (urlPath.startsWith(\"/@\") || urlPath.startsWith(\"/node_modules/\")) {\n return false;\n }\n\n // Skip explicit file requests.\n if (urlPath.includes(\".\")) return false;\n\n const config = { lang: options.lang, clientEntry: options.clientEntry };\n const match = matchRoute(urlPath, options.routes.pages);\n if (match) {\n try {\n const request = incomingMessageToRequest(req);\n if (options.middlewareHeaders) {\n for (const [name, value] of Object.entries(options.middlewareHeaders)) request.headers.set(name, value);\n }\n const { html, clearActionErrorCookie } = await renderPage({\n route: match.route,\n params: match.params,\n searchParams: new URLSearchParams(req.url?.split(\"?\")[1] ?? \"\"),\n config,\n importer: options.ssrLoad,\n actions: publicActions,\n request,\n });\n const responseHeaders: Record<string, string> = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n };\n if (clearActionErrorCookie) responseHeaders[\"Set-Cookie\"] = clearActionErrorCookie;\n res.writeHead(200, responseHeaders);\n res.end(html);\n return true;\n } catch (err) {\n console.error(\"[elur-kit] SSR render error:\", err);\n const errorResult = await renderErrorPage({\n routes: options.routes,\n status: 500,\n error: err,\n config,\n actions: publicActions,\n importer: options.ssrLoad,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n });\n res.end(errorResult.html);\n } else {\n res.writeHead(500, {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n });\n res.end(String(err));\n }\n return true;\n }\n }\n\n const errorResult = await renderErrorPage({\n routes: options.routes,\n status: 404,\n config,\n actions: publicActions,\n importer: options.ssrLoad,\n });\n if (errorResult) {\n res.writeHead(errorResult.status, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store, must-revalidate\",\n });\n res.end(errorResult.html);\n return true;\n }\n\n return false;\n}\n"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { Plugin } from "vite";
2
+ import { type ActionSecurityOptions } from "../action/server.js";
3
+ import { type InterpolationMode } from "./interpolation-plugin.js";
4
+ export interface ElurJsKitViteOptions {
5
+ /** App directory relative to Vite root (default: src/app). */
6
+ appDir?: string;
7
+ /** Islands directory relative to Vite root (default: src/islands). */
8
+ islandsDir?: string;
9
+ /** Content directory relative to Vite root (default: src/content). */
10
+ contentDir?: string;
11
+ /** Where to write the generated client entry (default: .elur/entry-client.ts). */
12
+ generatedEntry?: string;
13
+ /** Public path for the client entry module (default: /_elur/entry-client.js). */
14
+ clientEntry?: string;
15
+ /** HTML lang attribute (default: es). */
16
+ lang?: string;
17
+ /** Import specifier for hydrateIslands in the generated entry. */
18
+ hydrateImport?: string;
19
+ /** Import specifier for startClientRouter in the generated entry. */
20
+ routerImport?: string;
21
+ /** CSRF / origin policy applied to the server actions endpoint in dev. */
22
+ actionSecurity?: ActionSecurityOptions;
23
+ /**
24
+ * How the legacy interpolation transform is handled (default: "auto").
25
+ * With a Elur core that supports partial attribute interpolation natively
26
+ * the transform is not applied; use "legacy" for migrations against older
27
+ * cores and "off" to never transform.
28
+ */
29
+ interpolation?: InterpolationMode;
30
+ }
31
+ /**
32
+ * Official Vite plugin for elur-kit.
33
+ *
34
+ * In dev mode it generates the islands entry and renders every page via SSR.
35
+ * In production builds it can be combined with `elur-kit build` to generate
36
+ * static HTML files.
37
+ */
38
+ export declare function elurJsKit(options?: ElurJsKitViteOptions): Plugin[];
39
+ export { elurJsInterpolationPlugin, type InterpolationPluginOptions } from "./interpolation-plugin.js";
40
+ export type { InterpolationMode } from "./interpolation-plugin.js";
41
+ export { coreSupportsPartialInterpolation, shouldUseLegacyInterpolation } from "./interpolation-plugin.js";
@@ -0,0 +1,41 @@
1
+ import type { Plugin } from "vite";
2
+ import { type ActionSecurityOptions } from "../action/server.js";
3
+ import { type InterpolationMode } from "./interpolation-plugin.js";
4
+ export interface ElurJsKitViteOptions {
5
+ /** App directory relative to Vite root (default: src/app). */
6
+ appDir?: string;
7
+ /** Islands directory relative to Vite root (default: src/islands). */
8
+ islandsDir?: string;
9
+ /** Content directory relative to Vite root (default: src/content). */
10
+ contentDir?: string;
11
+ /** Where to write the generated client entry (default: .elur/entry-client.ts). */
12
+ generatedEntry?: string;
13
+ /** Public path for the client entry module (default: /_elur/entry-client.js). */
14
+ clientEntry?: string;
15
+ /** HTML lang attribute (default: es). */
16
+ lang?: string;
17
+ /** Import specifier for hydrateIslands in the generated entry. */
18
+ hydrateImport?: string;
19
+ /** Import specifier for startClientRouter in the generated entry. */
20
+ routerImport?: string;
21
+ /** CSRF / origin policy applied to the server actions endpoint in dev. */
22
+ actionSecurity?: ActionSecurityOptions;
23
+ /**
24
+ * How the legacy interpolation transform is handled (default: "auto").
25
+ * With a Elur core that supports partial attribute interpolation natively
26
+ * the transform is not applied; use "legacy" for migrations against older
27
+ * cores and "off" to never transform.
28
+ */
29
+ interpolation?: InterpolationMode;
30
+ }
31
+ /**
32
+ * Official Vite plugin for elur-kit.
33
+ *
34
+ * In dev mode it generates the islands entry and renders every page via SSR.
35
+ * In production builds it can be combined with `elur-kit build` to generate
36
+ * static HTML files.
37
+ */
38
+ export declare function elurJsKit(options?: ElurJsKitViteOptions): Plugin[];
39
+ export { elurJsInterpolationPlugin, type InterpolationPluginOptions } from "./interpolation-plugin.js";
40
+ export type { InterpolationMode } from "./interpolation-plugin.js";
41
+ export { coreSupportsPartialInterpolation, shouldUseLegacyInterpolation } from "./interpolation-plugin.js";