xanix 1.0.0 → 1.0.3

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 (120) hide show
  1. package/dist/BaseDocument.d.ts +1 -1
  2. package/dist/BaseDocument.js +3 -3
  3. package/dist/bin/bundler/buildCache.js +6 -23
  4. package/dist/bin/bundler/plugins/XanixReactRefresh.js +33 -33
  5. package/dist/bin/bundler/plugins/XanixResolveCacheDeps/index.js +5 -0
  6. package/dist/bin/bundler/plugins/XanixTsconfigAlias.d.ts +2 -0
  7. package/dist/bin/bundler/plugins/{xanixTsconfigAlias.js → XanixTsconfigAlias.js} +3 -5
  8. package/dist/bin/bundler/plugins/plugins.js +6 -0
  9. package/dist/bin/bundler/watchClient.js +7 -1
  10. package/dist/bin/cli/build.js +3 -1
  11. package/dist/bin/cli/dev.js +3 -0
  12. package/dist/bin/cli/start copy.d.ts +2 -0
  13. package/dist/bin/cli/start copy.js +34 -0
  14. package/dist/bin/index.js +0 -0
  15. package/dist/client/client-runtime.d.ts +10 -0
  16. package/dist/client/client-runtime.js +98 -0
  17. package/dist/client/index.d.ts +2 -2
  18. package/dist/client/index.js +2 -2
  19. package/dist/client/navigation.d.ts +3 -4
  20. package/dist/client/navigation.js +23 -10
  21. package/dist/client/runtime.d.ts +1 -1
  22. package/dist/components/Document/context.d.ts +4 -10
  23. package/dist/components/Document/context.js +6 -5
  24. package/dist/components/Document/index.d.ts +6 -5
  25. package/dist/components/Document/index.js +3 -7
  26. package/dist/components/Head.js +1 -1
  27. package/dist/document/Body.js +1 -2
  28. package/dist/document/Document.js +1 -2
  29. package/dist/document/DocumentContext.d.ts +1 -0
  30. package/dist/document/Head.js +4 -3
  31. package/dist/document/index.d.ts +1 -1
  32. package/dist/document/index.js +1 -1
  33. package/dist/document/useDocument.d.ts +1 -1
  34. package/dist/hooks/useCookie.d.ts +2 -0
  35. package/dist/hooks/useCookie.js +13 -0
  36. package/dist/hooks/useData.js +1 -3
  37. package/dist/hooks/useRequest copy.d.ts +2 -0
  38. package/dist/hooks/useRequest copy.js +8 -0
  39. package/dist/index.d.ts +0 -5
  40. package/dist/index.js +0 -4
  41. package/dist/navigation/navigate.js +6 -6
  42. package/dist/navigation/useLocation.js +1 -1
  43. package/dist/router/index.d.ts +3 -1
  44. package/dist/router/index.js +3 -1
  45. package/dist/router/useParams.d.ts +1 -9
  46. package/dist/router/useParams.js +3 -48
  47. package/dist/router/usePathname.d.ts +1 -0
  48. package/dist/router/usePathname.js +8 -0
  49. package/dist/router/useSearchParams.js +2 -8
  50. package/dist/runtime/createServer.d.ts +12 -0
  51. package/dist/runtime/createServer.js +40 -0
  52. package/dist/runtime/index.d.ts +12 -0
  53. package/dist/runtime/index.js +40 -0
  54. package/dist/runtime/readManifest.d.ts +14 -0
  55. package/dist/runtime/readManifest.js +8 -0
  56. package/dist/runtime/xanixPage.d.ts +9 -0
  57. package/dist/runtime/xanixPage.js +62 -0
  58. package/dist/server/createServer.d.ts +12 -0
  59. package/dist/server/createServer.js +40 -0
  60. package/dist/server/page.js +2 -0
  61. package/dist/server/runtime copy.d.ts +12 -0
  62. package/dist/server/runtime copy.js +40 -0
  63. package/dist/server/runtime.d.ts +12 -0
  64. package/dist/server/runtime.js +40 -0
  65. package/dist/server/xanixPage.d.ts +9 -0
  66. package/dist/server/xanixPage.js +62 -0
  67. package/dist/utils/index.d.ts +0 -9
  68. package/dist/utils/index.js +1 -27
  69. package/dist/xanix.js +12 -12
  70. package/package.json +73 -73
  71. package/{src/xanix-env.d.ts → xanix-env.d.ts} +79 -79
  72. package/dist/Document.d.ts +0 -7
  73. package/dist/Document.js +0 -7
  74. package/dist/bin/bundler/plugins/XanixWatchChange copy.d.ts +0 -10
  75. package/dist/bin/bundler/plugins/XanixWatchChange copy.js +0 -30
  76. package/dist/bin/bundler/plugins/XanixWatchChange.d.ts +0 -9
  77. package/dist/bin/bundler/plugins/XanixWatchChange.js +0 -27
  78. package/dist/bin/bundler/plugins/XanixWatchChangeClient.d.ts +0 -7
  79. package/dist/bin/bundler/plugins/XanixWatchChangeClient.js +0 -15
  80. package/dist/bin/bundler/plugins/pathResolver.d.ts +0 -5
  81. package/dist/bin/bundler/plugins/pathResolver.js +0 -57
  82. package/dist/bin/bundler/plugins/xanixServerData.d.ts +0 -6
  83. package/dist/bin/bundler/plugins/xanixServerData.js +0 -224
  84. package/dist/bin/bundler/plugins/xanixTsconfigAlias.d.ts +0 -6
  85. package/dist/client/components/Body.d.ts +0 -5
  86. package/dist/client/components/Body.js +0 -10
  87. package/dist/client/components/Document/context.d.ts +0 -3
  88. package/dist/client/components/Document/context.js +0 -14
  89. package/dist/client/components/Document/index.d.ts +0 -8
  90. package/dist/client/components/Document/index.js +0 -6
  91. package/dist/client/components/Head copy.d.ts +0 -5
  92. package/dist/client/components/Head copy.js +0 -8
  93. package/dist/client/components/Head.d.ts +0 -5
  94. package/dist/client/components/Head.js +0 -10
  95. package/dist/client/components/Link.d.ts +0 -6
  96. package/dist/client/components/Link.js +0 -10
  97. package/dist/client/refresh.d.ts +0 -7
  98. package/dist/client/refresh.js +0 -15
  99. package/dist/components/Document/Document.d.ts +0 -16
  100. package/dist/components/Document/Document.js +0 -15
  101. package/dist/components/DocumentContext/DocumentContext.d.ts +0 -15
  102. package/dist/components/DocumentContext/DocumentContext.js +0 -18
  103. package/dist/components/DocumentContext/context.d.ts +0 -11
  104. package/dist/components/DocumentContext/context.js +0 -14
  105. package/dist/components/DocumentContext/index.d.ts +0 -15
  106. package/dist/components/DocumentContext/index.js +0 -18
  107. package/dist/components/DocumentProvider.d.ts +0 -13
  108. package/dist/components/DocumentProvider.js +0 -7
  109. package/dist/document/Document/Document.d.ts +0 -7
  110. package/dist/document/Document/Document.js +0 -10
  111. package/dist/document/Document/context.d.ts +0 -17
  112. package/dist/document/Document/context.js +0 -13
  113. package/dist/document/Document/index.d.ts +0 -7
  114. package/dist/document/Document/index.js +0 -10
  115. package/dist/document/context.d.ts +0 -17
  116. package/dist/document/context.js +0 -13
  117. package/dist/loader.d.ts +0 -11
  118. package/dist/loader.js +0 -16
  119. package/dist/router/useSearchParams .d.ts +0 -9
  120. package/dist/router/useSearchParams .js +0 -50
@@ -0,0 +1,8 @@
1
+ import useDocument from "./useDocument";
2
+ const useRequest = () => {
3
+ const { request } = useDocument();
4
+ if (__XANIX_SERVER__) {
5
+ return request;
6
+ }
7
+ };
8
+ export default useRequest;
package/dist/index.d.ts CHANGED
@@ -14,10 +14,5 @@ import useHeaders from "./hooks/useHeaders.js";
14
14
  import useCookies from "./hooks/useCookies.js";
15
15
  import useData from "./hooks/useData.js";
16
16
  import { navigate, back, forward, preload, onNavigateStart, onNavigateEnd, reload } from "./navigate.js";
17
- export declare const isClient: boolean;
18
- export declare const isServer: boolean;
19
- export declare const isDevelopment: boolean;
20
- export declare const isProduction: boolean;
21
17
  export { Link, Document, Head, Body, Script, useDocument, useLocation, useParams, usePathname, useSearchParams, usePage, useRequest, useHeaders, useCookies, useData, navigate, back, forward, preload, onNavigateStart, onNavigateEnd, reload, };
22
- export type * from "./types";
23
18
  export type { DocumentProps };
package/dist/index.js CHANGED
@@ -16,10 +16,6 @@ import useCookies from "./hooks/useCookies.js";
16
16
  import useData from "./hooks/useData.js";
17
17
  // navigate
18
18
  import { navigate, back, forward, preload, onNavigateStart, onNavigateEnd, reload, } from "./navigate.js";
19
- export const isClient = __XANIX_CLIENT__;
20
- export const isServer = __XANIX_SERVER__;
21
- export const isDevelopment = __XANIX_DEV__;
22
- export const isProduction = __XANIX_PROD__;
23
19
  export { Link, Document, Head, Body, Script,
24
20
  // hooks
25
21
  useDocument, useLocation, useParams, usePathname, useSearchParams, usePage, useRequest, useHeaders, useCookies, useData,
@@ -20,12 +20,12 @@ export const reload = (hard = false) => {
20
20
  window.dispatchEvent(new CustomEvent("xanix:reload"));
21
21
  };
22
22
  export const onNavigateStart = (callback) => {
23
- if (typeof window === "undefined")
24
- return;
25
- window.addEventListener("xanix:navigate:start", callback);
23
+ if (__XANIX_CLIENT__) {
24
+ window.addEventListener("xanix:navigate:start", callback);
25
+ }
26
26
  };
27
27
  export const onNavigateEnd = (callback) => {
28
- if (typeof window === "undefined")
29
- return;
30
- window.addEventListener("xanix:navigate:end", callback);
28
+ if (__XANIX_CLIENT__) {
29
+ window.addEventListener("xanix:navigate:end", callback);
30
+ }
31
31
  };
@@ -4,7 +4,7 @@ export const useLocation = () => {
4
4
  const _document = useDocument();
5
5
  const req = _document?.request;
6
6
  let _url;
7
- if (req) {
7
+ if (__XANIX_SERVER__) {
8
8
  _url = new URL(req.originalUrl, `${req.protocol}://${req.get("host")}`);
9
9
  }
10
10
  else {
@@ -1 +1,3 @@
1
- export * from "./useSearchParams.js";
1
+ export * from "../hooks/useSearchParams.js";
2
+ export * from "../hooks/useParams.js";
3
+ export * from "../hooks/usePathname.js";
@@ -1 +1,3 @@
1
- export * from "./useSearchParams.js";
1
+ export * from "../hooks/useSearchParams.js";
2
+ export * from "../hooks/useParams.js";
3
+ export * from "../hooks/usePathname.js";
@@ -1,9 +1 @@
1
- export declare const useParams: () => {
2
- get: (key: string) => string | null;
3
- set: (key: string, value: string) => void;
4
- sets: (entries: Record<string, string>) => void;
5
- delete: (key: string) => void;
6
- deletes: (keys: string[]) => void;
7
- clear: () => void;
8
- has: (key: string) => boolean;
9
- };
1
+ export declare const useParams: () => any;
@@ -1,50 +1,5 @@
1
- import { navigate } from "../navigation/navigate.js";
2
- import { useEffect, useState } from "react";
3
- const getParams = () => {
4
- return new URLSearchParams(window.location.search);
5
- };
1
+ import useDocument from "../hooks/useDocument.js";
6
2
  export const useParams = () => {
7
- const [params, setParams] = useState(getParams());
8
- useEffect(() => {
9
- const onNavigate = () => setParams(getParams());
10
- window.addEventListener("xanix:navigate:end", onNavigate);
11
- return () => {
12
- window.removeEventListener("xanix:navigate:end", onNavigate);
13
- };
14
- }, []);
15
- return {
16
- get: (key) => params.get(key),
17
- set: (key, value) => {
18
- const newParams = new URLSearchParams(params.toString());
19
- newParams.set(key, value);
20
- navigate(window.location.pathname + "?" + newParams.toString());
21
- },
22
- sets: (entries) => {
23
- const newParams = new URLSearchParams(params.toString());
24
- for (const [key, value] of Object.entries(entries)) {
25
- newParams.set(key, value);
26
- }
27
- navigate(window.location.pathname + "?" + newParams.toString());
28
- },
29
- delete: (key) => {
30
- const newParams = new URLSearchParams(params.toString());
31
- newParams.delete(key);
32
- setParams(newParams);
33
- navigate(window.location.pathname + "?" + newParams.toString());
34
- },
35
- deletes: (keys) => {
36
- const newParams = new URLSearchParams(params.toString());
37
- for (const key of keys) {
38
- newParams.delete(key);
39
- }
40
- setParams(newParams);
41
- navigate(window.location.pathname + "?" + newParams.toString());
42
- },
43
- clear: () => {
44
- const newParams = new URLSearchParams();
45
- setParams(newParams);
46
- navigate(window.location.pathname + "?" + newParams.toString());
47
- },
48
- has: (key) => params.has(key),
49
- };
3
+ const { params } = useDocument();
4
+ return params;
50
5
  };
@@ -0,0 +1 @@
1
+ export declare const usePathname: () => any;
@@ -0,0 +1,8 @@
1
+ import useDocument from "../hooks/useDocument.js";
2
+ export const usePathname = () => {
3
+ if (__XANIX_CLIENT__) {
4
+ return window.location.pathname;
5
+ }
6
+ const { request } = useDocument();
7
+ return request?.path;
8
+ };
@@ -1,6 +1,6 @@
1
1
  import { navigate } from "../navigation/navigate.js";
2
2
  import { useEffect, useState } from "react";
3
- import useDocument from "../document/useDocument.js";
3
+ import useDocument from "../hooks/useDocument.js";
4
4
  const getParams = () => {
5
5
  return new URLSearchParams(window.location.search);
6
6
  };
@@ -12,13 +12,7 @@ const buildUrl = (params) => {
12
12
  };
13
13
  export const useSearchParams = () => {
14
14
  const { request } = useDocument();
15
- let _params;
16
- if (request) {
17
- _params = new URLSearchParams(request.url.split("?")[1] || "");
18
- }
19
- else {
20
- _params = getParams();
21
- }
15
+ let _params = new URLSearchParams(__XANIX_SERVER__ ? request.url.split("?")[1] || "" : window.location.search);
22
16
  const [params, setParams] = useState(_params);
23
17
  useEffect(() => {
24
18
  const onNavigate = () => {
@@ -0,0 +1,12 @@
1
+ import express from "express";
2
+ export interface XanixProps {
3
+ clientId: string;
4
+ req: any;
5
+ res: any;
6
+ component: React.ReactElement;
7
+ }
8
+ type Options = {
9
+ mode: "watch" | "start";
10
+ };
11
+ export declare function createXanixServer({ mode }: Options): express.Express;
12
+ export {};
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ export function createXanixServer({ mode }) {
3
+ const app = express();
4
+ if (mode === "watch") {
5
+ app.use("/.xanix/client", express.static(".xanix/client"));
6
+ app.use("/assets", express.static(".xanix/assets"));
7
+ app.use("/.xanix/cache", express.static(".xanix/cache"));
8
+ }
9
+ else {
10
+ app.use("/.xanix/client", express.static(".xanix/client", {
11
+ maxAge: "1y",
12
+ immutable: true,
13
+ etag: true,
14
+ }));
15
+ app.use("/assets", express.static(".xanix/assets", {
16
+ maxAge: "1y",
17
+ immutable: true,
18
+ etag: true,
19
+ }));
20
+ }
21
+ app.use((req, res, next) => {
22
+ let data = {
23
+ title: null,
24
+ meta: [],
25
+ };
26
+ if (!req.page) {
27
+ req.page = {
28
+ setTitle(title) {
29
+ data.title = title;
30
+ },
31
+ setMeta(name, content) {
32
+ data.meta.push({ name, content });
33
+ },
34
+ };
35
+ req.XanixPageData = data;
36
+ }
37
+ next();
38
+ });
39
+ return app;
40
+ }
@@ -0,0 +1,12 @@
1
+ import express from "express";
2
+ export interface XanixProps {
3
+ clientId: string;
4
+ req: any;
5
+ res: any;
6
+ component: React.ReactElement;
7
+ }
8
+ type Options = {
9
+ mode: "watch" | "start";
10
+ };
11
+ export declare function createXanixServer({ mode }: Options): express.Express;
12
+ export {};
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ export function createXanixServer({ mode }) {
3
+ const app = express();
4
+ if (mode === "watch") {
5
+ app.use("/.xanix/client", express.static(".xanix/client"));
6
+ app.use("/assets", express.static(".xanix/assets"));
7
+ app.use("/.xanix/cache", express.static(".xanix/cache"));
8
+ }
9
+ else {
10
+ app.use("/.xanix/client", express.static(".xanix/client", {
11
+ maxAge: "1y",
12
+ immutable: true,
13
+ etag: true,
14
+ }));
15
+ app.use("/assets", express.static(".xanix/assets", {
16
+ maxAge: "1y",
17
+ immutable: true,
18
+ etag: true,
19
+ }));
20
+ }
21
+ app.use((req, res, next) => {
22
+ let data = {
23
+ title: null,
24
+ meta: [],
25
+ };
26
+ if (!req.page) {
27
+ req.page = {
28
+ setTitle(title) {
29
+ data.title = title;
30
+ },
31
+ setMeta(name, content) {
32
+ data.meta.push({ name, content });
33
+ },
34
+ };
35
+ req.XanixPageData = data;
36
+ }
37
+ next();
38
+ });
39
+ return app;
40
+ }
@@ -0,0 +1,14 @@
1
+ interface XanixManifestEntry {
2
+ id: string;
3
+ name: string;
4
+ file: string;
5
+ path: string;
6
+ build: string;
7
+ export: string;
8
+ }
9
+ interface XanixManifest {
10
+ version: number;
11
+ entries: XanixManifestEntry[];
12
+ }
13
+ declare function readManifest(): Promise<XanixManifest>;
14
+ export default readManifest;
@@ -0,0 +1,8 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ async function readManifest() {
4
+ const manifestPath = path.resolve(process.cwd(), ".xanix", "client-manifest.json");
5
+ const source = await fs.readFile(manifestPath, "utf8");
6
+ return JSON.parse(source);
7
+ }
8
+ export default readManifest;
@@ -0,0 +1,9 @@
1
+ interface XanixPageProps {
2
+ pageId: string;
3
+ req: any;
4
+ res: any;
5
+ Component: (props: Record<string, any>) => React.ReactElement;
6
+ props: Record<string, any>;
7
+ }
8
+ export default function xanix_page({ pageId, req, res, Component, props, }: XanixPageProps): Promise<string | undefined>;
9
+ export {};
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { renderToPipeableStream } from "react-dom/server";
3
+ import readManifest from "./readManifest.js";
4
+ import { PassThrough } from "node:stream";
5
+ import path from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+ function renderPage(element) {
8
+ return new Promise((resolve, reject) => {
9
+ let html = "";
10
+ const stream = new PassThrough();
11
+ stream.on("data", (chunk) => {
12
+ html += chunk.toString();
13
+ });
14
+ stream.on("end", () => {
15
+ resolve(html);
16
+ });
17
+ stream.on("error", reject);
18
+ const { pipe } = renderToPipeableStream(element, {
19
+ onAllReady() {
20
+ pipe(stream);
21
+ },
22
+ onError(error) {
23
+ console.error("SSR error:", error);
24
+ },
25
+ });
26
+ });
27
+ }
28
+ export default async function xanix_page({ pageId, req, res, Component, props, }) {
29
+ const manifest = await readManifest();
30
+ const { title, meta } = req.XanixPageData;
31
+ const entry = manifest.entries.find((item) => item.id === pageId);
32
+ const method = req.method.toUpperCase();
33
+ if (method !== "GET") {
34
+ res.status(405).send("Method Not Allowed");
35
+ return;
36
+ }
37
+ if (!entry) {
38
+ throw new Error(`Xanix client entry "${pageId}" was not found in the manifest.`);
39
+ }
40
+ if ("x-navigation" in req.headers) {
41
+ res.setHeader("Content-Type", "application/json");
42
+ return JSON.stringify({
43
+ pageId,
44
+ props,
45
+ title: title ?? entry.name.replaceAll("-", " "),
46
+ meta,
47
+ params: req.params,
48
+ request: null,
49
+ });
50
+ }
51
+ const Document = (await import(pathToFileURL(path.join(process.cwd(), ".xanix", "xanix-document.js"))
52
+ .href)).default;
53
+ const html = await renderPage(_jsx(Document, { document: {
54
+ pageId,
55
+ props,
56
+ title: title ?? entry.name.replaceAll("-", " "),
57
+ meta,
58
+ params: req.params,
59
+ request: req,
60
+ }, children: _jsx(Component, { ...props }) }));
61
+ return `<!DOCTYPE html>${html}`;
62
+ }
@@ -0,0 +1,12 @@
1
+ import express from "express";
2
+ export interface XanixProps {
3
+ clientId: string;
4
+ req: any;
5
+ res: any;
6
+ component: React.ReactElement;
7
+ }
8
+ type Options = {
9
+ mode: "watch" | "start";
10
+ };
11
+ export declare function createXanixServer({ mode }: Options): express.Express;
12
+ export {};
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ export function createXanixServer({ mode }) {
3
+ const app = express();
4
+ if (mode === "watch") {
5
+ app.use("/.xanix/client", express.static(".xanix/client"));
6
+ app.use("/assets", express.static(".xanix/assets"));
7
+ app.use("/.xanix/cache", express.static(".xanix/cache"));
8
+ }
9
+ else {
10
+ app.use("/.xanix/client", express.static(".xanix/client", {
11
+ maxAge: "1y",
12
+ immutable: true,
13
+ etag: true,
14
+ }));
15
+ app.use("/assets", express.static(".xanix/assets", {
16
+ maxAge: "1y",
17
+ immutable: true,
18
+ etag: true,
19
+ }));
20
+ }
21
+ app.use((req, res, next) => {
22
+ let data = {
23
+ title: null,
24
+ meta: [],
25
+ };
26
+ if (!req.page) {
27
+ req.page = {
28
+ setTitle(title) {
29
+ data.title = title;
30
+ },
31
+ setMeta(name, content) {
32
+ data.meta.push({ name, content });
33
+ },
34
+ };
35
+ req.XanixPageData = data;
36
+ }
37
+ next();
38
+ });
39
+ return app;
40
+ }
@@ -44,6 +44,7 @@ export default async function xanix_page({ pageId, req, res, Component, props, }
44
44
  props,
45
45
  title: title ?? entry.name.replaceAll("-", " "),
46
46
  meta,
47
+ params: req.params,
47
48
  request: null,
48
49
  });
49
50
  }
@@ -54,6 +55,7 @@ export default async function xanix_page({ pageId, req, res, Component, props, }
54
55
  props,
55
56
  title: title ?? entry.name.replaceAll("-", " "),
56
57
  meta,
58
+ params: req.params,
57
59
  request: req,
58
60
  }, children: _jsx(Component, { ...props }) }));
59
61
  return `<!DOCTYPE html>${html}`;
@@ -0,0 +1,12 @@
1
+ import express from "express";
2
+ export interface XanixProps {
3
+ clientId: string;
4
+ req: any;
5
+ res: any;
6
+ component: React.ReactElement;
7
+ }
8
+ type Options = {
9
+ mode: "watch" | "start";
10
+ };
11
+ export declare function createXanixServer({ mode }: Options): express.Express;
12
+ export {};
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ export function createXanixServer({ mode }) {
3
+ const app = express();
4
+ if (mode === "watch") {
5
+ app.use("/.xanix/client", express.static(".xanix/client"));
6
+ app.use("/assets", express.static(".xanix/assets"));
7
+ app.use("/.xanix/cache", express.static(".xanix/cache"));
8
+ }
9
+ else {
10
+ app.use("/.xanix/client", express.static(".xanix/client", {
11
+ maxAge: "1y",
12
+ immutable: true,
13
+ etag: true,
14
+ }));
15
+ app.use("/assets", express.static(".xanix/assets", {
16
+ maxAge: "1y",
17
+ immutable: true,
18
+ etag: true,
19
+ }));
20
+ }
21
+ app.use((req, res, next) => {
22
+ let data = {
23
+ title: null,
24
+ meta: [],
25
+ };
26
+ if (!req.page) {
27
+ req.page = {
28
+ setTitle(title) {
29
+ data.title = title;
30
+ },
31
+ setMeta(name, content) {
32
+ data.meta.push({ name, content });
33
+ },
34
+ };
35
+ req.XanixPageData = data;
36
+ }
37
+ next();
38
+ });
39
+ return app;
40
+ }
@@ -0,0 +1,12 @@
1
+ import express from "express";
2
+ export interface XanixProps {
3
+ clientId: string;
4
+ req: any;
5
+ res: any;
6
+ component: React.ReactElement;
7
+ }
8
+ type Options = {
9
+ mode: "watch" | "start";
10
+ };
11
+ export declare function createXanixServer({ mode }: Options): express.Express;
12
+ export {};
@@ -0,0 +1,40 @@
1
+ import express from "express";
2
+ export function createXanixServer({ mode }) {
3
+ const app = express();
4
+ if (mode === "watch") {
5
+ app.use("/.xanix/client", express.static(".xanix/client"));
6
+ app.use("/assets", express.static(".xanix/assets"));
7
+ app.use("/.xanix/cache", express.static(".xanix/cache"));
8
+ }
9
+ else {
10
+ app.use("/.xanix/client", express.static(".xanix/client", {
11
+ maxAge: "1y",
12
+ immutable: true,
13
+ etag: true,
14
+ }));
15
+ app.use("/assets", express.static(".xanix/assets", {
16
+ maxAge: "1y",
17
+ immutable: true,
18
+ etag: true,
19
+ }));
20
+ }
21
+ app.use((req, res, next) => {
22
+ let data = {
23
+ title: null,
24
+ meta: [],
25
+ };
26
+ if (!req.page) {
27
+ req.page = {
28
+ setTitle(title) {
29
+ data.title = title;
30
+ },
31
+ setMeta(name, content) {
32
+ data.meta.push({ name, content });
33
+ },
34
+ };
35
+ req.XanixPageData = data;
36
+ }
37
+ next();
38
+ });
39
+ return app;
40
+ }
@@ -0,0 +1,9 @@
1
+ interface XanixPageProps {
2
+ pageId: string;
3
+ req: any;
4
+ res: any;
5
+ Component: (props: Record<string, any>) => React.ReactElement;
6
+ props: Record<string, any>;
7
+ }
8
+ export default function xanix_page({ pageId, req, res, Component, props, }: XanixPageProps): Promise<string | undefined>;
9
+ export {};
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { renderToPipeableStream } from "react-dom/server";
3
+ import readManifest from "./readManifest.js";
4
+ import { PassThrough } from "node:stream";
5
+ import path from "node:path";
6
+ import { pathToFileURL } from "node:url";
7
+ function renderPage(element) {
8
+ return new Promise((resolve, reject) => {
9
+ let html = "";
10
+ const stream = new PassThrough();
11
+ stream.on("data", (chunk) => {
12
+ html += chunk.toString();
13
+ });
14
+ stream.on("end", () => {
15
+ resolve(html);
16
+ });
17
+ stream.on("error", reject);
18
+ const { pipe } = renderToPipeableStream(element, {
19
+ onAllReady() {
20
+ pipe(stream);
21
+ },
22
+ onError(error) {
23
+ console.error("SSR error:", error);
24
+ },
25
+ });
26
+ });
27
+ }
28
+ export default async function xanix_page({ pageId, req, res, Component, props, }) {
29
+ const manifest = await readManifest();
30
+ const { title, meta } = req.XanixPageData;
31
+ const entry = manifest.entries.find((item) => item.id === pageId);
32
+ const method = req.method.toUpperCase();
33
+ if (method !== "GET") {
34
+ res.status(405).send("Method Not Allowed");
35
+ return;
36
+ }
37
+ if (!entry) {
38
+ throw new Error(`Xanix client entry "${pageId}" was not found in the manifest.`);
39
+ }
40
+ if ("x-navigation" in req.headers) {
41
+ res.setHeader("Content-Type", "application/json");
42
+ return JSON.stringify({
43
+ pageId,
44
+ props,
45
+ title: title ?? entry.name.replaceAll("-", " "),
46
+ meta,
47
+ params: req.params,
48
+ request: null,
49
+ });
50
+ }
51
+ const Document = (await import(pathToFileURL(path.join(process.cwd(), ".xanix", "xanix-document.js"))
52
+ .href)).default;
53
+ const html = await renderPage(_jsx(Document, { document: {
54
+ pageId,
55
+ props,
56
+ title: title ?? entry.name.replaceAll("-", " "),
57
+ meta,
58
+ params: req.params,
59
+ request: req,
60
+ }, children: _jsx(Component, { ...props }) }));
61
+ return `<!DOCTYPE html>${html}`;
62
+ }
@@ -1,9 +0,0 @@
1
- import { ReactNode } from "react";
2
- export declare const getGlobal: () => any;
3
- export declare const getGlobalXanix: () => Record<string, any>;
4
- export type DocumentData = {
5
- head: ReactNode;
6
- body: ReactNode;
7
- };
8
- export declare const getDocumentData: () => DocumentData;
9
- export declare const getDocumentFile: () => Promise<string>;