refactor!: switch to fresh@2

This commit is contained in:
Julien Oculi 2024-12-09 14:28:33 +01:00
parent c394c473c1
commit a90b488dcf
32 changed files with 188 additions and 114 deletions

View file

@ -32,7 +32,7 @@ TODO
echo 'cohabit.localhost' >> /etc/hosts # In sudo, one time echo 'cohabit.localhost' >> /etc/hosts # In sudo, one time
mkcert -install # If mkcert is not installed in your root ca mkcert -install # If mkcert is not installed in your root ca
mkcert -ecdsa localhost # Only once to issue localhost certificates mkcert -ecdsa localhost # Only once to issue localhost certificates
deno task start deno task dev
``` ```
### Production run ### Production run

View file

@ -1,4 +1,4 @@
import { asset } from '$fresh/runtime.ts' import { asset } from 'fresh/runtime'
import AiChatBox from ':islands/AiChatBox.tsx' import AiChatBox from ':islands/AiChatBox.tsx'
import MoreBox from ':islands/MoreBox.tsx' import MoreBox from ':islands/MoreBox.tsx'
import SearchBox from ':islands/SearchBox.tsx' import SearchBox from ':islands/SearchBox.tsx'

View file

@ -1,11 +1,11 @@
import { SignalLike } from '$fresh/src/types.ts' import type { Signal } from '@preact/signals'
import { render, RenderOptions } from '@deno/gfm' import { render, RenderOptions } from '@deno/gfm'
export type MarkdownTheme = 'light' | 'dark' | 'auto' export type MarkdownTheme = 'light' | 'dark' | 'auto'
export function Markdown( export function Markdown(
{ children, theme, options }: { { children, theme, options }: {
children?: SignalLike<string> | string children?: Signal<string> | string
theme?: SignalLike<MarkdownTheme> | MarkdownTheme theme?: Signal<MarkdownTheme> | MarkdownTheme
options?: RenderOptions options?: RenderOptions
}, },
) { ) {

View file

@ -1,4 +1,4 @@
import { asset } from '$fresh/runtime.ts' import { asset } from 'fresh/runtime'
import { Picture } from ':components/Picture.tsx' import { Picture } from ':components/Picture.tsx'
export function SponsorCards() { export function SponsorCards() {

View file

@ -2,13 +2,10 @@
"lock": false, "lock": false,
"tasks": { "tasks": {
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx", "check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -", "dev": "deno run -A --watch=static/,routes/ dev.ts",
"manifest": "deno task cli manifest $(pwd)",
"start": "deno run -A --watch=static/,routes/ dev.ts",
"build": "deno run -A dev.ts build", "build": "deno run -A dev.ts build",
"preview": "deno run -A main.ts", "start": "deno run -A main.ts",
"update": "deno run -A -r https://fresh.deno.dev/update .", "update": "deno run -A -r jsr:@fresh/update .",
"serve": "deno task preview",
"dev:add_package": "deno run --allow-net=git.cohabit.fr --allow-read=. --allow-write=./deno.json,./packages --allow-run=git,deno ./scripts/add_package.ts" "dev:add_package": "deno run --allow-net=git.cohabit.fr --allow-read=. --allow-write=./deno.json,./packages --allow-run=git,deno ./scripts/add_package.ts"
}, },
"fmt": { "fmt": {
@ -29,7 +26,7 @@
"packages/" "packages/"
], ],
"imports": { "imports": {
"$fresh/": "https://deno.land/x/fresh@1.6.8/", "fresh": "jsr:@fresh/core@^2.0.0-alpha.25",
"$std/": "https://deno.land/std@0.208.0/", "$std/": "https://deno.land/std@0.208.0/",
":components/": "./components/", ":components/": "./components/",
":islands/": "./islands/", ":islands/": "./islands/",
@ -40,8 +37,7 @@
"@deno/gfm": "https://deno.land/x/gfm@0.6.0/mod.ts", "@deno/gfm": "https://deno.land/x/gfm@0.6.0/mod.ts",
"@jotsr/delayed": "jsr:@jotsr/delayed@^2.1.1", "@jotsr/delayed": "jsr:@jotsr/delayed@^2.1.1",
"@jotsr/smart-css-bundler": "jsr:@jotsr/smart-css-bundler@^0.3.0", "@jotsr/smart-css-bundler": "jsr:@jotsr/smart-css-bundler@^0.3.0",
"@preact/signals": "https://esm.sh/*@preact/signals@^1.2.3", "@preact/signals": "npm:@preact/signals@^1.3.0",
"@preact/signals-core": "npm:@preact/signals-core@^1.6.1",
"@simplewebauthn/browser": "npm:@simplewebauthn/browser@^10.0.0", "@simplewebauthn/browser": "npm:@simplewebauthn/browser@^10.0.0",
"@simplewebauthn/server": "npm:@simplewebauthn/server@^10.0.0", "@simplewebauthn/server": "npm:@simplewebauthn/server@^10.0.0",
"@simplewebauthn/types": "npm:@simplewebauthn/types@^10.0.0", "@simplewebauthn/types": "npm:@simplewebauthn/types@^10.0.0",
@ -51,13 +47,27 @@
"@std/json": "jsr:@std/json@^0.224.1", "@std/json": "jsr:@std/json@^0.224.1",
"@std/streams": "jsr:@std/streams@^0.224.5", "@std/streams": "jsr:@std/streams@^0.224.5",
"@univoq/": "https://deno.land/x/univoq@0.2.0/", "@univoq/": "https://deno.land/x/univoq@0.2.0/",
"preact": "npm:preact@10.22.0", "preact": "npm:preact@^10.24.2",
"univoq": "https://deno.land/x/univoq@0.2.0/mod.ts", "univoq": "https://deno.land/x/univoq@0.2.0/mod.ts",
"web-push": "npm:web-push@^3.6.7" "web-push": "npm:web-push@^3.6.7"
}, },
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx", "lib": [
"jsxImportSource": "preact" "dom",
"dom.asynciterable",
"dom.iterable",
"deno.ns"
],
"jsx": "precompile",
"jsxImportSource": "preact",
"jsxPrecompileSkipElements": [
"a",
"img",
"source",
"body",
"html",
"head"
]
}, },
"unstable": [ "unstable": [
"kv" "kv"

19
dev.ts
View file

@ -1,14 +1,15 @@
#!/usr/bin/env -S deno run -A --watch=static/,routes/ #!/usr/bin/env -S deno run -A --watch=static/,routes/
import dev from '$fresh/dev.ts' import { Builder } from 'fresh/dev'
import config from './fresh.config.ts' import { app } from './main.ts'
import '$std/dotenv/load.ts'
const builder = new Builder()
const hostname = 'cohabit.localhost' const hostname = 'cohabit.localhost'
await dev(import.meta.url, './main.ts', {
...config, if (Deno.args.includes('build')) {
server: { await builder.build(app)
} else {
await builder.listen(app, {
cert: await Deno.readTextFile('./cert/cohabit.localhost.pem'), cert: await Deno.readTextFile('./cert/cohabit.localhost.pem'),
key: await Deno.readTextFile('./cert/cohabit.localhost-key.pem'), key: await Deno.readTextFile('./cert/cohabit.localhost-key.pem'),
hostname, hostname,
@ -20,5 +21,5 @@ await dev(import.meta.url, './main.ts', {
'color: blue; text-decoration: underline', 'color: blue; text-decoration: underline',
) )
}), }),
}, })
}) }

View file

@ -1,6 +1,6 @@
import { type Signal, useComputed, useSignal } from '@preact/signals' import { type Signal, useComputed, useSignal } from '@preact/signals'
import { useEffect } from 'preact/hooks' import { useEffect } from 'preact/hooks'
import { IS_BROWSER } from '$fresh/runtime.ts' import { IS_BROWSER } from 'fresh/runtime'
type NetworkConnection = { type NetworkConnection = {
addEventListener: ( addEventListener: (

View file

@ -1,5 +1,5 @@
import { useComputed, useSignal, useSignalEffect } from '@preact/signals' import { useComputed, useSignal, useSignalEffect } from '@preact/signals'
import { IS_BROWSER } from '$fresh/runtime.ts' import { IS_BROWSER } from 'fresh/runtime'
export default function ThemePicker() { export default function ThemePicker() {
const colorSchemeQuery = '(prefers-color-scheme: dark)' const colorSchemeQuery = '(prefers-color-scheme: dark)'

39
main.ts
View file

@ -1,13 +1,32 @@
/// <reference no-default-lib="true" /> import { App, fsRoutes, staticFiles } from 'fresh'
/// <reference lib="dom" /> import { type State } from './utils.ts'
/// <reference lib="dom.iterable" /> import { contentType } from 'jsr:@std/media-types@1/content-type'
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />
import '$std/dotenv/load.ts' export const app = new App<State>()
app.use(staticFiles())
import { start } from '$fresh/server.ts' // temp fix before updating cssBundler middleware
import manifest from './fresh.gen.ts' app.use(async (ctx) => {
import config from './fresh.config.ts' const response = await ctx.next()
if (response.status === 404) {
const ext = ctx.url.pathname.split('.').at(-1) ?? '.bin'
const mime = contentType(ext) ?? 'application/octet-stream'
const file = await Deno.readFile(`./_fresh/static/${ctx.url.pathname}`)
return new Response(file, {
headers: {
'Content-Type': mime,
},
})
}
return response
})
await start(manifest, config) await fsRoutes(app, {
dir: './',
loadIsland: (path) => import(`./islands/${path}`),
loadRoute: (path) => import(`./routes/${path}`),
})
if (import.meta.main) {
await app.listen()
}

View file

@ -1,18 +0,0 @@
import { Head } from '$fresh/runtime.ts'
export default function Error404() {
return (
<>
<Head>
<title>Page non trouvée</title>
</Head>
<div>
<h1>Erreur 404 - Page non trouvé</h1>
<p>
La page que vous recherché n'existe pas ou a é supprimée.
</p>
<a href='/'>Retourner à l'accueil</a>
</div>
</>
)
}

View file

@ -1,14 +1,16 @@
import { asset, Head, Partial } from '$fresh/runtime.ts' import { asset, Partial } from 'fresh/runtime'
import { type PageProps } from '$fresh/server.ts' import { type PageProps } from 'fresh'
import { Footer } from ':components/Footer.tsx' import { Footer } from ':components/Footer.tsx'
import { Header } from ':components/Header.tsx' import { Header } from ':components/Header.tsx'
import { ProgressiveWebApp } from ':components/ProgressiveWebApp.tsx' import { ProgressiveWebApp } from ':components/ProgressiveWebApp.tsx'
import IsOnline from ':islands/IsOnline.tsx' import IsOnline from ':islands/IsOnline.tsx'
export default function App({ Component }: PageProps) { export default function App(
{ Component, data }: PageProps<{ title?: string } | undefined>,
) {
return ( return (
<html lang='fr'> <html lang='fr'>
<Head> <head>
<meta charset='utf-8' /> <meta charset='utf-8' />
<meta <meta
name='viewport' name='viewport'
@ -40,7 +42,8 @@ export default function App({ Component }: PageProps) {
/> />
<link rel='stylesheet' href={asset('/main.css')} /> <link rel='stylesheet' href={asset('/main.css')} />
<link rel='stylesheet' href={asset('/imports/markdown_css')} /> <link rel='stylesheet' href={asset('/imports/markdown_css')} />
</Head> <title>{data?.title ?? 'Fablab Coh@bit'}</title>
</head>
<body> <body>
<Header /> <Header />
<IsOnline <IsOnline

40
routes/_error.tsx Normal file
View file

@ -0,0 +1,40 @@
import { HttpError } from 'fresh'
import { define } from '../utils.ts'
export const handler = define.handlers({
GET() {
return { data: { title: 'Page non trouvée' } }
},
})
export default define.page(function ErrorPage(ctx) {
if (!(ctx.error instanceof HttpError)) {
return (
<div>
<h1>Uknown server error</h1>
</div>
)
}
const status = ctx.error.status
if (status === 404) {
return (
<>
<div>
<h1>Erreur 404 - Page non trouvé</h1>
<p>
La page que vous recherché n'existe pas ou a é supprimée.
</p>
<a href='/'>Retourner à l'accueil</a>
</div>
</>
)
}
return (
<div>
<h1>Uknown http error</h1>
</div>
)
})

View file

@ -1,12 +1,14 @@
import { FreshContext } from '$fresh/server.ts'
import { useCache } from ':src/cache/middleware.ts' import { useCache } from ':src/cache/middleware.ts'
import { useCsp } from ':src/csp/middleware.ts' import { useCsp } from ':src/csp/middleware.ts'
import { useSecurityHeaders } from ':src/security_headers/middleware.ts' import { useSecurityHeaders } from ':src/security_headers/middleware.ts'
import { useServiceworker } from ':src/serviceworker/middleware.ts' import { useServiceworker } from ':src/serviceworker/middleware.ts'
import { useSession } from ':src/session/middleware.ts' import { useSession } from ':src/session/middleware.ts'
import { SessionStore } from ':src/session/mod.ts' import { SessionStore } from ':src/session/mod.ts'
import { define } from '../utils.ts'
export default define.middleware(async (ctx) => {
const request = ctx.req
export async function handler(request: Request, ctx: FreshContext) {
// Update fresh context state with session // Update fresh context state with session
ctx.state = { ...ctx.state, session: SessionStore.getFromRequest(request) } ctx.state = { ...ctx.state, session: SessionStore.getFromRequest(request) }
@ -25,4 +27,4 @@ export async function handler(request: Request, ctx: FreshContext) {
useCache(request, response, ctx) useCache(request, response, ctx)
return response return response
} })

View file

@ -1,9 +1,11 @@
import { FreshContext } from '$fresh/server.ts'
import { SessionStore } from ':src/session/mod.ts' import { SessionStore } from ':src/session/mod.ts'
import { respondApi } from ':src/utils.ts' import { respondApi } from ':src/utils.ts'
import { define } from '../../utils.ts'
export function handler(request: Request, ctx: FreshContext) { export const handler = define.handlers((ctx) => {
// Check CSRF token // Check CSRF token
const request = ctx.req
if (['POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'].includes(request.method)) { if (['POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'].includes(request.method)) {
const session = SessionStore.getFromRequest(request) const session = SessionStore.getFromRequest(request)
const csrf = session?.get('_csrf') const csrf = session?.get('_csrf')
@ -14,4 +16,4 @@ export function handler(request: Request, ctx: FreshContext) {
} }
return ctx.next() return ctx.next()
} })

View file

@ -1,7 +1,8 @@
import 'npm:iterator-polyfill' import 'npm:iterator-polyfill'
import { define } from '../../../utils.ts'
// Polyfill AsyncIterator // Polyfill AsyncIterator
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
import { db } from ':src/db/mod.ts' import { db } from ':src/db/mod.ts'
import { SessionHandlers, SessionStore } from ':src/session/mod.ts' import { SessionHandlers, SessionStore } from ':src/session/mod.ts'
import { respondApi } from ':src/utils.ts' import { respondApi } from ':src/utils.ts'
@ -24,9 +25,11 @@ export async function getUserByMail(email: string): Promise<User | undefined> {
return user return user
} }
*/
export const handler: SessionHandlers = { export const handler = define.handlers({})
async POST(request, ctx) { /*
async POST(ctx) {
const request = ctx.req
const { email } = await request.json() as { email: string } const { email } = await request.json() as { email: string }
// check email before continue // check email before continue
@ -118,8 +121,8 @@ export const handler: SessionHandlers = {
401, 401,
) )
}, },
} })
/*
function remoteId( function remoteId(
{ headers }: { headers: Headers }, { headers }: { headers: Headers },
{ remoteAddr }: { remoteAddr: FreshContext['remoteAddr'] }, { remoteAddr }: { remoteAddr: FreshContext['remoteAddr'] },

View file

@ -1,9 +1,9 @@
import { SessionHandlers } from ':src/session/mod.ts' import { define } from '../../../utils.ts'
export const handler: SessionHandlers = { export const handler = define.handlers({
GET(req: Request, ctx) { GET(ctx) {
const { response } = Deno.upgradeWebSocket(req) const { response } = Deno.upgradeWebSocket(ctx.req)
ctx.state.skipMiddlewares = true ctx.state.skipMiddlewares = true
return response return response
}, },
} })

View file

@ -1,9 +1,10 @@
import { Handlers } from '$fresh/server.ts'
import { respondApi } from ':src/utils.ts' import { respondApi } from ':src/utils.ts'
import { publicKey } from ':src/webpush/mod.ts' import { publicKey } from ':src/webpush/mod.ts'
import { define } from '../../../utils.ts'
export const handler: Handlers = { export const handler = define.handlers({
GET() { GET() {
console.log('VAPID', publicKey)
return respondApi('success', publicKey) return respondApi('success', publicKey)
}, },
} })

View file

@ -1,8 +1,8 @@
import { RouteContext } from '$fresh/server.ts' import { define } from '../../utils.ts'
import { BlogPost } from ':components/BlogBlocks.tsx' import { BlogPost } from ':components/BlogBlocks.tsx'
import { fetchNews } from ':src/blog/mod.ts' import { fetchNews } from ':src/blog/mod.ts'
export default async function Blog(_req: Request, { params }: RouteContext) { export default define.page(async ({ params }) => {
try { try {
const article = await fetchNews('cohabit', params.name) const article = await fetchNews('cohabit', params.name)
return BlogPost(article) return BlogPost(article)
@ -14,4 +14,4 @@ export default async function Blog(_req: Request, { params }: RouteContext) {
</> </>
) )
} }
} })

View file

@ -1,9 +1,9 @@
import { PageProps } from '$fresh/server.ts'
import { Markdown } from ':components/Markdown.tsx' import { Markdown } from ':components/Markdown.tsx'
import { db } from ':src/db/mod.ts' import { db } from ':src/db/mod.ts'
import { fetchCarnet } from ':src/members/mod.ts' import { fetchCarnet } from ':src/members/mod.ts'
import { define } from '../../utils.ts'
export default async function Member(_: Request, { params }: PageProps) { export default define.page(async ({ params }) => {
const uuid = params.id as ReturnType<Crypto['randomUUID']> const uuid = params.id as ReturnType<Crypto['randomUUID']>
const user = await db.resource.user.get({ uuid }).catch(() => undefined) const user = await db.resource.user.get({ uuid }).catch(() => undefined)
@ -24,4 +24,4 @@ export default async function Member(_: Request, { params }: PageProps) {
{carnet} {carnet}
</Markdown> </Markdown>
) )
} })

View file

@ -1,7 +1,7 @@
import { Handlers } from '$fresh/server.ts'
import { CSS, KATEX_CSS } from '@deno/gfm' import { CSS, KATEX_CSS } from '@deno/gfm'
import { define } from '../../utils.ts'
export const handler: Handlers = { export const handler = define.handlers({
GET() { GET() {
const styles = CSS + KATEX_CSS const styles = CSS + KATEX_CSS
return new Response(styles, { return new Response(styles, {
@ -11,4 +11,4 @@ export const handler: Handlers = {
}, },
}) })
}, },
} })

View file

@ -1,4 +1,3 @@
import { Head } from '$fresh/runtime.ts'
import { AutoGrid } from ':components/AutoGrid.tsx' import { AutoGrid } from ':components/AutoGrid.tsx'
import { CohabitInfoTable } from ':components/CohabitInfoTable.tsx' import { CohabitInfoTable } from ':components/CohabitInfoTable.tsx'
import { Heros } from ':components/Heros.tsx' import { Heros } from ':components/Heros.tsx'
@ -7,13 +6,17 @@ import { ProjectCard, projectMock } from ':components/ProjectCard.tsx'
import { SponsorCards } from ':components/SponsorCards.tsx' import { SponsorCards } from ':components/SponsorCards.tsx'
import BlogCardList from ':islands/BlogCardList.tsx' import BlogCardList from ':islands/BlogCardList.tsx'
import MemberCardList from ':islands/MemberCardList.tsx' import MemberCardList from ':islands/MemberCardList.tsx'
import { define } from '../utils.ts'
export const handler = define.handlers({
GET() {
return { data: { title: 'Fablab Coh@bit' } }
},
})
export default function Home() { export default function Home() {
return ( return (
<> <>
<Head>
<title>Fablab Coh@bit</title>
</Head>
<Heros /> <Heros />
<section id='first-section'> <section id='first-section'>
<h2>Nos actus</h2> <h2>Nos actus</h2>

View file

@ -1,10 +1,10 @@
import { PageProps } from '$fresh/server.ts' import { define } from '../../utils.ts'
import { MachineCard, machineMock } from ':components/MachineCard.tsx' import { MachineCard, machineMock } from ':components/MachineCard.tsx'
export default function Machine({ params }: PageProps) { export default define.page(({ params }) => {
const machine = machineMock.at(Number(params.id)) const machine = machineMock.at(Number(params.id))
return ( return (
machine ? MachineCard(machine) : <h3>Machine pas encore disponible</h3> machine ? MachineCard(machine) : <h3>Machine pas encore disponible</h3>
) )
} })

View file

@ -1,10 +1,10 @@
import { PageProps } from '$fresh/server.ts'
import { Markdown } from ':components/Markdown.tsx' import { Markdown } from ':components/Markdown.tsx'
import { MemberCard } from ':components/MemberCard.tsx' import { MemberCard } from ':components/MemberCard.tsx'
import { db } from ':src/db/mod.ts' import { db } from ':src/db/mod.ts'
import { fetchProfile, userToMemberCardProps } from ':src/members/mod.ts' import { fetchProfile, userToMemberCardProps } from ':src/members/mod.ts'
import { define } from '../../../utils.ts'
export default async function Member(_: Request, { params, url }: PageProps) { export default define.page(async ({ params, url }) => {
const uuid = params.id as ReturnType<Crypto['randomUUID']> const uuid = params.id as ReturnType<Crypto['randomUUID']>
const user = await db.resource.user.get({ uuid }).catch(() => undefined) const user = await db.resource.user.get({ uuid }).catch(() => undefined)
@ -56,4 +56,4 @@ export default async function Member(_: Request, { params, url }: PageProps) {
</Markdown> </Markdown>
</div> </div>
) )
} })

View file

@ -1,7 +1,7 @@
import { PageProps } from '$fresh/server.ts'
import { ProjectCard, projectMock } from ':components/ProjectCard.tsx' import { ProjectCard, projectMock } from ':components/ProjectCard.tsx'
import { define } from '../../utils.ts'
export default function Projets({ params }: PageProps) { export default define.page(({ params }) => {
const Projets = projectMock.at(Number(params.id)) const Projets = projectMock.at(Number(params.id))
return ( return (
@ -9,4 +9,4 @@ export default function Projets({ params }: PageProps) {
? ProjectCard(Projets) ? ProjectCard(Projets)
: <h3>Projets inconnu, peut être un futur</h3> : <h3>Projets inconnu, peut être un futur</h3>
) )
} })

View file

@ -1,11 +1,11 @@
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
export function useCache( export function useCache(
_request: Request, _request: Request,
response: Response, response: Response,
ctx: FreshContext, ctx: FreshContext,
) { ) {
if (ctx.config.dev) return if (ctx.config.mode === 'development') return
if ( if (
ctx.url.pathname.match( ctx.url.pathname.match(
/(.+\.|_)((css)|(ttf)|(woff2)|(png)|(svg)|(jpe?g)|(avif))/, /(.+\.|_)((css)|(ttf)|(woff2)|(png)|(svg)|(jpe?g)|(avif))/,

View file

@ -1,4 +1,4 @@
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
import { applyCspRulesWithNonce, CspRules } from ':src/csp/mod.ts' import { applyCspRulesWithNonce, CspRules } from ':src/csp/mod.ts'
export function useCsp( export function useCsp(

View file

@ -1,4 +1,4 @@
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
export function useSecurityHeaders( export function useSecurityHeaders(
_request: Request, _request: Request,

View file

@ -1,4 +1,4 @@
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
export function useServiceworker( export function useServiceworker(
_request: Request, _request: Request,

View file

@ -1,4 +1,4 @@
import { FreshContext } from '$fresh/server.ts' import { FreshContext } from 'fresh'
import { SessionStore } from ':src/session/mod.ts' import { SessionStore } from ':src/session/mod.ts'
import { getCookies, setCookie } from 'jsr:@std/http@^0.224.4/cookie' import { getCookies, setCookie } from 'jsr:@std/http@^0.224.4/cookie'

View file

@ -1,4 +1,4 @@
import type { Handlers, PageProps } from '$fresh/server.ts' import type { PageProps, RouteHandler } from 'fresh'
import { getCookies } from '@std/http/cookie' import { getCookies } from '@std/http/cookie'
type SessionEntry<T = unknown> = { type SessionEntry<T = unknown> = {
@ -15,7 +15,7 @@ export type SessionPageProps<T = unknown, S = Record<string, unknown>> =
PageProps<T, S & SessionState> PageProps<T, S & SessionState>
export type SessionHandlers<T = unknown, S = Record<string, unknown>> = export type SessionHandlers<T = unknown, S = Record<string, unknown>> =
Handlers<T, S & SessionState> RouteHandler<T, S & SessionState>
export class SessionStore { export class SessionStore {
static #store = new Map<string, Session>() static #store = new Map<string, Session>()

View file

@ -1,4 +1,4 @@
import { SignalLike } from '$fresh/src/types.ts' import type { Signal } from '@preact/signals'
import { JsonValue } from '$std/json/common.ts' import { JsonValue } from '$std/json/common.ts'
import { decodeBase64 } from '@std/encoding/base64' import { decodeBase64 } from '@std/encoding/base64'
import { JsonStringifyStream } from '@std/json' import { JsonStringifyStream } from '@std/json'
@ -173,7 +173,7 @@ export function base64ToString(base64: string): string {
return new TextDecoder().decode(bytes) return new TextDecoder().decode(bytes)
} }
export function unwrapSignalOrValue<T>(valueOrSignal: T | SignalLike<T>): T { export function unwrapSignalOrValue<T>(valueOrSignal: T | Signal<T>): T {
if (typeof valueOrSignal !== 'object') { if (typeof valueOrSignal !== 'object') {
return valueOrSignal return valueOrSignal
} }

8
utils.ts Normal file
View file

@ -0,0 +1,8 @@
import { createDefine } from 'fresh'
// deno-lint-ignore no-empty-interface
export interface State {
skipMiddlewares?: true
}
export const define = createDefine<State>()