~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
a0d404df
—
Peter John 2 years ago
remove layout
- bun.lockb +0 -0
- pages/layout.css → components/Layout/Layout.css +0 -0
- components/Layout/Layout.jsx +19 -0
- containers/TodoList/TodoList.jsx +0 -19
- main.js +0 -2
- package.json +1 -0
- pages/{404 → _404}/page.css +0 -0
- pages/{404 → _404}/page.jsx +5 -1
- pages/_500/page.css +38 -0
- pages/_500/page.jsx +19 -0
- pages/about/page.jsx +15 -12
- pages/layout.jsx +0 -20
- pages/page.jsx +3 -2
- pages/todos/page.css +1 -1
- pages/todos/page.jsx +22 -6
- parotta/runtime.js +10 -45
- parotta/server.js +16 -29
- services/todos.service.js +0 -2
bun.lockb
CHANGED
|
Binary file
|
pages/layout.css → components/Layout/Layout.css
RENAMED
|
File without changes
|
components/Layout/Layout.jsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Link } from "parotta/runtime";
|
|
3
|
+
import "./Layout.css";
|
|
4
|
+
|
|
5
|
+
const Layout = ({ children }) => {
|
|
6
|
+
return (
|
|
7
|
+
<div>
|
|
8
|
+
<header className="layout-header">
|
|
9
|
+
<Link href="/about">About us</Link>
|
|
10
|
+
<Link href="/todos">Todos</Link>
|
|
11
|
+
</header>
|
|
12
|
+
<div>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default Layout;
|
containers/TodoList/TodoList.jsx
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import Todo from "@/components/Todo/Todo";
|
|
3
|
-
import { getTodos } from "@/services/todos.service";
|
|
4
|
-
import { useRpc } from "parotta/runtime";
|
|
5
|
-
|
|
6
|
-
const TodoList = () => {
|
|
7
|
-
const { data } = useRpc(getTodos, {});
|
|
8
|
-
return (
|
|
9
|
-
<div className="todo-list">
|
|
10
|
-
<ul>
|
|
11
|
-
{data.map((item) => (
|
|
12
|
-
<Todo key={item.id} todo={item} />
|
|
13
|
-
))}
|
|
14
|
-
</ul>
|
|
15
|
-
</div>
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default TodoList;
|
main.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ReactDom from "react-dom/server";
|
|
3
1
|
import server from "parotta/server.js";
|
|
4
2
|
|
|
5
3
|
export default {
|
package.json
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"normalize.css": "^8.0.1",
|
|
18
18
|
"react": "18.2.0",
|
|
19
19
|
"react-dom": "^18.2.0",
|
|
20
|
+
"react-error-boundary": "^4.0.4",
|
|
20
21
|
"react-helmet-async": "^1.3.0",
|
|
21
22
|
"sql-highlight": "^4.3.2"
|
|
22
23
|
},
|
pages/{404 → _404}/page.css
RENAMED
|
File without changes
|
pages/{404 → _404}/page.jsx
RENAMED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { Helmet } from 'react-helmet-async';
|
|
2
3
|
import "./page.css";
|
|
3
4
|
|
|
4
5
|
const Page = () => {
|
|
5
6
|
return (
|
|
6
7
|
<div>
|
|
8
|
+
<Helmet>
|
|
9
|
+
<title>Page not found</title>
|
|
10
|
+
</Helmet>
|
|
7
|
-
<h1>404</h1>
|
|
11
|
+
<h1>404 - Page not found</h1>
|
|
8
12
|
<div className="content">
|
|
9
13
|
<h2>This page could not be found</h2>
|
|
10
14
|
</div>
|
pages/_500/page.css
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
body {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
color: #000;
|
|
7
|
+
background: #fff;
|
|
8
|
+
font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif;
|
|
9
|
+
height: 100vh;
|
|
10
|
+
text-align: center;
|
|
11
|
+
|
|
12
|
+
& h1 {
|
|
13
|
+
display: inline-block;
|
|
14
|
+
border-right: 1px solid rgba(0, 0, 0, .3);
|
|
15
|
+
margin: 0;
|
|
16
|
+
margin-right: 20px;
|
|
17
|
+
padding: 10px 23px 10px 0;
|
|
18
|
+
font-size: 24px;
|
|
19
|
+
font-weight: 500;
|
|
20
|
+
vertical-align: top;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
& .content {
|
|
24
|
+
display: inline-block;
|
|
25
|
+
text-align: left;
|
|
26
|
+
line-height: 49px;
|
|
27
|
+
height: 49px;
|
|
28
|
+
vertical-align: middle;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
& h2 {
|
|
32
|
+
font-size: 14px;
|
|
33
|
+
font-weight: normal;
|
|
34
|
+
line-height: inherit;
|
|
35
|
+
margin: 0;
|
|
36
|
+
padding: 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
pages/_500/page.jsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Helmet } from 'react-helmet-async';
|
|
3
|
+
import "./page.css";
|
|
4
|
+
|
|
5
|
+
const Page = () => {
|
|
6
|
+
return (
|
|
7
|
+
<div>
|
|
8
|
+
<Helmet>
|
|
9
|
+
<title>Oop's Something went wrong</title>
|
|
10
|
+
</Helmet>
|
|
11
|
+
<h1>Oop's Something went wrong</h1>
|
|
12
|
+
<div className="content">
|
|
13
|
+
<h2>Internal Server Error</h2>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default Page;
|
pages/about/page.jsx
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Link, useRouter } from "parotta/runtime";
|
|
3
3
|
import { Helmet } from 'react-helmet-async';
|
|
4
|
+
import Layout from '@/components/Layout/Layout';
|
|
4
5
|
import "./page.css";
|
|
5
6
|
|
|
6
7
|
export const Page = () => {
|
|
7
8
|
const router = useRouter();
|
|
8
9
|
return (
|
|
10
|
+
<Layout>
|
|
9
|
-
|
|
11
|
+
<div className="about-page">
|
|
10
|
-
|
|
12
|
+
<Helmet>
|
|
11
|
-
|
|
13
|
+
<title>About Page @ {router.pathname}</title>
|
|
12
|
-
|
|
14
|
+
<meta name="description" content="Showcase of using parotta meta-framework." />
|
|
13
|
-
|
|
15
|
+
</Helmet>
|
|
14
|
-
|
|
16
|
+
<div>
|
|
15
|
-
|
|
17
|
+
<h1>About Page @ {router.pathname}</h1>
|
|
16
|
-
|
|
18
|
+
<p>Showcase of using parotta meta-framework.</p>
|
|
19
|
+
</div>
|
|
20
|
+
<footer>
|
|
21
|
+
<Link href="/">Back</Link>
|
|
22
|
+
</footer>
|
|
17
23
|
</div>
|
|
18
|
-
<footer>
|
|
19
|
-
<Link href="/">Back</Link>
|
|
20
|
-
|
|
24
|
+
</Layout>
|
|
21
|
-
</div>
|
|
22
25
|
)
|
|
23
26
|
}
|
|
24
27
|
|
pages/layout.jsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React, { Suspense } from 'react';
|
|
2
|
-
import { Link } from "parotta/runtime";
|
|
3
|
-
import { ErrorBoundary } from "parotta/runtime";
|
|
4
|
-
import "./layout.css";
|
|
5
|
-
|
|
6
|
-
const Layout = ({ children }) => {
|
|
7
|
-
return (
|
|
8
|
-
<ErrorBoundary onError={(err) => console.log(err)} fallback={<p>Oops something went wrong</p>}>
|
|
9
|
-
<header className="layout-header">
|
|
10
|
-
<Link href="/about">About us</Link>
|
|
11
|
-
<Link href="/todos">Todos</Link>
|
|
12
|
-
</header>
|
|
13
|
-
<Suspense fallback={<p>Loading...</p>}>
|
|
14
|
-
{children}
|
|
15
|
-
</Suspense>
|
|
16
|
-
</ErrorBoundary>
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default Layout;
|
pages/page.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect } from 'react';
|
|
2
2
|
import { useRouter } from "parotta/runtime";
|
|
3
|
+
import Layout from '@/components/Layout/Layout';
|
|
3
4
|
import Counter from "@/components/Counter/Counter";
|
|
4
5
|
import { Helmet } from 'react-helmet-async';
|
|
5
6
|
import "./page.css";
|
|
@@ -10,7 +11,7 @@ const Page = () => {
|
|
|
10
11
|
|
|
11
12
|
}, []);
|
|
12
13
|
return (
|
|
13
|
-
<
|
|
14
|
+
<Layout>
|
|
14
15
|
<Helmet>
|
|
15
16
|
<title>Parotta App</title>
|
|
16
17
|
</Helmet>
|
|
@@ -21,7 +22,7 @@ const Page = () => {
|
|
|
21
22
|
</p>
|
|
22
23
|
<Counter />
|
|
23
24
|
</div>
|
|
24
|
-
</
|
|
25
|
+
</Layout>
|
|
25
26
|
)
|
|
26
27
|
}
|
|
27
28
|
|
pages/todos/page.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
body{
|
|
1
|
+
body {
|
|
2
2
|
padding: 10px;
|
|
3
3
|
background-color: turquoise;
|
|
4
4
|
}
|
pages/todos/page.jsx
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
import React, { Suspense } from 'react';
|
|
2
|
-
import TodoList from "@/containers/TodoList/TodoList";
|
|
3
2
|
import { Helmet } from 'react-helmet-async';
|
|
3
|
+
import { useRpc } from "parotta/runtime";
|
|
4
|
+
import Todo from "@/components/Todo/Todo";
|
|
5
|
+
import { getTodos } from "@/services/todos.service";
|
|
6
|
+
import Layout from '@/components/Layout/Layout';
|
|
4
7
|
import "./page.css";
|
|
5
8
|
|
|
9
|
+
const TodoList = () => {
|
|
10
|
+
const { data } = useRpc(getTodos, {});
|
|
11
|
+
return (
|
|
12
|
+
<ul>
|
|
13
|
+
{data.map((item) => (
|
|
14
|
+
<Todo key={item.id} todo={item} />
|
|
15
|
+
))}
|
|
16
|
+
</ul>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
const Page = () => {
|
|
7
21
|
return (
|
|
8
|
-
<
|
|
22
|
+
<Layout>
|
|
9
23
|
<h1>Todos</h1>
|
|
10
24
|
<Helmet>
|
|
11
25
|
<title>Todos Page</title>
|
|
12
26
|
</Helmet>
|
|
27
|
+
<div>
|
|
13
|
-
|
|
28
|
+
<Suspense fallback="Loading...">
|
|
14
|
-
|
|
29
|
+
<TodoList />
|
|
15
|
-
|
|
30
|
+
</Suspense>
|
|
16
|
-
|
|
31
|
+
</div>
|
|
32
|
+
</Layout>
|
|
17
33
|
)
|
|
18
34
|
}
|
|
19
35
|
|
parotta/runtime.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
createElement, createContext, useContext, useState, useEffect, useTransition
|
|
2
|
+
Suspense, createElement, createContext, useContext, useState, useEffect, useTransition
|
|
3
3
|
} from "react";
|
|
4
4
|
import { HelmetProvider } from 'react-helmet-async';
|
|
5
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
5
6
|
|
|
6
7
|
export const domain = () => typeof window !== 'undefined' ? window.origin : "http://0.0.0.0:3000";
|
|
7
8
|
|
|
8
|
-
const changedArray = (a = [], b = []) =>
|
|
9
|
-
a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))
|
|
10
|
-
|
|
11
9
|
export const rpc = (serviceName) => async (params = {}) => {
|
|
12
10
|
const res = await fetch(`${domain()}/services/${serviceName}`, {
|
|
13
11
|
method: "POST",
|
|
@@ -64,7 +62,7 @@ export const RouterContext = createContext(undefined);
|
|
|
64
62
|
const getMatch = (radixRouter, pathname) => {
|
|
65
63
|
const matchedPage = radixRouter.lookup(pathname);
|
|
66
64
|
if (!matchedPage) {
|
|
67
|
-
return
|
|
65
|
+
return React.lazy(() => import("/pages/_404/page.jsx"));
|
|
68
66
|
}
|
|
69
67
|
return matchedPage;
|
|
70
68
|
}
|
|
@@ -118,8 +116,13 @@ export const App = ({ nProgress, history, radixRouter, rpcCache, helmetContext }
|
|
|
118
116
|
history: history,
|
|
119
117
|
params: match.params || {},
|
|
120
118
|
},
|
|
119
|
+
children: createElement(ErrorBoundary, {
|
|
120
|
+
onError: (err) => console.log(err),
|
|
121
|
+
fallback: createElement("p", {}, "Oops something went wrong"),
|
|
121
|
-
|
|
122
|
+
children: createElement(Suspense, {
|
|
123
|
+
fallback: createElement("p", {}, "Loading..."),
|
|
122
|
-
|
|
124
|
+
children: createElement(match, {}),
|
|
125
|
+
}),
|
|
123
126
|
}),
|
|
124
127
|
}),
|
|
125
128
|
}),
|
|
@@ -167,42 +170,4 @@ export const NavLink = ({ children, className, activeClassName, ...props }) => {
|
|
|
167
170
|
className: classNames,
|
|
168
171
|
...props,
|
|
169
172
|
})
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export class ErrorBoundary extends React.Component {
|
|
173
|
-
// static propTypes = {
|
|
174
|
-
// resetKeys: PropTypes.arrayOf(PropTypes.any),
|
|
175
|
-
// }
|
|
176
|
-
static getDerivedStateFromError(error) {
|
|
177
|
-
return { error }
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
state = {}
|
|
181
|
-
|
|
182
|
-
componentDidCatch(error, info) {
|
|
183
|
-
this.props.onError?.(error, info)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
componentDidUpdate(prevProps, prevState) {
|
|
187
|
-
const { error } = this.state
|
|
188
|
-
const { resetKeys } = this.props
|
|
189
|
-
if (
|
|
190
|
-
error !== null &&
|
|
191
|
-
prevState.error !== null &&
|
|
192
|
-
changedArray(prevProps.resetKeys, resetKeys)
|
|
193
|
-
) {
|
|
194
|
-
this.setState({});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
render() {
|
|
199
|
-
const { error } = this.state;
|
|
200
|
-
const { children, fallback } = this.props;
|
|
201
|
-
if (error) {
|
|
202
|
-
if (React.isValidElement(fallback)) {
|
|
203
|
-
return fallback;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return children;
|
|
207
|
-
}
|
|
208
173
|
}
|
parotta/server.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { renderToReadableStream } from "react-dom/server";
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import fs from 'fs';
|
|
5
4
|
import walkdir from 'walkdir';
|
|
6
5
|
import postcss from "postcss"
|
|
7
6
|
import autoprefixer from "autoprefixer";
|
|
@@ -29,7 +28,8 @@ const createServerRouter = async () => {
|
|
|
29
28
|
.replace("/pages", "")
|
|
30
29
|
// .replaceAll("[", ":")
|
|
31
30
|
// .replaceAll("]", "")
|
|
32
|
-
)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
33
|
walkdir.sync(path.join(process.cwd(), "services"))
|
|
34
34
|
.map((s) => s.replace(process.cwd(), ""))
|
|
35
35
|
.filter((s) => s.includes(".service.js"))
|
|
@@ -43,12 +43,6 @@ const createServerRouter = async () => {
|
|
|
43
43
|
const key = page.route || "/";
|
|
44
44
|
routes[key] = { key: key, page: page.path };
|
|
45
45
|
});
|
|
46
|
-
dirs.filter((p) => p.includes('layout.jsx'))
|
|
47
|
-
.map((s) => ({ path: s, route: s.replace("/layout.jsx", "") }))
|
|
48
|
-
.forEach((item) => {
|
|
49
|
-
const key = item.route || "/";
|
|
50
|
-
routes[key].layout = item.path;
|
|
51
|
-
});
|
|
52
46
|
walkdir.sync(path.join(process.cwd(), "static"))
|
|
53
47
|
.map((s) => s.replace(process.cwd(), "").replace("/static", ""))
|
|
54
48
|
.forEach((route) => {
|
|
@@ -63,21 +57,15 @@ const createServerRouter = async () => {
|
|
|
63
57
|
|
|
64
58
|
const createClientRouter = async () => {
|
|
65
59
|
const routes = await walkdir.sync(path.join(process.cwd(), "pages"))
|
|
66
|
-
.filter((p) => p.includes(
|
|
60
|
+
.filter((p) => p.includes("page.jsx"))
|
|
61
|
+
.filter((p) => !p.includes("/_"))
|
|
67
62
|
.map((s) => s.replace(process.cwd(), ""))
|
|
68
63
|
.map((s) => s.replace("/pages", ""))
|
|
69
64
|
.map((s) => s.replace("/page.jsx", ""))
|
|
70
65
|
.reduce(async (accp, r) => {
|
|
71
66
|
const acc = await accp;
|
|
72
67
|
const src = await import(`${process.cwd()}/pages${r}/page.jsx`);
|
|
73
|
-
const exists = fs.existsSync(`${process.cwd()}/pages${r}/layout.jsx`);
|
|
74
|
-
const lpath = exists ? `/pages${r}/layout.jsx` : `/pages/layout.jsx`;
|
|
75
|
-
const lsrc = await import(`${process.cwd()}${lpath}`);
|
|
76
|
-
acc[r === "" ? "/" : r] =
|
|
68
|
+
acc[r === "" ? "/" : r] = src.default;
|
|
77
|
-
Page: src.default,
|
|
78
|
-
Layout: lsrc.default,
|
|
79
|
-
LayoutPath: lpath,
|
|
80
|
-
}
|
|
81
69
|
return acc
|
|
82
70
|
}, Promise.resolve({}));
|
|
83
71
|
// console.log(clientRoutes);
|
|
@@ -93,11 +81,7 @@ const createClientRouter = async () => {
|
|
|
93
81
|
const radixRouter = createRouter({
|
|
94
82
|
strictTrailingSlash: true,
|
|
95
83
|
routes: {
|
|
96
|
-
${Object.keys(routes).map((r) => `"${r}": {
|
|
97
|
-
|
|
84
|
+
${Object.keys(routes).map((r) => `"${r}": React.lazy(() => import("/pages${r}/page.jsx"))`).join(',\n ')}
|
|
98
|
-
Layout: React.lazy(() => import("${routes[r].LayoutPath}")),
|
|
99
|
-
LayoutPath: "${routes[r].LayoutPath}",
|
|
100
|
-
}`).join(',\n ')}
|
|
101
85
|
},
|
|
102
86
|
});
|
|
103
87
|
|
|
@@ -164,7 +148,6 @@ const renderPage = async (url) => {
|
|
|
164
148
|
return acc;
|
|
165
149
|
}, {})
|
|
166
150
|
const components = mapDeps("components");
|
|
167
|
-
const containers = mapDeps("containers");
|
|
168
151
|
const importMap = {
|
|
169
152
|
"radix3": `https://esm.sh/radix3`,
|
|
170
153
|
"history": "https://esm.sh/history@5.3.0",
|
|
@@ -177,7 +160,6 @@ const renderPage = async (url) => {
|
|
|
177
160
|
"parotta/runtime": `/parotta/runtime.js`,
|
|
178
161
|
...nodeDeps,
|
|
179
162
|
...components,
|
|
180
|
-
...containers,
|
|
181
163
|
};
|
|
182
164
|
const history = createMemoryHistory({
|
|
183
165
|
initialEntries: [url.pathname + url.search],
|
|
@@ -188,7 +170,6 @@ const renderPage = async (url) => {
|
|
|
188
170
|
<html lang="en">
|
|
189
171
|
<head>
|
|
190
172
|
<link rel="stylesheet" href="https://unpkg.com/nprogress@0.2.0/nprogress.css" />
|
|
191
|
-
{/* <link id="layoutCss" rel="stylesheet" href={ match.LayoutPath.replace("jsx", "css"),} /> */}
|
|
192
173
|
<link id="pageCss" rel="stylesheet" href={`/pages${url.pathname}/page.css`} />
|
|
193
174
|
<script type="importmap" dangerouslySetInnerHTML={{ __html: JSON.stringify({ "imports": importMap }) }} />
|
|
194
175
|
</head>
|
|
@@ -211,8 +192,11 @@ const renderPage = async (url) => {
|
|
|
211
192
|
</body>
|
|
212
193
|
</html >
|
|
213
194
|
);
|
|
195
|
+
// TODO:
|
|
214
|
-
|
|
196
|
+
// if (bot || isCrawler) {
|
|
197
|
+
// await stream.allReady
|
|
215
|
-
|
|
198
|
+
// add helmetContext to head
|
|
199
|
+
// }
|
|
216
200
|
return new Response(stream, {
|
|
217
201
|
headers: { 'Content-Type': 'text/html' },
|
|
218
202
|
status: 200,
|
|
@@ -311,7 +295,8 @@ const server = async (req) => {
|
|
|
311
295
|
return renderJs(path.join(process.cwd(), url.pathname));
|
|
312
296
|
}
|
|
313
297
|
const match = serverRouter.lookup(url.pathname);
|
|
298
|
+
// TODO: maybe remove this as renderPage would handle it in clientRouter
|
|
314
|
-
if (match) {
|
|
299
|
+
if (match && !match.key.includes("/_")) {
|
|
315
300
|
if (match.file) {
|
|
316
301
|
return sendFile(path.join(process.cwd(), `/static${match.file}`));
|
|
317
302
|
}
|
|
@@ -323,8 +308,10 @@ const server = async (req) => {
|
|
|
323
308
|
}
|
|
324
309
|
}
|
|
325
310
|
if (req.headers.get("Accept")?.includes('text/html')) {
|
|
326
|
-
|
|
311
|
+
// not found html page
|
|
312
|
+
return renderPage(new URL(`${url.protocol}//${url.host}/_404`));
|
|
327
313
|
}
|
|
314
|
+
// not found generic page
|
|
328
315
|
return new Response(`{"message": "not found"}`, {
|
|
329
316
|
headers: { 'Content-Type': 'application/json' },
|
|
330
317
|
status: 404,
|
services/todos.service.js
CHANGED
|
@@ -2,8 +2,6 @@ import { eq, asc } from 'drizzle-orm';
|
|
|
2
2
|
import db, { todos } from "@/db";
|
|
3
3
|
|
|
4
4
|
export const getTodos = async () => {
|
|
5
|
-
// console.log("getTodos");
|
|
6
|
-
// return [];
|
|
7
5
|
return await db.select().from(todos).orderBy(asc(todos.id));
|
|
8
6
|
}
|
|
9
7
|
|