edge-city
git clone https://git.pyrossh.dev/edge-city
edge-city is a next level meta-framework for react that runs only on edge runtimes
72a995b
— Peter John
2023-03-08T23:03:13+05:30
initial commit
- .gitignore +170 -0
- README.md +15 -0
- astroPlugin.js +40 -0
- bun.lockb +0 -0
- index.css +3 -0
- index.js +131 -0
- index.test.js +11 -0
- jsconfig.json +25 -0
- package-lock.json +111 -0
- package.json +17 -0
- public/favicon.ico +0 -0
- public/index.html +44 -0
- public/logo192.png +0 -0
- public/logo512.png +0 -0
- public/manifest.json +25 -0
- public/robots.txt +3 -0
- router.js +26 -0
- routes/about/index.jsx +12 -0
- routes/api/todos/index.js +5 -0
- routes/index.astro +33 -0
- utils.js +21 -0
.gitignore
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
|
2
|
+
|
|
3
|
+
# Logs
|
|
4
|
+
|
|
5
|
+
logs
|
|
6
|
+
_.log
|
|
7
|
+
npm-debug.log_
|
|
8
|
+
yarn-debug.log*
|
|
9
|
+
yarn-error.log*
|
|
10
|
+
lerna-debug.log*
|
|
11
|
+
.pnpm-debug.log*
|
|
12
|
+
|
|
13
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
14
|
+
|
|
15
|
+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
|
16
|
+
|
|
17
|
+
# Runtime data
|
|
18
|
+
|
|
19
|
+
pids
|
|
20
|
+
_.pid
|
|
21
|
+
_.seed
|
|
22
|
+
\*.pid.lock
|
|
23
|
+
|
|
24
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
25
|
+
|
|
26
|
+
lib-cov
|
|
27
|
+
|
|
28
|
+
# Coverage directory used by tools like istanbul
|
|
29
|
+
|
|
30
|
+
coverage
|
|
31
|
+
\*.lcov
|
|
32
|
+
|
|
33
|
+
# nyc test coverage
|
|
34
|
+
|
|
35
|
+
.nyc_output
|
|
36
|
+
|
|
37
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
38
|
+
|
|
39
|
+
.grunt
|
|
40
|
+
|
|
41
|
+
# Bower dependency directory (https://bower.io/)
|
|
42
|
+
|
|
43
|
+
bower_components
|
|
44
|
+
|
|
45
|
+
# node-waf configuration
|
|
46
|
+
|
|
47
|
+
.lock-wscript
|
|
48
|
+
|
|
49
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
50
|
+
|
|
51
|
+
build/Release
|
|
52
|
+
|
|
53
|
+
# Dependency directories
|
|
54
|
+
|
|
55
|
+
node_modules/
|
|
56
|
+
jspm_packages/
|
|
57
|
+
|
|
58
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
59
|
+
|
|
60
|
+
web_modules/
|
|
61
|
+
|
|
62
|
+
# TypeScript cache
|
|
63
|
+
|
|
64
|
+
\*.tsbuildinfo
|
|
65
|
+
|
|
66
|
+
# Optional npm cache directory
|
|
67
|
+
|
|
68
|
+
.npm
|
|
69
|
+
|
|
70
|
+
# Optional eslint cache
|
|
71
|
+
|
|
72
|
+
.eslintcache
|
|
73
|
+
|
|
74
|
+
# Optional stylelint cache
|
|
75
|
+
|
|
76
|
+
.stylelintcache
|
|
77
|
+
|
|
78
|
+
# Microbundle cache
|
|
79
|
+
|
|
80
|
+
.rpt2_cache/
|
|
81
|
+
.rts2_cache_cjs/
|
|
82
|
+
.rts2_cache_es/
|
|
83
|
+
.rts2_cache_umd/
|
|
84
|
+
|
|
85
|
+
# Optional REPL history
|
|
86
|
+
|
|
87
|
+
.node_repl_history
|
|
88
|
+
|
|
89
|
+
# Output of 'npm pack'
|
|
90
|
+
|
|
91
|
+
\*.tgz
|
|
92
|
+
|
|
93
|
+
# Yarn Integrity file
|
|
94
|
+
|
|
95
|
+
.yarn-integrity
|
|
96
|
+
|
|
97
|
+
# dotenv environment variable files
|
|
98
|
+
|
|
99
|
+
.env
|
|
100
|
+
.env.development.local
|
|
101
|
+
.env.test.local
|
|
102
|
+
.env.production.local
|
|
103
|
+
.env.local
|
|
104
|
+
|
|
105
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
106
|
+
|
|
107
|
+
.cache
|
|
108
|
+
.parcel-cache
|
|
109
|
+
|
|
110
|
+
# Next.js build output
|
|
111
|
+
|
|
112
|
+
.next
|
|
113
|
+
out
|
|
114
|
+
|
|
115
|
+
# Nuxt.js build / generate output
|
|
116
|
+
|
|
117
|
+
.nuxt
|
|
118
|
+
dist
|
|
119
|
+
|
|
120
|
+
# Gatsby files
|
|
121
|
+
|
|
122
|
+
.cache/
|
|
123
|
+
|
|
124
|
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
125
|
+
|
|
126
|
+
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
127
|
+
|
|
128
|
+
# public
|
|
129
|
+
|
|
130
|
+
# vuepress build output
|
|
131
|
+
|
|
132
|
+
.vuepress/dist
|
|
133
|
+
|
|
134
|
+
# vuepress v2.x temp and cache directory
|
|
135
|
+
|
|
136
|
+
.temp
|
|
137
|
+
.cache
|
|
138
|
+
|
|
139
|
+
# Docusaurus cache and generated files
|
|
140
|
+
|
|
141
|
+
.docusaurus
|
|
142
|
+
|
|
143
|
+
# Serverless directories
|
|
144
|
+
|
|
145
|
+
.serverless/
|
|
146
|
+
|
|
147
|
+
# FuseBox cache
|
|
148
|
+
|
|
149
|
+
.fusebox/
|
|
150
|
+
|
|
151
|
+
# DynamoDB Local files
|
|
152
|
+
|
|
153
|
+
.dynamodb/
|
|
154
|
+
|
|
155
|
+
# TernJS port file
|
|
156
|
+
|
|
157
|
+
.tern-port
|
|
158
|
+
|
|
159
|
+
# Stores VSCode versions used for testing VSCode extensions
|
|
160
|
+
|
|
161
|
+
.vscode-test
|
|
162
|
+
|
|
163
|
+
# yarn v2
|
|
164
|
+
|
|
165
|
+
.yarn/cache
|
|
166
|
+
.yarn/unplugged
|
|
167
|
+
.yarn/build-state.yml
|
|
168
|
+
.yarn/install-state.gz
|
|
169
|
+
.pnp.\*
|
|
170
|
+
dist
|
README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# quickstart
|
|
2
|
+
|
|
3
|
+
To install dependencies:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun run index.js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This project was created using `bun init` in bun v0.5.7. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
astroPlugin.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { plugin } from "bun";
|
|
2
|
+
|
|
3
|
+
const transpiler = new Bun.Transpiler({
|
|
4
|
+
loader: "jsx",
|
|
5
|
+
autoImportJSX: true,
|
|
6
|
+
jsxOptimizationInline: true,
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
plugin({
|
|
10
|
+
name: "Astro",
|
|
11
|
+
async setup(build) {
|
|
12
|
+
const { readFileSync, writeFileSync } = await import("fs");
|
|
13
|
+
build.onLoad({ filter: /\.astro$/ }, async (args) => {
|
|
14
|
+
const text = readFileSync(args.path, "utf8");
|
|
15
|
+
const [_, js, html] = text.split("---");
|
|
16
|
+
const imports = js.split("\n").filter((line) => line.startsWith("import")).join("\n");
|
|
17
|
+
const body = js.split("\n").filter((line) => !line.startsWith("import")).join("\n");
|
|
18
|
+
const code = await transpiler.transform(`
|
|
19
|
+
${imports}
|
|
20
|
+
|
|
21
|
+
export default () => {
|
|
22
|
+
${body}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
${html}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
// console.log('code', code);
|
|
30
|
+
writeFileSync("./dist/index.js", code)
|
|
31
|
+
const src = await import("./dist/index.js");
|
|
32
|
+
return {
|
|
33
|
+
exports: {
|
|
34
|
+
default: src.default,
|
|
35
|
+
},
|
|
36
|
+
loader: "object",
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
});
|
bun.lockb
ADDED
|
Binary file
|
index.css
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
.ccs {
|
|
2
|
+
display: flex;
|
|
3
|
+
}
|
index.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import './astroPlugin.js';
|
|
2
|
+
import { renderToString, renderToReadableStream } from 'react-dom/server';
|
|
3
|
+
import { RouterProvider } from './router.js';
|
|
4
|
+
|
|
5
|
+
const router = new Bun.FileSystemRouter({
|
|
6
|
+
style: "nextjs",
|
|
7
|
+
dir: "./routes",
|
|
8
|
+
origin: "https://mydomain.com",
|
|
9
|
+
assetPrefix: "./public"
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const transpiler = new Bun.Transpiler({
|
|
13
|
+
loader: "jsx",
|
|
14
|
+
autoImportJSX: true,
|
|
15
|
+
jsxOptimizationInline: true,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const renderApi = async (route, req) => {
|
|
19
|
+
const routeImport = await import(route.filePath);
|
|
20
|
+
console.log('routeImport', routeImport);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const renderPage = async (filePath, url, params) => {
|
|
24
|
+
const query = {};
|
|
25
|
+
for (const key of url.searchParams.keys()) {
|
|
26
|
+
query[key] = url.searchParams.get(key);
|
|
27
|
+
}
|
|
28
|
+
const initialRouteValue = {
|
|
29
|
+
query: query,
|
|
30
|
+
params: params,
|
|
31
|
+
pathname: url.pathname,
|
|
32
|
+
}
|
|
33
|
+
const routeImport = await import(filePath);
|
|
34
|
+
const Page = routeImport.default;
|
|
35
|
+
const stream = await renderToReadableStream(
|
|
36
|
+
<html lang="en">
|
|
37
|
+
<head>
|
|
38
|
+
{/* {routeImport.head()} */}
|
|
39
|
+
<script id="initial_route_context" type='application/json' dangerouslySetInnerHTML={{
|
|
40
|
+
__html: JSON.stringify(initialRouteValue)
|
|
41
|
+
}} />
|
|
42
|
+
<script type="importmap" dangerouslySetInnerHTML={{
|
|
43
|
+
__html: JSON.stringify(
|
|
44
|
+
{
|
|
45
|
+
"imports": {
|
|
46
|
+
"react": "https://esm.sh/[email protected]?dev",
|
|
47
|
+
"react-dom": "https://esm.sh/[email protected]?dev",
|
|
48
|
+
"react-dom/client": "https://esm.sh/[email protected]/client?dev",
|
|
49
|
+
"react/jsx-dev-runtime": "https://esm.sh/[email protected]/jsx-dev-runtime?dev",
|
|
50
|
+
"@/utils": "/assets/js/src/utils.js",
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
}}>
|
|
55
|
+
</script>
|
|
56
|
+
{/* <script id="initial_swr_fallback" dangerouslySetInnerHTML={{ __html: JSON.stringify(value) }} /> */}
|
|
57
|
+
<script type="module" src="/assets/js/routes/index.astro" defer></script>
|
|
58
|
+
</head>
|
|
59
|
+
<body>
|
|
60
|
+
<div id="root">
|
|
61
|
+
<RouterProvider value={initialRouteValue}>
|
|
62
|
+
<Page />
|
|
63
|
+
</RouterProvider>
|
|
64
|
+
</div>
|
|
65
|
+
</body>
|
|
66
|
+
</html >
|
|
67
|
+
);
|
|
68
|
+
return new Response(stream, {
|
|
69
|
+
headers: {
|
|
70
|
+
'Content-Type': 'text/html',
|
|
71
|
+
},
|
|
72
|
+
status: 200,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default {
|
|
77
|
+
port: 3000,
|
|
78
|
+
async fetch(req) {
|
|
79
|
+
const url = new URL(req.url);
|
|
80
|
+
if (url.pathname.startsWith("/dist/js")) {
|
|
81
|
+
const src = await Bun.file("./dist/index.js").text();
|
|
82
|
+
return new Response(src, {
|
|
83
|
+
headers: {
|
|
84
|
+
'Content-Type': 'application/javascript',
|
|
85
|
+
},
|
|
86
|
+
status: 200,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (url.pathname.startsWith("/assets/js")) {
|
|
90
|
+
const lib = url.pathname.replace("/assets/js/", "");
|
|
91
|
+
const localFile = lib.replace("src/", "");
|
|
92
|
+
let result;
|
|
93
|
+
if (localFile.includes("routes")) {
|
|
94
|
+
result = await transpiler.transform(`
|
|
95
|
+
import { hydrateRoot } from 'react-dom/client';
|
|
96
|
+
import {RouterProvider} from "@/utils";
|
|
97
|
+
import Page from "/dist/js/index.js";
|
|
98
|
+
|
|
99
|
+
const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
|
|
100
|
+
const root = hydrateRoot(document.getElementById('root'), (
|
|
101
|
+
<RouterProvider value={initialRouteValue}>
|
|
102
|
+
<Page />
|
|
103
|
+
</RouterProvider>
|
|
104
|
+
));
|
|
105
|
+
`);
|
|
106
|
+
} else {
|
|
107
|
+
const src = await Bun.file(localFile).text();
|
|
108
|
+
result = await transpiler.transform(src);
|
|
109
|
+
}
|
|
110
|
+
return new Response(result, {
|
|
111
|
+
headers: {
|
|
112
|
+
'Content-Type': 'application/javascript',
|
|
113
|
+
},
|
|
114
|
+
status: 200,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (url.pathname.startsWith("/api")) {
|
|
118
|
+
console.log('api', url.pathname);
|
|
119
|
+
// return renderApi(route, req);
|
|
120
|
+
}
|
|
121
|
+
return renderPage("./routes/index.astro", url, {});
|
|
122
|
+
// const route = router.match(url.pathname);
|
|
123
|
+
// if (route) {
|
|
124
|
+
// return renderPage(route, url);
|
|
125
|
+
// }
|
|
126
|
+
return new Response(`Not Found`, {
|
|
127
|
+
headers: { 'Content-Type': 'text/html' },
|
|
128
|
+
status: 404,
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
index.test.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
});
|
jsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": [
|
|
4
|
+
"ESNext"
|
|
5
|
+
],
|
|
6
|
+
"module": "esnext",
|
|
7
|
+
"target": "esnext",
|
|
8
|
+
"moduleResolution": "nodenext",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"downlevelIteration": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"jsx": "react",
|
|
13
|
+
"jsxFactory": "React.createElement",
|
|
14
|
+
"jsxImportSource": "react",
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"allowJs": true,
|
|
18
|
+
"types": [
|
|
19
|
+
"bun-types" // add Bun global
|
|
20
|
+
],
|
|
21
|
+
"paths": {
|
|
22
|
+
"@/*": ["./*"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package-lock.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "quickstart",
|
|
3
|
+
"lockfileVersion": 2,
|
|
4
|
+
"requires": true,
|
|
5
|
+
"packages": {
|
|
6
|
+
"": {
|
|
7
|
+
"name": "quickstart",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"react": "18.2.0",
|
|
10
|
+
"react-dom": "^18.2.0",
|
|
11
|
+
"zod": "^3.21.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"bun-types": "^0.5.0"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"node_modules/bun-types": {
|
|
18
|
+
"version": "0.5.7",
|
|
19
|
+
"dev": true
|
|
20
|
+
},
|
|
21
|
+
"node_modules/js-tokens": {
|
|
22
|
+
"version": "4.0.0",
|
|
23
|
+
"license": "MIT"
|
|
24
|
+
},
|
|
25
|
+
"node_modules/loose-envify": {
|
|
26
|
+
"version": "1.4.0",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"js-tokens": "^3.0.0 || ^4.0.0"
|
|
30
|
+
},
|
|
31
|
+
"bin": {
|
|
32
|
+
"loose-envify": "cli.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"node_modules/react": {
|
|
36
|
+
"version": "18.2.0",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"loose-envify": "^1.1.0"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=0.10.0"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"node_modules/react-dom": {
|
|
46
|
+
"version": "18.2.0",
|
|
47
|
+
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
|
48
|
+
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"loose-envify": "^1.1.0",
|
|
51
|
+
"scheduler": "^0.23.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"react": "^18.2.0"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"node_modules/scheduler": {
|
|
58
|
+
"version": "0.23.0",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"loose-envify": "^1.1.0"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"node_modules/zod": {
|
|
65
|
+
"version": "3.21.0",
|
|
66
|
+
"license": "MIT",
|
|
67
|
+
"funding": {
|
|
68
|
+
"url": "https://github.com/sponsors/colinhacks"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"bun-types": {
|
|
74
|
+
"version": "0.5.7",
|
|
75
|
+
"dev": true
|
|
76
|
+
},
|
|
77
|
+
"js-tokens": {
|
|
78
|
+
"version": "4.0.0"
|
|
79
|
+
},
|
|
80
|
+
"loose-envify": {
|
|
81
|
+
"version": "1.4.0",
|
|
82
|
+
"requires": {
|
|
83
|
+
"js-tokens": "^3.0.0 || ^4.0.0"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"react": {
|
|
87
|
+
"version": "18.2.0",
|
|
88
|
+
"requires": {
|
|
89
|
+
"loose-envify": "^1.1.0"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"react-dom": {
|
|
93
|
+
"version": "18.2.0",
|
|
94
|
+
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
|
95
|
+
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
|
96
|
+
"requires": {
|
|
97
|
+
"loose-envify": "^1.1.0",
|
|
98
|
+
"scheduler": "^0.23.0"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"scheduler": {
|
|
102
|
+
"version": "0.23.0",
|
|
103
|
+
"requires": {
|
|
104
|
+
"loose-envify": "^1.1.0"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"zod": {
|
|
108
|
+
"version": "3.21.0"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "quickstart",
|
|
3
|
+
"module": "index.js",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bun --hot index.js",
|
|
7
|
+
"start": "bun index.js"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"bun-types": "^0.5.0"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"react": "18.2.0",
|
|
14
|
+
"react-dom": "^18.2.0",
|
|
15
|
+
"zod": "^3.21.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
public/favicon.ico
ADDED
|
Binary file
|
public/index.html
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="theme-color" content="#000000" />
|
|
8
|
+
<meta
|
|
9
|
+
name="description"
|
|
10
|
+
content="Web site created using create-react-app"
|
|
11
|
+
/>
|
|
12
|
+
<link rel="apple-touch-icon" href="/logo192.png" />
|
|
13
|
+
<!--
|
|
14
|
+
manifest.json provides metadata used when your web app is installed on a
|
|
15
|
+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
16
|
+
-->
|
|
17
|
+
<link rel="manifest" href="/manifest.json" />
|
|
18
|
+
<!--
|
|
19
|
+
Notice the use of %PUBLIC_URL% in the tags above.
|
|
20
|
+
It will be replaced with the URL of the `public` folder during the build.
|
|
21
|
+
Only files inside the `public` folder can be referenced from the HTML.
|
|
22
|
+
|
|
23
|
+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
24
|
+
work correctly both with client-side routing and a non-root public URL.
|
|
25
|
+
Learn how to configure a non-root public URL by running `npm run build`.
|
|
26
|
+
-->
|
|
27
|
+
<title>React App</title>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
31
|
+
<div id="root"></div>
|
|
32
|
+
<!--
|
|
33
|
+
This HTML file is a template.
|
|
34
|
+
If you open it directly in the browser, you will see an empty page.
|
|
35
|
+
|
|
36
|
+
You can add webfonts, meta tags, or analytics to this file.
|
|
37
|
+
The build step will place the bundled scripts into the <body> tag.
|
|
38
|
+
|
|
39
|
+
To begin the development, run `npm start` or `yarn start`.
|
|
40
|
+
To create a production bundle, use `npm run build` or `yarn build`.
|
|
41
|
+
-->
|
|
42
|
+
<script src="/src/index.jsx" async type="module"></script>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
public/logo192.png
ADDED
|
Binary file
|
public/logo512.png
ADDED
|
Binary file
|
public/manifest.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"short_name": "React App",
|
|
3
|
+
"name": "Create React App Sample",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "favicon.ico",
|
|
7
|
+
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
+
"type": "image/x-icon"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "logo192.png",
|
|
12
|
+
"type": "image/png",
|
|
13
|
+
"sizes": "192x192"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"src": "logo512.png",
|
|
17
|
+
"type": "image/png",
|
|
18
|
+
"sizes": "512x512"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"start_url": ".",
|
|
22
|
+
"display": "standalone",
|
|
23
|
+
"theme_color": "#000000",
|
|
24
|
+
"background_color": "#ffffff"
|
|
25
|
+
}
|
public/robots.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# https://www.robotstxt.org/robotstxt.html
|
|
2
|
+
User-agent: *
|
|
3
|
+
Disallow:
|
router.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const Context = createContext(undefined)
|
|
4
|
+
|
|
5
|
+
export const RouterProvider = ({ value, children }) => {
|
|
6
|
+
return <Context.Provider value={value}>{children}</Context.Provider>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useRouter = () => {
|
|
10
|
+
const state = useContext(Context);
|
|
11
|
+
return {
|
|
12
|
+
query: state.query,
|
|
13
|
+
pathname: state.pathname,
|
|
14
|
+
params: state.params,
|
|
15
|
+
push: () => {
|
|
16
|
+
},
|
|
17
|
+
replace: () => {
|
|
18
|
+
},
|
|
19
|
+
prefetch: () => {
|
|
20
|
+
},
|
|
21
|
+
beforePopState: () => {
|
|
22
|
+
},
|
|
23
|
+
back: () => { },
|
|
24
|
+
reload: () => window.location.reload(),
|
|
25
|
+
}
|
|
26
|
+
}
|
routes/about/index.jsx
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { page, useRouter } from "@/utils";
|
|
2
|
+
|
|
3
|
+
export default page(() => {
|
|
4
|
+
const router = useRouter();
|
|
5
|
+
return (
|
|
6
|
+
<div>
|
|
7
|
+
<p>
|
|
8
|
+
Hello from server
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
);
|
|
12
|
+
});
|
routes/api/todos/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { json } from "@/utils";
|
|
2
|
+
|
|
3
|
+
export default async () => {
|
|
4
|
+
return json([])
|
|
5
|
+
};
|
routes/index.astro
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
const head = {
|
|
5
|
+
title: "pyros.sh",
|
|
6
|
+
description:
|
|
7
|
+
"Hi there, I'm Peter John, a fullstack dev from Bangalore, India",
|
|
8
|
+
image: "/favicon.png",
|
|
9
|
+
keywords: "pyros.sh,pyrossh",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const router = {};
|
|
13
|
+
const [count, setCount] = useState(5);
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div className="home-page">
|
|
17
|
+
<div>
|
|
18
|
+
<p>
|
|
19
|
+
Hello from server path: {router.pathname}
|
|
20
|
+
</p>
|
|
21
|
+
<div>
|
|
22
|
+
<button onClick={() => setCount(count - 1)}>
|
|
23
|
+
-
|
|
24
|
+
</button>
|
|
25
|
+
<div>
|
|
26
|
+
{count}
|
|
27
|
+
</div>
|
|
28
|
+
<button onClick={() => setCount(count + 1)}>
|
|
29
|
+
+
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
utils.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React, { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const Context = createContext(undefined)
|
|
4
|
+
|
|
5
|
+
export const RouterProvider = ({ value, children }) => {
|
|
6
|
+
return <Context.Provider value={value}>{children}</Context.Provider>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const json = async (body, status = 200, headers = {}) => {
|
|
10
|
+
return new Response(body, {
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
...headers,
|
|
14
|
+
},
|
|
15
|
+
status
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// const ErrorBoundary = () => {
|
|
20
|
+
|
|
21
|
+
// }
|