@pajecawav/yamf 0.0.2 → 0.0.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 (57) hide show
  1. package/dist/components/Head.d.ts.map +1 -1
  2. package/dist/components/Head.js.map +1 -1
  3. package/dist/context/ssr.d.ts +2 -3
  4. package/dist/context/ssr.d.ts.map +1 -1
  5. package/dist/context/ssr.js.map +1 -1
  6. package/dist/hooks/useEvent.d.ts +2 -3
  7. package/dist/hooks/useEvent.d.ts.map +1 -1
  8. package/dist/hooks/useEvent.js.map +1 -1
  9. package/dist/hooks/useHead.d.ts +3 -2
  10. package/dist/hooks/useHead.d.ts.map +1 -1
  11. package/dist/hooks/useHead.js +8 -2
  12. package/dist/hooks/useHead.js.map +1 -1
  13. package/dist/index.d.ts +3 -2
  14. package/dist/index.js +2 -2
  15. package/dist/island/client.js.map +1 -1
  16. package/dist/page.d.ts +9 -9
  17. package/dist/page.d.ts.map +1 -1
  18. package/dist/page.js +11 -5
  19. package/dist/page.js.map +1 -1
  20. package/dist/server/entry.d.mts +3 -4
  21. package/dist/server/entry.d.mts.map +1 -1
  22. package/dist/server/entry.mjs +8 -5
  23. package/dist/server/entry.mjs.map +1 -1
  24. package/dist/server/island/server.d.mts.map +1 -1
  25. package/dist/server/island/server.mjs.map +1 -1
  26. package/dist/server/shared/head.d.mts +9 -0
  27. package/dist/server/shared/head.d.mts.map +1 -0
  28. package/dist/shared/head.d.ts +9 -0
  29. package/dist/shared/head.d.ts.map +1 -0
  30. package/dist/vite/index.d.mts.map +1 -1
  31. package/dist/vite/index.mjs +2 -0
  32. package/dist/vite/index.mjs.map +1 -1
  33. package/dist/vite/islands.mjs.map +1 -1
  34. package/dist/vite/shared/utils.mjs.map +1 -1
  35. package/dist/vite/virtual-assets.mjs +2 -2
  36. package/dist/vite/virtual-assets.mjs.map +1 -1
  37. package/dist/vite/virtual-pages.mjs +1 -1
  38. package/dist/vite/virtual-pages.mjs.map +1 -1
  39. package/dist/vite/virtual-root.mjs +46 -0
  40. package/dist/vite/virtual-root.mjs.map +1 -0
  41. package/dist/vite/virtual-template.mjs +1 -1
  42. package/dist/vite/virtual-template.mjs.map +1 -1
  43. package/package.json +30 -26
  44. package/src/context/ssr.ts +1 -2
  45. package/src/hooks/useEvent.tsx +1 -2
  46. package/src/hooks/useHead.tsx +14 -2
  47. package/src/index.ts +2 -1
  48. package/src/island/client.tsx +2 -2
  49. package/src/island/server.tsx +1 -1
  50. package/src/page.tsx +21 -17
  51. package/src/server/entry.tsx +16 -13
  52. package/src/shared/head.ts +3 -0
  53. package/src/virtual.d.ts +7 -1
  54. package/src/vite/index.ts +2 -0
  55. package/src/vite/islands.ts +1 -1
  56. package/src/vite/virtual-assets.ts +1 -1
  57. package/src/vite/virtual-root.ts +48 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Head.d.ts","names":[],"sources":["../../src/components/Head.tsx"],"mappings":";;;KAGY,SAAA,GAAY,cAAA;AAAA,cAEX,IAAA,GAAQ,KAAA,EAAO,SAAA"}
1
+ {"version":3,"file":"Head.d.ts","names":[],"sources":["../../src/components/Head.tsx"],"mappings":";;;KAGY,SAAA,GAAY,cAAA;AAAA,cAEX,IAAA,GAAQ,KAAO,EAAA,SAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Head.js","names":[],"sources":["../../src/components/Head.tsx"],"sourcesContent":["import type { ResolvableHead } from \"unhead/types\";\nimport { useHead } from \"#/hooks/useHead\";\n\nexport type HeadProps = ResolvableHead;\n\nexport const Head = (props: HeadProps): void => {\n\tuseHead(props);\n};\n"],"mappings":";;AAKA,MAAa,QAAQ,UAA2B;CAC/C,QAAQ,MAAM"}
1
+ {"version":3,"file":"Head.js","names":[],"sources":["../../src/components/Head.tsx"],"sourcesContent":["import type { ResolvableHead } from \"unhead/types\";\nimport { useHead } from \"#/hooks/useHead\";\n\nexport type HeadProps = ResolvableHead;\n\nexport const Head = (props: HeadProps): void => {\n\tuseHead(props);\n};\n"],"mappings":";;AAKA,MAAa,QAAQ,UAA2B;CAC/C,QAAQ,KAAK;AACd"}
@@ -1,11 +1,10 @@
1
- import { EventHandlerRequest } from "nitro/h3";
2
1
  import { ServerUnhead } from "unhead/server";
3
- import { H3Event as H3Event$1 } from "nitro";
2
+ import { H3Event } from "nitro";
4
3
 
5
4
  //#region src/context/ssr.d.ts
6
5
  interface SSRContextValue {
7
6
  head: ServerUnhead;
8
- event: H3Event$1<EventHandlerRequest>;
7
+ event: H3Event;
9
8
  }
10
9
  declare const useSSRContext: () => SSRContextValue | null;
11
10
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.d.ts","names":[],"sources":["../../src/context/ssr.ts"],"mappings":";;;;;UAKU,eAAA;EACT,IAAA,EAAM,YAAA;EACN,KAAA,EAAO,SAAA,CAAQ,mBAAA;AAAA;AAAA,cAOH,aAAA,QAAoB,eAAA"}
1
+ {"version":3,"file":"ssr.d.ts","names":[],"sources":["../../src/context/ssr.ts"],"mappings":";;;;UAIU,eAAA;EACT,IAAA,EAAM,YAAA;EACN,KAAA,EAAO,OAAA;AAAA;AAAA,cAOK,aAAA,QAAoB,eAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.js","names":[],"sources":["../../src/context/ssr.ts"],"sourcesContent":["import { type Context, createContext, useContext } from \"hono/jsx\";\nimport type { H3Event } from \"nitro\";\nimport type { EventHandlerRequest } from \"nitro/h3\";\nimport type { ServerUnhead } from \"unhead/server\";\n\ninterface SSRContextValue {\n\thead: ServerUnhead;\n\tevent: H3Event<EventHandlerRequest>;\n}\n\nexport const SSRContext: Context<SSRContextValue | null> = createContext<SSRContextValue | null>(\n\tnull,\n);\n\nexport const useSSRContext = (): SSRContextValue | null => {\n\treturn useContext(SSRContext);\n};\n"],"mappings":";;AAUA,MAAa,aAA8C,cAC1D,KACA;AAED,MAAa,sBAA8C;CAC1D,OAAO,WAAW,WAAW"}
1
+ {"version":3,"file":"ssr.js","names":[],"sources":["../../src/context/ssr.ts"],"sourcesContent":["import { type Context, createContext, useContext } from \"hono/jsx\";\nimport type { H3Event } from \"nitro\";\nimport type { ServerUnhead } from \"unhead/server\";\n\ninterface SSRContextValue {\n\thead: ServerUnhead;\n\tevent: H3Event;\n}\n\nexport const SSRContext: Context<SSRContextValue | null> = createContext<SSRContextValue | null>(\n\tnull,\n);\n\nexport const useSSRContext = (): SSRContextValue | null => {\n\treturn useContext(SSRContext);\n};\n"],"mappings":";;AASA,MAAa,aAA8C,cAC1D,IACD;AAEA,MAAa,sBAA8C;CAC1D,OAAO,WAAW,UAAU;AAC7B"}
@@ -1,8 +1,7 @@
1
- import { EventHandlerRequest } from "nitro/h3";
2
- import { H3Event as H3Event$1 } from "nitro";
1
+ import { H3Event } from "nitro";
3
2
 
4
3
  //#region src/hooks/useEvent.d.ts
5
- declare const useEvent: () => H3Event$1<EventHandlerRequest>;
4
+ declare const useEvent: () => H3Event;
6
5
  //#endregion
7
6
  export { useEvent };
8
7
  //# sourceMappingURL=useEvent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEvent.d.ts","names":[],"sources":["../../src/hooks/useEvent.tsx"],"mappings":";;;;cAIa,QAAA,QAAe,SAAA,CAAQ,mBAAA"}
1
+ {"version":3,"file":"useEvent.d.ts","names":[],"sources":["../../src/hooks/useEvent.tsx"],"mappings":";;;cAGa,QAAA,QAAe,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEvent.js","names":[],"sources":["../../src/hooks/useEvent.tsx"],"sourcesContent":["import type { H3Event } from \"nitro\";\nimport type { EventHandlerRequest } from \"nitro/h3\";\nimport { useSSRContext } from \"#/context/ssr\";\n\nexport const useEvent = (): H3Event<EventHandlerRequest> => {\n\tconst ctx = useSSRContext();\n\n\tif (!ctx) {\n\t\tthrow new Error(\"SSR context not found\");\n\t}\n\n\treturn ctx.event;\n};\n"],"mappings":";;AAIA,MAAa,iBAA+C;CAC3D,MAAM,MAAM,eAAe;CAE3B,IAAI,CAAC,KACJ,MAAM,IAAI,MAAM,wBAAwB;CAGzC,OAAO,IAAI"}
1
+ {"version":3,"file":"useEvent.js","names":[],"sources":["../../src/hooks/useEvent.tsx"],"sourcesContent":["import type { H3Event } from \"nitro\";\nimport { useSSRContext } from \"#/context/ssr\";\n\nexport const useEvent = (): H3Event => {\n\tconst ctx = useSSRContext();\n\n\tif (!ctx) {\n\t\tthrow new Error(\"SSR context not found\");\n\t}\n\n\treturn ctx.event;\n};\n"],"mappings":";;AAGA,MAAa,iBAA0B;CACtC,MAAM,MAAM,cAAc;CAE1B,IAAI,CAAC,KACJ,MAAM,IAAI,MAAM,uBAAuB;CAGxC,OAAO,IAAI;AACZ"}
@@ -1,5 +1,5 @@
1
1
  import { ClientUnhead } from "unhead/client";
2
- import { ResolvableHead } from "unhead/types";
2
+ import { ResolvableHead, UseSeoMetaInput } from "unhead/types";
3
3
 
4
4
  //#region src/hooks/useHead.d.ts
5
5
  declare global {
@@ -8,6 +8,7 @@ declare global {
8
8
  }
9
9
  }
10
10
  declare const useHead: (input?: ResolvableHead) => void;
11
+ declare const useSeoMeta: (input?: UseSeoMetaInput) => void;
11
12
  //#endregion
12
- export { useHead };
13
+ export { useHead, useSeoMeta };
13
14
  //# sourceMappingURL=useHead.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHead.d.ts","names":[],"sources":["../../src/hooks/useHead.tsx"],"mappings":";;;;;YAOW,MAAA;IACT,UAAA,GAAa,YAAA;EAAA;AAAA;AAAA,cAQF,OAAA,GAAW,KAAA,GAAQ,cAAA"}
1
+ {"version":3,"file":"useHead.d.ts","names":[],"sources":["../../src/hooks/useHead.tsx"],"mappings":";;;;;YAOW,MAAA;IACT,UAAA,GAAa,YAAA;EAAA;AAAA;AAAA,cAQF,OAAA,GAAW,KAAQ,GAAA,cAAA;AAAA,cAYnB,UAAA,GAAc,KAAQ,GAAA,eAAA"}
@@ -1,5 +1,5 @@
1
1
  import { useSSRContext } from "../context/ssr.js";
2
- import { useHead } from "unhead";
2
+ import { useHead, useSeoMeta } from "unhead";
3
3
  import { createHead } from "unhead/client";
4
4
  //#region src/hooks/useHead.tsx
5
5
  if (!import.meta.env.SSR) window.__UNHEAD__ = createHead();
@@ -9,7 +9,13 @@ const useHead$1 = (input) => {
9
9
  if (ctx?.head) useHead(ctx.head, input);
10
10
  } else if (window.__UNHEAD__) useHead(window.__UNHEAD__, input);
11
11
  };
12
+ const useSeoMeta$1 = (input) => {
13
+ if (import.meta.env.SSR) {
14
+ const ctx = useSSRContext();
15
+ if (ctx?.head) useSeoMeta(ctx.head, input);
16
+ } else if (window.__UNHEAD__) useSeoMeta(window.__UNHEAD__, input);
17
+ };
12
18
  //#endregion
13
- export { useHead$1 as useHead };
19
+ export { useHead$1 as useHead, useSeoMeta$1 as useSeoMeta };
14
20
 
15
21
  //# sourceMappingURL=useHead.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHead.js","names":["useHead"],"sources":["../../src/hooks/useHead.tsx"],"sourcesContent":["import { useHead as _useHead } from \"unhead\";\nimport type { ClientUnhead } from \"unhead/client\";\nimport { createHead } from \"unhead/client\";\nimport type { ResolvableHead } from \"unhead/types\";\nimport { useSSRContext } from \"#/context/ssr\";\n\ndeclare global {\n\tinterface Window {\n\t\t__UNHEAD__?: ClientUnhead;\n\t}\n}\n\nif (!import.meta.env.SSR) {\n\twindow.__UNHEAD__ = createHead();\n}\n\nexport const useHead = (input?: ResolvableHead): void => {\n\tif (import.meta.env.SSR) {\n\t\tconst ctx = useSSRContext();\n\n\t\tif (ctx?.head) {\n\t\t\t_useHead(ctx.head, input);\n\t\t}\n\t} else if (window.__UNHEAD__) {\n\t\t_useHead(window.__UNHEAD__, input);\n\t}\n};\n"],"mappings":";;;;AAYA,IAAI,CAAC,OAAO,KAAK,IAAI,KACpB,OAAO,aAAa,YAAY;AAGjC,MAAaA,aAAW,UAAiC;CACxD,IAAI,OAAO,KAAK,IAAI,KAAK;EACxB,MAAM,MAAM,eAAe;EAE3B,IAAI,KAAK,MACR,QAAS,IAAI,MAAM,MAAM;QAEpB,IAAI,OAAO,YACjB,QAAS,OAAO,YAAY,MAAM"}
1
+ {"version":3,"file":"useHead.js","names":["useHead","useSeoMeta"],"sources":["../../src/hooks/useHead.tsx"],"sourcesContent":["import { useHead as _useHead, useSeoMeta as _useSeoMeta } from \"unhead\";\nimport type { ClientUnhead } from \"unhead/client\";\nimport { createHead } from \"unhead/client\";\nimport type { ResolvableHead, UseSeoMetaInput } from \"unhead/types\";\nimport { useSSRContext } from \"#/context/ssr\";\n\ndeclare global {\n\tinterface Window {\n\t\t__UNHEAD__?: ClientUnhead;\n\t}\n}\n\nif (!import.meta.env.SSR) {\n\twindow.__UNHEAD__ = createHead();\n}\n\nexport const useHead = (input?: ResolvableHead): void => {\n\tif (import.meta.env.SSR) {\n\t\tconst ctx = useSSRContext();\n\n\t\tif (ctx?.head) {\n\t\t\t_useHead(ctx.head, input);\n\t\t}\n\t} else if (window.__UNHEAD__) {\n\t\t_useHead(window.__UNHEAD__, input);\n\t}\n};\n\nexport const useSeoMeta = (input?: UseSeoMetaInput): void => {\n\tif (import.meta.env.SSR) {\n\t\tconst ctx = useSSRContext();\n\n\t\tif (ctx?.head) {\n\t\t\t_useSeoMeta(ctx.head, input);\n\t\t}\n\t} else if (window.__UNHEAD__) {\n\t\t_useSeoMeta(window.__UNHEAD__, input);\n\t}\n};\n"],"mappings":";;;;AAYA,IAAI,CAAC,OAAO,KAAK,IAAI,KACpB,OAAO,aAAa,WAAW;AAGhC,MAAaA,aAAW,UAAiC;CACxD,IAAI,OAAO,KAAK,IAAI,KAAK;EACxB,MAAM,MAAM,cAAc;EAE1B,IAAI,KAAK,MACR,QAAS,IAAI,MAAM,KAAK;CAE1B,OAAO,IAAI,OAAO,YACjB,QAAS,OAAO,YAAY,KAAK;AAEnC;AAEA,MAAaC,gBAAc,UAAkC;CAC5D,IAAI,OAAO,KAAK,IAAI,KAAK;EACxB,MAAM,MAAM,cAAc;EAE1B,IAAI,KAAK,MACR,WAAY,IAAI,MAAM,KAAK;CAE7B,OAAO,IAAI,OAAO,YACjB,WAAY,OAAO,YAAY,KAAK;AAEtC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { ImportAssetsResult, ImportAssetsResultRaw } from "./shared/assets.js";
2
+ import { YamfHead } from "./shared/head.js";
2
3
  import { PageHandler, definePage } from "./page.js";
3
4
  import { useSSRContext } from "./context/ssr.js";
4
5
  import { useEvent } from "./hooks/useEvent.js";
5
- import { useHead } from "./hooks/useHead.js";
6
+ import { useHead, useSeoMeta } from "./hooks/useHead.js";
6
7
  import { IslandClientDirective, IslandProps } from "./island/types.js";
7
8
  import { Head, HeadProps } from "./components/Head.js";
8
- export { Head, type HeadProps, type ImportAssetsResult, type ImportAssetsResultRaw, type IslandClientDirective, type IslandProps, type PageHandler, definePage, useEvent, useHead, useSSRContext };
9
+ export { Head, type HeadProps, type ImportAssetsResult, type ImportAssetsResultRaw, type IslandClientDirective, type IslandProps, type PageHandler, type YamfHead, definePage, useEvent, useHead, useSSRContext, useSeoMeta };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useSSRContext } from "./context/ssr.js";
2
2
  import { definePage } from "./page.js";
3
3
  import { useEvent } from "./hooks/useEvent.js";
4
- import { useHead } from "./hooks/useHead.js";
4
+ import { useHead, useSeoMeta } from "./hooks/useHead.js";
5
5
  import { Head } from "./components/Head.js";
6
- export { Head, definePage, useEvent, useHead, useSSRContext };
6
+ export { Head, definePage, useEvent, useHead, useSSRContext, useSeoMeta };
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../../src/island/client.tsx"],"sourcesContent":["import { parse } from \"devalue\";\nimport type { FC } from \"hono/jsx\";\nimport { hydrateRoot } from \"hono/jsx/dom/client\";\nimport { withLeadingSlash } from \"ufo\";\nimport type { IslandClientDirective } from \"./types\";\n\ndeclare let __island_raw_import__: <T>(file: string) => Promise<T>;\n\nconst listeners = new WeakMap<Element, VoidFunction>();\n\nconst observer = new IntersectionObserver(entries => {\n\tfor (const entry of entries) {\n\t\tif (entry.isIntersecting) {\n\t\t\tlisteners.get(entry.target)?.();\n\t\t\tunobserve(entry.target);\n\t\t}\n\t}\n});\n\nconst observe = (target: Element, cb: VoidFunction) => {\n\tobserver.observe(target);\n\tlisteners.set(target, cb);\n};\n\nconst unobserve = (target: Element) => {\n\tobserver.unobserve(target);\n\tlisteners.delete(target);\n};\n\ncustomElements.define(\n\t\"yamf-island\",\n\tclass extends HTMLElement {\n\t\tpublic connectedCallback() {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\tconst islandProps = parse(this.getAttribute(\"island-props\") ?? \"{}\");\n\t\t\tconst islandSrc = this.getAttribute(\"island-src\");\n\t\t\tconst islandEntry = this.getAttribute(\"island-entry\");\n\t\t\tconst islandClient = (this.getAttribute(\"island-client\") ??\n\t\t\t\t\"load\") as IslandClientDirective;\n\n\t\t\tif (!islandSrc) {\n\t\t\t\tthrow new Error(\"Missing island-src attribute\");\n\t\t\t}\n\n\t\t\tif (!islandEntry) {\n\t\t\t\tthrow new Error(\"Missing island-entry attribute\");\n\t\t\t}\n\n\t\t\tconst hydrateIsland = (mod: Record<string, FC>) => {\n\t\t\t\tconst Comp = mod[islandEntry];\n\n\t\t\t\tif (!Comp) {\n\t\t\t\t\tthrow new Error(`Missing island entry ${islandEntry} in ${islandSrc}`);\n\t\t\t\t}\n\n\t\t\t\thydrateRoot(this, <Comp {...islandProps} />);\n\t\t\t};\n\n\t\t\tconst initIsland = () => {\n\t\t\t\tconst src = withLeadingSlash(islandSrc);\n\t\t\t\tvoid __island_raw_import__<Record<string, FC>>(src).then(hydrateIsland);\n\t\t\t};\n\n\t\t\tswitch (islandClient) {\n\t\t\t\tcase \"load\":\n\t\t\t\t\tinitIsland();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"idle\":\n\t\t\t\t\trequestIdleCallback(initIsland);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"visible\":\n\t\t\t\t\t// yamf-island has `display: contents` which breaks IntersectionObserver\n\t\t\t\t\t// so we have to observe the first child instead if it exists\n\t\t\t\t\tif (this.firstElementChild) {\n\t\t\t\t\t\tobserve(this.firstElementChild, initIsland);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tinitIsland();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"skip\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n\t\t\t\t\tthrow new Error(`Invalid island-client value: ${islandClient}`);\n\t\t\t}\n\t\t}\n\n\t\tpublic disconnectedCallback() {\n\t\t\tunobserve(this);\n\t\t}\n\t},\n);\n"],"mappings":";;;;;AAQA,MAAM,4BAAY,IAAI,SAAgC;AAEtD,MAAM,WAAW,IAAI,sBAAqB,YAAW;CACpD,KAAK,MAAM,SAAS,SACnB,IAAI,MAAM,gBAAgB;EACzB,UAAU,IAAI,MAAM,OAAO,IAAI;EAC/B,UAAU,MAAM,OAAO;;EAGxB;AAEF,MAAM,WAAW,QAAiB,OAAqB;CACtD,SAAS,QAAQ,OAAO;CACxB,UAAU,IAAI,QAAQ,GAAG;;AAG1B,MAAM,aAAa,WAAoB;CACtC,SAAS,UAAU,OAAO;CAC1B,UAAU,OAAO,OAAO;;AAGzB,eAAe,OACd,eACA,cAAc,YAAY;CACzB,oBAA2B;EAE1B,MAAM,cAAc,MAAM,KAAK,aAAa,eAAe,IAAI,KAAK;EACpE,MAAM,YAAY,KAAK,aAAa,aAAa;EACjD,MAAM,cAAc,KAAK,aAAa,eAAe;EACrD,MAAM,eAAgB,KAAK,aAAa,gBAAgB,IACvD;EAED,IAAI,CAAC,WACJ,MAAM,IAAI,MAAM,+BAA+B;EAGhD,IAAI,CAAC,aACJ,MAAM,IAAI,MAAM,iCAAiC;EAGlD,MAAM,iBAAiB,QAA4B;GAClD,MAAM,OAAO,IAAI;GAEjB,IAAI,CAAC,MACJ,MAAM,IAAI,MAAM,wBAAwB,YAAY,MAAM,YAAY;GAGvE,YAAY,MAAM,oBAAC,MAAD,EAAM,GAAI,aAAe,CAAA,CAAC;;EAG7C,MAAM,mBAAmB;GACxB,MAAM,MAAM,iBAAiB,UAAU;GACvC,sBAA+C,IAAI,CAAC,KAAK,cAAc;;EAGxE,QAAQ,cAAR;GACC,KAAK;IACJ,YAAY;IACZ;GACD,KAAK;IACJ,oBAAoB,WAAW;IAC/B;GACD,KAAK;IAGJ,IAAI,KAAK,mBACR,QAAQ,KAAK,mBAAmB,WAAW;SAE3C,YAAY;IAEb;GACD,KAAK,QACJ;GACD,SAEC,MAAM,IAAI,MAAM,gCAAgC,eAAe;;;CAIlE,uBAA8B;EAC7B,UAAU,KAAK;;EAGjB"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../src/island/client.tsx"],"sourcesContent":["import { parse } from \"devalue\";\nimport type { FC } from \"hono/jsx\";\nimport { hydrateRoot } from \"hono/jsx/dom/client\";\nimport { withLeadingSlash } from \"ufo\";\nimport type { IslandClientDirective } from \"./types\";\n\ndeclare let __island_raw_import__: <T>(file: string) => Promise<T>;\n\nconst listeners = new WeakMap<Element, VoidFunction>();\n\nconst observer = new IntersectionObserver(entries => {\n\tfor (const entry of entries) {\n\t\tif (entry.isIntersecting) {\n\t\t\tlisteners.get(entry.target)?.();\n\t\t\tunobserve(entry.target);\n\t\t}\n\t}\n});\n\nconst observe = (target: Element, cb: VoidFunction) => {\n\tobserver.observe(target);\n\tlisteners.set(target, cb);\n};\n\nconst unobserve = (target: Element) => {\n\tobserver.unobserve(target);\n\tlisteners.delete(target);\n};\n\ncustomElements.define(\n\t\"yamf-island\",\n\tclass extends HTMLElement {\n\t\tpublic connectedCallback() {\n\t\t\tconst islandProps = parse(this.getAttribute(\"island-props\") ?? \"{}\");\n\t\t\tconst islandSrc = this.getAttribute(\"island-src\");\n\t\t\tconst islandEntry = this.getAttribute(\"island-entry\");\n\t\t\t// oxlint-disable-next-line typescript/no-unsafe-type-assertion\n\t\t\tconst islandClient = (this.getAttribute(\"island-client\") ??\n\t\t\t\t\"load\") as IslandClientDirective;\n\n\t\t\tif (!islandSrc) {\n\t\t\t\tthrow new Error(\"Missing island-src attribute\");\n\t\t\t}\n\n\t\t\tif (!islandEntry) {\n\t\t\t\tthrow new Error(\"Missing island-entry attribute\");\n\t\t\t}\n\n\t\t\tconst hydrateIsland = (mod: Record<string, FC>) => {\n\t\t\t\tconst Comp = mod[islandEntry];\n\n\t\t\t\tif (!Comp) {\n\t\t\t\t\tthrow new Error(`Missing island entry ${islandEntry} in ${islandSrc}`);\n\t\t\t\t}\n\n\t\t\t\thydrateRoot(this, <Comp {...islandProps} />);\n\t\t\t};\n\n\t\t\tconst initIsland = () => {\n\t\t\t\tconst src = withLeadingSlash(islandSrc);\n\t\t\t\tvoid __island_raw_import__<Record<string, FC>>(src).then(hydrateIsland);\n\t\t\t};\n\n\t\t\tswitch (islandClient) {\n\t\t\t\tcase \"load\":\n\t\t\t\t\tinitIsland();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"idle\":\n\t\t\t\t\trequestIdleCallback(initIsland);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"visible\":\n\t\t\t\t\t// yamf-island has `display: contents` which breaks IntersectionObserver\n\t\t\t\t\t// so we have to observe the first child instead if it exists\n\t\t\t\t\tif (this.firstElementChild) {\n\t\t\t\t\t\tobserve(this.firstElementChild, initIsland);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tinitIsland();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"skip\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t// oxlint-disable-next-line typescript/restrict-template-expressions\n\t\t\t\t\tthrow new Error(`Invalid island-client value: ${islandClient}`);\n\t\t\t}\n\t\t}\n\n\t\tpublic disconnectedCallback() {\n\t\t\tunobserve(this);\n\t\t}\n\t},\n);\n"],"mappings":";;;;;AAQA,MAAM,4BAAY,IAAI,QAA+B;AAErD,MAAM,WAAW,IAAI,sBAAqB,YAAW;CACpD,KAAK,MAAM,SAAS,SACnB,IAAI,MAAM,gBAAgB;EACzB,UAAU,IAAI,MAAM,MAAM,CAAC,GAAG;EAC9B,UAAU,MAAM,MAAM;CACvB;AAEF,CAAC;AAED,MAAM,WAAW,QAAiB,OAAqB;CACtD,SAAS,QAAQ,MAAM;CACvB,UAAU,IAAI,QAAQ,EAAE;AACzB;AAEA,MAAM,aAAa,WAAoB;CACtC,SAAS,UAAU,MAAM;CACzB,UAAU,OAAO,MAAM;AACxB;AAEA,eAAe,OACd,eACA,cAAc,YAAY;CACzB,oBAA2B;EAC1B,MAAM,cAAc,MAAM,KAAK,aAAa,cAAc,KAAK,IAAI;EACnE,MAAM,YAAY,KAAK,aAAa,YAAY;EAChD,MAAM,cAAc,KAAK,aAAa,cAAc;EAEpD,MAAM,eAAgB,KAAK,aAAa,eAAe,KACtD;EAED,IAAI,CAAC,WACJ,MAAM,IAAI,MAAM,8BAA8B;EAG/C,IAAI,CAAC,aACJ,MAAM,IAAI,MAAM,gCAAgC;EAGjD,MAAM,iBAAiB,QAA4B;GAClD,MAAM,OAAO,IAAI;GAEjB,IAAI,CAAC,MACJ,MAAM,IAAI,MAAM,wBAAwB,YAAY,MAAM,WAAW;GAGtE,YAAY,MAAM,oBAAC,MAAD,EAAM,GAAI,YAAc,CAAA,CAAC;EAC5C;EAEA,MAAM,mBAAmB;GACxB,MAAM,MAAM,iBAAiB,SAAS;GACtC,sBAA+C,GAAG,CAAC,CAAC,KAAK,aAAa;EACvE;EAEA,QAAQ,cAAR;GACC,KAAK;IACJ,WAAW;IACX;GACD,KAAK;IACJ,oBAAoB,UAAU;IAC9B;GACD,KAAK;IAGJ,IAAI,KAAK,mBACR,QAAQ,KAAK,mBAAmB,UAAU;SAE1C,WAAW;IAEZ;GACD,KAAK,QACJ;GACD,SAEC,MAAM,IAAI,MAAM,gCAAgC,cAAc;EAChE;CACD;CAEA,uBAA8B;EAC7B,UAAU,IAAI;CACf;AACD,CACD"}
package/dist/page.d.ts CHANGED
@@ -1,22 +1,22 @@
1
1
  import { ImportAssetsResult } from "./shared/assets.js";
2
- import { Child, FC, PropsWithChildren } from "hono/jsx";
3
- import { EventHandlerRequest, EventHandlerResponse, H3Event, HTTPResponse } from "nitro/h3";
2
+ import { YamfHead } from "./shared/head.js";
3
+ import { Child } from "hono/jsx";
4
+ import { EventHandlerResponse, H3Event, HTTPResponse } from "nitro/h3";
4
5
  import { Unhead } from "unhead/server";
5
- import { ResolvableHead } from "unhead/types";
6
+ import { UseSeoMetaInput } from "unhead/types";
6
7
 
7
8
  //#region src/page.d.ts
8
- type PageHandler = (event: H3Event<EventHandlerRequest>, params: {
9
- serverAssets?: ImportAssetsResult;
10
- head?: ResolvableHead;
11
- Layout?: FC<PropsWithChildren>;
9
+ type PageHandler = (event: H3Event, params: {
10
+ assets: ImportAssetsResult;
11
+ head?: YamfHead;
12
12
  }) => EventHandlerResponse;
13
- type PageRenderer = (event: H3Event<EventHandlerRequest>, params: {
13
+ type PageRenderer = (event: H3Event, params: {
14
14
  head: Unhead;
15
+ seoHead: (input: UseSeoMetaInput) => void;
15
16
  }) => HTTPResponse | Promise<HTTPResponse> | Child | Promise<Child>;
16
17
  interface DefinePageOptions {
17
18
  render: PageRenderer;
18
19
  stream?: boolean;
19
- Layout?: FC<PropsWithChildren>;
20
20
  }
21
21
  declare const definePage: (options: DefinePageOptions) => PageHandler;
22
22
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","names":[],"sources":["../src/page.tsx"],"mappings":";;;;;;;KAeY,WAAA,IACX,KAAA,EAAO,OAAA,CAAQ,mBAAA,GACf,MAAA;EACC,YAAA,GAAe,kBAAA;EACf,IAAA,GAAO,cAAA;EACP,MAAA,GAAS,EAAA,CAAG,iBAAA;AAAA,MAET,oBAAA;AAAA,KAEO,YAAA,IACX,KAAA,EAAO,OAAA,CAAQ,mBAAA,GACf,MAAA;EAAU,IAAA,EAAM,MAAA;AAAA,MACZ,YAAA,GAAe,OAAA,CAAQ,YAAA,IAAgB,KAAA,GAAQ,OAAA,CAAQ,KAAA;AAAA,UAElD,iBAAA;EACT,MAAA,EAAQ,YAAA;EACR,MAAA;EACA,MAAA,GAAS,EAAA,CAAG,iBAAA;AAAA;AAAA,cAGA,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA"}
1
+ {"version":3,"file":"page.d.ts","names":[],"sources":["../src/page.tsx"],"mappings":";;;;;;;;KAgBY,WAAA,IACX,KAAA,EAAO,OAAA,EACP,MAAA;EACC,MAAA,EAAQ,kBAAA;EACR,IAAA,GAAO,QAAA;AAAA,MAEJ,oBAAA;AAAA,KAEO,YAAA,IACX,KAAA,EAAO,OAAA,EACP,MAAA;EACC,IAAA,EAAM,MAAA;EACN,OAAA,GAAU,KAAA,EAAO,eAAA;AAAA,MAEd,YAAA,GAAe,OAAA,CAAQ,YAAA,IAAgB,KAAA,GAAQ,OAAA,CAAQ,KAAA;AAAA,UAElD,iBAAA;EACT,MAAA,EAAQ,YAAA;EACR,MAAA;AAAA;AAAA,cAGY,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA"}
package/dist/page.js CHANGED
@@ -3,16 +3,18 @@ import { Fragment } from "hono/jsx";
3
3
  import { renderToReadableStream } from "hono/jsx/streaming";
4
4
  import { Hono } from "hono/tiny";
5
5
  import { HTTPResponse, withServerTiming } from "nitro/h3";
6
+ import { useSeoMeta } from "unhead";
6
7
  import { transformHtmlTemplate } from "unhead/server";
7
8
  import { createStreamableHead, wrapStream } from "unhead/stream/server";
8
- import { clientAssets } from "virtual:yamf:assets";
9
+ import { Root } from "virtual:yamf:root";
9
10
  import { template } from "virtual:yamf:template";
10
11
  import { jsx } from "hono/jsx/jsx-runtime";
11
12
  //#region src/page.tsx
12
13
  const definePage = (options) => {
13
- return async (event, { serverAssets, head: headInit, Layout = options.Layout ?? Fragment }) => {
14
- const assets = serverAssets ? clientAssets.merge(serverAssets) : clientAssets;
14
+ return async (event, { assets, head: headInit }) => {
15
15
  const { head } = createStreamableHead({ init: [headInit] });
16
+ const seoHead = (input) => useSeoMeta(head, input);
17
+ seoHead(headInit?.seo);
16
18
  head.push({
17
19
  link: [...assets.js.map((attrs) => ({
18
20
  rel: "modulepreload",
@@ -26,14 +28,18 @@ const definePage = (options) => {
26
28
  src: assets.entry
27
29
  }]
28
30
  });
29
- const content = await options.render(event, { head });
31
+ const content = await options.render(event, {
32
+ head,
33
+ seoHead
34
+ });
30
35
  if (content instanceof HTTPResponse) return content;
36
+ const Root$1 = Root ?? Fragment;
31
37
  const App = async () => /* @__PURE__ */ jsx(SSRContext, {
32
38
  value: {
33
39
  head,
34
40
  event
35
41
  },
36
- children: /* @__PURE__ */ jsx(Layout, { children: content })
42
+ children: /* @__PURE__ */ jsx(Root$1, { children: content })
37
43
  });
38
44
  const responseInit = { headers: { "Content-Type": "text/html; charset=utf-8" } };
39
45
  if (!options.stream) return new Hono().get("/", async (c) => withServerTiming(event, "#render", async () => {
package/dist/page.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"page.js","names":[],"sources":["../src/page.tsx"],"sourcesContent":["import type { Child, FC, PropsWithChildren } from \"hono/jsx\";\nimport { Fragment } from \"hono/jsx\";\nimport { renderToReadableStream } from \"hono/jsx/streaming\";\nimport { Hono } from \"hono/tiny\";\nimport type { EventHandlerRequest, EventHandlerResponse, H3Event } from \"nitro/h3\";\nimport { HTTPResponse, withServerTiming } from \"nitro/h3\";\nimport type { Unhead } from \"unhead/server\";\nimport { transformHtmlTemplate } from \"unhead/server\";\nimport { createStreamableHead, wrapStream } from \"unhead/stream/server\";\nimport type { ResolvableHead, ResolvableLink } from \"unhead/types\";\nimport { clientAssets } from \"virtual:yamf:assets\";\nimport { template } from \"virtual:yamf:template\";\nimport { SSRContext } from \"./context/ssr\";\nimport type { ImportAssetsResult } from \"./shared/assets\";\n\nexport type PageHandler = (\n\tevent: H3Event<EventHandlerRequest>,\n\tparams: {\n\t\tserverAssets?: ImportAssetsResult;\n\t\thead?: ResolvableHead;\n\t\tLayout?: FC<PropsWithChildren>;\n\t},\n) => EventHandlerResponse;\n\nexport type PageRenderer = (\n\tevent: H3Event<EventHandlerRequest>,\n\tparams: { head: Unhead },\n) => HTTPResponse | Promise<HTTPResponse> | Child | Promise<Child>;\n\ninterface DefinePageOptions {\n\trender: PageRenderer;\n\tstream?: boolean;\n\tLayout?: FC<PropsWithChildren>;\n}\n\nexport const definePage = (options: DefinePageOptions): PageHandler => {\n\treturn async (event, { serverAssets, head: headInit, Layout = options.Layout ?? Fragment }) => {\n\t\tconst assets = serverAssets ? clientAssets.merge(serverAssets) : clientAssets;\n\n\t\tconst { head } = createStreamableHead({ init: [headInit] });\n\n\t\thead.push({\n\t\t\tlink: [\n\t\t\t\t...assets.js.map((attrs): ResolvableLink => ({ rel: \"modulepreload\", ...attrs })),\n\t\t\t\t...assets.css.map((attrs): ResolvableLink => ({ rel: \"stylesheet\", ...attrs })),\n\t\t\t],\n\t\t\tscript: [{ type: \"module\", src: assets.entry }],\n\t\t});\n\n\t\tconst content = await options.render(event, { head });\n\n\t\tif (content instanceof HTTPResponse) {\n\t\t\treturn content;\n\t\t}\n\n\t\tconst App = async () => (\n\t\t\t<SSRContext value={{ head, event }}>\n\t\t\t\t<Layout>{content}</Layout>\n\t\t\t</SSRContext>\n\t\t);\n\n\t\tconst responseInit = {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t},\n\t\t};\n\n\t\tif (!options.stream) {\n\t\t\t// TODO: figure out how expensive this is\n\t\t\treturn new Hono()\n\t\t\t\t.get(\"/\", async c =>\n\t\t\t\t\twithServerTiming(event, \"#render\", async () => {\n\t\t\t\t\t\tconst response = await c.html(<App />);\n\n\t\t\t\t\t\tlet html = await response.text();\n\n\t\t\t\t\t\thtml = transformHtmlTemplate(\n\t\t\t\t\t\t\thead,\n\t\t\t\t\t\t\ttemplate.replace(\"<!--ssr-outlet-->\", html ?? \"\"),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn new Response(html, responseInit);\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.request(\"/\");\n\t\t}\n\n\t\tconst stream = wrapStream(head, renderToReadableStream(<App />), template);\n\n\t\treturn new Response(stream, responseInit);\n\t};\n};\n"],"mappings":";;;;;;;;;;;AAmCA,MAAa,cAAc,YAA4C;CACtE,OAAO,OAAO,OAAO,EAAE,cAAc,MAAM,UAAU,SAAS,QAAQ,UAAU,eAAe;EAC9F,MAAM,SAAS,eAAe,aAAa,MAAM,aAAa,GAAG;EAEjE,MAAM,EAAE,SAAS,qBAAqB,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;EAE3D,KAAK,KAAK;GACT,MAAM,CACL,GAAG,OAAO,GAAG,KAAK,WAA2B;IAAE,KAAK;IAAiB,GAAG;IAAO,EAAE,EACjF,GAAG,OAAO,IAAI,KAAK,WAA2B;IAAE,KAAK;IAAc,GAAG;IAAO,EAAE,CAC/E;GACD,QAAQ,CAAC;IAAE,MAAM;IAAU,KAAK,OAAO;IAAO,CAAC;GAC/C,CAAC;EAEF,MAAM,UAAU,MAAM,QAAQ,OAAO,OAAO,EAAE,MAAM,CAAC;EAErD,IAAI,mBAAmB,cACtB,OAAO;EAGR,MAAM,MAAM,YACX,oBAAC,YAAD;GAAY,OAAO;IAAE;IAAM;IAAO;aACjC,oBAAC,QAAD,EAAA,UAAS,SAAiB,CAAA;GACd,CAAA;EAGd,MAAM,eAAe,EACpB,SAAS,EACR,gBAAgB,4BAChB,EACD;EAED,IAAI,CAAC,QAAQ,QAEZ,OAAO,IAAI,MAAM,CACf,IAAI,KAAK,OAAM,MACf,iBAAiB,OAAO,WAAW,YAAY;GAG9C,IAAI,OAAO,OAAM,MAFM,EAAE,KAAK,oBAAC,KAAD,EAAO,CAAA,CAAC,EAEZ,MAAM;GAEhC,OAAO,sBACN,MACA,SAAS,QAAQ,qBAAqB,QAAQ,GAAG,CACjD;GAED,OAAO,IAAI,SAAS,MAAM,aAAa;IACtC,CACF,CACA,QAAQ,IAAI;EAGf,MAAM,SAAS,WAAW,MAAM,uBAAuB,oBAAC,KAAD,EAAO,CAAA,CAAC,EAAE,SAAS;EAE1E,OAAO,IAAI,SAAS,QAAQ,aAAa"}
1
+ {"version":3,"file":"page.js","names":["Root","RootComponent"],"sources":["../src/page.tsx"],"sourcesContent":["import { Fragment, type Child } from \"hono/jsx\";\nimport { renderToReadableStream } from \"hono/jsx/streaming\";\nimport { Hono } from \"hono/tiny\";\nimport type { EventHandlerResponse, H3Event } from \"nitro/h3\";\nimport { HTTPResponse, withServerTiming } from \"nitro/h3\";\nimport { useSeoMeta } from \"unhead\";\nimport type { Unhead } from \"unhead/server\";\nimport { transformHtmlTemplate } from \"unhead/server\";\nimport { createStreamableHead, wrapStream } from \"unhead/stream/server\";\nimport type { ResolvableLink, UseSeoMetaInput } from \"unhead/types\";\nimport { Root as RootComponent } from \"virtual:yamf:root\";\nimport { template } from \"virtual:yamf:template\";\nimport { SSRContext } from \"./context/ssr\";\nimport type { ImportAssetsResult } from \"./shared/assets\";\nimport { YamfHead } from \"./shared/head\";\n\nexport type PageHandler = (\n\tevent: H3Event,\n\tparams: {\n\t\tassets: ImportAssetsResult;\n\t\thead?: YamfHead;\n\t},\n) => EventHandlerResponse;\n\nexport type PageRenderer = (\n\tevent: H3Event,\n\tparams: {\n\t\thead: Unhead;\n\t\tseoHead: (input: UseSeoMetaInput) => void;\n\t},\n) => HTTPResponse | Promise<HTTPResponse> | Child | Promise<Child>;\n\ninterface DefinePageOptions {\n\trender: PageRenderer;\n\tstream?: boolean;\n}\n\nexport const definePage = (options: DefinePageOptions): PageHandler => {\n\treturn async (event, { assets, head: headInit }) => {\n\t\tconst { head } = createStreamableHead({ init: [headInit] });\n\t\tconst seoHead = (input?: UseSeoMetaInput) => useSeoMeta(head, input);\n\t\tseoHead(headInit?.seo);\n\n\t\thead.push({\n\t\t\tlink: [\n\t\t\t\t...assets.js.map((attrs): ResolvableLink => ({ rel: \"modulepreload\", ...attrs })),\n\t\t\t\t...assets.css.map((attrs): ResolvableLink => ({ rel: \"stylesheet\", ...attrs })),\n\t\t\t],\n\t\t\tscript: [{ type: \"module\", src: assets.entry }],\n\t\t});\n\n\t\tconst content = await options.render(event, { head, seoHead });\n\n\t\tif (content instanceof HTTPResponse) {\n\t\t\treturn content;\n\t\t}\n\n\t\tconst Root = RootComponent ?? Fragment;\n\n\t\tconst App = async () => (\n\t\t\t<SSRContext value={{ head, event }}>\n\t\t\t\t<Root>{content}</Root>\n\t\t\t</SSRContext>\n\t\t);\n\n\t\tconst responseInit = {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html; charset=utf-8\",\n\t\t\t},\n\t\t};\n\n\t\tif (!options.stream) {\n\t\t\t// TODO: figure out how expensive this is\n\t\t\treturn new Hono()\n\t\t\t\t.get(\"/\", async c =>\n\t\t\t\t\twithServerTiming(event, \"#render\", async () => {\n\t\t\t\t\t\tconst response = await c.html(<App />);\n\n\t\t\t\t\t\tlet html = await response.text();\n\n\t\t\t\t\t\thtml = transformHtmlTemplate(\n\t\t\t\t\t\t\thead,\n\t\t\t\t\t\t\ttemplate.replace(\"<!--ssr-outlet-->\", html ?? \"\"),\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\treturn new Response(html, responseInit);\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.request(\"/\");\n\t\t}\n\n\t\tconst stream = wrapStream(head, renderToReadableStream(<App />), template);\n\n\t\treturn new Response(stream, responseInit);\n\t};\n};\n"],"mappings":";;;;;;;;;;;;AAqCA,MAAa,cAAc,YAA4C;CACtE,OAAO,OAAO,OAAO,EAAE,QAAQ,MAAM,eAAe;EACnD,MAAM,EAAE,SAAS,qBAAqB,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;EAC1D,MAAM,WAAW,UAA4B,WAAW,MAAM,KAAK;EACnE,QAAQ,UAAU,GAAG;EAErB,KAAK,KAAK;GACT,MAAM,CACL,GAAG,OAAO,GAAG,KAAK,WAA2B;IAAE,KAAK;IAAiB,GAAG;GAAM,EAAE,GAChF,GAAG,OAAO,IAAI,KAAK,WAA2B;IAAE,KAAK;IAAc,GAAG;GAAM,EAAE,CAC/E;GACA,QAAQ,CAAC;IAAE,MAAM;IAAU,KAAK,OAAO;GAAM,CAAC;EAC/C,CAAC;EAED,MAAM,UAAU,MAAM,QAAQ,OAAO,OAAO;GAAE;GAAM;EAAQ,CAAC;EAE7D,IAAI,mBAAmB,cACtB,OAAO;EAGR,MAAMA,SAAOC,QAAiB;EAE9B,MAAM,MAAM,YACX,oBAAC,YAAD;GAAY,OAAO;IAAE;IAAM;GAAM;aAChC,oBAACD,QAAD,EAAA,UAAO,QAAc,CAAA;EACV,CAAA;EAGb,MAAM,eAAe,EACpB,SAAS,EACR,gBAAgB,2BACjB,EACD;EAEA,IAAI,CAAC,QAAQ,QAEZ,OAAO,IAAI,KAAK,CAAC,CACf,IAAI,KAAK,OAAM,MACf,iBAAiB,OAAO,WAAW,YAAY;GAG9C,IAAI,OAAO,OAAM,MAFM,EAAE,KAAK,oBAAC,KAAD,CAAM,CAAA,CAAC,EAAA,CAEX,KAAK;GAE/B,OAAO,sBACN,MACA,SAAS,QAAQ,qBAAqB,QAAQ,EAAE,CACjD;GAEA,OAAO,IAAI,SAAS,MAAM,YAAY;EACvC,CAAC,CACF,CAAC,CACA,QAAQ,GAAG;EAGd,MAAM,SAAS,WAAW,MAAM,uBAAuB,oBAAC,KAAD,CAAM,CAAA,CAAC,GAAG,QAAQ;EAEzE,OAAO,IAAI,SAAS,QAAQ,YAAY;CACzC;AACD"}
@@ -1,12 +1,11 @@
1
+ import { YamfHead } from "./shared/head.mjs";
1
2
  import { EventHandlerRequest, EventHandlerWithFetch, H3Event } from "nitro/h3";
2
- import { FC, PropsWithChildren } from "hono/jsx";
3
- import { ResolvableHead } from "unhead/types";
4
3
 
5
4
  //#region src/server/entry.d.ts
6
5
  type ServerEntry = EventHandlerWithFetch<EventHandlerRequest, Promise<unknown>>;
7
6
  interface DefineServerEntryOptions {
8
- head?: ResolvableHead | ((event: H3Event<EventHandlerRequest>) => ResolvableHead);
9
- Layout?: FC<PropsWithChildren>;
7
+ head?: YamfHead | ((event: H3Event) => YamfHead);
8
+ disableEarlyHints?: boolean;
10
9
  }
11
10
  declare const defineServerEntry: (options?: DefineServerEntryOptions) => ServerEntry;
12
11
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"entry.d.mts","names":[],"sources":["../../src/server/entry.tsx"],"mappings":";;;;;KA8CY,WAAA,GAAc,qBAAA,CAAsB,mBAAA,EAAqB,OAAA;AAAA,UAEpD,wBAAA;EAChB,IAAA,GAAO,cAAA,KAAmB,KAAA,EAAO,OAAA,CAAQ,mBAAA,MAAyB,cAAA;EAClE,MAAA,GAAS,EAAA,CAAG,iBAAA;AAAA;AAAA,cAGA,iBAAA,GAAqB,OAAA,GAAU,wBAAA,KAA2B,WAAA"}
1
+ {"version":3,"file":"entry.d.mts","names":[],"sources":["../../src/server/entry.tsx"],"mappings":";;;;KA8CY,WAAA,GAAc,qBAAA,CAAsB,mBAAA,EAAqB,OAAA;AAAA,UAEpD,wBAAA;EAChB,IAAA,GAAO,QAAA,KAAa,KAAA,EAAO,OAAA,KAAY,QAAA;EACvC,iBAAA;AAAA;AAAA,cAGY,iBAAA,GAAqB,OAAA,GAAU,wBAAA,KAA2B,WAAA"}
@@ -4,6 +4,7 @@ import { addRoute, createRouter, findRoute } from "rou3";
4
4
  import { withLeadingSlash, withoutTrailingSlash } from "ufo";
5
5
  import { clientAssets } from "virtual:yamf:assets";
6
6
  import { assets, pages } from "virtual:yamf:pages";
7
+ import { rootAssets } from "virtual:yamf:root";
7
8
  //#region src/server/entry.tsx
8
9
  const router = createRouter();
9
10
  for (const [relativePath, handler] of Object.entries(pages).toSorted((a, b) => a[0].localeCompare(b[0]))) {
@@ -23,12 +24,14 @@ const defineServerEntry = (options) => {
23
24
  if (!route) throw new HTTPError("Not found", { status: 404 });
24
25
  const { handler, serverAssets } = route.data;
25
26
  event.context.params = route.params;
26
- const assets = serverAssets ? serverAssets.merge(clientAssets) : clientAssets;
27
- await writeEarlyHints(event, { link: [...assets.js.map((script) => `<${script.href}>; rel=modulepreload`), ...assets.css.map((style) => `<${style.href}>; rel=preload; as=style`)] });
27
+ const assets = clientAssets.merge(...[rootAssets, serverAssets].filter((x) => !!x));
28
+ if (!options?.disableEarlyHints) {
29
+ const link = [...assets.js.map((script) => `<${script.href}>; rel=modulepreload`), ...assets.css.map((style) => `<${style.href}>; rel=preload; as=style`)];
30
+ if (link.length) await writeEarlyHints(event, { link });
31
+ }
28
32
  return (await handler())(event, {
29
- serverAssets,
30
- head: typeof options?.head === "function" ? options.head(event) : options?.head,
31
- Layout: options?.Layout
33
+ assets,
34
+ head: typeof options?.head === "function" ? options.head(event) : options?.head
32
35
  });
33
36
  });
34
37
  };
@@ -1 +1 @@
1
- {"version":3,"file":"entry.mjs","names":["serverAssets"],"sources":["../../src/server/entry.tsx"],"sourcesContent":["import path from \"node:path\";\nimport type { FC, PropsWithChildren } from \"hono/jsx\";\nimport type { EventHandlerRequest, EventHandlerWithFetch, H3Event } from \"nitro/h3\";\nimport { defineHandler, HTTPError, writeEarlyHints } from \"nitro/h3\";\nimport { addRoute, createRouter, findRoute } from \"rou3\";\nimport { withLeadingSlash, withoutTrailingSlash } from \"ufo\";\nimport type { ResolvableHead } from \"unhead/types\";\nimport { clientAssets } from \"virtual:yamf:assets\";\nimport { pages, assets as serverAssets } from \"virtual:yamf:pages\";\nimport type { PageHandler } from \"#/page\";\n\ninterface Route {\n\thandler: () => Promise<PageHandler>;\n\tserverAssets?: ImportAssetsResult;\n}\n\nconst router = createRouter<Route>();\n\nfor (const [relativePath, handler] of Object.entries(pages).toSorted((a, b) =>\n\ta[0].localeCompare(b[0]),\n)) {\n\tconst ext = path.extname(relativePath);\n\n\tlet route = path.relative(\"/src/pages\", relativePath);\n\n\tif (ext.length) {\n\t\troute = route.slice(0, -ext.length);\n\t}\n\n\troute =\n\t\troute\n\t\t\t.replace(/\\.[A-Za-z]+$/, \"\")\n\t\t\t.replace(/\\(([^(/\\\\]+)\\)[/\\\\]/g, \"\")\n\t\t\t.replace(/\\[\\.{3}]/g, \"**\")\n\t\t\t.replace(/\\[\\.{3}([^\\]]+)]/g, (_, p: string) => \"**:\" + p.replace(/[^\\w-]/g, \"_\"))\n\t\t\t.replace(/\\[([^/\\]]+)]/g, (_, p: string) => \":\" + p.replace(/[^\\w-]/g, \"_\"))\n\t\t\t.replace(/(\\/|^)index$/, \"\") || \"/\";\n\n\troute = withLeadingSlash(withoutTrailingSlash(route));\n\n\taddRoute(router, \"GET\", route, {\n\t\thandler,\n\t\tserverAssets: serverAssets[relativePath],\n\t});\n}\n\nexport type ServerEntry = EventHandlerWithFetch<EventHandlerRequest, Promise<unknown>>;\n\nexport interface DefineServerEntryOptions {\n\thead?: ResolvableHead | ((event: H3Event<EventHandlerRequest>) => ResolvableHead);\n\tLayout?: FC<PropsWithChildren>;\n}\n\nexport const defineServerEntry = (options?: DefineServerEntryOptions): ServerEntry => {\n\treturn defineHandler(async event => {\n\t\tconst route = findRoute(router, \"GET\", event.url.pathname);\n\n\t\tif (!route) {\n\t\t\tthrow new HTTPError(\"Not found\", { status: 404 });\n\t\t}\n\n\t\tconst { handler, serverAssets } = route.data;\n\t\tevent.context.params = route.params;\n\n\t\tconst assets = serverAssets ? serverAssets.merge(clientAssets) : clientAssets;\n\n\t\tawait writeEarlyHints(event, {\n\t\t\tlink: [\n\t\t\t\t...assets.js.map(script => `<${script.href}>; rel=modulepreload`),\n\t\t\t\t...assets.css.map(style => `<${style.href}>; rel=preload; as=style`),\n\t\t\t],\n\t\t});\n\n\t\treturn (await handler())(event, {\n\t\t\tserverAssets,\n\t\t\thead: typeof options?.head === \"function\" ? options.head(event) : options?.head,\n\t\t\tLayout: options?.Layout,\n\t\t});\n\t});\n};\n"],"mappings":";;;;;;;AAgBA,MAAM,SAAS,cAAqB;AAEpC,KAAK,MAAM,CAAC,cAAc,YAAY,OAAO,QAAQ,MAAM,CAAC,UAAU,GAAG,MACxE,EAAE,GAAG,cAAc,EAAE,GAAG,CACxB,EAAE;CACF,MAAM,MAAM,KAAK,QAAQ,aAAa;CAEtC,IAAI,QAAQ,KAAK,SAAS,cAAc,aAAa;CAErD,IAAI,IAAI,QACP,QAAQ,MAAM,MAAM,GAAG,CAAC,IAAI,OAAO;CAGpC,QACC,MACE,QAAQ,gBAAgB,GAAG,CAC3B,QAAQ,wBAAwB,GAAG,CACnC,QAAQ,aAAa,KAAK,CAC1B,QAAQ,sBAAsB,GAAG,MAAc,QAAQ,EAAE,QAAQ,WAAW,IAAI,CAAC,CACjF,QAAQ,kBAAkB,GAAG,MAAc,MAAM,EAAE,QAAQ,WAAW,IAAI,CAAC,CAC3E,QAAQ,gBAAgB,GAAG,IAAI;CAElC,QAAQ,iBAAiB,qBAAqB,MAAM,CAAC;CAErD,SAAS,QAAQ,OAAO,OAAO;EAC9B;EACA,cAAcA,OAAa;EAC3B,CAAC;;AAUH,MAAa,qBAAqB,YAAoD;CACrF,OAAO,cAAc,OAAM,UAAS;EACnC,MAAM,QAAQ,UAAU,QAAQ,OAAO,MAAM,IAAI,SAAS;EAE1D,IAAI,CAAC,OACJ,MAAM,IAAI,UAAU,aAAa,EAAE,QAAQ,KAAK,CAAC;EAGlD,MAAM,EAAE,SAAS,iBAAiB,MAAM;EACxC,MAAM,QAAQ,SAAS,MAAM;EAE7B,MAAM,SAAS,eAAe,aAAa,MAAM,aAAa,GAAG;EAEjE,MAAM,gBAAgB,OAAO,EAC5B,MAAM,CACL,GAAG,OAAO,GAAG,KAAI,WAAU,IAAI,OAAO,KAAK,sBAAsB,EACjE,GAAG,OAAO,IAAI,KAAI,UAAS,IAAI,MAAM,KAAK,0BAA0B,CACpE,EACD,CAAC;EAEF,QAAQ,MAAM,SAAS,EAAE,OAAO;GAC/B;GACA,MAAM,OAAO,SAAS,SAAS,aAAa,QAAQ,KAAK,MAAM,GAAG,SAAS;GAC3E,QAAQ,SAAS;GACjB,CAAC;GACD"}
1
+ {"version":3,"file":"entry.mjs","names":["pagesServerAssets"],"sources":["../../src/server/entry.tsx"],"sourcesContent":["import path from \"node:path\";\nimport type { EventHandlerRequest, EventHandlerWithFetch, H3Event } from \"nitro/h3\";\nimport { defineHandler, HTTPError, writeEarlyHints } from \"nitro/h3\";\nimport { addRoute, createRouter, findRoute } from \"rou3\";\nimport { withLeadingSlash, withoutTrailingSlash } from \"ufo\";\nimport { clientAssets } from \"virtual:yamf:assets\";\nimport { pages, assets as pagesServerAssets } from \"virtual:yamf:pages\";\nimport { rootAssets } from \"virtual:yamf:root\";\nimport type { PageHandler } from \"#/page\";\nimport { YamfHead } from \"#/shared/head\";\n\ninterface Route {\n\thandler: () => Promise<PageHandler>;\n\tserverAssets?: ImportAssetsResult;\n}\n\nconst router = createRouter<Route>();\n\nfor (const [relativePath, handler] of Object.entries(pages).toSorted((a, b) =>\n\ta[0].localeCompare(b[0]),\n)) {\n\tconst ext = path.extname(relativePath);\n\n\tlet route = path.relative(\"/src/pages\", relativePath);\n\n\tif (ext.length) {\n\t\troute = route.slice(0, -ext.length);\n\t}\n\n\troute =\n\t\troute\n\t\t\t.replace(/\\.[A-Za-z]+$/, \"\")\n\t\t\t.replace(/\\(([^(/\\\\]+)\\)[/\\\\]/g, \"\")\n\t\t\t.replace(/\\[\\.{3}]/g, \"**\")\n\t\t\t.replace(/\\[\\.{3}([^\\]]+)]/g, (_, p: string) => \"**:\" + p.replace(/[^\\w-]/g, \"_\"))\n\t\t\t.replace(/\\[([^/\\]]+)]/g, (_, p: string) => \":\" + p.replace(/[^\\w-]/g, \"_\"))\n\t\t\t.replace(/(\\/|^)index$/, \"\") || \"/\";\n\n\troute = withLeadingSlash(withoutTrailingSlash(route));\n\n\taddRoute(router, \"GET\", route, {\n\t\thandler,\n\t\tserverAssets: pagesServerAssets[relativePath],\n\t});\n}\n\nexport type ServerEntry = EventHandlerWithFetch<EventHandlerRequest, Promise<unknown>>;\n\nexport interface DefineServerEntryOptions {\n\thead?: YamfHead | ((event: H3Event) => YamfHead);\n\tdisableEarlyHints?: boolean;\n}\n\nexport const defineServerEntry = (options?: DefineServerEntryOptions): ServerEntry => {\n\treturn defineHandler(async event => {\n\t\tconst route = findRoute(router, \"GET\", event.url.pathname);\n\n\t\tif (!route) {\n\t\t\tthrow new HTTPError(\"Not found\", { status: 404 });\n\t\t}\n\n\t\tconst { handler, serverAssets } = route.data;\n\t\tevent.context.params = route.params;\n\n\t\tconst assets = clientAssets.merge(...[rootAssets, serverAssets].filter(x => !!x));\n\n\t\tif (!options?.disableEarlyHints) {\n\t\t\tconst link = [\n\t\t\t\t...assets.js.map(script => `<${script.href}>; rel=modulepreload`),\n\t\t\t\t...assets.css.map(style => `<${style.href}>; rel=preload; as=style`),\n\t\t\t];\n\n\t\t\tif (link.length) {\n\t\t\t\tawait writeEarlyHints(event, { link });\n\t\t\t}\n\t\t}\n\n\t\treturn (await handler())(event, {\n\t\t\tassets,\n\t\t\thead: typeof options?.head === \"function\" ? options.head(event) : options?.head,\n\t\t});\n\t});\n};\n"],"mappings":";;;;;;;;AAgBA,MAAM,SAAS,aAAoB;AAEnC,KAAK,MAAM,CAAC,cAAc,YAAY,OAAO,QAAQ,KAAK,CAAC,CAAC,UAAU,GAAG,MACxE,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CACxB,GAAG;CACF,MAAM,MAAM,KAAK,QAAQ,YAAY;CAErC,IAAI,QAAQ,KAAK,SAAS,cAAc,YAAY;CAEpD,IAAI,IAAI,QACP,QAAQ,MAAM,MAAM,GAAG,CAAC,IAAI,MAAM;CAGnC,QACC,MACE,QAAQ,gBAAgB,EAAE,CAAC,CAC3B,QAAQ,wBAAwB,EAAE,CAAC,CACnC,QAAQ,aAAa,IAAI,CAAC,CAC1B,QAAQ,sBAAsB,GAAG,MAAc,QAAQ,EAAE,QAAQ,WAAW,GAAG,CAAC,CAAC,CACjF,QAAQ,kBAAkB,GAAG,MAAc,MAAM,EAAE,QAAQ,WAAW,GAAG,CAAC,CAAC,CAC3E,QAAQ,gBAAgB,EAAE,KAAK;CAElC,QAAQ,iBAAiB,qBAAqB,KAAK,CAAC;CAEpD,SAAS,QAAQ,OAAO,OAAO;EAC9B;EACA,cAAcA,OAAkB;CACjC,CAAC;AACF;AASA,MAAa,qBAAqB,YAAoD;CACrF,OAAO,cAAc,OAAM,UAAS;EACnC,MAAM,QAAQ,UAAU,QAAQ,OAAO,MAAM,IAAI,QAAQ;EAEzD,IAAI,CAAC,OACJ,MAAM,IAAI,UAAU,aAAa,EAAE,QAAQ,IAAI,CAAC;EAGjD,MAAM,EAAE,SAAS,iBAAiB,MAAM;EACxC,MAAM,QAAQ,SAAS,MAAM;EAE7B,MAAM,SAAS,aAAa,MAAM,GAAG,CAAC,YAAY,YAAY,CAAC,CAAC,QAAO,MAAK,CAAC,CAAC,CAAC,CAAC;EAEhF,IAAI,CAAC,SAAS,mBAAmB;GAChC,MAAM,OAAO,CACZ,GAAG,OAAO,GAAG,KAAI,WAAU,IAAI,OAAO,KAAK,qBAAqB,GAChE,GAAG,OAAO,IAAI,KAAI,UAAS,IAAI,MAAM,KAAK,yBAAyB,CACpE;GAEA,IAAI,KAAK,QACR,MAAM,gBAAgB,OAAO,EAAE,KAAK,CAAC;EAEvC;EAEA,QAAQ,MAAM,QAAQ,EAAA,CAAG,OAAO;GAC/B;GACA,MAAM,OAAO,SAAS,SAAS,aAAa,QAAQ,KAAK,KAAK,IAAI,SAAS;EAC5E,CAAC;CACF,CAAC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../../../src/island/server.tsx"],"mappings":";;;;;;YAOW,GAAA;IAAA,UACC,iBAAA;MACT,aAAA;QACC,cAAA;QACA,YAAA;QACA,cAAA;QACA,eAAA,EAAiB,qBAAA;QACjB,QAAA,EAAU,KAAA;QACV,KAAA,GAAQ,GAAA,CAAI,aAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAMH,YAAA,GACZ,SAAA,EAAW,EAAA,EACX,UAAA,UACA,MAAA,EAAQ,qBAAA,KACN,EAAA"}
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../../src/island/server.tsx"],"mappings":";;;;;;YAMW,GAAA;IAAA,UACC,iBAAA;MACT,aAAA;QACC,cAAA;QACA,YAAA;QACA,cAAA;QACA,eAAA,EAAiB,qBAAA;QACjB,QAAA,EAAU,KAAA;QACV,KAAA,GAAQ,GAAA,CAAI,aAAA;MAAA;IAAA;EAAA;AAAA;AAAA,cAMH,YAAA,GACZ,SAAA,EAAW,EAAA,EACX,UAAA,UACA,MAAA,EAAQ,qBAAA,KACN,EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":[],"sources":["../../../src/island/server.tsx"],"sourcesContent":["import { stringify } from \"devalue\";\nimport type { Child, FC } from \"hono/jsx\";\nimport type { ImportAssetsResultRaw } from \"#/shared/assets\";\nimport type { IslandClientDirective } from \"./types\";\n\ndeclare module \"hono/jsx\" {\n\t// eslint-disable-next-line @typescript-eslint/no-namespace\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t\"yamf-island\": {\n\t\t\t\t\"island-props\"?: string;\n\t\t\t\t\"island-src\": string;\n\t\t\t\t\"island-entry\": string;\n\t\t\t\t\"island-client\": IslandClientDirective;\n\t\t\t\tchildren: Child;\n\t\t\t\tstyle?: JSX.CSSProperties;\n\t\t\t};\n\t\t}\n\t}\n}\n\nexport const createIsland = (\n\tComponent: FC,\n\texportName: string,\n\tassets: ImportAssetsResultRaw,\n): FC => {\n\tconst ComponentWrapper: FC & { name: string } = props => {\n\t\tif (!assets.entry) {\n\t\t\tthrow new Error(`Missing island entry for island ${Component.name}`);\n\t\t}\n\n\t\treturn (\n\t\t\t<yamf-island\n\t\t\t\tisland-props={stringify(props)}\n\t\t\t\tisland-src={assets.entry}\n\t\t\t\tisland-entry={exportName}\n\t\t\t\tisland-client={props[\"yamf-client\"] as IslandClientDirective}\n\t\t\t\t// TODO: export CSS?\n\t\t\t\tstyle={{ display: \"contents\" }}\n\t\t\t>\n\t\t\t\t<Component {...props} />\n\t\t\t</yamf-island>\n\t\t);\n\t};\n\n\tObject.defineProperty(ComponentWrapper, \"name\", {\n\t\tvalue: Component.name,\n\t});\n\n\treturn ComponentWrapper;\n};\n"],"mappings":";;;AAqBA,MAAa,gBACZ,WACA,YACA,WACQ;CACR,MAAM,oBAA0C,UAAS;EACxD,IAAI,CAAC,OAAO,OACX,MAAM,IAAI,MAAM,mCAAmC,UAAU,OAAO;EAGrE,OACC,oBAAC,eAAD;GACC,gBAAc,UAAU,MAAM;GAC9B,cAAY,OAAO;GACnB,gBAAc;GACd,iBAAe,MAAM;GAErB,OAAO,EAAE,SAAS,YAAY;aAE9B,oBAAC,WAAD,EAAW,GAAI,OAAS,CAAA;GACX,CAAA;;CAIhB,OAAO,eAAe,kBAAkB,QAAQ,EAC/C,OAAO,UAAU,MACjB,CAAC;CAEF,OAAO"}
1
+ {"version":3,"file":"server.mjs","names":[],"sources":["../../../src/island/server.tsx"],"sourcesContent":["import { stringify } from \"devalue\";\nimport type { Child, FC } from \"hono/jsx\";\nimport type { ImportAssetsResultRaw } from \"#/shared/assets\";\nimport type { IslandClientDirective } from \"./types\";\n\ndeclare module \"hono/jsx\" {\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t\"yamf-island\": {\n\t\t\t\t\"island-props\"?: string;\n\t\t\t\t\"island-src\": string;\n\t\t\t\t\"island-entry\": string;\n\t\t\t\t\"island-client\": IslandClientDirective;\n\t\t\t\tchildren: Child;\n\t\t\t\tstyle?: JSX.CSSProperties;\n\t\t\t};\n\t\t}\n\t}\n}\n\nexport const createIsland = (\n\tComponent: FC,\n\texportName: string,\n\tassets: ImportAssetsResultRaw,\n): FC => {\n\tconst ComponentWrapper: FC & { name: string } = props => {\n\t\tif (!assets.entry) {\n\t\t\tthrow new Error(`Missing island entry for island ${Component.name}`);\n\t\t}\n\n\t\treturn (\n\t\t\t<yamf-island\n\t\t\t\tisland-props={stringify(props)}\n\t\t\t\tisland-src={assets.entry}\n\t\t\t\tisland-entry={exportName}\n\t\t\t\t// oxlint-disable-next-line typescript/no-unsafe-type-assertion\n\t\t\t\tisland-client={props[\"yamf-client\"] as IslandClientDirective}\n\t\t\t\t// TODO: export CSS?\n\t\t\t\tstyle={{ display: \"contents\" }}\n\t\t\t>\n\t\t\t\t<Component {...props} />\n\t\t\t</yamf-island>\n\t\t);\n\t};\n\n\tObject.defineProperty(ComponentWrapper, \"name\", {\n\t\tvalue: Component.name,\n\t});\n\n\treturn ComponentWrapper;\n};\n"],"mappings":";;;AAoBA,MAAa,gBACZ,WACA,YACA,WACQ;CACR,MAAM,oBAA0C,UAAS;EACxD,IAAI,CAAC,OAAO,OACX,MAAM,IAAI,MAAM,mCAAmC,UAAU,MAAM;EAGpE,OACC,oBAAC,eAAD;GACC,gBAAc,UAAU,KAAK;GAC7B,cAAY,OAAO;GACnB,gBAAc;GAEd,iBAAe,MAAM;GAErB,OAAO,EAAE,SAAS,WAAW;aAE7B,oBAAC,WAAD,EAAW,GAAI,MAAQ,CAAA;EACX,CAAA;CAEf;CAEA,OAAO,eAAe,kBAAkB,QAAQ,EAC/C,OAAO,UAAU,KAClB,CAAC;CAED,OAAO;AACR"}
@@ -0,0 +1,9 @@
1
+ import { ResolvableHead, UseSeoMetaInput } from "unhead/types";
2
+
3
+ //#region src/shared/head.d.ts
4
+ type YamfHead = ResolvableHead & {
5
+ seo?: UseSeoMetaInput;
6
+ };
7
+ //#endregion
8
+ export { YamfHead };
9
+ //# sourceMappingURL=head.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.mts","names":[],"sources":["../../../src/shared/head.ts"],"mappings":";;;KAEY,QAAA,GAAW,cAAA;EAAmB,GAAA,GAAM,eAAA;AAAA"}
@@ -0,0 +1,9 @@
1
+ import { ResolvableHead, UseSeoMetaInput } from "unhead/types";
2
+
3
+ //#region src/shared/head.d.ts
4
+ type YamfHead = ResolvableHead & {
5
+ seo?: UseSeoMetaInput;
6
+ };
7
+ //#endregion
8
+ export { YamfHead };
9
+ //# sourceMappingURL=head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head.d.ts","names":[],"sources":["../../src/shared/head.ts"],"mappings":";;;KAEY,QAAA,GAAW,cAAA;EAAmB,GAAA,GAAM,eAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/vite/index.ts"],"mappings":";;;;UASiB,WAAA;EAChB,KAAA,GAAQ,iBAAA;AAAA;AAAA,cAGH,IAAA,GAAQ,OAAA,GAAU,WAAA,KAAc,YAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/vite/index.ts"],"mappings":";;;;UAUiB,WAAA;EAChB,KAAA,GAAQ,iBAAA;AAAA;AAAA,cAGH,IAAA,GAAQ,OAAA,GAAU,WAAA,KAAc,YAAA"}
@@ -1,6 +1,7 @@
1
1
  import { islands } from "./islands.mjs";
2
2
  import { virtualAssets } from "./virtual-assets.mjs";
3
3
  import { virtualPages } from "./virtual-pages.mjs";
4
+ import { virtualRoot } from "./virtual-root.mjs";
4
5
  import { virtualTemplate } from "./virtual-template.mjs";
5
6
  import { existsSync } from "node:fs";
6
7
  import { nitro } from "nitro/vite";
@@ -33,6 +34,7 @@ const yamf = (options) => {
33
34
  plugins.push(virtualAssets());
34
35
  plugins.push(virtualPages());
35
36
  plugins.push(virtualTemplate());
37
+ plugins.push(virtualRoot());
36
38
  plugins.push(nitro({
37
39
  serverDir: "./src",
38
40
  renderer: false,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/vite/index.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport type { NitroPluginConfig } from \"nitro/vite\";\nimport { nitro } from \"nitro/vite\";\nimport type { EnvironmentOptions, PluginOption } from \"vite\";\nimport { islands } from \"./islands\";\nimport { virtualAssets } from \"./virtual-assets\";\nimport { virtualPages } from \"./virtual-pages\";\nimport { virtualTemplate } from \"./virtual-template\";\n\nexport interface YamfOptions {\n\tnitro?: NitroPluginConfig;\n}\n\nconst yamf = (options?: YamfOptions): PluginOption[] => {\n\tconst plugins: PluginOption[] = [];\n\n\t// TODO: extendable config\n\tplugins.push({\n\t\tname: \"yamf:config\",\n\t\tconfig() {\n\t\t\tconst ssrEnv: EnvironmentOptions = {\n\t\t\t\tbuild: {\n\t\t\t\t\t// TODO: figure out if this should be true\n\t\t\t\t\tcssCodeSplit: false,\n\t\t\t\t\trolldownOptions: {\n\t\t\t\t\t\tinput: \"./src/server.tsx\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tssr: {\n\t\t\t\t\t// we need to inline because otherwise fullstack plugin fails to build manifest for assets imports\n\t\t\t\t\tnoExternal: [\"@pajecawav/yamf\"],\n\t\t\t\t},\n\t\t\t\toptimizeDeps: {\n\t\t\t\t\tinclude: [\n\t\t\t\t\t\t\"hono\",\n\t\t\t\t\t\t\"hono/jsx/dom/client\",\n\t\t\t\t\t\t\"hono/jsx/jsx-runtime\",\n\t\t\t\t\t\t\"devalue\",\n\t\t\t\t\t\t\"ufo\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tenvironments: {\n\t\t\t\t\t...(existsSync(\"./src/server.tsx\") ? { ssr: ssrEnv } : {}),\n\t\t\t\t\tclient: {\n\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\trolldownOptions: {\n\t\t\t\t\t\t\t\tinput: \"./src/client/index.ts\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n\n\tplugins.push(islands());\n\n\tplugins.push(virtualAssets());\n\tplugins.push(virtualPages());\n\tplugins.push(virtualTemplate());\n\n\tplugins.push(\n\t\tnitro({\n\t\t\tserverDir: \"./src\",\n\t\t\trenderer: false,\n\t\t\t...options?.nitro,\n\t\t\tcompressPublicAssets: {\n\t\t\t\tgzip: true,\n\t\t\t\tbrotli: true,\n\t\t\t},\n\t\t\tpublicAssets: [\n\t\t\t\t{\n\t\t\t\t\tbaseURL: \"assets\",\n\t\t\t\t\tdir: \"./public/assets\",\n\t\t\t\t\tmaxAge: 365 * 24 * 60 * 60,\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t);\n\n\treturn plugins;\n};\n\nexport default yamf;\n"],"mappings":";;;;;;;AAaA,MAAM,QAAQ,YAA0C;CACvD,MAAM,UAA0B,EAAE;CAGlC,QAAQ,KAAK;EACZ,MAAM;EACN,SAAS;GAWR,OAAO;IACN,KAAK,EAEJ,YAAY,CAAC,kBAAkB,EAC/B;IACD,cAAc,EACb,SAAS;KACR;KACA;KACA;KACA;KACA;KACA,EACD;IACD,cAAc;KACb,GAAI,WAAW,mBAAmB,GAAG,EAAE,KAAK,EAxB7C,OAAO;MAEN,cAAc;MACd,iBAAiB,EAChB,OAAO,oBACP;MACD,EAkBkD,EAAE,GAAG,EAAE;KACzD,QAAQ,EACP,OAAO,EACN,iBAAiB,EAChB,OAAO,yBACP,EACD,EACD;KACD;IACD;;EAEF,CAAC;CAEF,QAAQ,KAAK,SAAS,CAAC;CAEvB,QAAQ,KAAK,eAAe,CAAC;CAC7B,QAAQ,KAAK,cAAc,CAAC;CAC5B,QAAQ,KAAK,iBAAiB,CAAC;CAE/B,QAAQ,KACP,MAAM;EACL,WAAW;EACX,UAAU;EACV,GAAG,SAAS;EACZ,sBAAsB;GACrB,MAAM;GACN,QAAQ;GACR;EACD,cAAc,CACb;GACC,SAAS;GACT,KAAK;GACL,QAAQ,MAAM,KAAK,KAAK;GACxB,CACD;EACD,CAAC,CACF;CAED,OAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/vite/index.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport type { NitroPluginConfig } from \"nitro/vite\";\nimport { nitro } from \"nitro/vite\";\nimport type { EnvironmentOptions, PluginOption } from \"vite\";\nimport { islands } from \"./islands\";\nimport { virtualAssets } from \"./virtual-assets\";\nimport { virtualPages } from \"./virtual-pages\";\nimport { virtualRoot } from \"./virtual-root\";\nimport { virtualTemplate } from \"./virtual-template\";\n\nexport interface YamfOptions {\n\tnitro?: NitroPluginConfig;\n}\n\nconst yamf = (options?: YamfOptions): PluginOption[] => {\n\tconst plugins: PluginOption[] = [];\n\n\t// TODO: extendable config\n\tplugins.push({\n\t\tname: \"yamf:config\",\n\t\tconfig() {\n\t\t\tconst ssrEnv: EnvironmentOptions = {\n\t\t\t\tbuild: {\n\t\t\t\t\t// TODO: figure out if this should be true\n\t\t\t\t\tcssCodeSplit: false,\n\t\t\t\t\trolldownOptions: {\n\t\t\t\t\t\tinput: \"./src/server.tsx\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\tssr: {\n\t\t\t\t\t// we need to inline because otherwise fullstack plugin fails to build manifest for assets imports\n\t\t\t\t\tnoExternal: [\"@pajecawav/yamf\"],\n\t\t\t\t},\n\t\t\t\toptimizeDeps: {\n\t\t\t\t\tinclude: [\n\t\t\t\t\t\t\"hono\",\n\t\t\t\t\t\t\"hono/jsx/dom/client\",\n\t\t\t\t\t\t\"hono/jsx/jsx-runtime\",\n\t\t\t\t\t\t\"devalue\",\n\t\t\t\t\t\t\"ufo\",\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\tenvironments: {\n\t\t\t\t\t...(existsSync(\"./src/server.tsx\") ? { ssr: ssrEnv } : {}),\n\t\t\t\t\tclient: {\n\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\trolldownOptions: {\n\t\t\t\t\t\t\t\tinput: \"./src/client/index.ts\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n\n\tplugins.push(islands());\n\n\tplugins.push(virtualAssets());\n\tplugins.push(virtualPages());\n\tplugins.push(virtualTemplate());\n\tplugins.push(virtualRoot());\n\n\tplugins.push(\n\t\tnitro({\n\t\t\tserverDir: \"./src\",\n\t\t\trenderer: false,\n\t\t\t...options?.nitro,\n\t\t\tcompressPublicAssets: {\n\t\t\t\tgzip: true,\n\t\t\t\tbrotli: true,\n\t\t\t},\n\t\t\tpublicAssets: [\n\t\t\t\t{\n\t\t\t\t\tbaseURL: \"assets\",\n\t\t\t\t\tdir: \"./public/assets\",\n\t\t\t\t\tmaxAge: 365 * 24 * 60 * 60,\n\t\t\t\t},\n\t\t\t],\n\t\t}),\n\t);\n\n\treturn plugins;\n};\n\nexport default yamf;\n"],"mappings":";;;;;;;;AAcA,MAAM,QAAQ,YAA0C;CACvD,MAAM,UAA0B,CAAC;CAGjC,QAAQ,KAAK;EACZ,MAAM;EACN,SAAS;GAWR,OAAO;IACN,KAAK,EAEJ,YAAY,CAAC,iBAAiB,EAC/B;IACA,cAAc,EACb,SAAS;KACR;KACA;KACA;KACA;KACA;IACD,EACD;IACA,cAAc;KACb,GAAI,WAAW,kBAAkB,IAAI,EAAE,KAAK,EAxB7C,OAAO;MAEN,cAAc;MACd,iBAAiB,EAChB,OAAO,mBACR;KACD,EAkBkD,EAAE,IAAI,CAAC;KACxD,QAAQ,EACP,OAAO,EACN,iBAAiB,EAChB,OAAO,wBACR,EACD,EACD;IACD;GACD;EACD;CACD,CAAC;CAED,QAAQ,KAAK,QAAQ,CAAC;CAEtB,QAAQ,KAAK,cAAc,CAAC;CAC5B,QAAQ,KAAK,aAAa,CAAC;CAC3B,QAAQ,KAAK,gBAAgB,CAAC;CAC9B,QAAQ,KAAK,YAAY,CAAC;CAE1B,QAAQ,KACP,MAAM;EACL,WAAW;EACX,UAAU;EACV,GAAG,SAAS;EACZ,sBAAsB;GACrB,MAAM;GACN,QAAQ;EACT;EACA,cAAc,CACb;GACC,SAAS;GACT,KAAK;GACL,QAAQ,MAAM,KAAK,KAAK;EACzB,CACD;CACD,CAAC,CACF;CAEA,OAAO;AACR"}
@@ -1 +1 @@
1
- {"version":3,"file":"islands.mjs","names":[],"sources":["../../src/vite/islands.ts"],"sourcesContent":["// reference https://github.com/hi-ogawa/vite-plugin-fullstack/blob/28e9540a68529c58842e9a3bf17d2193a065d524/examples/island/src/framework/island/plugin.ts\nimport { generate } from \"@babel/generator\";\nimport { parse } from \"@babel/parser\";\nimport _traverse from \"@babel/traverse\";\nimport {\n\tcallExpression,\n\texportDefaultDeclaration,\n\texportNamedDeclaration,\n\tfunctionDeclaration,\n\tfunctionExpression,\n\tidentifier,\n\timportDeclaration,\n\timportDefaultSpecifier,\n\timportNamespaceSpecifier,\n\tmemberExpression,\n\tstringLiteral,\n\tvariableDeclaration,\n\tvariableDeclarator,\n} from \"@babel/types\";\nimport type { Plugin } from \"vite\";\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nconst traverse = (_traverse.default as typeof _traverse) ?? _traverse;\n\nconst ISLAND_REGEX = /\\.island\\.(j|t)sx?$/;\n\nexport const islands = (): Plugin[] => {\n\treturn [\n\t\t{\n\t\t\tname: \"yamf:islands\",\n\t\t\ttransform: {\n\t\t\t\tfilter: { id: ISLAND_REGEX },\n\t\t\t\thandler(code, id) {\n\t\t\t\t\tif (this.environment.name !== \"ssr\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst seenExports = new Set<string>();\n\n\t\t\t\t\tconst ast = parse(code, {\n\t\t\t\t\t\tsourceType: \"module\",\n\t\t\t\t\t\tplugins: [\"typescript\", \"jsx\"],\n\t\t\t\t\t});\n\n\t\t\t\t\ttraverse(ast, {\n\t\t\t\t\t\tProgram(path) {\n\t\t\t\t\t\t\t// prepends server island runtime\n\t\t\t\t\t\t\t// import * as __runtime from \"yamf/server\";\n\t\t\t\t\t\t\tpath.unshiftContainer(\n\t\t\t\t\t\t\t\t\"body\",\n\t\t\t\t\t\t\t\timportDeclaration(\n\t\t\t\t\t\t\t\t\t[importNamespaceSpecifier(identifier(\"__runtime\"))],\n\t\t\t\t\t\t\t\t\tstringLiteral(\"@pajecawav/yamf/server\"),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// prepends asset imports for the island:\n\t\t\t\t\t\t\t// import __assets from \"MODULE_ID?assets=client\";\n\t\t\t\t\t\t\tpath.unshiftContainer(\n\t\t\t\t\t\t\t\t\"body\",\n\t\t\t\t\t\t\t\timportDeclaration(\n\t\t\t\t\t\t\t\t\t[importDefaultSpecifier(identifier(\"__assets\"))],\n\t\t\t\t\t\t\t\t\tstringLiteral(`${id}?assets=client`),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExportDefaultDeclaration(path) {\n\t\t\t\t\t\t\tconst declarationType = path.node.declaration.type;\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\tdeclarationType === \"FunctionDeclaration\" ||\n\t\t\t\t\t\t\t\t\tdeclarationType === \"FunctionExpression\" ||\n\t\t\t\t\t\t\t\t\tdeclarationType === \"ArrowFunctionExpression\"\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst originalFunction =\n\t\t\t\t\t\t\t\tpath.node.declaration.type === \"FunctionExpression\" ||\n\t\t\t\t\t\t\t\tpath.node.declaration.type === \"ArrowFunctionExpression\"\n\t\t\t\t\t\t\t\t\t? path.node.declaration\n\t\t\t\t\t\t\t\t\t: functionExpression(\n\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.params,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.body,\n\t\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.async,\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tconst islandIdentifier = identifier(\"__ISLAND__\");\n\n\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\tvariableDeclarator(islandIdentifier, originalFunction),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\texportDefaultDeclaration(\n\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\tstringLiteral(\"default\"),\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExportNamedDeclaration(path) {\n\t\t\t\t\t\t\tif (path.node.declaration?.type === \"VariableDeclaration\") {\n\t\t\t\t\t\t\t\tconst declaration = path.node.declaration.declarations.at(0);\n\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!declaration ||\n\t\t\t\t\t\t\t\t\tdeclaration.id.type !== \"Identifier\" ||\n\t\t\t\t\t\t\t\t\tseenExports.has(declaration.id.name)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst exportName = declaration.id.name;\n\t\t\t\t\t\t\t\tseenExports.add(exportName);\n\n\t\t\t\t\t\t\t\tconst islandIdentifier = identifier(`__wrap_${exportName}`);\n\n\t\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\tvariableDeclarator(islandIdentifier, declaration.init),\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\t\texportNamedDeclaration(\n\t\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\t\tvariableDeclarator(\n\t\t\t\t\t\t\t\t\t\t\t\tidentifier(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstringLiteral(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (path.node.declaration?.type === \"FunctionDeclaration\") {\n\t\t\t\t\t\t\t\tconst declaration = path.node.declaration;\n\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!declaration ||\n\t\t\t\t\t\t\t\t\tdeclaration.id?.type !== \"Identifier\" ||\n\t\t\t\t\t\t\t\t\tseenExports.has(declaration.id.name)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst exportName = declaration.id.name;\n\t\t\t\t\t\t\t\tseenExports.add(exportName);\n\n\t\t\t\t\t\t\t\tconst islandIdentifier = identifier(`__wrap_${exportName}`);\n\n\t\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\t\tfunctionDeclaration(\n\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\tdeclaration.params,\n\t\t\t\t\t\t\t\t\t\tdeclaration.body,\n\t\t\t\t\t\t\t\t\t\tdeclaration.generator,\n\t\t\t\t\t\t\t\t\t\tdeclaration.async,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\t\texportNamedDeclaration(\n\t\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\t\tvariableDeclarator(\n\t\t\t\t\t\t\t\t\t\t\t\tidentifier(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstringLiteral(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\tconst result = generate(ast);\n\n\t\t\t\t\treturn { code: result.code, map: result.map };\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"yamf:islands:raw-import\",\n\t\t\ttransform: {\n\t\t\t\torder: \"post\",\n\t\t\t\thandler(code) {\n\t\t\t\t\tif (code.includes(\"__island_raw_import__\")) {\n\t\t\t\t\t\treturn code.replaceAll(\"__island_raw_import__\", \"import\");\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t];\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"islands.mjs","names":[],"sources":["../../src/vite/islands.ts"],"sourcesContent":["// reference https://github.com/hi-ogawa/vite-plugin-fullstack/blob/28e9540a68529c58842e9a3bf17d2193a065d524/examples/island/src/framework/island/plugin.ts\nimport { generate } from \"@babel/generator\";\nimport { parse } from \"@babel/parser\";\nimport _traverse from \"@babel/traverse\";\nimport {\n\tcallExpression,\n\texportDefaultDeclaration,\n\texportNamedDeclaration,\n\tfunctionDeclaration,\n\tfunctionExpression,\n\tidentifier,\n\timportDeclaration,\n\timportDefaultSpecifier,\n\timportNamespaceSpecifier,\n\tmemberExpression,\n\tstringLiteral,\n\tvariableDeclaration,\n\tvariableDeclarator,\n} from \"@babel/types\";\nimport type { Plugin } from \"vite\";\n\n// @ts-ignore\n// oxlint-disable-next-line typescript/no-unsafe-type-assertion\nconst traverse = (_traverse.default as typeof _traverse) ?? _traverse;\n\nconst ISLAND_REGEX = /\\.island\\.(j|t)sx?$/;\n\nexport const islands = (): Plugin[] => {\n\treturn [\n\t\t{\n\t\t\tname: \"yamf:islands\",\n\t\t\ttransform: {\n\t\t\t\tfilter: { id: ISLAND_REGEX },\n\t\t\t\thandler(code, id) {\n\t\t\t\t\tif (this.environment.name !== \"ssr\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst seenExports = new Set<string>();\n\n\t\t\t\t\tconst ast = parse(code, {\n\t\t\t\t\t\tsourceType: \"module\",\n\t\t\t\t\t\tplugins: [\"typescript\", \"jsx\"],\n\t\t\t\t\t});\n\n\t\t\t\t\ttraverse(ast, {\n\t\t\t\t\t\tProgram(path) {\n\t\t\t\t\t\t\t// prepends server island runtime\n\t\t\t\t\t\t\t// import * as __runtime from \"yamf/server\";\n\t\t\t\t\t\t\tpath.unshiftContainer(\n\t\t\t\t\t\t\t\t\"body\",\n\t\t\t\t\t\t\t\timportDeclaration(\n\t\t\t\t\t\t\t\t\t[importNamespaceSpecifier(identifier(\"__runtime\"))],\n\t\t\t\t\t\t\t\t\tstringLiteral(\"@pajecawav/yamf/server\"),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// prepends asset imports for the island:\n\t\t\t\t\t\t\t// import __assets from \"MODULE_ID?assets=client\";\n\t\t\t\t\t\t\tpath.unshiftContainer(\n\t\t\t\t\t\t\t\t\"body\",\n\t\t\t\t\t\t\t\timportDeclaration(\n\t\t\t\t\t\t\t\t\t[importDefaultSpecifier(identifier(\"__assets\"))],\n\t\t\t\t\t\t\t\t\tstringLiteral(`${id}?assets=client`),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExportDefaultDeclaration(path) {\n\t\t\t\t\t\t\tconst declarationType = path.node.declaration.type;\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\tdeclarationType === \"FunctionDeclaration\" ||\n\t\t\t\t\t\t\t\t\tdeclarationType === \"FunctionExpression\" ||\n\t\t\t\t\t\t\t\t\tdeclarationType === \"ArrowFunctionExpression\"\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst originalFunction =\n\t\t\t\t\t\t\t\tpath.node.declaration.type === \"FunctionExpression\" ||\n\t\t\t\t\t\t\t\tpath.node.declaration.type === \"ArrowFunctionExpression\"\n\t\t\t\t\t\t\t\t\t? path.node.declaration\n\t\t\t\t\t\t\t\t\t: functionExpression(\n\t\t\t\t\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.params,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.body,\n\t\t\t\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t\t\t\tpath.node.declaration.async,\n\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tconst islandIdentifier = identifier(\"__ISLAND__\");\n\n\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\tvariableDeclarator(islandIdentifier, originalFunction),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\texportDefaultDeclaration(\n\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\tstringLiteral(\"default\"),\n\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExportNamedDeclaration(path) {\n\t\t\t\t\t\t\tif (path.node.declaration?.type === \"VariableDeclaration\") {\n\t\t\t\t\t\t\t\tconst declaration = path.node.declaration.declarations.at(0);\n\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!declaration ||\n\t\t\t\t\t\t\t\t\tdeclaration.id.type !== \"Identifier\" ||\n\t\t\t\t\t\t\t\t\tseenExports.has(declaration.id.name)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst exportName = declaration.id.name;\n\t\t\t\t\t\t\t\tseenExports.add(exportName);\n\n\t\t\t\t\t\t\t\tconst islandIdentifier = identifier(`__wrap_${exportName}`);\n\n\t\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\tvariableDeclarator(islandIdentifier, declaration.init),\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\t\texportNamedDeclaration(\n\t\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\t\tvariableDeclarator(\n\t\t\t\t\t\t\t\t\t\t\t\tidentifier(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstringLiteral(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (path.node.declaration?.type === \"FunctionDeclaration\") {\n\t\t\t\t\t\t\t\tconst declaration = path.node.declaration;\n\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t!declaration ||\n\t\t\t\t\t\t\t\t\tdeclaration.id?.type !== \"Identifier\" ||\n\t\t\t\t\t\t\t\t\tseenExports.has(declaration.id.name)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst exportName = declaration.id.name;\n\t\t\t\t\t\t\t\tseenExports.add(exportName);\n\n\t\t\t\t\t\t\t\tconst islandIdentifier = identifier(`__wrap_${exportName}`);\n\n\t\t\t\t\t\t\t\tpath.insertBefore(\n\t\t\t\t\t\t\t\t\tfunctionDeclaration(\n\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\tdeclaration.params,\n\t\t\t\t\t\t\t\t\t\tdeclaration.body,\n\t\t\t\t\t\t\t\t\t\tdeclaration.generator,\n\t\t\t\t\t\t\t\t\t\tdeclaration.async,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\tpath.replaceWith(\n\t\t\t\t\t\t\t\t\texportNamedDeclaration(\n\t\t\t\t\t\t\t\t\t\tvariableDeclaration(\"const\", [\n\t\t\t\t\t\t\t\t\t\t\tvariableDeclarator(\n\t\t\t\t\t\t\t\t\t\t\t\tidentifier(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\tcallExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\tmemberExpression(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__runtime\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"createIsland\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tislandIdentifier,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstringLiteral(exportName),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tidentifier(\"__assets\"),\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\tconst result = generate(ast);\n\n\t\t\t\t\treturn { code: result.code, map: result.map };\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"yamf:islands:raw-import\",\n\t\t\ttransform: {\n\t\t\t\torder: \"post\",\n\t\t\t\thandler(code) {\n\t\t\t\t\tif (code.includes(\"__island_raw_import__\")) {\n\t\t\t\t\t\treturn code.replaceAll(\"__island_raw_import__\", \"import\");\n\t\t\t\t\t}\n\n\t\t\t\t\treturn undefined;\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t];\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/shared/utils.ts"],"sourcesContent":["export const js = (str: TemplateStringsArray, ...args: unknown[]): string => {\n\treturn str.reduce((acc, cur, i) => {\n\t\treturn acc + cur + String(args[i]);\n\t}, \"\");\n};\n"],"mappings":";AAAA,MAAa,MAAM,KAA2B,GAAG,SAA4B;CAC5E,OAAO,IAAI,QAAQ,KAAK,KAAK,MAAM;EAClC,OAAO,MAAM,MAAM,OAAO,KAAK,GAAG;IAChC,GAAG"}
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/shared/utils.ts"],"sourcesContent":["export const js = (str: TemplateStringsArray, ...args: unknown[]): string => {\n\treturn str.reduce((acc, cur, i) => {\n\t\treturn acc + cur + String(args[i]);\n\t}, \"\");\n};\n"],"mappings":";AAAA,MAAa,MAAM,KAA2B,GAAG,SAA4B;CAC5E,OAAO,IAAI,QAAQ,KAAK,KAAK,MAAM;EAClC,OAAO,MAAM,MAAM,OAAO,KAAK,EAAE;CAClC,GAAG,EAAE;AACN"}
@@ -2,7 +2,7 @@ import { js } from "./shared/utils.mjs";
2
2
  //#region src/vite/virtual-assets.ts
3
3
  const virtualAssets = () => {
4
4
  const virtualModuleId = "virtual:yamf:assets";
5
- const resolvedVirtualModuleId = "\0" + virtualModuleId;
5
+ const resolvedVirtualModuleId = "\0virtual:yamf:assets";
6
6
  return {
7
7
  name: "yamf:virtual-assets",
8
8
  resolveId(id) {
@@ -11,7 +11,7 @@ const virtualAssets = () => {
11
11
  load(id) {
12
12
  if (id !== resolvedVirtualModuleId) return;
13
13
  return js`
14
- import clientAssets from "./src/client/index.ts?assets=client";
14
+ import clientAssets from "./src/client?assets=client";
15
15
 
16
16
  export { clientAssets };
17
17
  `.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-assets.mjs","names":[],"sources":["../../src/vite/virtual-assets.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nexport const virtualAssets = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:assets\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-assets\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn js`\nimport clientAssets from \"./src/client/index.ts?assets=client\";\n\nexport { clientAssets };\n`.trim();\n\t\t},\n\t};\n};\n"],"mappings":";;AAGA,MAAa,sBAA8B;CAC1C,MAAM,kBAAkB;CACxB,MAAM,0BAA0B,OAAO;CAEvC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;;EAKT,KAAK,IAAI;GACR,IAAI,OAAO,yBACV;GAGD,OAAO,EAAE;;;;EAIV,MAAM;;EAEN"}
1
+ {"version":3,"file":"virtual-assets.mjs","names":[],"sources":["../../src/vite/virtual-assets.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nexport const virtualAssets = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:assets\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-assets\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn js`\nimport clientAssets from \"./src/client?assets=client\";\n\nexport { clientAssets };\n`.trim();\n\t\t},\n\t};\n};\n"],"mappings":";;AAGA,MAAa,sBAA8B;CAC1C,MAAM,kBAAkB;CACxB,MAAM,0BAA0B;CAEhC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;EAIT;EACA,KAAK,IAAI;GACR,IAAI,OAAO,yBACV;GAGD,OAAO,EAAE;;;;EAIV,KAAK;EACL;CACD;AACD"}
@@ -2,7 +2,7 @@ import { js } from "./shared/utils.mjs";
2
2
  //#region src/vite/virtual-pages.ts
3
3
  const virtualPages = () => {
4
4
  const virtualModuleId = "virtual:yamf:pages";
5
- const resolvedVirtualModuleId = "\0" + virtualModuleId;
5
+ const resolvedVirtualModuleId = "\0virtual:yamf:pages";
6
6
  return {
7
7
  name: "yamf:virtual-pages",
8
8
  resolveId(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-pages.mjs","names":[],"sources":["../../src/vite/virtual-pages.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nexport const virtualPages = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:pages\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-pages\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn js`\nconst pages = import.meta.glob(\"/src/pages/**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}\", {\n\timport: \"default\",\n});\nconst assets = import.meta.glob(\n\t\"/src/pages/**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}\",\n\t{\n\t\timport: \"default\",\n\t\tquery: \"?assets=ssr\",\n\t\teager: true,\n\t},\n);\n\nexport { pages, assets };\n`.trim();\n\t\t},\n\t};\n};\n"],"mappings":";;AAGA,MAAa,qBAA6B;CACzC,MAAM,kBAAkB;CACxB,MAAM,0BAA0B,OAAO;CAEvC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;;EAKT,KAAK,IAAI;GACR,IAAI,OAAO,yBACV;GAGD,OAAO,EAAE;;;;;;;;;;;;;;EAcV,MAAM;;EAEN"}
1
+ {"version":3,"file":"virtual-pages.mjs","names":[],"sources":["../../src/vite/virtual-pages.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nexport const virtualPages = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:pages\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-pages\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn js`\nconst pages = import.meta.glob(\"/src/pages/**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}\", {\n\timport: \"default\",\n});\nconst assets = import.meta.glob(\n\t\"/src/pages/**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}\",\n\t{\n\t\timport: \"default\",\n\t\tquery: \"?assets=ssr\",\n\t\teager: true,\n\t},\n);\n\nexport { pages, assets };\n`.trim();\n\t\t},\n\t};\n};\n"],"mappings":";;AAGA,MAAa,qBAA6B;CACzC,MAAM,kBAAkB;CACxB,MAAM,0BAA0B;CAEhC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;EAIT;EACA,KAAK,IAAI;GACR,IAAI,OAAO,yBACV;GAGD,OAAO,EAAE;;;;;;;;;;;;;;EAcV,KAAK;EACL;CACD;AACD"}
@@ -0,0 +1,46 @@
1
+ import { js } from "./shared/utils.mjs";
2
+ import { resolveModulePath } from "exsolve";
3
+ //#region src/vite/virtual-root.ts
4
+ const ROOT_PATH = "./src/root";
5
+ const virtualRoot = () => {
6
+ const virtualModuleId = "virtual:yamf:root";
7
+ const resolvedVirtualModuleId = "\0virtual:yamf:root";
8
+ return {
9
+ name: "yamf:virtual-root",
10
+ resolveId(id) {
11
+ if (id === virtualModuleId) return resolvedVirtualModuleId;
12
+ },
13
+ load(id) {
14
+ if (id !== resolvedVirtualModuleId) return;
15
+ if (!resolveModulePath(ROOT_PATH, {
16
+ try: true,
17
+ suffixes: ["", "/index"],
18
+ extensions: [
19
+ ".tsx",
20
+ ".jsx",
21
+ ".ts",
22
+ ".js",
23
+ ".mjs",
24
+ ".cjs",
25
+ ".mts",
26
+ ".cts"
27
+ ]
28
+ })) return js`
29
+ const Root = null;
30
+ const rootAssets = null;
31
+
32
+ export { Root, rootAssets };
33
+ `;
34
+ return js`
35
+ import Root from "${ROOT_PATH}";
36
+ import rootAssets from "${ROOT_PATH}?assets=ssr";
37
+
38
+ export { Root, rootAssets };
39
+ `.trim();
40
+ }
41
+ };
42
+ };
43
+ //#endregion
44
+ export { virtualRoot };
45
+
46
+ //# sourceMappingURL=virtual-root.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-root.mjs","names":[],"sources":["../../src/vite/virtual-root.ts"],"sourcesContent":["import { resolveModulePath } from \"exsolve\";\nimport type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nconst ROOT_PATH = \"./src/root\";\n\nexport const virtualRoot = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:root\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-root\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst root = resolveModulePath(ROOT_PATH, {\n\t\t\t\ttry: true,\n\t\t\t\tsuffixes: [\"\", \"/index\"],\n\t\t\t\textensions: [\".tsx\", \".jsx\", \".ts\", \".js\", \".mjs\", \".cjs\", \".mts\", \".cts\"],\n\t\t\t});\n\n\t\t\tif (!root) {\n\t\t\t\treturn js`\nconst Root = null;\nconst rootAssets = null;\n\nexport { Root, rootAssets };\n `;\n\t\t\t}\n\n\t\t\treturn js`\nimport Root from \"${ROOT_PATH}\";\nimport rootAssets from \"${ROOT_PATH}?assets=ssr\";\n\nexport { Root, rootAssets };\n`.trim();\n\t\t},\n\t};\n};\n"],"mappings":";;;AAIA,MAAM,YAAY;AAElB,MAAa,oBAA4B;CACxC,MAAM,kBAAkB;CACxB,MAAM,0BAA0B;CAEhC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;EAIT;EACA,KAAK,IAAI;GACR,IAAI,OAAO,yBACV;GASD,IAAI,CANS,kBAAkB,WAAW;IACzC,KAAK;IACL,UAAU,CAAC,IAAI,QAAQ;IACvB,YAAY;KAAC;KAAQ;KAAQ;KAAO;KAAO;KAAQ;KAAQ;KAAQ;IAAM;GAC1E,CAEQ,GACP,OAAO,EAAE;;;;;;GAQV,OAAO,EAAE;oBACQ,UAAU;0BACJ,UAAU;;;EAGlC,KAAK;EACL;CACD;AACD"}
@@ -14,7 +14,7 @@ const DEFAULT_TEMPLATE = `
14
14
  `.trim();
15
15
  const virtualTemplate = () => {
16
16
  const virtualModuleId = "virtual:yamf:template";
17
- const resolvedVirtualModuleId = "\0" + virtualModuleId;
17
+ const resolvedVirtualModuleId = "\0virtual:yamf:template";
18
18
  return {
19
19
  name: "yamf:virtual-template",
20
20
  resolveId(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-template.mjs","names":[],"sources":["../../src/vite/virtual-template.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nconst TEMPLATE_PATH = \"./src/template.html\";\n\nconst DEFAULT_TEMPLATE = /* html */ `\n<!DOCTYPE html>\n<html>\n <head></head>\n <body>\n <!--ssr-outlet-->\n </body>\n</html>\n`.trim();\n\nexport const virtualTemplate = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:template\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-template\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tasync load(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst template = await readFile(TEMPLATE_PATH, \"utf8\");\n\n\t\t\t\treturn js`export const template = ${JSON.stringify(template)};`;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n\t\t\t\t\treturn js`export const template = ${JSON.stringify(DEFAULT_TEMPLATE)};`;\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\thandleHotUpdate({ file, server }) {\n\t\t\tif (relative(file, TEMPLATE_PATH) === \"\") {\n\t\t\t\tconst mod = server.moduleGraph.getModuleById(resolvedVirtualModuleId);\n\n\t\t\t\tif (mod) {\n\t\t\t\t\tserver.moduleGraph.invalidateModule(mod);\n\t\t\t\t}\n\n\t\t\t\t// TODO: should reload?\n\t\t\t\t// server.ws.send({ type: \"full-reload\" });\n\t\t\t}\n\t\t},\n\t};\n};\n"],"mappings":";;;;AAKA,MAAM,gBAAgB;AAEtB,MAAM,mBAA8B;;;;;;;;EAQlC,MAAM;AAER,MAAa,wBAAgC;CAC5C,MAAM,kBAAkB;CACxB,MAAM,0BAA0B,OAAO;CAEvC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;;EAKT,MAAM,KAAK,IAAI;GACd,IAAI,OAAO,yBACV;GAGD,IAAI;IACH,MAAM,WAAW,MAAM,SAAS,eAAe,OAAO;IAEtD,OAAO,EAAE,2BAA2B,KAAK,UAAU,SAAS,CAAC;YACrD,OAAO;IACf,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC/D,OAAO,EAAE,2BAA2B,KAAK,UAAU,iBAAiB,CAAC;IAGtE,MAAM;;;EAGR,gBAAgB,EAAE,MAAM,UAAU;GACjC,IAAI,SAAS,MAAM,cAAc,KAAK,IAAI;IACzC,MAAM,MAAM,OAAO,YAAY,cAAc,wBAAwB;IAErE,IAAI,KACH,OAAO,YAAY,iBAAiB,IAAI;;;EAO3C"}
1
+ {"version":3,"file":"virtual-template.mjs","names":[],"sources":["../../src/vite/virtual-template.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\nimport type { Plugin } from \"vite\";\nimport { js } from \"../shared/utils\";\n\nconst TEMPLATE_PATH = \"./src/template.html\";\n\nconst DEFAULT_TEMPLATE = /* html */ `\n<!DOCTYPE html>\n<html>\n <head></head>\n <body>\n <!--ssr-outlet-->\n </body>\n</html>\n`.trim();\n\nexport const virtualTemplate = (): Plugin => {\n\tconst virtualModuleId = \"virtual:yamf:template\";\n\tconst resolvedVirtualModuleId = \"\\0\" + virtualModuleId;\n\n\treturn {\n\t\tname: \"yamf:virtual-template\",\n\t\tresolveId(id) {\n\t\t\tif (id === virtualModuleId) {\n\t\t\t\treturn resolvedVirtualModuleId;\n\t\t\t}\n\n\t\t\treturn undefined;\n\t\t},\n\t\tasync load(id) {\n\t\t\tif (id !== resolvedVirtualModuleId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst template = await readFile(TEMPLATE_PATH, \"utf8\");\n\n\t\t\t\treturn js`export const template = ${JSON.stringify(template)};`;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n\t\t\t\t\treturn js`export const template = ${JSON.stringify(DEFAULT_TEMPLATE)};`;\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\thandleHotUpdate({ file, server }) {\n\t\t\tif (relative(file, TEMPLATE_PATH) === \"\") {\n\t\t\t\tconst mod = server.moduleGraph.getModuleById(resolvedVirtualModuleId);\n\n\t\t\t\tif (mod) {\n\t\t\t\t\tserver.moduleGraph.invalidateModule(mod);\n\t\t\t\t}\n\n\t\t\t\t// TODO: should reload?\n\t\t\t\t// server.ws.send({ type: \"full-reload\" });\n\t\t\t}\n\t\t},\n\t};\n};\n"],"mappings":";;;;AAKA,MAAM,gBAAgB;AAEtB,MAAM,mBAA8B;;;;;;;;EAQlC,KAAK;AAEP,MAAa,wBAAgC;CAC5C,MAAM,kBAAkB;CACxB,MAAM,0BAA0B;CAEhC,OAAO;EACN,MAAM;EACN,UAAU,IAAI;GACb,IAAI,OAAO,iBACV,OAAO;EAIT;EACA,MAAM,KAAK,IAAI;GACd,IAAI,OAAO,yBACV;GAGD,IAAI;IACH,MAAM,WAAW,MAAM,SAAS,eAAe,MAAM;IAErD,OAAO,EAAE,2BAA2B,KAAK,UAAU,QAAQ,EAAE;GAC9D,SAAS,OAAO;IACf,IAAI,iBAAiB,SAAS,UAAU,SAAS,MAAM,SAAS,UAC/D,OAAO,EAAE,2BAA2B,KAAK,UAAU,gBAAgB,EAAE;IAGtE,MAAM;GACP;EACD;EACA,gBAAgB,EAAE,MAAM,UAAU;GACjC,IAAI,SAAS,MAAM,aAAa,MAAM,IAAI;IACzC,MAAM,MAAM,OAAO,YAAY,cAAc,uBAAuB;IAEpE,IAAI,KACH,OAAO,YAAY,iBAAiB,GAAG;GAKzC;EACD;CACD;AACD"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pajecawav/yamf",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.0.4",
5
5
  "description": "Yet another meta framework",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/pajecawav/yamf#readme",
@@ -30,50 +30,54 @@
30
30
  "access": "public"
31
31
  },
32
32
  "peerDependencies": {
33
- "hono": "^4.12.12",
34
- "vite": "^8.0.0"
33
+ "hono": "^4.12.23",
34
+ "vite": "^8.0.16"
35
35
  },
36
36
  "dependencies": {
37
- "@babel/generator": "^7.29.1",
38
- "@babel/parser": "^7.29.3",
39
- "@babel/traverse": "^7.29.0",
40
- "@babel/types": "^7.29.0",
41
- "devalue": "^5.8.0",
42
- "nitro": "3.0.260429-beta",
37
+ "@babel/generator": "^7.29.7",
38
+ "@babel/parser": "^7.29.7",
39
+ "@babel/traverse": "^7.29.7",
40
+ "@babel/types": "^7.29.7",
41
+ "devalue": "^5.8.1",
42
+ "exsolve": "^1.0.8",
43
+ "nitro": "3.0.260610-beta",
43
44
  "rou3": "^0.8.1",
44
45
  "ufo": "^1.6.4",
45
- "unhead": "^3.1.0"
46
+ "unhead": "^3.1.4"
46
47
  },
47
48
  "devDependencies": {
48
- "@pajecawav/tools": "^0.0.2",
49
+ "@pajecawav/tools": "^0.0.4",
49
50
  "@types/babel__generator": "^7.27.0",
50
51
  "@types/babel__traverse": "^7.28.0",
51
- "@types/node": "^24.12.3",
52
- "@vitest/coverage-v8": "^4.1.5",
53
- "@vitest/ui": "^4.1.5",
52
+ "@types/node": "^24.13.2",
53
+ "@typescript/native-preview": "7.0.0-dev.20260612.1",
54
+ "@vitest/coverage-v8": "^4.1.8",
55
+ "@vitest/ui": "^4.1.8",
54
56
  "cross-env": "^10.1.0",
55
- "hono": "^4.12.18",
57
+ "hono": "^4.12.25",
56
58
  "husky": "^9.1.7",
57
- "npm-run-all2": "^8.0.4",
58
- "oxfmt": "^0.48.0",
59
- "oxlint": "^1.63.0",
60
- "oxlint-tsgolint": "^0.22.1",
61
- "publint": "^0.3.20",
62
- "tsdown": "0.22.0",
63
- "typescript": "^6.0.3",
64
- "vite": "^8.0.11",
65
- "vitest": "^4.1.5"
59
+ "npm-run-all2": "^9.0.1",
60
+ "oxfmt": "^0.54.0",
61
+ "oxlint": "^1.69.0",
62
+ "oxlint-tsgolint": "^0.23.0",
63
+ "publint": "^0.3.21",
64
+ "tsdown": "0.22.2",
65
+ "vite": "^8.0.16",
66
+ "vitest": "^4.1.8"
66
67
  },
67
68
  "scripts": {
68
69
  "build": "tsdown",
69
70
  "dev": "tsdown --watch",
71
+ "play": "pnpm --filter=playground dev",
72
+ "play:build": "pnpm --filter=playground build",
73
+ "play:preview": "pnpm --filter=playground preview",
70
74
  "test": "vitest run --passWithNoTests",
71
75
  "test:watch": "vitest watch",
72
76
  "test:coverage": "vitest run --coverage",
73
77
  "test:ui": "vitest --ui",
74
- "lint": "run-p -l lint:*",
78
+ "lint": "cross-env FORCE_COLOR=1 run-p -l lint:*",
75
79
  "lint:oxlint": "oxlint .",
76
- "lint:tsc": "tsc -b --noEmit",
80
+ "lint:tsc": "tsgo -b --noEmit",
77
81
  "lint:format": "pt format --check",
78
82
  "lint:package": "publint",
79
83
  "format": "pt format"
@@ -1,11 +1,10 @@
1
1
  import { type Context, createContext, useContext } from "hono/jsx";
2
2
  import type { H3Event } from "nitro";
3
- import type { EventHandlerRequest } from "nitro/h3";
4
3
  import type { ServerUnhead } from "unhead/server";
5
4
 
6
5
  interface SSRContextValue {
7
6
  head: ServerUnhead;
8
- event: H3Event<EventHandlerRequest>;
7
+ event: H3Event;
9
8
  }
10
9
 
11
10
  export const SSRContext: Context<SSRContextValue | null> = createContext<SSRContextValue | null>(
@@ -1,8 +1,7 @@
1
1
  import type { H3Event } from "nitro";
2
- import type { EventHandlerRequest } from "nitro/h3";
3
2
  import { useSSRContext } from "#/context/ssr";
4
3
 
5
- export const useEvent = (): H3Event<EventHandlerRequest> => {
4
+ export const useEvent = (): H3Event => {
6
5
  const ctx = useSSRContext();
7
6
 
8
7
  if (!ctx) {
@@ -1,7 +1,7 @@
1
- import { useHead as _useHead } from "unhead";
1
+ import { useHead as _useHead, useSeoMeta as _useSeoMeta } from "unhead";
2
2
  import type { ClientUnhead } from "unhead/client";
3
3
  import { createHead } from "unhead/client";
4
- import type { ResolvableHead } from "unhead/types";
4
+ import type { ResolvableHead, UseSeoMetaInput } from "unhead/types";
5
5
  import { useSSRContext } from "#/context/ssr";
6
6
 
7
7
  declare global {
@@ -25,3 +25,15 @@ export const useHead = (input?: ResolvableHead): void => {
25
25
  _useHead(window.__UNHEAD__, input);
26
26
  }
27
27
  };
28
+
29
+ export const useSeoMeta = (input?: UseSeoMetaInput): void => {
30
+ if (import.meta.env.SSR) {
31
+ const ctx = useSSRContext();
32
+
33
+ if (ctx?.head) {
34
+ _useSeoMeta(ctx.head, input);
35
+ }
36
+ } else if (window.__UNHEAD__) {
37
+ _useSeoMeta(window.__UNHEAD__, input);
38
+ }
39
+ };
package/src/index.ts CHANGED
@@ -3,10 +3,11 @@ export type { PageHandler } from "./page";
3
3
 
4
4
  export { useSSRContext } from "./context/ssr";
5
5
  export { useEvent } from "./hooks/useEvent";
6
- export { useHead } from "./hooks/useHead";
6
+ export { useHead, useSeoMeta } from "./hooks/useHead";
7
7
 
8
8
  export type { IslandClientDirective, IslandProps } from "./island/types";
9
9
 
10
10
  export type { ImportAssetsResult, ImportAssetsResultRaw } from "./shared/assets";
11
+ export type { YamfHead } from "./shared/head";
11
12
 
12
13
  export { Head, type HeadProps } from "./components/Head";
@@ -31,10 +31,10 @@ customElements.define(
31
31
  "yamf-island",
32
32
  class extends HTMLElement {
33
33
  public connectedCallback() {
34
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
35
34
  const islandProps = parse(this.getAttribute("island-props") ?? "{}");
36
35
  const islandSrc = this.getAttribute("island-src");
37
36
  const islandEntry = this.getAttribute("island-entry");
37
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
38
38
  const islandClient = (this.getAttribute("island-client") ??
39
39
  "load") as IslandClientDirective;
40
40
 
@@ -80,7 +80,7 @@ customElements.define(
80
80
  case "skip":
81
81
  break;
82
82
  default:
83
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
83
+ // oxlint-disable-next-line typescript/restrict-template-expressions
84
84
  throw new Error(`Invalid island-client value: ${islandClient}`);
85
85
  }
86
86
  }
@@ -4,7 +4,6 @@ import type { ImportAssetsResultRaw } from "#/shared/assets";
4
4
  import type { IslandClientDirective } from "./types";
5
5
 
6
6
  declare module "hono/jsx" {
7
- // eslint-disable-next-line @typescript-eslint/no-namespace
8
7
  namespace JSX {
9
8
  interface IntrinsicElements {
10
9
  "yamf-island": {
@@ -34,6 +33,7 @@ export const createIsland = (
34
33
  island-props={stringify(props)}
35
34
  island-src={assets.entry}
36
35
  island-entry={exportName}
36
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
37
37
  island-client={props["yamf-client"] as IslandClientDirective}
38
38
  // TODO: export CSS?
39
39
  style={{ display: "contents" }}
package/src/page.tsx CHANGED
@@ -1,43 +1,45 @@
1
- import type { Child, FC, PropsWithChildren } from "hono/jsx";
2
- import { Fragment } from "hono/jsx";
1
+ import { Fragment, type Child } from "hono/jsx";
3
2
  import { renderToReadableStream } from "hono/jsx/streaming";
4
3
  import { Hono } from "hono/tiny";
5
- import type { EventHandlerRequest, EventHandlerResponse, H3Event } from "nitro/h3";
4
+ import type { EventHandlerResponse, H3Event } from "nitro/h3";
6
5
  import { HTTPResponse, withServerTiming } from "nitro/h3";
6
+ import { useSeoMeta } from "unhead";
7
7
  import type { Unhead } from "unhead/server";
8
8
  import { transformHtmlTemplate } from "unhead/server";
9
9
  import { createStreamableHead, wrapStream } from "unhead/stream/server";
10
- import type { ResolvableHead, ResolvableLink } from "unhead/types";
11
- import { clientAssets } from "virtual:yamf:assets";
10
+ import type { ResolvableLink, UseSeoMetaInput } from "unhead/types";
11
+ import { Root as RootComponent } from "virtual:yamf:root";
12
12
  import { template } from "virtual:yamf:template";
13
13
  import { SSRContext } from "./context/ssr";
14
14
  import type { ImportAssetsResult } from "./shared/assets";
15
+ import { YamfHead } from "./shared/head";
15
16
 
16
17
  export type PageHandler = (
17
- event: H3Event<EventHandlerRequest>,
18
+ event: H3Event,
18
19
  params: {
19
- serverAssets?: ImportAssetsResult;
20
- head?: ResolvableHead;
21
- Layout?: FC<PropsWithChildren>;
20
+ assets: ImportAssetsResult;
21
+ head?: YamfHead;
22
22
  },
23
23
  ) => EventHandlerResponse;
24
24
 
25
25
  export type PageRenderer = (
26
- event: H3Event<EventHandlerRequest>,
27
- params: { head: Unhead },
26
+ event: H3Event,
27
+ params: {
28
+ head: Unhead;
29
+ seoHead: (input: UseSeoMetaInput) => void;
30
+ },
28
31
  ) => HTTPResponse | Promise<HTTPResponse> | Child | Promise<Child>;
29
32
 
30
33
  interface DefinePageOptions {
31
34
  render: PageRenderer;
32
35
  stream?: boolean;
33
- Layout?: FC<PropsWithChildren>;
34
36
  }
35
37
 
36
38
  export const definePage = (options: DefinePageOptions): PageHandler => {
37
- return async (event, { serverAssets, head: headInit, Layout = options.Layout ?? Fragment }) => {
38
- const assets = serverAssets ? clientAssets.merge(serverAssets) : clientAssets;
39
-
39
+ return async (event, { assets, head: headInit }) => {
40
40
  const { head } = createStreamableHead({ init: [headInit] });
41
+ const seoHead = (input?: UseSeoMetaInput) => useSeoMeta(head, input);
42
+ seoHead(headInit?.seo);
41
43
 
42
44
  head.push({
43
45
  link: [
@@ -47,15 +49,17 @@ export const definePage = (options: DefinePageOptions): PageHandler => {
47
49
  script: [{ type: "module", src: assets.entry }],
48
50
  });
49
51
 
50
- const content = await options.render(event, { head });
52
+ const content = await options.render(event, { head, seoHead });
51
53
 
52
54
  if (content instanceof HTTPResponse) {
53
55
  return content;
54
56
  }
55
57
 
58
+ const Root = RootComponent ?? Fragment;
59
+
56
60
  const App = async () => (
57
61
  <SSRContext value={{ head, event }}>
58
- <Layout>{content}</Layout>
62
+ <Root>{content}</Root>
59
63
  </SSRContext>
60
64
  );
61
65
 
@@ -1,13 +1,13 @@
1
1
  import path from "node:path";
2
- import type { FC, PropsWithChildren } from "hono/jsx";
3
2
  import type { EventHandlerRequest, EventHandlerWithFetch, H3Event } from "nitro/h3";
4
3
  import { defineHandler, HTTPError, writeEarlyHints } from "nitro/h3";
5
4
  import { addRoute, createRouter, findRoute } from "rou3";
6
5
  import { withLeadingSlash, withoutTrailingSlash } from "ufo";
7
- import type { ResolvableHead } from "unhead/types";
8
6
  import { clientAssets } from "virtual:yamf:assets";
9
- import { pages, assets as serverAssets } from "virtual:yamf:pages";
7
+ import { pages, assets as pagesServerAssets } from "virtual:yamf:pages";
8
+ import { rootAssets } from "virtual:yamf:root";
10
9
  import type { PageHandler } from "#/page";
10
+ import { YamfHead } from "#/shared/head";
11
11
 
12
12
  interface Route {
13
13
  handler: () => Promise<PageHandler>;
@@ -40,15 +40,15 @@ for (const [relativePath, handler] of Object.entries(pages).toSorted((a, b) =>
40
40
 
41
41
  addRoute(router, "GET", route, {
42
42
  handler,
43
- serverAssets: serverAssets[relativePath],
43
+ serverAssets: pagesServerAssets[relativePath],
44
44
  });
45
45
  }
46
46
 
47
47
  export type ServerEntry = EventHandlerWithFetch<EventHandlerRequest, Promise<unknown>>;
48
48
 
49
49
  export interface DefineServerEntryOptions {
50
- head?: ResolvableHead | ((event: H3Event<EventHandlerRequest>) => ResolvableHead);
51
- Layout?: FC<PropsWithChildren>;
50
+ head?: YamfHead | ((event: H3Event) => YamfHead);
51
+ disableEarlyHints?: boolean;
52
52
  }
53
53
 
54
54
  export const defineServerEntry = (options?: DefineServerEntryOptions): ServerEntry => {
@@ -62,19 +62,22 @@ export const defineServerEntry = (options?: DefineServerEntryOptions): ServerEnt
62
62
  const { handler, serverAssets } = route.data;
63
63
  event.context.params = route.params;
64
64
 
65
- const assets = serverAssets ? serverAssets.merge(clientAssets) : clientAssets;
65
+ const assets = clientAssets.merge(...[rootAssets, serverAssets].filter(x => !!x));
66
66
 
67
- await writeEarlyHints(event, {
68
- link: [
67
+ if (!options?.disableEarlyHints) {
68
+ const link = [
69
69
  ...assets.js.map(script => `<${script.href}>; rel=modulepreload`),
70
70
  ...assets.css.map(style => `<${style.href}>; rel=preload; as=style`),
71
- ],
72
- });
71
+ ];
72
+
73
+ if (link.length) {
74
+ await writeEarlyHints(event, { link });
75
+ }
76
+ }
73
77
 
74
78
  return (await handler())(event, {
75
- serverAssets,
79
+ assets,
76
80
  head: typeof options?.head === "function" ? options.head(event) : options?.head,
77
- Layout: options?.Layout,
78
81
  });
79
82
  });
80
83
  };
@@ -0,0 +1,3 @@
1
+ import type { ResolvableHead, UseSeoMetaInput } from "unhead/types";
2
+
3
+ export type YamfHead = ResolvableHead & { seo?: UseSeoMetaInput };
package/src/virtual.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  declare module "virtual:yamf:assets" {
2
- // eslint-disable-next-line @typescript-eslint/consistent-type-imports
3
2
  export const clientAssets: import("./shared/assets").ImportAssetsResult;
4
3
  }
5
4
 
@@ -12,3 +11,10 @@ declare module "virtual:yamf:pages" {
12
11
  declare module "virtual:yamf:template" {
13
12
  export const template: string;
14
13
  }
14
+
15
+ declare module "virtual:yamf:root" {
16
+ const Root: import("hono/jsx").FC | null;
17
+ const rootAssets: import("./shared/assets").ImportAssetsResult | null;
18
+
19
+ export { Root, rootAssets };
20
+ }
package/src/vite/index.ts CHANGED
@@ -5,6 +5,7 @@ import type { EnvironmentOptions, PluginOption } from "vite";
5
5
  import { islands } from "./islands";
6
6
  import { virtualAssets } from "./virtual-assets";
7
7
  import { virtualPages } from "./virtual-pages";
8
+ import { virtualRoot } from "./virtual-root";
8
9
  import { virtualTemplate } from "./virtual-template";
9
10
 
10
11
  export interface YamfOptions {
@@ -61,6 +62,7 @@ const yamf = (options?: YamfOptions): PluginOption[] => {
61
62
  plugins.push(virtualAssets());
62
63
  plugins.push(virtualPages());
63
64
  plugins.push(virtualTemplate());
65
+ plugins.push(virtualRoot());
64
66
 
65
67
  plugins.push(
66
68
  nitro({
@@ -19,8 +19,8 @@ import {
19
19
  } from "@babel/types";
20
20
  import type { Plugin } from "vite";
21
21
 
22
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
23
22
  // @ts-ignore
23
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion
24
24
  const traverse = (_traverse.default as typeof _traverse) ?? _traverse;
25
25
 
26
26
  const ISLAND_REGEX = /\.island\.(j|t)sx?$/;
@@ -20,7 +20,7 @@ export const virtualAssets = (): Plugin => {
20
20
  }
21
21
 
22
22
  return js`
23
- import clientAssets from "./src/client/index.ts?assets=client";
23
+ import clientAssets from "./src/client?assets=client";
24
24
 
25
25
  export { clientAssets };
26
26
  `.trim();
@@ -0,0 +1,48 @@
1
+ import { resolveModulePath } from "exsolve";
2
+ import type { Plugin } from "vite";
3
+ import { js } from "../shared/utils";
4
+
5
+ const ROOT_PATH = "./src/root";
6
+
7
+ export const virtualRoot = (): Plugin => {
8
+ const virtualModuleId = "virtual:yamf:root";
9
+ const resolvedVirtualModuleId = "\0" + virtualModuleId;
10
+
11
+ return {
12
+ name: "yamf:virtual-root",
13
+ resolveId(id) {
14
+ if (id === virtualModuleId) {
15
+ return resolvedVirtualModuleId;
16
+ }
17
+
18
+ return undefined;
19
+ },
20
+ load(id) {
21
+ if (id !== resolvedVirtualModuleId) {
22
+ return;
23
+ }
24
+
25
+ const root = resolveModulePath(ROOT_PATH, {
26
+ try: true,
27
+ suffixes: ["", "/index"],
28
+ extensions: [".tsx", ".jsx", ".ts", ".js", ".mjs", ".cjs", ".mts", ".cts"],
29
+ });
30
+
31
+ if (!root) {
32
+ return js`
33
+ const Root = null;
34
+ const rootAssets = null;
35
+
36
+ export { Root, rootAssets };
37
+ `;
38
+ }
39
+
40
+ return js`
41
+ import Root from "${ROOT_PATH}";
42
+ import rootAssets from "${ROOT_PATH}?assets=ssr";
43
+
44
+ export { Root, rootAssets };
45
+ `.trim();
46
+ },
47
+ };
48
+ };