format
This commit is contained in:
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
"editor.formatOnSave": true
|
||||
"editor.formatOnSave": true,
|
||||
"biome.configurationPath": "biome.json"
|
||||
}
|
||||
+12
-1
@@ -9,7 +9,18 @@
|
||||
"recommended": true
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentWidth": 2,
|
||||
"indentStyle": "space"
|
||||
},
|
||||
"files": {
|
||||
"ignore": ["dist/**", "*.js", "*.cjs", "*.mjs", "*.spec.ts"]
|
||||
"ignore": [
|
||||
"dist/**",
|
||||
"*.js",
|
||||
"*.cjs",
|
||||
"*.mjs",
|
||||
"*.spec.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -4,6 +4,7 @@ import { NavLink } from "@mantine/core";
|
||||
export function Link({ href, label }: { href: string; label: string }) {
|
||||
const pageContext = usePageContext();
|
||||
const { urlPathname } = pageContext;
|
||||
const isActive = href === "/" ? urlPathname === href : urlPathname.startsWith(href);
|
||||
const isActive =
|
||||
href === "/" ? urlPathname === href : urlPathname.startsWith(href);
|
||||
return <NavLink href={href} label={label} active={isActive} />;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ const database =
|
||||
// - We use globalThis so that the database isn't reset upon HMR.
|
||||
// - The database is reset when restarting the server, use a proper database (SQLite/PostgreSQL/...) if you want persistent data.
|
||||
// biome-ignore lint:
|
||||
((globalThis as unknown as { __database: { todos: TodoItem[] } }).__database ??= { todos: todosDefault });
|
||||
((
|
||||
globalThis as unknown as { __database: { todos: TodoItem[] } }
|
||||
).__database ??= { todos: todosDefault });
|
||||
|
||||
const { todos } = database;
|
||||
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@ import { env } from "hono/adapter";
|
||||
import { compress } from "hono/compress";
|
||||
import app from "./hono-entry.js";
|
||||
|
||||
const envs = env<{ NODE_ENV?: string; PORT?: string }>({ env: {} } as unknown as Context<{
|
||||
const envs = env<{ NODE_ENV?: string; PORT?: string }>({
|
||||
env: {},
|
||||
} as unknown as Context<{
|
||||
Bindings: { NODE_ENV?: string; PORT?: string };
|
||||
}>);
|
||||
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
import { authjsHandler, authjsSessionMiddleware } from "./server/authjs-handler";
|
||||
import {
|
||||
authjsHandler,
|
||||
authjsSessionMiddleware,
|
||||
} from "./server/authjs-handler";
|
||||
import { vikeHandler } from "./server/vike-handler";
|
||||
import { Hono } from "hono";
|
||||
import { createHandler, createMiddleware } from "@universal-middleware/hono";
|
||||
|
||||
@@ -6,18 +6,29 @@ import theme from "./theme.js";
|
||||
import logoUrl from "../assets/logo.svg";
|
||||
import { Link } from "../components/Link";
|
||||
|
||||
export default function LayoutDefault({ children }: { children: React.ReactNode }) {
|
||||
export default function LayoutDefault({
|
||||
children,
|
||||
}: { children: React.ReactNode }) {
|
||||
const [opened, { toggle }] = useDisclosure();
|
||||
return (
|
||||
<MantineProvider theme={theme}>
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
navbar={{ width: 300, breakpoint: "sm", collapsed: { mobile: !opened } }}
|
||||
padding="md"
|
||||
navbar={{
|
||||
width: 300,
|
||||
breakpoint: "sm",
|
||||
collapsed: { mobile: !opened },
|
||||
}}
|
||||
padding="lg"
|
||||
>
|
||||
<AppShell.Header>
|
||||
<Group h="100%" px="md">
|
||||
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size="sm" />
|
||||
<Burger
|
||||
opened={opened}
|
||||
onClick={toggle}
|
||||
hiddenFrom="sm"
|
||||
size="sm"
|
||||
/>
|
||||
<a href="/">
|
||||
{" "}
|
||||
<Image h={50} fit="contain" src={logoUrl} />{" "}
|
||||
|
||||
@@ -3,7 +3,11 @@ import { Counter } from "./Counter.js";
|
||||
export default function Page() {
|
||||
return (
|
||||
<>
|
||||
<h1 css={{ fontWeight: "700", fontSize: "1.875rem", paddingBottom: "1rem" }}>My Vike app</h1>
|
||||
<h1
|
||||
css={{ fontWeight: "700", fontSize: "1.875rem", paddingBottom: "1rem" }}
|
||||
>
|
||||
My Vike app
|
||||
</h1>
|
||||
This page is:
|
||||
<ul>
|
||||
<li>Rendered to HTML.</li>
|
||||
|
||||
@@ -10,7 +10,9 @@ export const data = async (pageContext: PageContextServer) => {
|
||||
// https://vike.dev/useConfig
|
||||
const config = useConfig();
|
||||
|
||||
const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`);
|
||||
const response = await fetch(
|
||||
`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`,
|
||||
);
|
||||
let movie = (await response.json()) as MovieDetails;
|
||||
|
||||
config({
|
||||
|
||||
@@ -14,7 +14,11 @@ export default function Page() {
|
||||
))}
|
||||
</ol>
|
||||
<p>
|
||||
Source: <a href="https://brillout.github.io/star-wars">brillout.github.io/star-wars</a>.
|
||||
Source:{" "}
|
||||
<a href="https://brillout.github.io/star-wars">
|
||||
brillout.github.io/star-wars
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,9 @@ export const data = async () => {
|
||||
// https://vike.dev/useConfig
|
||||
const config = useConfig();
|
||||
|
||||
const response = await fetch("https://brillout.github.io/star-wars/api/films.json");
|
||||
const response = await fetch(
|
||||
"https://brillout.github.io/star-wars/api/films.json",
|
||||
);
|
||||
const moviesData = (await response.json()) as MovieDetails[];
|
||||
|
||||
config({
|
||||
|
||||
+3
-1
@@ -6,6 +6,8 @@ export type Data = {
|
||||
todo: { text: string }[];
|
||||
};
|
||||
|
||||
export default async function data(_pageContext: PageContextServer): Promise<Data> {
|
||||
export default async function data(
|
||||
_pageContext: PageContextServer,
|
||||
): Promise<Data> {
|
||||
return { todo: todos };
|
||||
}
|
||||
|
||||
+11
-2
@@ -1,7 +1,11 @@
|
||||
import { trpc } from "../../trpc/client";
|
||||
import { useState } from "react";
|
||||
|
||||
export function TodoList({ initialTodoItems }: { initialTodoItems: { text: string }[] }) {
|
||||
export function TodoList({
|
||||
initialTodoItems,
|
||||
}: {
|
||||
initialTodoItems: { text: string }[];
|
||||
}) {
|
||||
const [todoItems, setTodoItems] = useState(initialTodoItems);
|
||||
const [newTodo, setNewTodo] = useState("");
|
||||
return (
|
||||
@@ -16,6 +20,7 @@ export function TodoList({ initialTodoItems }: { initialTodoItems: { text: strin
|
||||
<form
|
||||
onSubmit={async (ev) => {
|
||||
ev.preventDefault();
|
||||
if (newTodo.trim() === "") return;
|
||||
|
||||
// Optimistic UI update
|
||||
setTodoItems((prev) => [...prev, { text: newTodo }]);
|
||||
@@ -29,7 +34,11 @@ export function TodoList({ initialTodoItems }: { initialTodoItems: { text: strin
|
||||
}
|
||||
}}
|
||||
>
|
||||
<input type="text" onChange={(ev) => setNewTodo(ev.target.value)} value={newTodo} />
|
||||
<input
|
||||
type="text"
|
||||
onChange={(ev) => setNewTodo(ev.target.value)}
|
||||
value={newTodo}
|
||||
/>
|
||||
<button type="submit">Add to-do</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
+52
-22
@@ -1,14 +1,27 @@
|
||||
import { Auth, type AuthConfig, createActionURL, setEnvDefaults } from "@auth/core";
|
||||
import {
|
||||
Auth,
|
||||
type AuthConfig,
|
||||
createActionURL,
|
||||
setEnvDefaults,
|
||||
} from "@auth/core";
|
||||
import CredentialsProvider from "@auth/core/providers/credentials";
|
||||
import type { Session } from "@auth/core/types";
|
||||
// TODO: stop using universal-middleware and directly integrate server middlewares instead and/or use vike-server https://vike.dev/server. (Bati generates boilerplates that use universal-middleware https://github.com/magne4000/universal-middleware to make Bati's internal logic easier. This is temporary and will be removed soon.)
|
||||
import type { Get, UniversalHandler, UniversalMiddleware } from "@universal-middleware/core";
|
||||
import type {
|
||||
Get,
|
||||
UniversalHandler,
|
||||
UniversalMiddleware,
|
||||
} from "@universal-middleware/core";
|
||||
|
||||
const env: Record<string, string | undefined> =
|
||||
typeof process?.env !== "undefined"
|
||||
? process.env
|
||||
: import.meta && "env" in import.meta
|
||||
? (import.meta as ImportMeta & { env: Record<string, string | undefined> }).env
|
||||
? (
|
||||
import.meta as ImportMeta & {
|
||||
env: Record<string, string | undefined>;
|
||||
}
|
||||
).env
|
||||
: {};
|
||||
|
||||
if (!globalThis.crypto) {
|
||||
@@ -16,7 +29,9 @@ if (!globalThis.crypto) {
|
||||
* Polyfill needed if Auth.js code runs on node18
|
||||
*/
|
||||
Object.defineProperty(globalThis, "crypto", {
|
||||
value: await import("node:crypto").then((crypto) => crypto.webcrypto as Crypto),
|
||||
value: await import("node:crypto").then(
|
||||
(crypto) => crypto.webcrypto as Crypto,
|
||||
),
|
||||
writable: false,
|
||||
configurable: true,
|
||||
});
|
||||
@@ -24,7 +39,9 @@ if (!globalThis.crypto) {
|
||||
|
||||
const authjsConfig = {
|
||||
basePath: "/api/auth",
|
||||
trustHost: Boolean(env.AUTH_TRUST_HOST ?? env.VERCEL ?? env.NODE_ENV !== "production"),
|
||||
trustHost: Boolean(
|
||||
env.AUTH_TRUST_HOST ?? env.VERCEL ?? env.NODE_ENV !== "production",
|
||||
),
|
||||
// TODO: Replace secret {@see https://authjs.dev/reference/core#secret}
|
||||
secret: "MY_SECRET",
|
||||
providers: [
|
||||
@@ -51,12 +68,24 @@ const authjsConfig = {
|
||||
/**
|
||||
* Retrieve Auth.js session from Request
|
||||
*/
|
||||
export async function getSession(req: Request, config: Omit<AuthConfig, "raw">): Promise<Session | null> {
|
||||
export async function getSession(
|
||||
req: Request,
|
||||
config: Omit<AuthConfig, "raw">,
|
||||
): Promise<Session | null> {
|
||||
setEnvDefaults(process.env, config);
|
||||
const requestURL = new URL(req.url);
|
||||
const url = createActionURL("session", requestURL.protocol, req.headers, process.env, config);
|
||||
const url = createActionURL(
|
||||
"session",
|
||||
requestURL.protocol,
|
||||
req.headers,
|
||||
process.env,
|
||||
config,
|
||||
);
|
||||
|
||||
const response = await Auth(new Request(url, { headers: { cookie: req.headers.get("cookie") ?? "" } }), config);
|
||||
const response = await Auth(
|
||||
new Request(url, { headers: { cookie: req.headers.get("cookie") ?? "" } }),
|
||||
config,
|
||||
);
|
||||
|
||||
const { status = 200 } = response;
|
||||
|
||||
@@ -71,20 +100,21 @@ export async function getSession(req: Request, config: Omit<AuthConfig, "raw">):
|
||||
* Add Auth.js session to context
|
||||
* @link {@see https://authjs.dev/getting-started/session-management/get-session}
|
||||
**/
|
||||
export const authjsSessionMiddleware: Get<[], UniversalMiddleware> = () => async (request, context) => {
|
||||
try {
|
||||
return {
|
||||
...context,
|
||||
session: await getSession(request, authjsConfig),
|
||||
};
|
||||
} catch (error) {
|
||||
console.debug("authjsSessionMiddleware:", error);
|
||||
return {
|
||||
...context,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
export const authjsSessionMiddleware: Get<[], UniversalMiddleware> =
|
||||
() => async (request, context) => {
|
||||
try {
|
||||
return {
|
||||
...context,
|
||||
session: await getSession(request, authjsConfig),
|
||||
};
|
||||
} catch (error) {
|
||||
console.debug("authjsSessionMiddleware:", error);
|
||||
return {
|
||||
...context,
|
||||
session: null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth.js route
|
||||
|
||||
+17
-11
@@ -3,16 +3,22 @@ import { renderPage } from "vike/server";
|
||||
// TODO: stop using universal-middleware and directly integrate server middlewares instead and/or use vike-server https://vike.dev/server. (Bati generates boilerplates that use universal-middleware https://github.com/magne4000/universal-middleware to make Bati's internal logic easier. This is temporary and will be removed soon.)
|
||||
import type { Get, UniversalHandler } from "@universal-middleware/core";
|
||||
|
||||
export const vikeHandler: Get<[], UniversalHandler> = () => async (request, context, runtime) => {
|
||||
const pageContextInit = { ...context, ...runtime, urlOriginal: request.url, headersOriginal: request.headers };
|
||||
const pageContext = await renderPage(pageContextInit);
|
||||
const response = pageContext.httpResponse;
|
||||
export const vikeHandler: Get<[], UniversalHandler> =
|
||||
() => async (request, context, runtime) => {
|
||||
const pageContextInit = {
|
||||
...context,
|
||||
...runtime,
|
||||
urlOriginal: request.url,
|
||||
headersOriginal: request.headers,
|
||||
};
|
||||
const pageContext = await renderPage(pageContextInit);
|
||||
const response = pageContext.httpResponse;
|
||||
|
||||
const { readable, writable } = new TransformStream();
|
||||
response.pipe(writable);
|
||||
const { readable, writable } = new TransformStream();
|
||||
response.pipe(writable);
|
||||
|
||||
return new Response(readable, {
|
||||
status: response.statusCode,
|
||||
headers: response.headers,
|
||||
});
|
||||
};
|
||||
return new Response(readable, {
|
||||
status: response.statusCode,
|
||||
headers: response.headers,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { initTRPC } from "@trpc/server";
|
||||
import { todos } from "../database/todoItems";
|
||||
|
||||
/**
|
||||
* Initialization of tRPC backend
|
||||
@@ -26,6 +27,7 @@ export const appRouter = router({
|
||||
})
|
||||
.mutation(async (opts) => {
|
||||
console.log("Received new todo", { text: opts.input });
|
||||
todos.push({ text: opts.input });
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
+3
-13
@@ -10,20 +10,10 @@
|
||||
"noEmit": true,
|
||||
"moduleResolution": "Bundler",
|
||||
"target": "ES2022",
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ESNext"
|
||||
],
|
||||
"types": [
|
||||
"vite/client",
|
||||
"vike-react",
|
||||
"vike-cloudflare/types"
|
||||
],
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"types": ["vite/client", "vike-react", "vike-cloudflare/types"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
},
|
||||
"exclude": [
|
||||
"dist"
|
||||
]
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user