Compare commits
No commits in common. "master-fresh" and "master" have entirely different histories.
master-fre
...
master
42 changed files with 602 additions and 622 deletions
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -1,12 +0,0 @@
|
|||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# Fresh build directory
|
||||
_fresh/
|
||||
# npm dependencies
|
||||
node_modules/
|
||||
/local
|
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"denoland.vscode-deno"
|
||||
]
|
||||
}
|
18
.vscode/settings.json
vendored
18
.vscode/settings.json
vendored
|
@ -1,18 +1,8 @@
|
|||
{
|
||||
"deno.enablePaths": [
|
||||
"./"
|
||||
],
|
||||
"deno.enable": true,
|
||||
"deno.lint": true,
|
||||
"deno.unstable": true,
|
||||
"editor.defaultFormatter": "denoland.vscode-deno",
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||
}
|
||||
"editor.inlayHints.enabled": "off"
|
||||
}
|
||||
|
|
17
README.md
17
README.md
|
@ -1,16 +1,7 @@
|
|||
# Fresh project
|
||||
# Twifeur
|
||||
|
||||
Your new Fresh project is ready to go. You can follow the Fresh "Getting
|
||||
Started" guide here: https://fresh.deno.dev/docs/getting-started
|
||||
Feur
|
||||
|
||||
### Usage
|
||||
## Feur
|
||||
|
||||
Make sure to install Deno: https://deno.land/manual/getting_started/installation
|
||||
|
||||
Then start the project:
|
||||
|
||||
```
|
||||
deno task start
|
||||
```
|
||||
|
||||
This will watch the project directory and restart as necessary.
|
||||
Feur feur.
|
||||
|
|
16
api/login.ts
Normal file
16
api/login.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { login, set_user } from "../lib/auth.ts";
|
||||
|
||||
export async function login_route(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const data = await context.req.formData();
|
||||
let username = data.get("login"), pass = data.get("password");
|
||||
if (username === null || pass === null) return context.redirect("/login");
|
||||
username = username.toString(), pass = pass.toString();
|
||||
const logged = await login(username, pass);
|
||||
if (logged === null) return context.redirect("/login");
|
||||
console.log("Logged in", { username });
|
||||
set_user(context, logged);
|
||||
return context.redirect("/user");
|
||||
}
|
9
api/logout.ts
Normal file
9
api/logout.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { set_user } from "../lib/auth.ts";
|
||||
|
||||
export function logout_route(context: Context<FeurEnv, string, BlankInput>) {
|
||||
set_user(context, null);
|
||||
return context.redirect("/");
|
||||
}
|
72
auth/auth.ts
72
auth/auth.ts
|
@ -1,72 +0,0 @@
|
|||
import { assert } from "$std/assert/assert.ts";
|
||||
import { User } from "../lib/store.ts";
|
||||
import { generate } from "https://deno.land/std@0.224.0/uuid/v1.ts";
|
||||
|
||||
class Authentificator {
|
||||
tokens;
|
||||
user_storage;
|
||||
constructor(user_storage: UserStorage) {
|
||||
this.tokens = new TokenSet();
|
||||
this.user_storage = user_storage;
|
||||
}
|
||||
}
|
||||
|
||||
interface UserStorage {
|
||||
get_user(login: string): User | null;
|
||||
}
|
||||
|
||||
export class Token {
|
||||
raw;
|
||||
user_id;
|
||||
constructor(raw: string, user_id: string) {
|
||||
this.raw = raw;
|
||||
this.user_id = user_id;
|
||||
}
|
||||
}
|
||||
|
||||
class TokenSet {
|
||||
tokens;
|
||||
|
||||
constructor() {
|
||||
this.tokens = new Map<string, Token>();
|
||||
}
|
||||
|
||||
get(token: string) {
|
||||
return this.tokens.get(token) ?? null;
|
||||
}
|
||||
|
||||
create(user_id: string) {
|
||||
const raw = generate();
|
||||
assert(typeof raw == "string");
|
||||
const token = new Token(raw, user_id);
|
||||
this.tokens.set(raw, token);
|
||||
}
|
||||
}
|
||||
|
||||
class StaticUserStorage implements UserStorage {
|
||||
users;
|
||||
|
||||
constructor() {
|
||||
this.users = new Map<string, User>();
|
||||
}
|
||||
|
||||
get_user(user_id: string) {
|
||||
return this.users.get(user_id) ?? null;
|
||||
}
|
||||
|
||||
with(user: User) {
|
||||
this.users.set(user.id, user);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export const auth = new Authentificator(
|
||||
new StaticUserStorage().with({
|
||||
id: "pleinplein",
|
||||
email: "feur@feur.feur",
|
||||
like_set: new Set(),
|
||||
name: "Feur",
|
||||
password: "feurfeur",
|
||||
pfp_url: "https://feur.feur.feur/feur.feur",
|
||||
}),
|
||||
);
|
|
@ -1,12 +0,0 @@
|
|||
import { JSX } from "preact";
|
||||
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||
|
||||
export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
disabled={!IS_BROWSER || props.disabled}
|
||||
class="px-2 py-1 border-gray-500 border-2 rounded bg-white hover:bg-gray-200 transition-colors"
|
||||
/>
|
||||
);
|
||||
}
|
37
deno.json
37
deno.json
|
@ -1,39 +1,6 @@
|
|||
{
|
||||
"lock": false,
|
||||
"tasks": {
|
||||
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
|
||||
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
|
||||
"manifest": "deno task cli manifest $(pwd)",
|
||||
"start": "deno run -A --unstable --watch=static/,routes/ dev.ts",
|
||||
"build": "deno run -A dev.ts build",
|
||||
"preview": "deno run -A main.ts",
|
||||
"update": "deno run -A -r https://fresh.deno.dev/update ."
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"tags": [
|
||||
"fresh",
|
||||
"recommended"
|
||||
]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"**/_fresh/*"
|
||||
],
|
||||
"imports": {
|
||||
"$fresh/": "https://deno.land/x/fresh@1.6.8/",
|
||||
"preact": "https://esm.sh/preact@10.19.6",
|
||||
"preact/": "https://esm.sh/preact@10.19.6/",
|
||||
"@preact/signals": "https://esm.sh/*@preact/signals@1.2.2",
|
||||
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.1",
|
||||
"$std/": "https://deno.land/std@0.216.0/"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact"
|
||||
},
|
||||
"fmt": {
|
||||
"useTabs": true,
|
||||
"lineWidth": 120
|
||||
"lineWidth": 120,
|
||||
"useTabs": true
|
||||
}
|
||||
}
|
||||
|
|
223
deno.lock
generated
Normal file
223
deno.lock
generated
Normal file
|
@ -0,0 +1,223 @@
|
|||
{
|
||||
"version": "3",
|
||||
"packages": {
|
||||
"specifiers": {
|
||||
"npm:@types/node": "npm:@types/node@18.16.19",
|
||||
"npm:hono@^4.0.0": "npm:hono@4.4.0",
|
||||
"npm:iron-webcrypto@0.10.1": "npm:iron-webcrypto@0.10.1"
|
||||
},
|
||||
"npm": {
|
||||
"@types/node@18.16.19": {
|
||||
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"hono@4.4.0": {
|
||||
"integrity": "sha512-Bb2GHk8jmlLIuxc3U+7UBGOoA5lByJTAFnRdH2N2fqEVy9TEQzJ9saIJUQ/ZqBvEvgEFe7UjPFNSFi8cyeU+3Q==",
|
||||
"dependencies": {}
|
||||
},
|
||||
"iron-webcrypto@0.10.1": {
|
||||
"integrity": "sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==",
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redirects": {
|
||||
"https://deno.land/x/deno_dom/deno-dom-wasm.ts": "https://deno.land/x/deno_dom@v0.1.45/deno-dom-wasm.ts",
|
||||
"https://deno.land/x/hono/middleware.ts": "https://deno.land/x/hono@v4.3.10/middleware.ts",
|
||||
"https://deno.land/x/hono_sessions/mod.ts": "https://deno.land/x/hono_sessions@v0.5.8/mod.ts",
|
||||
"https://esm.sh/v135/@types/css@latest/index.d.ts": "https://esm.sh/v135/@types/css@0.0.37/index.d.ts"
|
||||
},
|
||||
"remote": {
|
||||
"https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8",
|
||||
"https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c",
|
||||
"https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||
"https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a",
|
||||
"https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15",
|
||||
"https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c",
|
||||
"https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d",
|
||||
"https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00",
|
||||
"https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808",
|
||||
"https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/build/deno-wasm/deno-wasm.js": "d6841a06342eb6a2798ef28de79ad69c0f2fa349fa04d3ca45e5fcfbf50a9340",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/deno-dom-wasm.ts": "a33d160421bbb6e3104285ea5ebf33352b7ad50d82ea8765e3cf65f972b25119",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/api.ts": "0ff5790f0a3eeecb4e00b7d8fbfa319b165962cf6d0182a65ba90f158d74f7d7",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/constructor-lock.ts": "59714df7e0571ec7bd338903b1f396202771a6d4d7f55a452936bd0de9deb186",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/deserialize.ts": "1cf4096678d8afed8ed28dbad690504c4d2c28149ba768b26eacd1416873425b",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/document-fragment.ts": "1c7352a3c816587ed7fad574b42636198f680f17abc3836fcfe7799b31e7718f",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/document.ts": "a182727dd9179e5712e31be66f4f72b766a5b714c765a75950babe6dd756b4ee",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/dom-parser.ts": "609097b426f8c2358f3e5d2bca55ed026cf26cdf86562e94130dfdb0f2537f92",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/element.ts": "d5371cd83ff2128353c1975465c368ef83d7441568626b386557deba51315111",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/elements/html-template-element.ts": "740b97a5378c9a14cccf3429299846eda240b613013e2d2d7f20b393897453c2",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/html-collection.ts": "829a965f419f8286d5f43a12e27886d10836d519ca2d5e74cb3f2e1d35f35746",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/node-list.ts": "9008303fe236e40e74f9f93e398bd173d2e9b09065932a0153dd0142c759397b",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/node.ts": "3069e6fc93ac4111a136ed68199d76673339842b9751610ba06f111ba7dc10a7",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/custom-api.ts": "852696bd58e534bc41bd3be9e2250b60b67cd95fd28ed16b1deff1d548531a71",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/nwsapi-types.ts": "c43b36c36acc5d32caabaa54fda8c9d239b2b0fcbce9a28efb93c84aa1021698",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/nwsapi.js": "985d7d8fc1eabbb88946b47a1c44c1b2d4aa79ff23c21424219f1528fa27a2ff",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/selectors.ts": "83eab57be2290fb48e3130533448c93c6c61239f2a2f3b85f1917f80ca0fdc75",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/sizzle-types.ts": "78149e2502409989ce861ed636b813b059e16bc267bb543e7c2b26ef43e4798b",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/selectors/sizzle.js": "c3aed60c1045a106d8e546ac2f85cc82e65f62d9af2f8f515210b9212286682a",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/utils-types.ts": "96db30e3e4a75b194201bb9fa30988215da7f91b380fca6a5143e51ece2a8436",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/dom/utils.ts": "4c6206516fb8f61f37a209c829e812c4f5a183e46d082934dd14c91bde939263",
|
||||
"https://deno.land/x/deno_dom@v0.1.45/src/parser.ts": "e06b2300d693e6ae7564e53dfa5c9a9e97fdb8c044c39c52c8b93b5d60860be3",
|
||||
"https://deno.land/x/hono@v4.3.10/adapter/deno/serve-static.ts": "db226d30f08f1a8bb77653ead42a911357b2f8710d653e43c01eccebb424b295",
|
||||
"https://deno.land/x/hono@v4.3.10/client/client.ts": "dcda3887257fa3164db7b32c56665c6e757f0ef047a14f3f9599ef41725c1525",
|
||||
"https://deno.land/x/hono@v4.3.10/client/index.ts": "30def535310a37bede261f1b23d11a9758983b8e9d60a6c56309cee5f6746ab2",
|
||||
"https://deno.land/x/hono@v4.3.10/client/types.ts": "73fbec704cf968ca5c5bba10aa1131758c52ab31a78301451c79cfc47368d43c",
|
||||
"https://deno.land/x/hono@v4.3.10/client/utils.ts": "8be84b49c5c7952666875a8e901fde3044c85c853ea6ba3a7e2c0468478459c0",
|
||||
"https://deno.land/x/hono@v4.3.10/compose.ts": "37d6e33b7db80e4c43a0629b12fd3a1e3406e7d9e62a4bfad4b30426ea7ae4f1",
|
||||
"https://deno.land/x/hono@v4.3.10/context.ts": "facfd749d823a645039571d66d9d228f5ae6836818b65d3b6c4c6891adfe071e",
|
||||
"https://deno.land/x/hono@v4.3.10/helper/adapter/index.ts": "ff7e11eb1ca1fbd74ca3c46cd1d24014582f91491ef6d3846d66ed1cede18ec4",
|
||||
"https://deno.land/x/hono@v4.3.10/helper/cookie/index.ts": "689c84eae410f0444a4598f136a4f859b9122ec6f790dff74412d34405883db8",
|
||||
"https://deno.land/x/hono@v4.3.10/helper/html/index.ts": "48a0ddc576c10452db6c3cab03dd4ee6986ab61ebdc667335b40a81fa0487f69",
|
||||
"https://deno.land/x/hono@v4.3.10/hono-base.ts": "fd7e9c1bba1e13119e95158270011784da3a7c3014c149ba0700e700f840ae0d",
|
||||
"https://deno.land/x/hono@v4.3.10/hono.ts": "23edd0140bf0bd5a68c14ae96e5856a5cec6b844277e853b91025e91ea74f416",
|
||||
"https://deno.land/x/hono@v4.3.10/http-exception.ts": "f5dd375e61aa4b764eb9b99dd45a7160f8317fd36d3f79ae22585b9a5e8ad7c5",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/base.ts": "33f1c302c8f72ae948abd9c3ef85f4b3be6525251a13b95fd18fe2910b7d4a0d",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/children.ts": "26ead0f151faba5307883614b5b064299558f06798c695c432f32acbb1127d56",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/components.ts": "f79ab215f59388f01a69e2d6ec0b841fd3b42ba38e0ee7c93a525cdf06e159f9",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/constants.ts": "984e0797194be1fbc935cb688c8d0a60c112b21bc59301be5354c02232f18820",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/context.ts": "2b7a86e6b35da171fab27aa05f09748bb3eba64b26c037ea1da655c07e8f6bc1",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/components.ts": "733da654edb3d4c178a4479649fac2c64e79069e37e848add0c3a49f90e7f2d7",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/context.ts": "06209d14553398750c69252cc826082018cefa277f5c82cbe58d7261c8a2d81e",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/jsx-dev-runtime.ts": "ba87562d14b77dd5f2a3cc30d41b1eb5edb0800e5f4a7337b5b87b2e66f8a099",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/jsx-runtime.ts": "6a50a65306771a9000030f494d92a5fdeeb055112e0126234b2fd9179de1d4f5",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/render.ts": "7db816d40de58c60e1cbdab64ac3f170b1e30696ed61ad449bbb823f60b46146",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/dom/utils.ts": "5d3e8c14996902db9c1223041fb21480fa0e921a4ccdc59f8c7571c08b7810f2",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/hooks/index.ts": "b7e0f0a754f31a1e1fbe0ac636b38b031603eb0ae195c32a30769a11d79fb871",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/index.ts": "fe3e582c2a4e24e5f8b6027925bddccaae0283747d8f0161eb6f5a34616edd11",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/intrinsic-elements.ts": "21c3a8f6ba07f0d7d7c0ec7293c79c26b9b62df2894e26cb6c17b6c7ec381264",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/streaming.ts": "5e5dde9a546041353b9a3860fc9020471f762813f10e1290009ab6bd40e7bdcf",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/types.ts": "51c2bdbb373860e2570ad403546a7fdbbb1cf00a47ce7ed10b2aece922031ac4",
|
||||
"https://deno.land/x/hono@v4.3.10/jsx/utils.ts": "4b8299d402ba5395472c552d1fe3297ee60112bfc32e0ef86cfe8e40086f7d54",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware.ts": "2e7c6062e36b0e5f84b44a62e7b0e1cef33a9827c19937c648be4b63e1b7d7c6",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/basic-auth/index.ts": "2c8cb563f3b89df1a7a2232be37377c3df6194af38613dc0a823c6595816fc66",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/bearer-auth/index.ts": "b3b7469bc0eb9543c6c47f3ff67de879210dd73063307a61536042ff30e8720e",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/body-limit/index.ts": "3fefeaf7e6e576aa1b33f2694072d2eaab692842acd29cb360d98e20eebfe5aa",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/cache/index.ts": "5e6273e5c9ea73ef387b25923ab23274c220b29d7c981b62ac0be26d6a1aa3d8",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/compress/index.ts": "98c403a5fe7e9c5f5d776350b422b0a125fb34696851b8b14f825b9b7b06f2ac",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/cors/index.ts": "976eb9ce8cefc214b403a2939503a13177cec76223274609a07ca554e0dc623b",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/csrf/index.ts": "077bb0ce299d79d0d232cb9e462aaa4eaa901164f1310f74a7630f7e6cfe74e8",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/etag/index.ts": "95e0270ea349cf00537ee6e58985a4cc7dba44091ca8e2dc42b6d8b2f01bcfe7",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/jsx-renderer/index.ts": "229322c66ebc7f426cd2d71f282438025b4ee7ce8cb8e97e87c7efbc94530c19",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/jwt/index.ts": "4cb997d3d7a09d0b0c0e273841d29729e13e35dfc00021089aebaad868a7f8c6",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/logger/index.ts": "52a2e968890ada2c11ce89a7a783692c5767b8ed7fb23ccf6b559d255d13ccbc",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/method-override/index.ts": "bc13bdcf70c777b72b1300a5cca1b51a8bd126e0d922b991d89e96fe7c694b5b",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/powered-by/index.ts": "6faba0cf042278d60b317b690640bb0b58747690cf280fa09024424c5174e66d",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/pretty-json/index.ts": "2216ce4c9910be009fecac63367c3626b46137d4cf7cb9a82913e501104b4a88",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/secure-headers/index.ts": "f2e4c3858d26ff47bc6909513607e6a3c31184aabe78fb272ed08e1d62a750f0",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/serve-static/index.ts": "14b760bbbc4478cc3a7fb9728730bc6300581c890365b7101b80c16e70e4b21e",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/timing/index.ts": "6fddbb3e47ae875c16907cf23b9bb503ec2ad858406418b5f38f1e7fbca8c6f6",
|
||||
"https://deno.land/x/hono@v4.3.10/middleware/trailing-slash/index.ts": "419cf0af99a137f591b72cc71c053e524fe3574393ce81e0e9dbce84a4046e24",
|
||||
"https://deno.land/x/hono@v4.3.10/mod.ts": "35fd2a2e14b52365e0ad66f168b067363fd0a60d75cbcb1b01685b04de97d60e",
|
||||
"https://deno.land/x/hono@v4.3.10/request.ts": "7b08602858e642d1626c3106c0bedc2aa8d97e30691a079351d9acef7c5955e6",
|
||||
"https://deno.land/x/hono@v4.3.10/router.ts": "880316f561918fc197481755aac2165fdbe2f530b925c5357a9f98d6e2cc85c7",
|
||||
"https://deno.land/x/hono@v4.3.10/router/linear-router/index.ts": "8a2a7144c50b1f4a92d9ee99c2c396716af144c868e10608255f969695efccd0",
|
||||
"https://deno.land/x/hono@v4.3.10/router/linear-router/router.ts": "928d29894e4b45b047a4f453c7f1745c8b1869cd68447e1cb710c7bbf99a4e29",
|
||||
"https://deno.land/x/hono@v4.3.10/router/pattern-router/index.ts": "304a66c50e243872037ed41c7dd79ed0c89d815e17e172e7ad7cdc4bc07d3383",
|
||||
"https://deno.land/x/hono@v4.3.10/router/pattern-router/router.ts": "1b5f68e6af942579d3a40ee834294fea3d1f05fd5f70514e46ae301dd0107e46",
|
||||
"https://deno.land/x/hono@v4.3.10/router/reg-exp-router/index.ts": "52755829213941756159b7a963097bafde5cc4fc22b13b1c7c9184dc0512d1db",
|
||||
"https://deno.land/x/hono@v4.3.10/router/reg-exp-router/node.ts": "7efaa6f4301efc2aad0519c84973061be8555da02e5868409293a1fd98536aaf",
|
||||
"https://deno.land/x/hono@v4.3.10/router/reg-exp-router/router.ts": "632f2fa426b3e45a66aeed03f7205dad6d13e8081bed6f8d1d987b6cad8fb455",
|
||||
"https://deno.land/x/hono@v4.3.10/router/reg-exp-router/trie.ts": "852ce7207e6701e47fa30889a0d2b8bfcd56d8862c97e7bc9831e0a64bd8835f",
|
||||
"https://deno.land/x/hono@v4.3.10/router/smart-router/index.ts": "74f9b4fe15ea535900f2b9b048581915f12fe94e531dd2b0032f5610e61c3bef",
|
||||
"https://deno.land/x/hono@v4.3.10/router/smart-router/router.ts": "dc22a8505a0f345476f07dca3054c0c50a64d7b81c9af5a904476490dfd5cbb4",
|
||||
"https://deno.land/x/hono@v4.3.10/router/trie-router/index.ts": "3eb75e7f71ba81801631b30de6b1f5cefb2c7239c03797e2b2cbab5085911b41",
|
||||
"https://deno.land/x/hono@v4.3.10/router/trie-router/node.ts": "d3e00e8f1ba7fb26896459d5bba882356891a07793387c4655d1864c519a91de",
|
||||
"https://deno.land/x/hono@v4.3.10/router/trie-router/router.ts": "54ced78d35676302c8fcdda4204f7bdf5a7cc907fbf9967c75674b1e394f830d",
|
||||
"https://deno.land/x/hono@v4.3.10/types.ts": "b561c3ee846121b33c2d81331246cdedf7781636ed72dad7406677105b4275de",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/body.ts": "774cb319dfbe886a9d39f12c43dea15a39f9d01e45de0323167cdd5d0aad14d4",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/buffer.ts": "2fae689954b427b51fb84ad02bed11a72eae96692c2973802b3b4c1e39cd5b9c",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/color.ts": "10575c221f48bc806887710da8285f859f51daf9e6878bbdf99cb406b8494457",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/cookie.ts": "662529d55703d2c0bad8736cb1274eb97524c0ef7882d99254fc7c8fa925b46c",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/crypto.ts": "bda0e141bbe46d3a4a20f8fbcb6380d473b617123d9fdfa93e4499410b537acc",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/encode.ts": "311dfdfae7eb0b6345e9680f7ebbb3a692e872ed964e2029aca38567af8d1f33",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/filepath.ts": "a83e5fe87396bb291a6c5c28e13356fcbea0b5547bad2c3ba9660100ff964000",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/html.ts": "6ea4f6bf41587a51607dff7a6d2865ef4d5001e4203b07e5c8a45b63a098e871",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/http-status.ts": "f5b820f2793e45209f34deddf147b23e3133a89eb4c57dc643759a504706636b",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/index.ts": "3b66f48cdd3fcc2caed5e908ca31776e11b1c30391008931276da3035e6ba1e9",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/jwa.ts": "6874cacd8b6dde386636b81b5ea2754f8e4c61757802fa908dd1ce54b91a52fa",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/jws.ts": "878fa7d1966b0db20ae231cfee279ba2bb198943e949049cab3f5845cd5ee2d1",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/jwt.ts": "80452edc3498c6670a211fdcd33cfc4d5c00dfac79aa9f403b0623dedc039554",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/types.ts": "b6659ac85e7f8fcdd8cdfc7d51f5d1a91107ad8dfb647a8e4ea9c80f0f02afee",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/jwt/utf8.ts": "17c507f68f23ccb82503ea6183e54b5f748a6fe621eb60994adfb4a8c2a3f561",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/mime.ts": "d1fc2c047191ccb01d736c6acf90df731324536298181dba0ecc2259e5f7d661",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/types.ts": "050bfa9dc6d0cc4b7c5069944a8bd60066c2f9f95ee69833623ad104f11f92bf",
|
||||
"https://deno.land/x/hono@v4.3.10/utils/url.ts": "855169632c61d03703bd08cafb27664ba3fdb352892f01687d5cce8fd49e3cb1",
|
||||
"https://deno.land/x/hono@v4.3.10/validator/index.ts": "6c986e8b91dcf857ecc8164a506ae8eea8665792a4ff7215471df669c632ae7c",
|
||||
"https://deno.land/x/hono@v4.3.10/validator/validator.ts": "53f3d2ad442e22f0bc2d85b7d8d90320d4e5ecf5fdd58882f906055d33a18e13",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/deps.ts": "a86ee9f6d96c0dcc80380eaa3d1cef13ff972a56003d8e1d7f461cc32554fa34",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/mod.ts": "67e89aebb3c0e87e7e6065aefb56606d2f1017dd8ed030ef742f5bb73398abda",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Crypto.ts": "dcbf1dc60d5c67426f3a25bcd56a38012336c2418ab1291550f2fa1f76b66e25",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Middleware.ts": "05879181e4f649098c05800a47c12c21649dde41f8d21aceefc7b2dbb91b261b",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/Session.ts": "9de1c3661a9b713a4eded0457a60432a96118be59741cb32e43c39a437da33cd",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/CookieStore.ts": "9175f9da3e555c0e07928db03bb26ad40b6b0c1f661bfccd9aeddad0a615ccc2",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/MemoryStore.ts": "f702d81a948a775207f047b60e2dd6c903a4b25b041c827309486055be3103fd",
|
||||
"https://deno.land/x/hono_sessions@v0.5.8/src/store/Store.ts": "8f26b96fa22c330846ccb318cb90d3d1135aec9078c0faa7b5dc39ceb49a0da4",
|
||||
"https://deno.land/x/zod@v3.22.4/ZodError.ts": "4de18ff525e75a0315f2c12066b77b5c2ae18c7c15ef7df7e165d63536fdf2ea",
|
||||
"https://deno.land/x/zod@v3.22.4/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef",
|
||||
"https://deno.land/x/zod@v3.22.4/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/parseUtil.ts": "f791e6e65a0340d85ad37d26cd7a3ba67126cd9957eac2b7163162155283abb1",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e",
|
||||
"https://deno.land/x/zod@v3.22.4/helpers/util.ts": "8baf19b19b2fca8424380367b90364b32503b6b71780269a6e3e67700bb02774",
|
||||
"https://deno.land/x/zod@v3.22.4/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268",
|
||||
"https://deno.land/x/zod@v3.22.4/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c",
|
||||
"https://deno.land/x/zod@v3.22.4/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4",
|
||||
"https://deno.land/x/zod@v3.22.4/types.ts": "724185522fafe43ee56a52333958764c8c8cd6ad4effa27b42651df873fc151e",
|
||||
"https://esm.sh/jsdom@22.1.0": "2efb54a90536dc0f4bb00f442c32fcedb2224af5aad5c87db87660f15c013170",
|
||||
"https://esm.sh/v128/@tootallnate/once@2.0.0/denonext/once.mjs": "2c69d53dd1de1d7e5f9a78d46041f5d869f7d058f22d72e7f25821e61dddd147",
|
||||
"https://esm.sh/v128/abab@2.0.6/denonext/abab.mjs": "7101c07a728882d686222e5f5c5a6fa956a558e4f406c521f1c0b61bc60cd07d",
|
||||
"https://esm.sh/v128/agent-base@6.0.2/denonext/agent-base.mjs": "73a5fb40647fa22367f61cb5573a0404c21fed9d86445d21ece399ff47e097ad",
|
||||
"https://esm.sh/v128/bufferutil@4.0.7/denonext/bufferutil.mjs": "f08b440283b2993a9e360b0e092c1714bc689230323961d60d7aad805b79c026",
|
||||
"https://esm.sh/v128/canvas@2.11.2/denonext/canvas.mjs": "4245b1d01d91b5e807b85e40e98efe28c93634260bd8cb5ac0da71c42098a1a4",
|
||||
"https://esm.sh/v128/cssstyle@3.0.0/denonext/cssstyle.mjs": "4fe8a9be3507541807575ed9254ca9e74c3ad950777a4478876ed52ac9c2e6da",
|
||||
"https://esm.sh/v128/data-urls@4.0.0/denonext/data-urls.mjs": "fa125b728922f32cac094291ac3b8c0abcfac2c9963ee2c6280769f0e972519d",
|
||||
"https://esm.sh/v128/debug@4.3.4/denonext/debug.mjs": "b837e7a39e434a676c751cd5ebd29351d8ad48d083006582edcf40361cadeccc",
|
||||
"https://esm.sh/v128/decimal.js@10.4.3/denonext/decimal.mjs": "ece864b80732112b324aed7fd89ec03128627206e1e4b30057651f495b594dee",
|
||||
"https://esm.sh/v128/domexception@4.0.0/denonext/webidl2js-wrapper.js": "d5c3a0961bc0fe877f335ade79e191d3e0848785a6b4521f67c54303f0c5a39d",
|
||||
"https://esm.sh/v128/entities@4.5.0/denonext/lib/decode.js": "7fea6d8bd725edbbf7ea05031d2ea1bbbc1166dc11e3345d541198dd2dc16f1e",
|
||||
"https://esm.sh/v128/entities@4.5.0/denonext/lib/escape.js": "7ebdc622bf3618bab25db40da4a49e2b9d03f044745f125f0bc3359f2d060def",
|
||||
"https://esm.sh/v128/form-data@4.0.0/denonext/form-data.mjs": "48e84ac3b590bc364839367938d7e48ca37615a0c66e56dcc7356c3172ec7790",
|
||||
"https://esm.sh/v128/html-encoding-sniffer@3.0.0/denonext/html-encoding-sniffer.mjs": "e5ca81202625bbf8802002b420cad9ddd1facb5ebd834c3a23bbac0a2362bbbc",
|
||||
"https://esm.sh/v128/http-proxy-agent@5.0.0/denonext/http-proxy-agent.mjs": "b17dce342ba465c56d371c0ce5c0ee4ab56182bf878e465695c24380acebf29f",
|
||||
"https://esm.sh/v128/https-proxy-agent@5.0.1/denonext/https-proxy-agent.mjs": "e250f991702f9f98f94e631d4d1a4a90020ddc667686c86390af1c50fa585f30",
|
||||
"https://esm.sh/v128/iconv-lite@0.6.3/denonext/iconv-lite.mjs": "5840545a9ac1cea4684c800dfafca7200d8b0b7ea0f561b85c8445c12fc004d8",
|
||||
"https://esm.sh/v128/is-potential-custom-element-name@1.0.1/denonext/is-potential-custom-element-name.mjs": "de2781ef99795b662f43c0840c3dcfdc303f9e60a75e66924370f902133469ed",
|
||||
"https://esm.sh/v128/jsdom@22.1.0/denonext/jsdom.mjs": "de374334080b3d18ac730f117aceab674e50642285a3f94f3b7db5de04c6798b",
|
||||
"https://esm.sh/v128/ms@2.1.2/denonext/ms.mjs": "aa4dc45ba72554c5011168f8910cc646c37af53cfff1a15a4decced838b8eb14",
|
||||
"https://esm.sh/v128/node-gyp-build@4.6.0/denonext/node-gyp-build.mjs": "0de7d4d97a896a89efb9b3a31a0746f89f5c0e86d7f92badd0fddc3cd22ca40b",
|
||||
"https://esm.sh/v128/nwsapi@2.2.6/denonext/nwsapi.mjs": "def5ad23c81fba69b806c0daf07c6b932a8069715e41404d27fe443cd46d75bd",
|
||||
"https://esm.sh/v128/parse5@7.1.2/denonext/parse5.mjs": "9885dc571f470bdb484d8f0e1dbab42af18f406200ed5bcf7ebb9c183faa32ae",
|
||||
"https://esm.sh/v128/psl@1.9.0/denonext/psl.mjs": "f40e9bcba5f6602eeb677f85f8e2b5c24b706bade58ced5b272044ebea609d9b",
|
||||
"https://esm.sh/v128/querystringify@2.2.0/denonext/querystringify.mjs": "4f0f639f99ec4a7ddaffb886bd7e6f3fe4b088e1fcd60336dd10d447d2093ef6",
|
||||
"https://esm.sh/v128/requires-port@1.0.0/denonext/requires-port.mjs": "c4f20b71539d08fc2662d75dfd79881fce985a0e4592268f18ac13bf53679efa",
|
||||
"https://esm.sh/v128/rrweb-cssom@0.6.0/denonext/rrweb-cssom.mjs": "e2a14692d801a24edadd3fd4ecdf017382494258064134e33390a6bf1146950d",
|
||||
"https://esm.sh/v128/safer-buffer@2.1.2/denonext/safer-buffer.mjs": "ce0e787812c668ba082ad5b75958490c714b6e05836bd5b6013d9f75727c006f",
|
||||
"https://esm.sh/v128/saxes@6.0.0/denonext/saxes.mjs": "51f5349277fb67f314089490b16b9732fc85e85eae0c2ae6c5efcb965a57260f",
|
||||
"https://esm.sh/v128/symbol-tree@3.2.4/denonext/symbol-tree.mjs": "67199d1e47bd6e5b7d2715dd04d25658061c95fc4464f7d200b6aab9e439b5f4",
|
||||
"https://esm.sh/v128/tough-cookie@4.1.3/denonext/tough-cookie.mjs": "f9f24f23ada31799b530ed23b265f7cf5e17b70b8141687ee0c3e613ef55d766",
|
||||
"https://esm.sh/v128/tr46@4.1.1/denonext/tr46.mjs": "2042307b546151186c6912a27265e444331e3d0bd6820c92a750aa67b3e5fdfc",
|
||||
"https://esm.sh/v128/universalify@0.2.0/denonext/universalify.mjs": "6ebb2a9b372d4ae89f494d9b0044942dc76a5b5fb366ab3018e2bf0aeb8eae94",
|
||||
"https://esm.sh/v128/url-parse@1.5.10/denonext/url-parse.mjs": "f04a3a5b4b960a62bab9c4dc9a4f8cfe3094ce24cc870c979b6cf9c3890c9a19",
|
||||
"https://esm.sh/v128/utf-8-validate@6.0.3/denonext/utf-8-validate.mjs": "5f09fc9a7a6d2ed3fedf17fbfee3d906fb3acecfe18e9351de026b857e4b1d86",
|
||||
"https://esm.sh/v128/w3c-xmlserializer@4.0.0/denonext/w3c-xmlserializer.mjs": "e23495a59a8c55bf3c1202a2e7ee4b1c8e25d1c6be14f5872d51ef8e50f6382f",
|
||||
"https://esm.sh/v128/webidl-conversions@7.0.0/denonext/webidl-conversions.mjs": "04e3e6917179380727c6f65cd16a5a89836fb5a104fe5524c10a0a697f88d552",
|
||||
"https://esm.sh/v128/whatwg-encoding@2.0.0/denonext/whatwg-encoding.mjs": "3483d367364a2aaf503a4fc0e56e6163c88c50d1aede2117c9ec264ea558e0a6",
|
||||
"https://esm.sh/v128/whatwg-mimetype@3.0.0/denonext/whatwg-mimetype.mjs": "59446370c8333e5956416535e9773585645c22e7ea3420c8df5d78d1e9127c59",
|
||||
"https://esm.sh/v128/whatwg-url@12.0.1/denonext/webidl2js-wrapper.js": "d9a6264ca46bf11a22eb24577dd549f2c5778fb0ec4783e69ff9a705a8aa3baa",
|
||||
"https://esm.sh/v128/whatwg-url@12.0.1/denonext/whatwg-url.mjs": "efecc5954d62474ceb6a528a81e8b6503ab2473f0913fa2341ddcf381651bbf9",
|
||||
"https://esm.sh/v128/ws@8.13.0/denonext/ws.mjs": "9891167e91ecedb8aa3e01398b564429aff5538ba58a9f27c680552b7ccab835",
|
||||
"https://esm.sh/v128/xml-name-validator@4.0.0/denonext/xml-name-validator.mjs": "69af66c891312f304a8be720961ad5cce5c49c85a3bba03275b56a70dec7a21e",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xml/1.0/ed5.js": "60f8f018eb1d79d69a41324155b7d9f52f1058b37060b28acc1dfc49446e549d",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xml/1.1/ed2.js": "ba7d1fe5694f62469c4b293a1fadad332c637cbcfbc74147a296475c2ff8ad3d",
|
||||
"https://esm.sh/v128/xmlchars@2.2.0/denonext/xmlns/1.0/ed3.js": "929d15ffc72d56c8909f87e7df8288f060bda0256622e8e95c24f0decb06adc7",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/mod.ts": "bc9436bcf45f3204ebcd0b2559f53e5d38162195fc48ac6d435cf8ca38c77ae3",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/entry.ts": "243a53b27e494c01e944331e2b71dfbe96ff906921aca8870603eb19bbce8235",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/lib.ts": "76973ce240e2bcadaf13e43115d050dee70b92dc5cd7cd726cdd5d9adf4c1ad6",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/store.ts": "ff6cdb0c045818d8e4ab6eb2bb304db8ac387ef05514af09e6c731bb65815a10",
|
||||
"https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/src/typing.ts": "cb0d315461aab883ddd2396f5a5ce2a88615257b402d5a5cd06c10dc44ffa453"
|
||||
}
|
||||
}
|
8
dev.ts
8
dev.ts
|
@ -1,8 +0,0 @@
|
|||
#!/usr/bin/env -S deno run -A --watch=static/,routes/
|
||||
|
||||
import dev from "$fresh/dev.ts";
|
||||
import config from "./fresh.config.ts";
|
||||
|
||||
import "$std/dotenv/load.ts";
|
||||
|
||||
await dev(import.meta.url, "./main.ts", config);
|
|
@ -1,46 +0,0 @@
|
|||
## Views
|
||||
|
||||
- Home
|
||||
- Landing
|
||||
- Feed (logged)
|
||||
|
||||
- Post
|
||||
- new
|
||||
- view
|
||||
- likes
|
||||
- add (logged)
|
||||
- comment section
|
||||
- new (logged)
|
||||
|
||||
- Account
|
||||
- Login
|
||||
- Register
|
||||
|
||||
## Models
|
||||
|
||||
- User
|
||||
- name
|
||||
- email
|
||||
- password
|
||||
- pfp_url
|
||||
- like_set
|
||||
* posts
|
||||
* comments
|
||||
|
||||
- Post
|
||||
- title
|
||||
- content
|
||||
- date
|
||||
- like_count
|
||||
+ author
|
||||
* comments
|
||||
|
||||
- Comment
|
||||
- date
|
||||
+ post
|
||||
+ author
|
||||
|
||||
---
|
||||
|
||||
- trend algo ?
|
||||
- notifications ?
|
|
@ -1,3 +0,0 @@
|
|||
import { defineConfig } from "$fresh/server.ts";
|
||||
|
||||
export default defineConfig({});
|
31
fresh.gen.ts
31
fresh.gen.ts
|
@ -1,31 +0,0 @@
|
|||
// DO NOT EDIT. This file is generated by Fresh.
|
||||
// This file SHOULD be checked into source version control.
|
||||
// This file is automatically updated during development when running `dev.ts`.
|
||||
|
||||
import * as $_404 from "./routes/_404.tsx";
|
||||
import * as $_app from "./routes/_app.tsx";
|
||||
import * as $_middleware from "./routes/_middleware.ts";
|
||||
import * as $api_joke from "./routes/api/joke.ts";
|
||||
import * as $feur from "./routes/feur.tsx";
|
||||
import * as $greet_name_ from "./routes/greet/[name].tsx";
|
||||
import * as $index from "./routes/index.tsx";
|
||||
import * as $Counter from "./islands/Counter.tsx";
|
||||
import { type Manifest } from "$fresh/server.ts";
|
||||
|
||||
const manifest = {
|
||||
routes: {
|
||||
"./routes/_404.tsx": $_404,
|
||||
"./routes/_app.tsx": $_app,
|
||||
"./routes/_middleware.ts": $_middleware,
|
||||
"./routes/api/joke.ts": $api_joke,
|
||||
"./routes/feur.tsx": $feur,
|
||||
"./routes/greet/[name].tsx": $greet_name_,
|
||||
"./routes/index.tsx": $index,
|
||||
},
|
||||
islands: {
|
||||
"./islands/Counter.tsx": $Counter,
|
||||
},
|
||||
baseUrl: import.meta.url,
|
||||
} satisfies Manifest;
|
||||
|
||||
export default manifest;
|
|
@ -1,16 +0,0 @@
|
|||
import type { Signal } from "@preact/signals";
|
||||
import { Button } from "../components/Button.tsx";
|
||||
|
||||
interface CounterProps {
|
||||
count: Signal<number>;
|
||||
}
|
||||
|
||||
export default function Counter(props: CounterProps) {
|
||||
return (
|
||||
<div class="flex gap-8 py-6">
|
||||
<Button onClick={() => props.count.value -= 1}>-1</Button>
|
||||
<p class="text-3xl tabular-nums">{props.count}</p>
|
||||
<Button onClick={() => props.count.value += 1}>+1</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
24
lib/auth.ts
Normal file
24
lib/auth.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { db, User } from "./storage.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
|
||||
export async function login(login: string, password: string) {
|
||||
for await (const user of db.all("user")) {
|
||||
if (await user.get("username") !== login) continue;
|
||||
if (await user.get("password") === password) return user;
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function get_user(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const id = context.get("session").get("user");
|
||||
if (typeof id !== "string") return null;
|
||||
return await db.get("user", id);
|
||||
}
|
||||
|
||||
export function set_user(context: Context<FeurEnv, string, BlankInput>, user: User | null) {
|
||||
if (user === null) context.get("session").set("user", "");
|
||||
else context.get("session").set("user", user.id);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import { z } from "https://deno.land/x/zod@v3.23.8/mod.ts";
|
||||
|
||||
export const UserModel = z.object({
|
||||
id: z.string().uuid().describe("primary"),
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
password: z.string(),
|
||||
pfp_url: z.string(),
|
||||
});
|
36
lib/storage.ts
Normal file
36
lib/storage.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import {
|
||||
EntryFor,
|
||||
Schema,
|
||||
Store,
|
||||
} from "https://git.barnulf.net/mb/debilus/raw/commit/fc701bec680dd73be29c72164f47ee87fac540c7/mod.ts";
|
||||
import { project_root } from "./utils.ts";
|
||||
|
||||
export const db = await Store.open(
|
||||
new Schema({
|
||||
user: {
|
||||
username: "string",
|
||||
password: "string",
|
||||
upvoted_posts: ["many", "post"],
|
||||
upvoted_comments: ["many", "comment"],
|
||||
posts: ["many", "post"],
|
||||
},
|
||||
post: {
|
||||
title: "string",
|
||||
content: "string",
|
||||
upvotes: "number",
|
||||
author: ["one", "user"],
|
||||
comments: ["many", "comment"],
|
||||
},
|
||||
comment: {
|
||||
content: "string",
|
||||
upvotes: "number",
|
||||
author: ["one", "user"],
|
||||
post: ["one", "post"],
|
||||
},
|
||||
}),
|
||||
`${project_root()}/local/db.kv`,
|
||||
);
|
||||
|
||||
export type User = EntryFor<typeof db, "user">;
|
||||
export type Post = EntryFor<typeof db, "post">;
|
||||
export type Comment = EntryFor<typeof db, "comment">;
|
57
lib/store.ts
57
lib/store.ts
|
@ -1,57 +0,0 @@
|
|||
import { createPentagon } from "https://deno.land/x/pentagon@v0.1.5/mod.ts";
|
||||
import { project_root_dir } from "../utils.ts";
|
||||
import { z } from "https://deno.land/x/zod@v3.21.4/mod.ts";
|
||||
|
||||
const kv = await Deno.openKv(project_root_dir() + "local/kv");
|
||||
|
||||
export type User = z.infer<typeof user_model>;
|
||||
export const user_model = z.object({
|
||||
id: z.string().uuid().describe("primary"),
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
password: z.string(),
|
||||
pfp_url: z.string(),
|
||||
like_set: z.set(z.string().uuid()),
|
||||
});
|
||||
|
||||
export type Post = z.infer<typeof post_model>;
|
||||
export const post_model = z.object({
|
||||
id: z.string().uuid().describe("primary"),
|
||||
title: z.string(),
|
||||
content: z.string(),
|
||||
date: z.number(),
|
||||
like_count: z.number(),
|
||||
author_id: z.string().uuid(),
|
||||
});
|
||||
|
||||
export type Comment = z.infer<typeof comment_model>;
|
||||
export const comment_model = z.object({
|
||||
id: z.string().uuid().describe("primary"),
|
||||
date: z.number(),
|
||||
post_id: z.string().uuid(),
|
||||
author_id: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const db = createPentagon(kv, {
|
||||
users: {
|
||||
schema: user_model,
|
||||
relations: {
|
||||
posts: ["posts", [post_model], "id", "author_id"],
|
||||
comments: ["comments", [comment_model], "id", "author_id"],
|
||||
},
|
||||
},
|
||||
posts: {
|
||||
schema: post_model,
|
||||
relations: {
|
||||
author: ["users", user_model, "author_id", "id"],
|
||||
comments: ["comments", [comment_model], "id", "post_id"],
|
||||
},
|
||||
},
|
||||
comments: {
|
||||
schema: comment_model,
|
||||
relations: {
|
||||
author: ["users", user_model, "author_id", "id"],
|
||||
post: ["post", post_model, "post_id", "id"],
|
||||
},
|
||||
},
|
||||
});
|
14
lib/utils.ts
Normal file
14
lib/utils.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { dirname } from "https://deno.land/std@0.224.0/path/dirname.ts";
|
||||
|
||||
import { CSSProperties } from "https://deno.land/std@0.40.0/types/react.d.ts";
|
||||
|
||||
export function _css(prop: CSSProperties) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
export function project_root() {
|
||||
const this_url = new URL(import.meta.url);
|
||||
const this_abs_path = Deno.realPathSync(this_url.pathname);
|
||||
const lib_path = dirname(this_abs_path);
|
||||
return dirname(lib_path);
|
||||
}
|
2
local/.gitignore
vendored
Normal file
2
local/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!/.gitignore
|
41
main.ts
Normal file → Executable file
41
main.ts
Normal file → Executable file
|
@ -1,14 +1,33 @@
|
|||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
/// <reference lib="dom.asynciterable" />
|
||||
/// <reference lib="deno.ns" />
|
||||
/// <reference lib="deno.unstable" />
|
||||
#!/bin/env -S deno run --allow-net --unstable-kv --watch --allow-read=./pages,./local,./lib,. --allow-write=./local
|
||||
|
||||
import "$std/dotenv/load.ts";
|
||||
import { Hono } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { serveStatic } from "https://deno.land/x/hono@v4.3.10/middleware.ts";
|
||||
import { CookieStore, Session, sessionMiddleware } from "https://deno.land/x/hono_sessions@v0.5.8/mod.ts";
|
||||
|
||||
import { start } from "$fresh/server.ts";
|
||||
import manifest from "./fresh.gen.ts";
|
||||
import config from "./fresh.config.ts";
|
||||
export type FeurEnv = { Variables: { session: Session } };
|
||||
const app = new Hono<FeurEnv>();
|
||||
|
||||
await start(manifest, config);
|
||||
app.use("/static/*", serveStatic({ root: "./pages/" }));
|
||||
|
||||
const store = new CookieStore();
|
||||
const encryptionKey = "FeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeurFeur";
|
||||
app.use("*", sessionMiddleware({ store, encryptionKey }));
|
||||
|
||||
app.get("/", (c) => c.redirect("/home"));
|
||||
|
||||
import HomePage from "./pages/home.tsx";
|
||||
app.get("/home", (c) => c.html(HomePage(c)));
|
||||
|
||||
import LoginPage from "./pages/login.tsx";
|
||||
app.get("/login", (c) => c.html(LoginPage()));
|
||||
|
||||
import { login_route } from "./api/login.ts";
|
||||
app.post("/api/login", (c) => login_route(c));
|
||||
|
||||
import { logout_route } from "./api/logout.ts";
|
||||
app.get("/api/logout", (c) => logout_route(c));
|
||||
|
||||
import UserPage from "./pages/user.tsx";
|
||||
app.get("/user", async (c) => await UserPage(c));
|
||||
|
||||
Deno.serve(app.fetch);
|
||||
|
|
22
pages/components/base.tsx
Normal file
22
pages/components/base.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { PropsWithChildren, jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { _css } from "../../lib/utils.ts";
|
||||
|
||||
export function BasePage({ name, children }: PropsWithChildren<{ name: string }>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="UTF-8"/>
|
||||
<title>{name} - Twifeur</title>
|
||||
<link rel="stylesheet" href="/static/style.css" />
|
||||
</head>
|
||||
<body style={_css({
|
||||
width: "100%",
|
||||
minHeight: "100%",
|
||||
})}>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
53
pages/components/heading.tsx
Normal file
53
pages/components/heading.tsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { PropsWithChildren, jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { _css } from "../../lib/utils.ts";
|
||||
import { User } from "../../lib/storage.ts";
|
||||
|
||||
//
|
||||
export default function Heading({ username }: PropsWithChildren<{username: string | null}>) {
|
||||
return (
|
||||
<header style={_css({
|
||||
width: "100vw",
|
||||
display: "grid",
|
||||
placeContent: "center",
|
||||
backgroundColor: "#202020",
|
||||
borderBottom: "1px solid #444",
|
||||
boxShadow: "0px 0px 10px #0008",
|
||||
position: "fixed",
|
||||
})}>
|
||||
<div style={_css({
|
||||
width: "100vw",
|
||||
maxWidth: "900px",
|
||||
display: "flex",
|
||||
})}>
|
||||
<div style={_css({
|
||||
borderLeft: '1px solid #444',
|
||||
borderRight: '1px solid #444',
|
||||
})}>
|
||||
<h1 style={_css({
|
||||
margin: "0.3rem",
|
||||
marginLeft: "3rem",
|
||||
marginRight: "3rem",
|
||||
})}>TwiFeur</h1>
|
||||
</div>
|
||||
<MenuItem name="Content" location="/home"/>
|
||||
<MenuItem name="About" location="/about"/>
|
||||
<MenuItem name="User" location="/user"/>
|
||||
{(username !== null) && <MenuItem name={`Logout (${username})`} location="/api/logout" />}
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
function MenuItem({ name, location }: { name: string, location: string }) {
|
||||
return (
|
||||
<a href={location} style={_css({
|
||||
borderRight: '1px solid #444',
|
||||
textDecoration: 'none',
|
||||
color: 'unset'
|
||||
})}>
|
||||
<h3 style={_css({ margin: "0.7rem" })}>{name}</h3>
|
||||
</a>
|
||||
)
|
||||
}
|
13
pages/components/login.tsx
Normal file
13
pages/components/login.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<form action="/api/login" method="post">
|
||||
<input type="text" name="login"/>
|
||||
<input type="password" name="password"/>
|
||||
<input type="submit" value="login" />
|
||||
</form>
|
||||
)
|
||||
}
|
51
pages/components/main.tsx
Normal file
51
pages/components/main.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { PropsWithChildren, jsx, Fragment } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { _css } from "../../lib/utils.ts";
|
||||
|
||||
export default function Main({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<Fragment>
|
||||
<main style={_css({
|
||||
width: "100vw",
|
||||
display: "grid",
|
||||
placeContent: "center",
|
||||
})}>
|
||||
<div style={_css({
|
||||
width: "100vw",
|
||||
maxWidth: "1000px",
|
||||
backgroundColor: "#202020",
|
||||
borderLeft: "1px solid #444",
|
||||
borderRight: "1px solid #444",
|
||||
boxShadow: "0px 0px 10px #0008",
|
||||
paddingTop: "2rem"
|
||||
})}>
|
||||
<div style={_css({
|
||||
minHeight: "100vh",
|
||||
padding: "2rem"
|
||||
})}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer style={_css({
|
||||
width: "100vw",
|
||||
display: "grid",
|
||||
placeContent: "center",
|
||||
backgroundColor: "#202020",
|
||||
borderTop: "1px solid #444",
|
||||
boxShadow: "0px 0px 10px #0008",
|
||||
position: "relative",
|
||||
})}>
|
||||
<div style={_css({
|
||||
width: "100vw",
|
||||
maxWidth: "900px",
|
||||
display: "flex",
|
||||
padding: "1rem"
|
||||
})}>
|
||||
Footer
|
||||
</div>
|
||||
</footer>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
12
pages/components/post.tsx
Normal file
12
pages/components/post.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { PropsWithChildren, jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { _css } from "../../lib/utils.ts";
|
||||
|
||||
export function Post({ children, name }: PropsWithChildren<{ name: string }>) {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
20
pages/home.tsx
Normal file
20
pages/home.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { BasePage } from "./components/base.tsx"
|
||||
import Main from "./components/main.tsx";
|
||||
import Heading from "./components/heading.tsx";
|
||||
import { get_user } from "../lib/auth.ts";
|
||||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
|
||||
export default async function HomePage(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const user = await get_user(context);
|
||||
return (
|
||||
<BasePage name="Home">
|
||||
<Heading username={await user?.get("username") ?? null}></Heading>
|
||||
<Main>Main</Main>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
18
pages/login.tsx
Normal file
18
pages/login.tsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { BasePage } from "./components/base.tsx";
|
||||
import Heading from "./components/heading.tsx";
|
||||
import Main from "./components/main.tsx";
|
||||
import Login from "./components/login.tsx";
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<BasePage name="Login">
|
||||
<Main>
|
||||
<h1>Login</h1>
|
||||
<Login/>
|
||||
</Main>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
23
pages/static/style.css
Normal file
23
pages/static/style.css
Normal file
|
@ -0,0 +1,23 @@
|
|||
html,
|
||||
body,
|
||||
header,
|
||||
main,
|
||||
footer {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #181818;
|
||||
color: #eee;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
overflow-x: hidden
|
||||
}
|
24
pages/user.tsx
Normal file
24
pages/user.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
/** @jsx jsx */
|
||||
|
||||
import { jsx } from "https://deno.land/x/hono@v4.3.10/middleware.ts"
|
||||
import { BasePage } from "./components/base.tsx";
|
||||
import Heading from "./components/heading.tsx";
|
||||
import Main from "./components/main.tsx";
|
||||
import Login from "./components/login.tsx";
|
||||
import { User } from "../lib/storage.ts";
|
||||
import { Context } from "https://deno.land/x/hono@v4.3.10/mod.ts";
|
||||
import { FeurEnv } from "../main.ts";
|
||||
import { BlankInput } from "https://deno.land/x/hono@v4.3.10/types.ts";
|
||||
import { get_user } from "../lib/auth.ts";
|
||||
|
||||
export default async function UserPage(context: Context<FeurEnv, string, BlankInput>) {
|
||||
const user = await get_user(context);
|
||||
if (user === null) return context.text("Must be logged.", 401);
|
||||
return context.html(
|
||||
<BasePage name="Login">
|
||||
<Main>
|
||||
<h1>Logged as {await user.get("username")}</h1>
|
||||
</Main>
|
||||
</BasePage>
|
||||
)
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import { Head } from "$fresh/runtime.ts";
|
||||
|
||||
export default function Error404() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>404 - Page not found</title>
|
||||
</Head>
|
||||
<div class="px-4 py-8 mx-auto bg-[#86efac]">
|
||||
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
||||
<img
|
||||
class="my-6"
|
||||
src="/logo.svg"
|
||||
width="128"
|
||||
height="128"
|
||||
alt="the Fresh logo: a sliced lemon dripping with juice"
|
||||
/>
|
||||
<h1 class="text-4xl font-bold">404 - Page not found</h1>
|
||||
<p class="my-4">
|
||||
The page you were looking for doesn't exist.
|
||||
</p>
|
||||
<a href="/" class="underline">Go back home</a>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { type PageProps } from "$fresh/server.ts";
|
||||
export default function App({ Component }: PageProps) {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>twifeur</title>
|
||||
<link rel="stylesheet" href="/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<Component />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
import { FreshContext } from "$fresh/server.ts";
|
||||
import { deleteCookie, getCookies, setCookie } from "$std/http/cookie.ts";
|
||||
import { auth, Token } from "../auth/auth.ts";
|
||||
|
||||
type State = {
|
||||
user_id: string | null;
|
||||
};
|
||||
|
||||
export async function handler(
|
||||
req: Request,
|
||||
ctx: FreshContext<State>,
|
||||
) {
|
||||
const cookies = getCookies(req.headers);
|
||||
const token = get_session_token(cookies);
|
||||
|
||||
ctx.state.user_id = token?.user_id ?? null;
|
||||
|
||||
const resp = await ctx.next();
|
||||
set_session_token(resp.headers, token);
|
||||
return resp;
|
||||
}
|
||||
|
||||
function get_session_token(cookies: Record<string, string>) {
|
||||
const stored = cookies["auth_token"];
|
||||
if (stored === undefined) return null;
|
||||
const token = auth.tokens.get(stored);
|
||||
if (token === null) return null;
|
||||
return token;
|
||||
}
|
||||
|
||||
function set_session_token(headers: Headers, token: Token | null) {
|
||||
if (token === null) {
|
||||
deleteCookie(headers, "auth_token");
|
||||
return;
|
||||
}
|
||||
setCookie(headers, {
|
||||
name: "auth_token",
|
||||
value: token.raw,
|
||||
});
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import { FreshContext } from "$fresh/server.ts";
|
||||
|
||||
// Jokes courtesy of https://punsandoneliners.com/randomness/programmer-jokes/
|
||||
const JOKES = [
|
||||
"Why do Java developers often wear glasses? They can't C#.",
|
||||
"A SQL query walks into a bar, goes up to two tables and says “can I join you?”",
|
||||
"Wasn't hard to crack Forrest Gump's password. 1forrest1.",
|
||||
"I love pressing the F5 key. It's refreshing.",
|
||||
"Called IT support and a chap from Australia came to fix my network connection. I asked “Do you come from a LAN down under?”",
|
||||
"There are 10 types of people in the world. Those who understand binary and those who don't.",
|
||||
"Why are assembly programmers often wet? They work below C level.",
|
||||
"My favourite computer based band is the Black IPs.",
|
||||
"What programme do you use to predict the music tastes of former US presidential candidates? An Al Gore Rhythm.",
|
||||
"An SEO expert walked into a bar, pub, inn, tavern, hostelry, public house.",
|
||||
];
|
||||
|
||||
export const handler = (_req: Request, _ctx: FreshContext): Response => {
|
||||
const randomIndex = Math.floor(Math.random() * JOKES.length);
|
||||
const body = JOKES[randomIndex];
|
||||
return new Response(body);
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
import { PageProps } from "$fresh/server.ts";
|
||||
|
||||
export default function Greet(props: PageProps) {
|
||||
return <div>Hello {props.params.name}</div>;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { useSignal } from "@preact/signals";
|
||||
import Counter from "../islands/Counter.tsx";
|
||||
|
||||
export default function Home() {
|
||||
const count = useSignal(3);
|
||||
return (
|
||||
<div class="px-4 py-8 mx-auto bg-[#86efac]">
|
||||
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
||||
<img
|
||||
class="my-6"
|
||||
src="/logo.svg"
|
||||
width="128"
|
||||
height="128"
|
||||
alt="the Fresh logo: a sliced lemon dripping with juice"
|
||||
/>
|
||||
<h1 class="text-4xl font-bold">Welcome to Fresh</h1>
|
||||
<p class="my-4">
|
||||
Try updating this message in the
|
||||
<code class="mx-2">./routes/index.tsx</code> file, and refresh.
|
||||
</p>
|
||||
<Counter count={count} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
|
@ -1,6 +0,0 @@
|
|||
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M34.092 8.845C38.929 20.652 34.092 27 30 30.5c1 3.5-2.986 4.222-4.5 2.5-4.457 1.537-13.512 1.487-20-5C2 24.5 4.73 16.714 14 11.5c8-4.5 16-7 20.092-2.655Z" fill="#FFDB1E"/>
|
||||
<path d="M14 11.5c6.848-4.497 15.025-6.38 18.368-3.47C37.5 12.5 21.5 22.612 15.5 25c-6.5 2.587-3 8.5-6.5 8.5-3 0-2.5-4-5.183-7.75C2.232 23.535 6.16 16.648 14 11.5Z" fill="#fff" stroke="#FFDB1E"/>
|
||||
<path d="M28.535 8.772c4.645 1.25-.365 5.695-4.303 8.536-3.732 2.692-6.606 4.21-7.923 4.83-.366.173-1.617-2.252-1.617-1 0 .417-.7 2.238-.934 2.326-1.365.512-4.223 1.29-5.835 1.29-3.491 0-1.923-4.754 3.014-9.122.892-.789 1.478-.645 2.283-.645-.537-.773-.534-.917.403-1.546C17.79 10.64 23 8.77 25.212 8.42c.366.014.82.35.82.629.41-.14 2.095-.388 2.503-.278Z" fill="#FFE600"/>
|
||||
<path d="M14.297 16.49c.985-.747 1.644-1.01 2.099-2.526.566.121.841-.08 1.29-.701.324.466 1.657.608 2.453.701-.715.451-1.057.852-1.452 2.106-1.464-.611-3.167-.302-4.39.42Z" fill="#fff"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1 KiB |
|
@ -1,129 +0,0 @@
|
|||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
button {
|
||||
color: inherit;
|
||||
}
|
||||
button, [role="button"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
"Liberation Mono", "Courier New", monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
img,
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
img,
|
||||
video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.5;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
}
|
||||
.transition-colors {
|
||||
transition-property: background-color, border-color, color, fill, stroke;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
.my-6 {
|
||||
margin-bottom: 1.5rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.text-4xl {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
.mx-2 {
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.my-4 {
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.py-8 {
|
||||
padding-bottom: 2rem;
|
||||
padding-top: 2rem;
|
||||
}
|
||||
.bg-\[\#86efac\] {
|
||||
background-color: #86efac;
|
||||
}
|
||||
.text-3xl {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
.py-6 {
|
||||
padding-bottom: 1.5rem;
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
.py-1 {
|
||||
padding-bottom: 0.25rem;
|
||||
padding-top: 0.25rem;
|
||||
}
|
||||
.border-gray-500 {
|
||||
border-color: #6b7280;
|
||||
}
|
||||
.bg-white {
|
||||
background-color: #fff;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.gap-8 {
|
||||
grid-gap: 2rem;
|
||||
gap: 2rem;
|
||||
}
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
.max-w-screen-md {
|
||||
max-width: 768px;
|
||||
}
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
.rounded {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.hover\:bg-gray-200:hover {
|
||||
background-color: #e5e7eb;
|
||||
}
|
||||
.tabular-nums {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
7
utils.ts
7
utils.ts
|
@ -1,7 +0,0 @@
|
|||
import { dirname } from "$std/path/dirname.ts";
|
||||
|
||||
export function project_root_dir() {
|
||||
const this_url = new URL(import.meta.url);
|
||||
const this_dir = dirname(this_url.pathname);
|
||||
return this_dir + "/";
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue