format
This commit is contained in:
Vendored
+2
-1
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"editor.defaultFormatter": "biomejs.biome",
|
"editor.defaultFormatter": "biomejs.biome",
|
||||||
"editor.formatOnSave": true
|
"editor.formatOnSave": true,
|
||||||
|
"biome.configurationPath": "biome.json"
|
||||||
}
|
}
|
||||||
+12
-1
@@ -9,7 +9,18 @@
|
|||||||
"recommended": true
|
"recommended": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"indentWidth": 2,
|
||||||
|
"indentStyle": "space"
|
||||||
|
},
|
||||||
"files": {
|
"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 }) {
|
export function Link({ href, label }: { href: string; label: string }) {
|
||||||
const pageContext = usePageContext();
|
const pageContext = usePageContext();
|
||||||
const { urlPathname } = pageContext;
|
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} />;
|
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.
|
// - 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.
|
// - The database is reset when restarting the server, use a proper database (SQLite/PostgreSQL/...) if you want persistent data.
|
||||||
// biome-ignore lint:
|
// 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;
|
const { todos } = database;
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@ import { env } from "hono/adapter";
|
|||||||
import { compress } from "hono/compress";
|
import { compress } from "hono/compress";
|
||||||
import app from "./hono-entry.js";
|
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 };
|
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 { vikeHandler } from "./server/vike-handler";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { createHandler, createMiddleware } from "@universal-middleware/hono";
|
import { createHandler, createMiddleware } from "@universal-middleware/hono";
|
||||||
|
|||||||
@@ -6,18 +6,29 @@ import theme from "./theme.js";
|
|||||||
import logoUrl from "../assets/logo.svg";
|
import logoUrl from "../assets/logo.svg";
|
||||||
import { Link } from "../components/Link";
|
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();
|
const [opened, { toggle }] = useDisclosure();
|
||||||
return (
|
return (
|
||||||
<MantineProvider theme={theme}>
|
<MantineProvider theme={theme}>
|
||||||
<AppShell
|
<AppShell
|
||||||
header={{ height: 60 }}
|
header={{ height: 60 }}
|
||||||
navbar={{ width: 300, breakpoint: "sm", collapsed: { mobile: !opened } }}
|
navbar={{
|
||||||
padding="md"
|
width: 300,
|
||||||
|
breakpoint: "sm",
|
||||||
|
collapsed: { mobile: !opened },
|
||||||
|
}}
|
||||||
|
padding="lg"
|
||||||
>
|
>
|
||||||
<AppShell.Header>
|
<AppShell.Header>
|
||||||
<Group h="100%" px="md">
|
<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="/">
|
<a href="/">
|
||||||
{" "}
|
{" "}
|
||||||
<Image h={50} fit="contain" src={logoUrl} />{" "}
|
<Image h={50} fit="contain" src={logoUrl} />{" "}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import { Counter } from "./Counter.js";
|
|||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
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:
|
This page is:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Rendered to HTML.</li>
|
<li>Rendered to HTML.</li>
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ export const data = async (pageContext: PageContextServer) => {
|
|||||||
// https://vike.dev/useConfig
|
// https://vike.dev/useConfig
|
||||||
const config = 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;
|
let movie = (await response.json()) as MovieDetails;
|
||||||
|
|
||||||
config({
|
config({
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ export default function Page() {
|
|||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
<p>
|
<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>
|
</p>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ export const data = async () => {
|
|||||||
// https://vike.dev/useConfig
|
// https://vike.dev/useConfig
|
||||||
const config = 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[];
|
const moviesData = (await response.json()) as MovieDetails[];
|
||||||
|
|
||||||
config({
|
config({
|
||||||
|
|||||||
+3
-1
@@ -6,6 +6,8 @@ export type Data = {
|
|||||||
todo: { text: string }[];
|
todo: { text: string }[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function data(_pageContext: PageContextServer): Promise<Data> {
|
export default async function data(
|
||||||
|
_pageContext: PageContextServer,
|
||||||
|
): Promise<Data> {
|
||||||
return { todo: todos };
|
return { todo: todos };
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-2
@@ -1,7 +1,11 @@
|
|||||||
import { trpc } from "../../trpc/client";
|
import { trpc } from "../../trpc/client";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export function TodoList({ initialTodoItems }: { initialTodoItems: { text: string }[] }) {
|
export function TodoList({
|
||||||
|
initialTodoItems,
|
||||||
|
}: {
|
||||||
|
initialTodoItems: { text: string }[];
|
||||||
|
}) {
|
||||||
const [todoItems, setTodoItems] = useState(initialTodoItems);
|
const [todoItems, setTodoItems] = useState(initialTodoItems);
|
||||||
const [newTodo, setNewTodo] = useState("");
|
const [newTodo, setNewTodo] = useState("");
|
||||||
return (
|
return (
|
||||||
@@ -16,6 +20,7 @@ export function TodoList({ initialTodoItems }: { initialTodoItems: { text: strin
|
|||||||
<form
|
<form
|
||||||
onSubmit={async (ev) => {
|
onSubmit={async (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
if (newTodo.trim() === "") return;
|
||||||
|
|
||||||
// Optimistic UI update
|
// Optimistic UI update
|
||||||
setTodoItems((prev) => [...prev, { text: newTodo }]);
|
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>
|
<button type="submit">Add to-do</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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 CredentialsProvider from "@auth/core/providers/credentials";
|
||||||
import type { Session } from "@auth/core/types";
|
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.)
|
// 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> =
|
const env: Record<string, string | undefined> =
|
||||||
typeof process?.env !== "undefined"
|
typeof process?.env !== "undefined"
|
||||||
? process.env
|
? process.env
|
||||||
: import.meta && "env" in import.meta
|
: 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) {
|
if (!globalThis.crypto) {
|
||||||
@@ -16,7 +29,9 @@ if (!globalThis.crypto) {
|
|||||||
* Polyfill needed if Auth.js code runs on node18
|
* Polyfill needed if Auth.js code runs on node18
|
||||||
*/
|
*/
|
||||||
Object.defineProperty(globalThis, "crypto", {
|
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,
|
writable: false,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
@@ -24,7 +39,9 @@ if (!globalThis.crypto) {
|
|||||||
|
|
||||||
const authjsConfig = {
|
const authjsConfig = {
|
||||||
basePath: "/api/auth",
|
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}
|
// TODO: Replace secret {@see https://authjs.dev/reference/core#secret}
|
||||||
secret: "MY_SECRET",
|
secret: "MY_SECRET",
|
||||||
providers: [
|
providers: [
|
||||||
@@ -51,12 +68,24 @@ const authjsConfig = {
|
|||||||
/**
|
/**
|
||||||
* Retrieve Auth.js session from Request
|
* 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);
|
setEnvDefaults(process.env, config);
|
||||||
const requestURL = new URL(req.url);
|
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;
|
const { status = 200 } = response;
|
||||||
|
|
||||||
@@ -71,7 +100,8 @@ export async function getSession(req: Request, config: Omit<AuthConfig, "raw">):
|
|||||||
* Add Auth.js session to context
|
* Add Auth.js session to context
|
||||||
* @link {@see https://authjs.dev/getting-started/session-management/get-session}
|
* @link {@see https://authjs.dev/getting-started/session-management/get-session}
|
||||||
**/
|
**/
|
||||||
export const authjsSessionMiddleware: Get<[], UniversalMiddleware> = () => async (request, context) => {
|
export const authjsSessionMiddleware: Get<[], UniversalMiddleware> =
|
||||||
|
() => async (request, context) => {
|
||||||
try {
|
try {
|
||||||
return {
|
return {
|
||||||
...context,
|
...context,
|
||||||
|
|||||||
@@ -3,8 +3,14 @@ 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.)
|
// 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";
|
import type { Get, UniversalHandler } from "@universal-middleware/core";
|
||||||
|
|
||||||
export const vikeHandler: Get<[], UniversalHandler> = () => async (request, context, runtime) => {
|
export const vikeHandler: Get<[], UniversalHandler> =
|
||||||
const pageContextInit = { ...context, ...runtime, urlOriginal: request.url, headersOriginal: request.headers };
|
() => async (request, context, runtime) => {
|
||||||
|
const pageContextInit = {
|
||||||
|
...context,
|
||||||
|
...runtime,
|
||||||
|
urlOriginal: request.url,
|
||||||
|
headersOriginal: request.headers,
|
||||||
|
};
|
||||||
const pageContext = await renderPage(pageContextInit);
|
const pageContext = await renderPage(pageContextInit);
|
||||||
const response = pageContext.httpResponse;
|
const response = pageContext.httpResponse;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { initTRPC } from "@trpc/server";
|
import { initTRPC } from "@trpc/server";
|
||||||
|
import { todos } from "../database/todoItems";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization of tRPC backend
|
* Initialization of tRPC backend
|
||||||
@@ -26,6 +27,7 @@ export const appRouter = router({
|
|||||||
})
|
})
|
||||||
.mutation(async (opts) => {
|
.mutation(async (opts) => {
|
||||||
console.log("Received new todo", { text: opts.input });
|
console.log("Received new todo", { text: opts.input });
|
||||||
|
todos.push({ text: opts.input });
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+3
-13
@@ -10,20 +10,10 @@
|
|||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"moduleResolution": "Bundler",
|
"moduleResolution": "Bundler",
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"lib": [
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
"DOM",
|
"types": ["vite/client", "vike-react", "vike-cloudflare/types"],
|
||||||
"DOM.Iterable",
|
|
||||||
"ESNext"
|
|
||||||
],
|
|
||||||
"types": [
|
|
||||||
"vite/client",
|
|
||||||
"vike-react",
|
|
||||||
"vike-cloudflare/types"
|
|
||||||
],
|
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"jsxImportSource": "react"
|
"jsxImportSource": "react"
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": ["dist"]
|
||||||
"dist"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user