Merge branch 'next'
All checks were successful
Build / build (push) Successful in 47s
Lint / lint (push) Successful in 13s

This commit is contained in:
Julien Valverdé
2025-10-03 16:04:20 +02:00
10 changed files with 97 additions and 83 deletions

View File

@@ -1,3 +1,6 @@
{ {
"typescript.tsdk": "node_modules/typescript/lib" "typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit"
}
} }

View File

@@ -1,34 +1,36 @@
{ {
"$schema": "https://biomejs.dev/schemas/latest/schema.json", "$schema": "https://biomejs.dev/schemas/latest/schema.json",
"vcs": { "vcs": {
"enabled": false, "enabled": false,
"clientKind": "git", "clientKind": "git",
"useIgnoreFile": false "useIgnoreFile": false
}, },
"files": { "files": {
"ignoreUnknown": false "ignoreUnknown": false
}, },
"formatter": { "formatter": {
"enabled": false, "enabled": false
"indentStyle": "tab" },
}, "linter": {
"linter": { "enabled": true,
"enabled": true, "rules": {
"rules": { "recommended": true,
"recommended": true "nursery": {
} "useSortedClasses": "error"
}, }
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
} }
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
} }

View File

@@ -1,8 +1,8 @@
{ {
"$schema": "https://biomejs.dev/schemas/latest/schema.json", "$schema": "https://biomejs.dev/schemas/latest/schema.json",
"root": false, "root": false,
"extends": "//", "extends": "//",
"files": { "files": {
"includes": ["./src/**"] "includes": ["./src/**"]
} }
} }

View File

@@ -1,8 +1,8 @@
{ {
"$schema": "https://biomejs.dev/schemas/latest/schema.json", "$schema": "https://biomejs.dev/schemas/latest/schema.json",
"root": false, "root": false,
"extends": "//", "extends": "//",
"files": { "files": {
"includes": ["./src/**"] "includes": ["./src/**"]
} }
} }

View File

@@ -1,6 +1,6 @@
import { createServer } from "node:http"
import { NodeContext, NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { NodeContext, NodeHttpServer, NodeRuntime } from "@effect/platform-node"
import { Effect, Layer } from "effect" import { Effect, Layer } from "effect"
import { createServer } from "node:http"
import { ServerConfig } from "./config" import { ServerConfig } from "./config"
import { Server } from "./server" import { Server } from "./server"

View File

@@ -16,51 +16,41 @@ const makeWebRpcRoute = Effect.all([
Effect.provide(WebRpcLive), Effect.provide(WebRpcLive),
) )
const makeProductionWebappMiddleware = Effect.gen(function*() { const makeProductionWebappRoute = Effect.fnUntraced(function*(route: HttpRouter.PathInput) {
const path = yield* Path.Path const path = yield* Path.Path
const fs = yield* FileSystem.FileSystem const fs = yield* FileSystem.FileSystem
const dist = path.join(yield* path.fromFileUrl(new URL(".", import.meta.resolve("@website/webapp"))), "dist") const dist = path.join(yield* path.fromFileUrl(new URL(".", import.meta.resolve("@website/webapp"))), "dist")
return () => Effect.gen(function*() { return HttpRouter.all(route, Effect.gen(function*() {
const req = yield* HttpServerRequest.HttpServerRequest const req = yield* HttpServerRequest.HttpServerRequest
const source = path.join(dist, req.url) const source = path.join(dist, req.url)
const isValid = yield* fs.stat(source).pipe( const exists = yield* fs.stat(source).pipe(
Effect.andThen(stat => stat.type === "File"), Effect.andThen(stat => stat.type === "File"),
Effect.catchAll(() => Effect.succeed(false)), Effect.catchAll(() => Effect.succeed(false)),
) )
return yield* HttpServerResponse.setHeader( return yield* HttpServerResponse.setHeader(
yield* HttpServerResponse.file(isValid ? source : path.join(dist, "index.html")), yield* HttpServerResponse.file(exists ? source : path.join(dist, "index.html")),
"Cache-Control", "Cache-Control",
`public, max-age=${Duration.toSeconds("365 days")}, immutable` `public, max-age=${Duration.toSeconds("365 days")}, immutable`
) )
}) }))
}) })
export const HttpAppDevelopment = Effect.provide(makeWebRpcRoute, WebRpcSerializationDevelopment).pipe( export const HttpAppDevelopment = Layer.unwrapScoped(Effect.gen(function*() {
Effect.map(serveWebRpc => router.pipe( return router.pipe(
serveWebRpc, yield* Effect.provide(makeWebRpcRoute, WebRpcSerializationDevelopment),
HttpServer.serve(flow( HttpServer.serve(flow(HttpMiddleware.logger, HttpMiddleware.xForwardedHeaders)),
HttpMiddleware.logger,
HttpMiddleware.xForwardedHeaders,
)),
HttpServer.withLogAddress, HttpServer.withLogAddress,
)), )
}))
Layer.unwrapScoped, export const HttpAppProduction = Layer.unwrapScoped(Effect.gen(function*() {
) return router.pipe(
yield* Effect.provide(makeWebRpcRoute, WebRpcSerializationProduction),
export const HttpAppProduction = Effect.all([ yield* makeProductionWebappRoute("*"),
Effect.provide(makeWebRpcRoute, WebRpcSerializationProduction),
makeProductionWebappMiddleware,
]).pipe(
Effect.map(([serveWebRpc, serveProductionWebapp]) => router.pipe(
serveWebRpc,
serveProductionWebapp,
HttpServer.serve(HttpMiddleware.xForwardedHeaders), HttpServer.serve(HttpMiddleware.xForwardedHeaders),
HttpServer.withLogAddress, HttpServer.withLogAddress,
)), )
}))
Layer.unwrapScoped,
)

View File

@@ -1,8 +1,8 @@
{ {
"$schema": "https://biomejs.dev/schemas/latest/schema.json", "$schema": "https://biomejs.dev/schemas/latest/schema.json",
"root": false, "root": false,
"extends": "//", "extends": "//",
"files": { "files": {
"includes": ["./src/**", "!src/routeTree.gen.ts"] "includes": ["./src/**", "!src/routeTree.gen.ts"]
} }
} }

View File

@@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
<div <div
data-slot="card" data-slot="card"
className={cn( className={cn(
"rounded-base flex flex-col shadow-shadow border-2 gap-6 py-6 border-border bg-background text-foreground font-base", "flex flex-col gap-6 rounded-base border-2 border-border bg-background py-6 font-base text-foreground shadow-shadow",
className, className,
)} )}
{...props} {...props}
@@ -42,7 +42,7 @@ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return ( return (
<div <div
data-slot="card-description" data-slot="card-description"
className={cn("text-sm font-base", className)} className={cn("font-base text-sm", className)}
{...props} {...props}
/> />
) )

View File

@@ -1,6 +1,6 @@
import { Card, CardContent } from "@/components/ui/card" import { createRootRoute, Outlet } from "@tanstack/react-router"
import { Outlet, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools" import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"
import { Card, CardContent } from "@/components/ui/card"
export const Route = createRootRoute({ export const Route = createRootRoute({
@@ -9,7 +9,7 @@ export const Route = createRootRoute({
function RootComponent() { function RootComponent() {
return <> return <>
<div className="text-foreground mx-auto w-[750px] max-w-full px-5 pt-28 pb-10"> <div className="mx-auto w-[750px] max-w-full px-5 pt-28 pb-10 text-foreground">
<Card> <Card>
<CardContent> <CardContent>
<Outlet /> <Outlet />

View File

@@ -2,5 +2,24 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:recommended" "config:recommended"
],
"packageRules": [
{
"matchManagers": ["npm"],
"matchPaths": ["./packages/**"],
"manager": "bun"
},
{
"matchManagers": ["bun", "npm"],
"matchUpdateTypes": ["minor", "patch"],
"groupName": "bun minor+patch updates",
"groupSlug": "bun-minor-patch"
},
{
"matchManagers": ["bun", "npm"],
"matchUpdateTypes": ["major"],
"groupName": "bun major updates",
"groupSlug": "bun-major"
}
] ]
} }