~repos /edge-city
git clone https://pyrossh.dev/repos/edge-city.git
edge-city is a next level meta-framework for react that runs only on edge runtimes
c121e198
—
Peter John 2 years ago
improve component
- bun.lockb +0 -0
- components/Todo.astro +0 -15
- components/Todo.jsx +9 -0
- containers/TodoList.astro +0 -10
- containers/TodoList.jsx +21 -0
- index.js +9 -40
- index.test.js +0 -11
- astroPlugin.js → jsxPlugin.js +11 -24
- package.json +1 -0
- pages/index.css +11 -0
- pages/index.jsx +27 -0
- routes/index.astro +0 -34
- routes/index.css +0 -11
- routes/index.jsx +0 -27
- routes/layout.astro +0 -0
- routes/page.jsx +0 -25
bun.lockb
CHANGED
|
Binary file
|
components/Todo.astro
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
const { id, text } = Astro.props;
|
|
3
|
-
const todos = [{ text: "123" }];
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
<div>
|
|
7
|
-
<p>
|
|
8
|
-
{item.text}
|
|
9
|
-
</p>
|
|
10
|
-
</div>
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
div {
|
|
14
|
-
font-size: 20px;
|
|
15
|
-
}
|
components/Todo.jsx
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default ({ id, text }) => {
|
|
2
|
+
return (
|
|
3
|
+
<div id={id}>
|
|
4
|
+
<p>
|
|
5
|
+
{text}
|
|
6
|
+
</p>
|
|
7
|
+
</div>
|
|
8
|
+
)
|
|
9
|
+
}
|
containers/TodoList.astro
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
const todos = [{ text: "123" }];
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
<div className="todo-list">
|
|
6
|
-
<h1>Todos</h1>
|
|
7
|
-
<ul>
|
|
8
|
-
{todos.map((item) => <li key={item.text}>{item.text}</li>)}
|
|
9
|
-
</ul>
|
|
10
|
-
</div>
|
containers/TodoList.jsx
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Todo from "@/components/Todo.jsx";
|
|
2
|
+
|
|
3
|
+
const todos = [
|
|
4
|
+
{ id: '1', text: "123" },
|
|
5
|
+
{ id: '2', text: "AEQ" }
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export default () => {
|
|
9
|
+
return (
|
|
10
|
+
<div className="todo-list">
|
|
11
|
+
<h1>Todos</h1>
|
|
12
|
+
<ul>
|
|
13
|
+
{todos.map((item) => (
|
|
14
|
+
<li key={item.text}>
|
|
15
|
+
<Todo id={item.id} text={item.text} />
|
|
16
|
+
</li>
|
|
17
|
+
))}
|
|
18
|
+
</ul>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
index.js
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './jsxPlugin.js';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { SWRConfig } from 'swr';
|
|
4
4
|
import { renderToReadableStream } from 'react-dom/server';
|
|
5
5
|
import { RouterProvider } from './router.js';
|
|
6
6
|
import packageJson from "./package.json";
|
|
7
7
|
|
|
8
|
-
const router = new Bun.FileSystemRouter({
|
|
9
|
-
style: "nextjs",
|
|
10
|
-
dir: "./routes",
|
|
11
|
-
origin: "https://mydomain.com",
|
|
12
|
-
assetPrefix: "./public"
|
|
13
|
-
});
|
|
14
|
-
|
|
15
8
|
const transpiler = new Bun.Transpiler({
|
|
16
9
|
loader: "jsx",
|
|
17
10
|
autoImportJSX: true,
|
|
@@ -29,7 +22,6 @@ const deps = Object.keys(packageJson.dependencies).reduce((acc, dep) => {
|
|
|
29
22
|
}, {})
|
|
30
23
|
|
|
31
24
|
const renderPage = async (filePath, url, params) => {
|
|
32
|
-
const file = path.basename(url.pathname).replace("astro", "js") + "index.js";
|
|
33
25
|
const query = {};
|
|
34
26
|
for (const key of url.searchParams.keys()) {
|
|
35
27
|
query[key] = url.searchParams.get(key);
|
|
@@ -39,13 +31,13 @@ const renderPage = async (filePath, url, params) => {
|
|
|
39
31
|
params: params,
|
|
40
32
|
pathname: url.pathname,
|
|
41
33
|
}
|
|
34
|
+
console.log('filePath', filePath);
|
|
42
35
|
const routeImport = await import(filePath);
|
|
43
36
|
const Page = routeImport.default;
|
|
44
37
|
const stream = await renderToReadableStream(
|
|
45
38
|
<html lang="en">
|
|
46
39
|
<head>
|
|
47
|
-
{/* {routeImport.head()} */}
|
|
48
|
-
<link rel="stylesheet" href="/
|
|
40
|
+
<link rel="stylesheet" href="/pages/index.css" />
|
|
49
41
|
<script id="initial_route_context" type='application/json' dangerouslySetInnerHTML={{
|
|
50
42
|
__html: JSON.stringify(initialRouteValue)
|
|
51
43
|
}} />
|
|
@@ -57,9 +49,9 @@ const renderPage = async (filePath, url, params) => {
|
|
|
57
49
|
"react-dom/client": "https://esm.sh/react-dom@18.2.0/client?dev",
|
|
58
50
|
"react/jsx-dev-runtime": "https://esm.sh/react@18.2.0/jsx-dev-runtime?dev",
|
|
59
51
|
"@/router.js": "/assets/js/src/router.js",
|
|
60
|
-
"@/
|
|
52
|
+
"@/pages/index.jsx": "/pages/index.js",
|
|
61
|
-
"@/components/Todo.
|
|
53
|
+
"@/components/Todo.jsx": "/components/Todo.js",
|
|
62
|
-
"@/containers/TodoList.
|
|
54
|
+
"@/containers/TodoList.jsx": "/containers/TodoList.js"
|
|
63
55
|
}
|
|
64
56
|
}
|
|
65
57
|
)
|
|
@@ -72,7 +64,7 @@ const renderPage = async (filePath, url, params) => {
|
|
|
72
64
|
import { hydrateRoot } from 'react-dom/client';
|
|
73
65
|
import { SWRConfig } from 'swr';
|
|
74
66
|
import {RouterProvider} from "@/router.js";
|
|
75
|
-
import Page from "@/
|
|
67
|
+
import Page from "@/pages/index.jsx";
|
|
76
68
|
|
|
77
69
|
const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
|
|
78
70
|
const root = hydrateRoot(document.getElementById("root"), $jsx(SWRConfig, {
|
|
@@ -103,29 +95,6 @@ const renderPage = async (filePath, url, params) => {
|
|
|
103
95
|
});
|
|
104
96
|
}
|
|
105
97
|
|
|
106
|
-
// const renderBootstrap = async (url) => {
|
|
107
|
-
// const folder = path.dirname(url.pathname);
|
|
108
|
-
// const file = path.basename(url.pathname).replace("astro", "js");
|
|
109
|
-
// const result = await transpiler.transform(`
|
|
110
|
-
// import { hydrateRoot } from 'react-dom/client';
|
|
111
|
-
// import {RouterProvider} from "@/router.js";
|
|
112
|
-
// import Page from "@/routes/${file}";
|
|
113
|
-
|
|
114
|
-
// const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
|
|
115
|
-
// const root = hydrateRoot(document.getElementById('root'), (
|
|
116
|
-
// <RouterProvider value={initialRouteValue}>
|
|
117
|
-
// <Page />
|
|
118
|
-
// </RouterProvider>
|
|
119
|
-
// ));
|
|
120
|
-
// `);
|
|
121
|
-
// return new Response(result, {
|
|
122
|
-
// headers: {
|
|
123
|
-
// 'Content-Type': 'application/javascript',
|
|
124
|
-
// },
|
|
125
|
-
// status: 200,
|
|
126
|
-
// });
|
|
127
|
-
// }
|
|
128
|
-
|
|
129
98
|
const renderJs = async (url) => {
|
|
130
99
|
const localFile = url.pathname.replace("/assets/js/", "").replace("src/", "");
|
|
131
100
|
const src = await Bun.file(localFile).text();
|
|
@@ -158,7 +127,7 @@ export default {
|
|
|
158
127
|
async fetch(req) {
|
|
159
128
|
const url = new URL(req.url);
|
|
160
129
|
console.log(req.method, url.pathname)
|
|
161
|
-
if (url.pathname.includes("/components/") || url.pathname.includes("/containers/") || url.pathname.includes("/
|
|
130
|
+
if (url.pathname.includes("/components/") || url.pathname.includes("/containers/") || url.pathname.includes("/pages/")) {
|
|
162
131
|
return sendFile(url);
|
|
163
132
|
}
|
|
164
133
|
if (url.pathname.includes("/assets/js")) {
|
|
@@ -173,7 +142,7 @@ export default {
|
|
|
173
142
|
status: 404,
|
|
174
143
|
});
|
|
175
144
|
}
|
|
176
|
-
return renderPage("./
|
|
145
|
+
return renderPage("./pages/index.jsx", url, {});
|
|
177
146
|
// const route = router.match(url.pathname);
|
|
178
147
|
// if (route) {
|
|
179
148
|
// return renderPage(route, url);
|
index.test.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
describe("arithmetic", () => {
|
|
4
|
-
test("2 + 2", () => {
|
|
5
|
-
expect(2 + 2).toBe(4);
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
test("2 * 2", () => {
|
|
9
|
-
expect(2 * 2).toBe(4);
|
|
10
|
-
});
|
|
11
|
-
});
|
astroPlugin.js → jsxPlugin.js
RENAMED
|
@@ -14,43 +14,30 @@ const transpiler = new Bun.Transpiler({
|
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
plugin({
|
|
17
|
-
name: "
|
|
17
|
+
name: "JsxPlugin",
|
|
18
18
|
async setup(build) {
|
|
19
|
-
build.onLoad({ filter: /\.
|
|
19
|
+
build.onLoad({ filter: /\.jsx$/ }, async (args) => {
|
|
20
20
|
const folder = path.dirname(args.path).replace(process.cwd(), "");
|
|
21
|
-
const filename = path.basename(args.path).replace("
|
|
21
|
+
const filename = path.basename(args.path).replace("jsx", "js");
|
|
22
|
+
const cssFile = args.path.replace("jsx", "css");
|
|
22
23
|
const outputFolder = path.join(process.cwd(), ".cache", folder);
|
|
23
24
|
const outputFile = path.join(outputFolder, filename);
|
|
24
|
-
const
|
|
25
|
+
const jsxCode = readFileSync(args.path, "utf8");
|
|
25
|
-
const [_, js, html, css] = text.split("---");
|
|
26
|
-
const imports = js.split("\n").filter((line) => line.startsWith("import")).join("\n");
|
|
27
|
-
const body = js.split("\n").filter((line) => !line.startsWith("import")).join("\n");
|
|
28
|
-
const tpl = `
|
|
29
|
-
${imports}
|
|
30
|
-
|
|
31
|
-
export default () => {
|
|
32
|
-
${body}
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
${html}
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
`;
|
|
39
|
-
// console.log('tpl', tpl);
|
|
40
|
-
const code = await transpiler.transform(
|
|
26
|
+
const code = await transpiler.transform(jsxCode);
|
|
41
27
|
// console.log('code', code);
|
|
42
28
|
if (!existsSync(outputFolder)) {
|
|
43
29
|
mkdirSync(outputFolder);
|
|
44
30
|
}
|
|
45
31
|
writeFileSync(outputFile, code);
|
|
46
|
-
if (
|
|
32
|
+
if (existsSync(cssFile)) {
|
|
33
|
+
const cssText = readFileSync(cssFile, "utf-8");
|
|
47
34
|
const result = postcss([
|
|
48
35
|
autoprefixer(),
|
|
49
36
|
postcssCustomMedia(),
|
|
50
37
|
// postcssNormalize({ browsers: 'last 2 versions' }),
|
|
51
|
-
postcssNesting
|
|
38
|
+
postcssNesting,
|
|
52
|
-
]).process(
|
|
39
|
+
]).process(cssText);
|
|
53
|
-
writeFileSync(
|
|
40
|
+
writeFileSync(outputFile.replace("js", "css"), result.css);
|
|
54
41
|
}
|
|
55
42
|
const src = await import(outputFile);
|
|
56
43
|
return {
|
package.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"bun-types": "^0.5.0"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
+
"@blueprintjs/core": "^4.17.6",
|
|
13
14
|
"autoprefixer": "^10.4.14",
|
|
14
15
|
"postcss": "^8.4.21",
|
|
15
16
|
"postcss-custom-media": "^9.1.2",
|
pages/index.css
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
.home-page {
|
|
2
|
+
padding: 10px;
|
|
3
|
+
background-color: turquoise;
|
|
4
|
+
|
|
5
|
+
& .count {
|
|
6
|
+
color: black;
|
|
7
|
+
padding: 40px;
|
|
8
|
+
font-size: 30px;
|
|
9
|
+
font-weight: 600;
|
|
10
|
+
}
|
|
11
|
+
}
|
pages/index.jsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { useRouter } from "@/router.js";
|
|
3
|
+
import TodoList from "@/containers/TodoList.jsx";
|
|
4
|
+
// import "./index.css";
|
|
5
|
+
|
|
6
|
+
export default () => {
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const [count, setCount] = useState(5);
|
|
9
|
+
// const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
|
|
10
|
+
return (
|
|
11
|
+
<div className="home-page">
|
|
12
|
+
<div>
|
|
13
|
+
<p>
|
|
14
|
+
Hello from server path 123: {router.pathname}
|
|
15
|
+
</p>
|
|
16
|
+
<TodoList />
|
|
17
|
+
<div>
|
|
18
|
+
<button onClick={() => setCount(count - 1)}>-</button>
|
|
19
|
+
<span className="count">
|
|
20
|
+
{count}
|
|
21
|
+
</span>
|
|
22
|
+
<button onClick={() => setCount(count + 1)}>+</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
)
|
|
27
|
+
}
|
routes/index.astro
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import { useRouter } from "@/router.js";
|
|
3
|
-
import TodoList from "@/containers/TodoList.astro";
|
|
4
|
-
|
|
5
|
-
const router = useRouter();
|
|
6
|
-
const [count, setCount] = useState(5);
|
|
7
|
-
|
|
8
|
-
return (
|
|
9
|
-
<div>
|
|
10
|
-
<div>
|
|
11
|
-
<p>
|
|
12
|
-
Hello from server path 123: {router.pathname}
|
|
13
|
-
</p>
|
|
14
|
-
<TodoList />
|
|
15
|
-
<div>
|
|
16
|
-
<button onClick={() => setCount(count - 1)}>-</button>
|
|
17
|
-
<span>
|
|
18
|
-
{count}
|
|
19
|
-
</span>
|
|
20
|
-
<button onClick={() => setCount(count + 1)}>+</button>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
div {
|
|
28
|
-
padding: 10px;
|
|
29
|
-
background-color: yellow;
|
|
30
|
-
|
|
31
|
-
& span {
|
|
32
|
-
color: black;
|
|
33
|
-
}
|
|
34
|
-
}
|
routes/index.css
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
div {
|
|
2
|
-
padding: 10px;
|
|
3
|
-
background - color: turquoise;
|
|
4
|
-
|
|
5
|
-
& span {
|
|
6
|
-
color: black;
|
|
7
|
-
padding: 40px;
|
|
8
|
-
font - size: 30px;
|
|
9
|
-
font - weight: 600;
|
|
10
|
-
}
|
|
11
|
-
}
|
routes/index.jsx
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import { useRouter } from "@/router.js";
|
|
3
|
-
import TodoList from "@/containers/TodoList.astro";
|
|
4
|
-
import "index.css";
|
|
5
|
-
|
|
6
|
-
const { name, title } = props;
|
|
7
|
-
const router = useRouter();
|
|
8
|
-
const [count, setCount] = useState(5);
|
|
9
|
-
// const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div className="container">
|
|
13
|
-
<div>
|
|
14
|
-
<p>
|
|
15
|
-
Hello from server path 123: {router.pathname}
|
|
16
|
-
</p>
|
|
17
|
-
<TodoList />
|
|
18
|
-
<div>
|
|
19
|
-
<button onClick={() => setCount(count - 1)}>-</button>
|
|
20
|
-
<span>
|
|
21
|
-
{count}
|
|
22
|
-
</span>
|
|
23
|
-
<button onClick={() => setCount(count + 1)}>+</button>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
routes/layout.astro
DELETED
|
File without changes
|
routes/page.jsx
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<!--js-->
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { useRouter } from "@/router.js";
|
|
4
|
-
import TodoList from "@/containers/TodoList.astro";
|
|
5
|
-
|
|
6
|
-
const router = useRouter();
|
|
7
|
-
const [count, setCount] = useState(5);
|
|
8
|
-
// const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
|
|
9
|
-
|
|
10
|
-
<!--jsx-->
|
|
11
|
-
<div>
|
|
12
|
-
<div>
|
|
13
|
-
<p>
|
|
14
|
-
Hello from server path 123: {router.pathname}
|
|
15
|
-
</p>
|
|
16
|
-
<TodoList />
|
|
17
|
-
<div>
|
|
18
|
-
<button onClick={() => setCount(count - 1)}>-</button>
|
|
19
|
-
<span>
|
|
20
|
-
{count}
|
|
21
|
-
</span>
|
|
22
|
-
<button onClick={() => setCount(count + 1)}>+</button>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|