create-waku 0.5.0 → 0.5.2

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 (109) hide show
  1. package/dist/cli.js +7744 -0
  2. package/package.json +2 -1
  3. package/src/cli.ts +3 -3
  4. package/template/01_counter/node_modules/.bin/tsc +17 -0
  5. package/template/01_counter/node_modules/.bin/tsserver +17 -0
  6. package/template/01_counter/node_modules/.bin/waku +17 -0
  7. package/template/01_counter/package.json +23 -0
  8. package/template/01_counter/src/components/App.tsx +13 -0
  9. package/template/01_counter/src/components/Counter.tsx +14 -0
  10. package/template/01_counter/src/entries.tsx +34 -0
  11. package/template/01_counter/src/index.html +36 -0
  12. package/template/01_counter/src/main.tsx +13 -0
  13. package/template/01_counter/tsconfig.json +13 -0
  14. package/template/02_async/node_modules/.bin/tsc +17 -0
  15. package/template/02_async/node_modules/.bin/tsserver +17 -0
  16. package/template/02_async/node_modules/.bin/waku +17 -0
  17. package/template/02_async/package.json +23 -0
  18. package/template/02_async/src/components/App.tsx +35 -0
  19. package/template/02_async/src/components/Counter.tsx +14 -0
  20. package/template/02_async/src/entries.tsx +34 -0
  21. package/template/02_async/src/index.html +36 -0
  22. package/template/02_async/src/main.tsx +24 -0
  23. package/template/02_async/tsconfig.json +13 -0
  24. package/template/02_async/vite.config.ts +16 -0
  25. package/template/03_promise/node_modules/.bin/tsc +17 -0
  26. package/template/03_promise/node_modules/.bin/tsserver +17 -0
  27. package/template/03_promise/node_modules/.bin/waku +17 -0
  28. package/template/03_promise/package.json +23 -0
  29. package/template/03_promise/src/components/App.tsx +18 -0
  30. package/template/03_promise/src/components/Counter.tsx +34 -0
  31. package/template/03_promise/src/entries.tsx +39 -0
  32. package/template/03_promise/src/index.html +36 -0
  33. package/template/03_promise/src/main.tsx +15 -0
  34. package/template/03_promise/tsconfig.json +13 -0
  35. package/template/04_callserver/node_modules/.bin/tsc +17 -0
  36. package/template/04_callserver/node_modules/.bin/tsserver +17 -0
  37. package/template/04_callserver/node_modules/.bin/waku +17 -0
  38. package/template/04_callserver/package.json +23 -0
  39. package/template/04_callserver/src/components/App.tsx +18 -0
  40. package/template/04_callserver/src/components/Counter.tsx +31 -0
  41. package/template/04_callserver/src/components/funcs.ts +3 -0
  42. package/template/04_callserver/src/entries.tsx +34 -0
  43. package/template/04_callserver/src/index.html +36 -0
  44. package/template/04_callserver/src/main.tsx +13 -0
  45. package/template/04_callserver/tsconfig.json +13 -0
  46. package/template/05_mutation/node_modules/.bin/tsc +17 -0
  47. package/template/05_mutation/node_modules/.bin/tsserver +17 -0
  48. package/template/05_mutation/node_modules/.bin/waku +17 -0
  49. package/template/05_mutation/package.json +23 -0
  50. package/template/05_mutation/src/components/App.tsx +21 -0
  51. package/template/05_mutation/src/components/Counter.tsx +24 -0
  52. package/template/05_mutation/src/components/funcs.ts +13 -0
  53. package/template/05_mutation/src/entries.tsx +34 -0
  54. package/template/05_mutation/src/index.html +36 -0
  55. package/template/05_mutation/src/main.tsx +13 -0
  56. package/template/05_mutation/tsconfig.json +13 -0
  57. package/template/06_nesting/node_modules/.bin/tsc +17 -0
  58. package/template/06_nesting/node_modules/.bin/tsserver +17 -0
  59. package/template/06_nesting/node_modules/.bin/waku +17 -0
  60. package/template/06_nesting/package.json +23 -0
  61. package/template/06_nesting/src/components/App.tsx +13 -0
  62. package/template/06_nesting/src/components/Counter.tsx +32 -0
  63. package/template/06_nesting/src/components/InnerApp.tsx +13 -0
  64. package/template/06_nesting/src/entries.tsx +49 -0
  65. package/template/06_nesting/src/index.html +36 -0
  66. package/template/06_nesting/src/main.tsx +13 -0
  67. package/template/06_nesting/tsconfig.json +13 -0
  68. package/template/07_router/node_modules/.bin/glob +17 -0
  69. package/template/07_router/node_modules/.bin/tsc +17 -0
  70. package/template/07_router/node_modules/.bin/tsserver +17 -0
  71. package/template/07_router/node_modules/.bin/waku +17 -0
  72. package/template/07_router/package.json +24 -0
  73. package/template/07_router/src/components/Counter.tsx +17 -0
  74. package/template/07_router/src/components/ErrorBoundary.tsx +28 -0
  75. package/template/07_router/src/entries.tsx +38 -0
  76. package/template/07_router/src/index.html +36 -0
  77. package/template/07_router/src/main.tsx +15 -0
  78. package/template/07_router/src/routes/bar/page.tsx +10 -0
  79. package/template/07_router/src/routes/foo/page.tsx +10 -0
  80. package/template/07_router/src/routes/layout.tsx +54 -0
  81. package/template/07_router/src/routes/nested/baz/page.tsx +7 -0
  82. package/template/07_router/src/routes/nested/layout.tsx +13 -0
  83. package/template/07_router/src/routes/nested/qux/page.tsx +7 -0
  84. package/template/07_router/src/routes/page.tsx +8 -0
  85. package/template/07_router/tsconfig.json +13 -0
  86. package/template/07_router/vite.config.ts +22 -0
  87. package/template/08_cookies/dev.js +29 -0
  88. package/template/08_cookies/node_modules/.bin/tsc +17 -0
  89. package/template/08_cookies/node_modules/.bin/tsserver +17 -0
  90. package/template/08_cookies/node_modules/.bin/waku +17 -0
  91. package/template/08_cookies/package.json +24 -0
  92. package/template/08_cookies/src/components/App.tsx +16 -0
  93. package/template/08_cookies/src/components/Counter.tsx +14 -0
  94. package/template/08_cookies/src/entries.tsx +38 -0
  95. package/template/08_cookies/src/index.html +36 -0
  96. package/template/08_cookies/src/main.tsx +13 -0
  97. package/template/08_cookies/start.js +36 -0
  98. package/template/08_cookies/tsconfig.json +13 -0
  99. package/template/09_cssmodules/node_modules/.bin/tsc +17 -0
  100. package/template/09_cssmodules/node_modules/.bin/tsserver +17 -0
  101. package/template/09_cssmodules/node_modules/.bin/waku +17 -0
  102. package/template/09_cssmodules/package.json +23 -0
  103. package/template/09_cssmodules/src/components/App.module.css +3 -0
  104. package/template/09_cssmodules/src/components/App.tsx +15 -0
  105. package/template/09_cssmodules/src/components/Counter.tsx +14 -0
  106. package/template/09_cssmodules/src/entries.tsx +34 -0
  107. package/template/09_cssmodules/src/index.html +36 -0
  108. package/template/09_cssmodules/src/main.tsx +13 -0
  109. package/template/09_cssmodules/tsconfig.json +13 -0
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "waku-example",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "waku dev --with-ssr",
8
+ "build": "waku build",
9
+ "start": "waku start --with-ssr"
10
+ },
11
+ "dependencies": {
12
+ "express": "^4.18.2",
13
+ "react": "18.3.0-canary-7118f5dd7-20230705",
14
+ "react-dom": "18.3.0-canary-7118f5dd7-20230705",
15
+ "react-server-dom-webpack": "18.3.0-canary-7118f5dd7-20230705",
16
+ "waku": "0.15.0"
17
+ },
18
+ "devDependencies": {
19
+ "@types/react": "^18.2.21",
20
+ "@types/react-dom": "^18.2.7",
21
+ "typescript": "^5.2.2"
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ import { Counter } from "./Counter.js";
2
+
3
+ const App = ({ name }: { name: string }) => {
4
+ return (
5
+ <div style={{ border: "3px red dashed", margin: "1em", padding: "1em" }}>
6
+ <h1>Hello {name}!!</h1>
7
+ <h3>This is a server component.</h3>
8
+ <Counter enableInnerApp />
9
+ </div>
10
+ );
11
+ };
12
+
13
+ export default App;
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import { useState, useTransition } from "react";
4
+ import { Slot, useRefetch } from "waku/client";
5
+
6
+ export const Counter = ({ enableInnerApp = false }) => {
7
+ const [count, setCount] = useState(0);
8
+ const [isPending, startTransition] = useTransition();
9
+ const refetch = useRefetch();
10
+ const handleClick = () => {
11
+ if (enableInnerApp) {
12
+ startTransition(() => {
13
+ const nextCount = count + 1;
14
+ setCount(nextCount);
15
+ if (enableInnerApp) {
16
+ refetch("InnerApp=" + nextCount);
17
+ }
18
+ });
19
+ } else {
20
+ setCount((c) => c + 1);
21
+ }
22
+ };
23
+ return (
24
+ <div style={{ border: "3px blue dashed", margin: "1em", padding: "1em" }}>
25
+ <p>Count: {count}</p>
26
+ <button onClick={handleClick}>Increment</button>{" "}
27
+ {isPending && "Pending..."}
28
+ <h3>This is a client component.</h3>
29
+ {enableInnerApp && <Slot id="InnerApp" />}
30
+ </div>
31
+ );
32
+ };
@@ -0,0 +1,13 @@
1
+ import { Counter } from "./Counter.js";
2
+
3
+ const InnerApp = ({ count = -1 }) => {
4
+ return (
5
+ <div style={{ border: "3px red dashed", margin: "1em", padding: "1em" }}>
6
+ <h3>This is another server component.</h3>
7
+ <p>The outer count is {count}.</p>
8
+ <Counter />
9
+ </div>
10
+ );
11
+ };
12
+
13
+ export default InnerApp;
@@ -0,0 +1,49 @@
1
+ import { lazy } from "react";
2
+ import type { ReactNode } from "react";
3
+
4
+ import { defineEntries } from "waku/server";
5
+
6
+ const App = lazy(() => import("./components/App.js"));
7
+ const InnerApp = lazy(() => import("./components/InnerApp.js"));
8
+
9
+ export default defineEntries(
10
+ // renderEntries
11
+ async (input) => {
12
+ const params = new URLSearchParams(input || "App=Waku&InnerApp=0");
13
+ const result: Record<string, ReactNode> = {};
14
+ if (params.has("App")) {
15
+ result.App = <App name={params.get("App")!} />;
16
+ }
17
+ if (params.has("InnerApp")) {
18
+ result.InnerApp = <InnerApp count={Number(params.get("InnerApp"))} />;
19
+ }
20
+ return result;
21
+ },
22
+ // getBuildConfig
23
+ async () => {
24
+ return {
25
+ "/": {
26
+ entries: [
27
+ [""],
28
+ ["InnerApp=1", true],
29
+ ["InnerApp=2", true],
30
+ ["InnerApp=3", true],
31
+ ["InnerApp=4", true],
32
+ ["InnerApp=5", true],
33
+ ],
34
+ },
35
+ };
36
+ },
37
+ // getSsrConfig
38
+ async () => ({
39
+ getInput: (pathStr) => {
40
+ switch (pathStr) {
41
+ case "/":
42
+ return "App=Waku";
43
+ default:
44
+ return null;
45
+ }
46
+ },
47
+ filter: (elements) => elements.App,
48
+ }),
49
+ );
@@ -0,0 +1,36 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Waku example</title>
6
+ <style>
7
+ @keyframes spinner {
8
+ to {
9
+ transform: rotate(360deg);
10
+ }
11
+ }
12
+ .spinner {
13
+ width: 36px;
14
+ height: 36px;
15
+ margin: auto;
16
+ border: 2px solid #ddd;
17
+ border-top-color: #222;
18
+ border-radius: 50%;
19
+ animation: spinner 1s linear infinite;
20
+ }
21
+ #root > .spinner {
22
+ margin-top: calc(50% - 18px);
23
+ }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <!--placeholder1-->
28
+ <div id="root">
29
+ <div class="spinner"></div>
30
+ </div>
31
+ <!--/placeholder1-->
32
+ <script src="/main.tsx" async type="module"></script>
33
+ <!--placeholder2-->
34
+ <!--/placeholder2-->
35
+ </body>
36
+ </html>
@@ -0,0 +1,13 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { Root, Slot } from "waku/client";
4
+
5
+ const rootElement = (
6
+ <StrictMode>
7
+ <Root>
8
+ <Slot id="App" />
9
+ </Root>
10
+ </StrictMode>
11
+ );
12
+
13
+ createRoot(document.getElementById("root")!).render(rootElement);
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "target": "esnext",
5
+ "downlevelIteration": true,
6
+ "esModuleInterop": true,
7
+ "module": "nodenext",
8
+ "skipLibCheck": true,
9
+ "noUncheckedIndexedAccess": true,
10
+ "exactOptionalPropertyTypes": true,
11
+ "jsx": "react-jsx"
12
+ }
13
+ }
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/src/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/src/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules/glob/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/glob@10.3.4/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/src/bin.js" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/glob@10.3.4/node_modules/glob/dist/cjs/src/bin.js" "$@"
17
+ fi
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsc" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsc" "$@"
17
+ fi
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsserver" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsserver" "$@"
17
+ fi
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/waku/waku/packages/waku/dist/node_modules:/home/runner/work/waku/waku/packages/waku/node_modules:/home/runner/work/waku/waku/packages/node_modules:/home/runner/work/waku/waku/node_modules:/home/runner/work/waku/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/waku/waku/packages/waku/dist/node_modules:/home/runner/work/waku/waku/packages/waku/node_modules:/home/runner/work/waku/waku/packages/node_modules:/home/runner/work/waku/waku/node_modules:/home/runner/work/waku/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../packages/waku/dist/cli.js" "$@"
15
+ else
16
+ exec node "$basedir/../../../../packages/waku/dist/cli.js" "$@"
17
+ fi
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "waku-example",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "waku dev --with-ssr",
8
+ "build": "waku build",
9
+ "start": "waku start --with-ssr"
10
+ },
11
+ "dependencies": {
12
+ "express": "^4.18.2",
13
+ "glob": "^10.3.4",
14
+ "react": "18.3.0-canary-7118f5dd7-20230705",
15
+ "react-dom": "18.3.0-canary-7118f5dd7-20230705",
16
+ "react-server-dom-webpack": "18.3.0-canary-7118f5dd7-20230705",
17
+ "waku": "0.15.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/react": "^18.2.21",
21
+ "@types/react-dom": "^18.2.7",
22
+ "typescript": "^5.2.2"
23
+ }
24
+ }
@@ -0,0 +1,17 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+
5
+ import { Link } from "waku/router/client";
6
+
7
+ export const Counter = () => {
8
+ const [count, setCount] = useState(0);
9
+ return (
10
+ <div style={{ border: "3px blue dashed", margin: "1em", padding: "1em" }}>
11
+ <p>Count: {count}</p>
12
+ <button onClick={() => setCount((c) => c + 1)}>Increment</button>
13
+ <h3>This is a client component.</h3>
14
+ <Link href="/">Go to Home</Link>
15
+ </div>
16
+ );
17
+ };
@@ -0,0 +1,28 @@
1
+ import { Component } from "react";
2
+ import type { ReactNode, FunctionComponent } from "react";
3
+
4
+ interface Props {
5
+ fallback: (error: unknown) => ReactNode;
6
+ children: ReactNode;
7
+ }
8
+
9
+ class ErrorBoundaryClass extends Component<Props, { error?: unknown }> {
10
+ constructor(props: Props) {
11
+ super(props);
12
+ this.state = {};
13
+ }
14
+
15
+ static getDerivedStateFromError(error: unknown) {
16
+ return { error };
17
+ }
18
+
19
+ render() {
20
+ if ("error" in this.state) {
21
+ return this.props.fallback(this.state.error);
22
+ }
23
+ return this.props.children;
24
+ }
25
+ }
26
+
27
+ export const ErrorBoundary =
28
+ ErrorBoundaryClass as unknown as FunctionComponent<Props>;
@@ -0,0 +1,38 @@
1
+ import url from "node:url";
2
+ import path from "node:path";
3
+
4
+ import { glob } from "glob";
5
+ import { defineRouter } from "waku/router/server";
6
+
7
+ const routesDir = path.join(
8
+ path.dirname(url.fileURLToPath(import.meta.url)),
9
+ "routes",
10
+ );
11
+
12
+ export default defineRouter(
13
+ // getComponent (id is "**/layout" or "**/page")
14
+ async (id) => {
15
+ const files = await glob(`${id}.{tsx,js}`, { cwd: routesDir });
16
+ if (files.length === 0) {
17
+ return null;
18
+ }
19
+ const items = id.split("/");
20
+ switch (items.length) {
21
+ case 1:
22
+ return import(`./routes/${items[0]}.tsx`);
23
+ case 2:
24
+ return import(`./routes/${items[0]}/${items[1]}.tsx`);
25
+ case 3:
26
+ return import(`./routes/${items[0]}/${items[1]}/${items[2]}.tsx`);
27
+ default:
28
+ throw new Error("too deep route");
29
+ }
30
+ },
31
+ // getAllPaths
32
+ async () => {
33
+ const files = await glob("**/page.{tsx,js}", { cwd: routesDir });
34
+ return files.map(
35
+ (file) => "/" + file.slice(0, Math.max(0, file.lastIndexOf("/"))),
36
+ );
37
+ },
38
+ );
@@ -0,0 +1,36 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Waku example</title>
6
+ <style>
7
+ @keyframes spinner {
8
+ to {
9
+ transform: rotate(360deg);
10
+ }
11
+ }
12
+ .spinner {
13
+ width: 36px;
14
+ height: 36px;
15
+ margin: auto;
16
+ border: 2px solid #ddd;
17
+ border-top-color: #222;
18
+ border-radius: 50%;
19
+ animation: spinner 1s linear infinite;
20
+ }
21
+ #root > .spinner {
22
+ margin-top: calc(50% - 18px);
23
+ }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <!--placeholder1-->
28
+ <div id="root">
29
+ <div class="spinner"></div>
30
+ </div>
31
+ <!--/placeholder1-->
32
+ <script src="/main.tsx" async type="module"></script>
33
+ <!--placeholder2-->
34
+ <!--/placeholder2-->
35
+ </body>
36
+ </html>
@@ -0,0 +1,15 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { Router } from "waku/router/client";
4
+
5
+ import { ErrorBoundary } from "./components/ErrorBoundary.js";
6
+
7
+ const rootElement = (
8
+ <StrictMode>
9
+ <ErrorBoundary fallback={(error) => <h1>{String(error)}</h1>}>
10
+ <Router shouldSkip={() => true} />
11
+ </ErrorBoundary>
12
+ </StrictMode>
13
+ );
14
+
15
+ createRoot(document.getElementById("root")!).render(rootElement);
@@ -0,0 +1,10 @@
1
+ import { Counter } from "../../components/Counter.js";
2
+
3
+ const Bar = () => (
4
+ <div>
5
+ <h2>Bar</h2>
6
+ <Counter />
7
+ </div>
8
+ );
9
+
10
+ export default Bar;
@@ -0,0 +1,10 @@
1
+ import { Counter } from "../../components/Counter.js";
2
+
3
+ const Foo = () => (
4
+ <div>
5
+ <h2>Foo</h2>
6
+ <Counter />
7
+ </div>
8
+ );
9
+
10
+ export default Foo;
@@ -0,0 +1,54 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { Link } from "waku/router/server";
4
+
5
+ const Pending = ({ isPending }: { isPending: boolean }) => (
6
+ <span
7
+ style={{
8
+ marginLeft: 5,
9
+ transition: "opacity 75ms 100ms",
10
+ opacity: isPending ? 1 : 0,
11
+ }}
12
+ >
13
+ Pending...
14
+ </span>
15
+ );
16
+
17
+ const HomeLayout = ({ children }: { children: ReactNode }) => (
18
+ <div>
19
+ <ul>
20
+ <li>
21
+ <Link
22
+ href="/"
23
+ pending={<Pending isPending />}
24
+ notPending={<Pending isPending={false} />}
25
+ >
26
+ Home
27
+ </Link>
28
+ </li>
29
+ <li>
30
+ <Link
31
+ href="/foo"
32
+ pending={<Pending isPending />}
33
+ notPending={<Pending isPending={false} />}
34
+ >
35
+ Foo
36
+ </Link>
37
+ </li>
38
+ <li>
39
+ <Link href="/bar" unstable_prefetchOnEnter>
40
+ Bar
41
+ </Link>
42
+ </li>
43
+ <li>
44
+ <Link href="/nested/baz">Nested / Baz</Link>
45
+ </li>
46
+ <li>
47
+ <Link href="/nested/qux">Nested / Qux</Link>
48
+ </li>
49
+ </ul>
50
+ {children}
51
+ </div>
52
+ );
53
+
54
+ export default HomeLayout;
@@ -0,0 +1,7 @@
1
+ const Baz = () => (
2
+ <div>
3
+ <h3>Baz</h3>
4
+ </div>
5
+ );
6
+
7
+ export default Baz;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { Counter } from "../../components/Counter.js";
4
+
5
+ const Nested = ({ children }: { children: ReactNode }) => (
6
+ <div>
7
+ <h2>Nested</h2>
8
+ <Counter />
9
+ {children}
10
+ </div>
11
+ );
12
+
13
+ export default Nested;
@@ -0,0 +1,7 @@
1
+ const Qux = () => (
2
+ <div>
3
+ <h3>Qux</h3>
4
+ </div>
5
+ );
6
+
7
+ export default Qux;
@@ -0,0 +1,8 @@
1
+ const Home = () => (
2
+ <div>
3
+ <h2>Home</h2>
4
+ <p>This is the home page.</p>
5
+ </div>
6
+ );
7
+
8
+ export default Home;
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "target": "esnext",
5
+ "downlevelIteration": true,
6
+ "esModuleInterop": true,
7
+ "module": "nodenext",
8
+ "skipLibCheck": true,
9
+ "noUncheckedIndexedAccess": true,
10
+ "exactOptionalPropertyTypes": true,
11
+ "jsx": "react-jsx"
12
+ }
13
+ }
@@ -0,0 +1,22 @@
1
+ import url from "node:url";
2
+ import path from "node:path";
3
+
4
+ import { defineConfig } from "waku/config";
5
+
6
+ const modulesRoot = path.join(
7
+ path.dirname(url.fileURLToPath(import.meta.url)),
8
+ "src",
9
+ );
10
+
11
+ export default defineConfig({
12
+ build: {
13
+ rollupOptions: {
14
+ output: {
15
+ // FIXME this doesn't seem to provide nice output.
16
+ // TODO we should use `input` instead.
17
+ preserveModules: true,
18
+ preserveModulesRoot: modulesRoot,
19
+ },
20
+ },
21
+ },
22
+ });
@@ -0,0 +1,29 @@
1
+ import express from "express";
2
+ import cookieParser from "cookie-parser";
3
+ import {
4
+ rsc,
5
+ //ssr,
6
+ devServer,
7
+ } from "waku";
8
+
9
+ const app = express();
10
+ app.use(cookieParser());
11
+ app.use(
12
+ rsc({
13
+ command: "dev",
14
+ unstable_prehook: (req) => {
15
+ return { count: Number(req.cookies.count) || 0 };
16
+ },
17
+ unstable_posthook: (req, res, ctx) => {
18
+ res.cookie("count", String(ctx.count));
19
+ },
20
+ }),
21
+ );
22
+ // Passing cookies through SSR server isn't supported (yet).
23
+ // app.use(ssr({ command: "dev" }));
24
+ app.use(devServer());
25
+
26
+ const port = process.env.PORT || 3000;
27
+ app.listen(port, () => {
28
+ console.info("Listening on", port);
29
+ });
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -z "$NODE_PATH" ]; then
9
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules"
10
+ else
11
+ export NODE_PATH="/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/typescript@5.2.2/node_modules:/home/runner/work/waku/waku/node_modules/.pnpm/node_modules:$NODE_PATH"
12
+ fi
13
+ if [ -x "$basedir/node" ]; then
14
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsc" "$@"
15
+ else
16
+ exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.2.2/node_modules/typescript/bin/tsc" "$@"
17
+ fi