Skip to content

Commit

Permalink
Merge pull request #20 from Octo8080X/feature/add-kv-session
Browse files Browse the repository at this point in the history
Add kv store.
  • Loading branch information
Octo8080X authored May 23, 2023
2 parents d76cbd7 + dfb5fd6 commit 308a3ed
Show file tree
Hide file tree
Showing 23 changed files with 436 additions and 11 deletions.
9 changes: 9 additions & 0 deletions example/use_kv_store/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM denoland/deno:1.33.1

RUN apt-get update

RUN mkdir /usr/src/app
WORKDIR /usr/src/app


EXPOSE 8080
15 changes: 15 additions & 0 deletions example/use_kv_store/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Use Redis store sample

This project is fresh project used fresh-session with redis store.

## Usage

```sh
$ docker compose build

$ docker compose up -d

$ docker compose exec app deno task start

# Please access with brawser to http://localhost:8000.
```
12 changes: 12 additions & 0 deletions example/use_kv_store/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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-100 2) hover:bg-gray-200"
/>
);
}
10 changes: 10 additions & 0 deletions example/use_kv_store/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"tasks": {
"start": "deno run -A --unstable --watch=static/,routes/ dev.ts"
},
"importMap": "./import_map.json",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact"
}
}
5 changes: 5 additions & 0 deletions example/use_kv_store/dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env -S deno run -A --watch=static/,routes/

import dev from "$fresh/dev.ts";

await dev(import.meta.url, "./main.ts");
14 changes: 14 additions & 0 deletions example/use_kv_store/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: "3"
services:
app:
build:
context: .
dockerfile: Dockerfile
privileged: true
command: tail -f /dev/null
ports:
- "8000:8000"
- "35729:35729"
volumes:
- .:/usr/src/app:cached
tty: true
24 changes: 24 additions & 0 deletions example/use_kv_store/fresh.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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 config from "./deno.json" assert { type: "json" };
import * as $0 from "./routes/_middleware.ts";
import * as $1 from "./routes/api/joke.ts";
import * as $2 from "./routes/index.tsx";
import * as $$0 from "./islands/Counter.tsx";

const manifest = {
routes: {
"./routes/_middleware.ts": $0,
"./routes/api/joke.ts": $1,
"./routes/index.tsx": $2,
},
islands: {
"./islands/Counter.tsx": $$0,
},
baseUrl: import.meta.url,
config,
};

export default manifest;
13 changes: 13 additions & 0 deletions example/use_kv_store/import_map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"imports": {
"$fresh/": "https://deno.land/x/[email protected]/",
"preact": "https://esm.sh/[email protected]",
"preact/": "https://esm.sh/[email protected]/",
"preact-render-to-string": "https://esm.sh/*[email protected]",
"@preact/signals": "https://esm.sh/*@preact/[email protected]",
"@preact/signals-core": "https://esm.sh/*@preact/[email protected]",
"twind": "https://esm.sh/[email protected]",
"twind/": "https://esm.sh/[email protected]/",
"fresh-session/": "https://deno.land/x/[email protected]/"
}
}
17 changes: 17 additions & 0 deletions example/use_kv_store/islands/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useState } from "preact/hooks";
import { Button } from "../components/Button.tsx";

interface CounterProps {
start: number;
}

export default function Counter(props: CounterProps) {
const [count, setCount] = useState(props.start);
return (
<div class="flex gap-2 w-full">
<p class="flex-grow-1 font-bold text-xl">{count}</p>
<Button onClick={() => setCount(count - 1)}>-1</Button>
<Button onClick={() => setCount(count + 1)}>+1</Button>
</div>
);
}
13 changes: 13 additions & 0 deletions example/use_kv_store/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/// <reference no-default-lib="true" />
/// <reference lib="dom" />
/// <reference lib="dom.iterable" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />

import { start } from "$fresh/server.ts";
import manifest from "./fresh.gen.ts";

import twindPlugin from "$fresh/plugins/twind.ts";
import twindConfig from "./twind.config.ts";

await start(manifest, { plugins: [twindPlugin(twindConfig)] });
19 changes: 19 additions & 0 deletions example/use_kv_store/routes/_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MiddlewareHandlerContext } from "$fresh/server.ts";
import { kvSession, WithSession } from "fresh-session/mod.ts";
export type State = WithSession;

async function sessionHundler(
req: Request,
ctx: MiddlewareHandlerContext<State>,
) {
const session = kvSession(null, {
maxAge: 10,
httpOnly: true,
});

if (req.url === `http://localhost:${ctx.localAddr?.port}/`) {
return session(req, ctx);
}
return ctx.next();
}
export const handler = [sessionHundler];
21 changes: 21 additions & 0 deletions example/use_kv_store/routes/api/joke.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { HandlerContext } 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: HandlerContext): Response => {
const randomIndex = Math.floor(Math.random() * JOKES.length);
const body = JOKES[randomIndex];
return new Response(body);
};
70 changes: 70 additions & 0 deletions example/use_kv_store/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { HandlerContext, Handlers, PageProps } from "$fresh/server.ts";
import { Head } from "$fresh/runtime.ts";
import { WithSession } from "fresh-session/mod.ts";
export type SessionData = { session: Record<string, string>; message?: string };

export const handler: Handlers<SessionData, WithSession> = {
GET(_req: Request, ctx: HandlerContext<SessionData, WithSession>) {
const { session } = ctx.state;

const message = session.flash("message");

return ctx.render({
session: session.data,
message,
});
},
async POST(req: Request, ctx: HandlerContext<SessionData, WithSession>) {
const { session } = ctx.state;
const form = await req.formData();

if (
typeof form.get("method") === "string" &&
form.get("method") === "DELETE"
) {
session.clear();
session.flash("message", "Delete value!");
} else {
const text = form.get("new_session_text_value");
session.set("text", text);
session.flash("message", "Session value update!");
}

return new Response("", {
status: 303,
headers: { Location: "/" },
});
},
};

export default function Index({ data }: PageProps<SessionData>) {
return (
<>
<Head>
<title>frash-session example[redis in use]</title>
</Head>
<div>
<div>Flash Message: {data.message}</div>
<div>Now Session Value: {data.session.text}</div>
<div>
<form method="POST" action="/">
<div>
<input
type="text"
name="new_session_text_value"
placeholder="New session_text_value"
/>
</div>
<div>
<button type="submit">Update Session Value!</button>
</div>
</form>
<form method="POST" action="/">
<input type="hidden" name="method" value="DELETE" />
<button type="submit">Delete Session!</button>
</form>
</div>
</div>
</>
);
}
Binary file added example/use_kv_store/static/favicon.ico
Binary file not shown.
6 changes: 6 additions & 0 deletions example/use_kv_store/static/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions example/use_kv_store/twind.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Options } from "$fresh/plugins/twind.ts";

export default {
selfURL: import.meta.url,
} as Options;
2 changes: 1 addition & 1 deletion src/deps.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export type { MiddlewareHandlerContext } from "https://deno.land/x/[email protected]/server.ts";
export {
deleteCookie,
getCookies,
setCookie,
deleteCookie,
type Cookie,
} from "https://deno.land/[email protected]/http/mod.ts";
export { create, decode, verify } from "https://deno.land/x/[email protected]/mod.ts";
1 change: 1 addition & 0 deletions src/mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./stores/cookie.ts";
export * from "./stores/redis.ts";
export * from "./stores/kv.ts";
export * from "./session.ts";
6 changes: 3 additions & 3 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export class Session {
#data = new Map();
#flash = new Map();
#doDelete = false;

constructor(data = {}, flash = {}) {
this.#data = new Map(Object.entries(data));
this.#flash = new Map(Object.entries(flash));
Expand All @@ -16,8 +16,8 @@ export class Session {
return Object.fromEntries(this.#flash);
}

get doDelete(){
return this.#doDelete
get doDelete() {
return this.#doDelete;
}

set(key: string, value: any) {
Expand Down
5 changes: 1 addition & 4 deletions src/stores/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "../deps.ts";
import { type CookieOptions } from "./cookie_option.ts";
import { Session } from "../session.ts";
import type { WithSession } from "./interface.ts";

export function key() {
const key = Deno.env.get("APP_KEY");
Expand All @@ -27,10 +28,6 @@ export function key() {
);
}

export type WithSession = {
session: Session;
};

export function createCookieSessionStorage(cookieOptions?: CookieOptions) {
let cookieOptionsParam = cookieOptions;
if (!cookieOptionsParam) {
Expand Down
4 changes: 4 additions & 0 deletions src/stores/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Session } from "../session.ts";
export type WithSession = {
session: Session;
};
Loading

0 comments on commit 308a3ed

Please sign in to comment.