hono-sessions 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -83
- package/esm/src/Middleware.js +7 -2
- package/esm/src/store/CookieStore.d.ts +1 -1
- package/esm/src/store/CookieStore.js +15 -4
- package/esm/src/store/bun/BunSqliteStore.d.ts +11 -0
- package/esm/src/store/bun/BunSqliteStore.js +42 -0
- package/esm/src/store/cloudflare/CloudflareD1Store.d.ts +11 -0
- package/esm/src/store/cloudflare/CloudflareD1Store.js +37 -0
- package/package.json +9 -1
- package/script/src/Middleware.js +7 -2
- package/script/src/store/CookieStore.d.ts +1 -1
- package/script/src/store/CookieStore.js +15 -4
- package/script/src/store/bun/BunSqliteStore.d.ts +11 -0
- package/script/src/store/bun/BunSqliteStore.js +46 -0
- package/script/src/store/cloudflare/CloudflareD1Store.d.ts +11 -0
- package/script/src/store/cloudflare/CloudflareD1Store.js +41 -0
package/README.md
CHANGED
|
@@ -1,128 +1,104 @@
|
|
|
1
1
|
# Hono Sessions Middleware
|
|
2
|
-
Use cookie-based sessions with the [Hono](https://hono.dev/) framework. Currently tested to work with Cloudflare Workers and
|
|
2
|
+
Use cookie-based sessions with the [Hono](https://hono.dev/) framework. Currently tested to work with Deno, Cloudflare Workers, and Bun.
|
|
3
3
|
|
|
4
4
|
### 🛠️ Features
|
|
5
|
-
- Runs in Deno
|
|
5
|
+
- Runs in Deno, Cloudflare Workers, and Bun (possibly others, currently untested)
|
|
6
6
|
- Flash messages — data that is deleted once it's read (one-off error messages, etc.)
|
|
7
7
|
- Built-in Memory and Cookie storage drivers (more coming soon)
|
|
8
8
|
- Encrypted cookies thanks to [iron-webcrypto](https://github.com/brc-dd/iron-webcrypto)
|
|
9
9
|
- Session expiration after inactivity
|
|
10
|
-
- Session key rotation
|
|
10
|
+
- Session key rotation*
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
> *CookieStore is not able to rotate session keys by nature of how a pure cookie session works (no server-side state).
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Installation and Usage
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
npm install hono-sessions
|
|
19
|
-
```
|
|
16
|
+
### Deno
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
Simply include the package from `deno.land/x`
|
|
22
19
|
|
|
23
20
|
```ts
|
|
24
|
-
import {
|
|
25
|
-
|
|
21
|
+
import { sessionMiddleware } from 'https://deno.land/x/hono_sessions/mod.ts'
|
|
22
|
+
```
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
### Bun, Cloudflare Workers
|
|
25
|
+
|
|
26
|
+
Install the NPM package
|
|
27
|
+
```
|
|
28
|
+
npm install hono-sessions
|
|
29
|
+
```
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
## Examples
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
### Deno
|
|
34
|
+
```ts
|
|
35
|
+
import { Hono } from 'https://deno.land/x/hono@v3.5.8/mod.ts'
|
|
36
|
+
import {
|
|
37
|
+
Session,
|
|
38
|
+
sessionMiddleware,
|
|
39
|
+
CookieStore
|
|
40
|
+
} from 'https://deno.land/x/hono_sessions/mod.ts'
|
|
41
|
+
|
|
42
|
+
const app = new Hono<{
|
|
32
43
|
Variables: {
|
|
33
44
|
session: Session,
|
|
34
45
|
session_key_rotation: boolean
|
|
35
46
|
}
|
|
36
47
|
}>()
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
const store = new CookieStore()
|
|
50
|
+
|
|
51
|
+
app.use('*', sessionMiddleware({
|
|
39
52
|
store,
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
encryptionKey: 'password_at_least_32_characters_long', // Required for CookieStore, recommended for others
|
|
54
|
+
expireAfterSeconds: 900, // Expire session after 15 minutes
|
|
55
|
+
cookieOptions: {
|
|
56
|
+
sameSite: 'Lax',
|
|
57
|
+
},
|
|
42
58
|
}))
|
|
43
59
|
|
|
44
|
-
|
|
60
|
+
app.get('/', async (c, next) => {
|
|
45
61
|
const session = c.get('session')
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (password === 'correct') {
|
|
50
|
-
c.set('session_key_rotation', true)
|
|
51
|
-
session.set('email', email)
|
|
52
|
-
session.set('failed-login-attempts', null)
|
|
53
|
-
session.flash('message', 'Login Successful')
|
|
63
|
+
if (session.get('counter')) {
|
|
64
|
+
session.set('counter', session.get('counter') as number + 1)
|
|
54
65
|
} else {
|
|
55
|
-
|
|
56
|
-
session.set('failed-login-attempts', failedLoginAttempts + 1)
|
|
57
|
-
session.flash('error', 'Incorrect username or password')
|
|
66
|
+
session.set('counter', 1)
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
return c.
|
|
69
|
+
return c.html(`<h1>You have visited this page ${ session.get('counter') } times</h1>`)
|
|
61
70
|
})
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return c.redirect('/')
|
|
66
|
-
})
|
|
72
|
+
Deno.serve(app.fetch)
|
|
73
|
+
```
|
|
67
74
|
|
|
68
|
-
|
|
69
|
-
const session = c.get('session')
|
|
75
|
+
### Bun
|
|
70
76
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const email = session.get('email')
|
|
75
|
-
|
|
76
|
-
return c.html(`<!DOCTYPE html>
|
|
77
|
-
<html lang="en">
|
|
78
|
-
<head>
|
|
79
|
-
<meta charset="UTF-8">
|
|
80
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
81
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
82
|
-
<title>Hono Sessions</title>
|
|
83
|
-
</head>
|
|
84
|
-
<body>
|
|
85
|
-
<p>${message}</p>
|
|
86
|
-
<p>${error}</p>
|
|
87
|
-
<p>${failedLoginAttempts ? `Failed login attempts: ${failedLoginAttempts}` : ''}</p>
|
|
88
|
-
|
|
89
|
-
${email ?
|
|
90
|
-
`<form id="logout" action="/logout" method="post">
|
|
91
|
-
<button name="logout" type="submit">Log out ${email}</button>
|
|
92
|
-
</form>`
|
|
93
|
-
:
|
|
94
|
-
`<form id="login" action="/login" method="post">
|
|
95
|
-
<p>
|
|
96
|
-
<input id="email" name="email" type="text" placeholder="you@email.com">
|
|
97
|
-
</p>
|
|
98
|
-
<p>
|
|
99
|
-
<input id="password" name="password" type="password" placeholder="password">
|
|
100
|
-
</p>
|
|
101
|
-
<button name="login" type="submit">Log in</button>
|
|
102
|
-
</form>`
|
|
103
|
-
}
|
|
104
|
-
</body>
|
|
105
|
-
</html>`)
|
|
106
|
-
})
|
|
77
|
+
```ts
|
|
78
|
+
import { Hono } from 'hono'
|
|
79
|
+
import { sessionMiddleware, CookieStore, Session } from 'hono-sessions'
|
|
107
80
|
|
|
108
|
-
|
|
81
|
+
// Same as Deno, however instead of:
|
|
82
|
+
// Deno.serve(app.fetch)
|
|
83
|
+
// use:
|
|
109
84
|
|
|
110
|
-
export default
|
|
85
|
+
export default {
|
|
86
|
+
port: 3000,
|
|
87
|
+
fetch: app.fetch
|
|
88
|
+
}
|
|
111
89
|
```
|
|
112
90
|
|
|
113
|
-
###
|
|
114
|
-
|
|
115
|
-
There is a Deno package available on `deno.land/x`.
|
|
91
|
+
### Cloudflare Workers
|
|
116
92
|
|
|
117
93
|
```ts
|
|
118
|
-
import { Hono } from '
|
|
119
|
-
import { sessionMiddleware, CookieStore, Session } from '
|
|
94
|
+
import { Hono } from 'hono'
|
|
95
|
+
import { sessionMiddleware, CookieStore, Session } from 'hono-sessions'
|
|
120
96
|
|
|
121
|
-
// Same as
|
|
122
|
-
//
|
|
97
|
+
// Same as Deno, however instead of:
|
|
98
|
+
// Deno.serve(app.fetch)
|
|
123
99
|
// use:
|
|
124
100
|
|
|
125
|
-
|
|
101
|
+
export default app
|
|
126
102
|
```
|
|
127
103
|
|
|
128
104
|
## Contributing
|
|
@@ -132,5 +108,13 @@ This package is built Deno-first, so you'll need to have Deno installed in your
|
|
|
132
108
|
Once Deno is installed, there is a test server you can run a basic web server to check your changes:
|
|
133
109
|
|
|
134
110
|
```
|
|
135
|
-
deno run --allow-net --watch test/server_deno.ts
|
|
111
|
+
deno run --allow-net --watch test/deno/server_deno.ts
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
There's also a [Playwright](https://playwright.dev/) test suite. By default, it is set up to run a Deno server with the MemoryStore driver. In Github actions, it runs through a series of runtimes and storage drivers when a pull request is made.
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
cd playwright
|
|
118
|
+
npm install
|
|
119
|
+
npx playwright test
|
|
136
120
|
```
|
package/esm/src/Middleware.js
CHANGED
|
@@ -31,8 +31,13 @@ export function sessionMiddleware(options) {
|
|
|
31
31
|
session_data = await store.getSession(c);
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
try {
|
|
35
|
+
sid = (encryptionKey ? await decrypt(encryptionKey, sessionCookie) : sessionCookie);
|
|
36
|
+
session_data = await store.getSessionById(sid);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
createNewSession = true;
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
if (session_data) {
|
|
38
43
|
session.setCache(session_data);
|
|
@@ -10,7 +10,7 @@ declare class CookieStore {
|
|
|
10
10
|
cookieOptions: CookieOptions | undefined;
|
|
11
11
|
sessionCookieName: string;
|
|
12
12
|
constructor(options?: CookieStoreOptions);
|
|
13
|
-
getSession(c: Context): Promise<
|
|
13
|
+
getSession(c: Context): Promise<SessionData | null>;
|
|
14
14
|
createSession(c: Context, initial_data: SessionData): Promise<void>;
|
|
15
15
|
deleteSession(c: Context): Promise<void>;
|
|
16
16
|
persistSessionData(c: Context, session_data: SessionData): Promise<void>;
|
|
@@ -25,12 +25,23 @@ class CookieStore {
|
|
|
25
25
|
this.sessionCookieName = options?.sessionCookieName || 'session';
|
|
26
26
|
}
|
|
27
27
|
async getSession(c) {
|
|
28
|
-
let
|
|
28
|
+
let session_data_raw;
|
|
29
29
|
const sessionCookie = getCookie(c, this.sessionCookieName);
|
|
30
30
|
if (this.encryptionKey && sessionCookie) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// Decrypt cookie string. If decryption fails, return null
|
|
32
|
+
try {
|
|
33
|
+
session_data_raw = (await decrypt(this.encryptionKey, sessionCookie));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
// Parse session object from cookie string and return result. If fails, return null
|
|
39
|
+
try {
|
|
40
|
+
const session_data = JSON.parse(session_data_raw);
|
|
41
|
+
return session_data;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
47
|
else {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Store from '../Store.js';
|
|
2
|
+
import { SessionData } from '../../Session.js';
|
|
3
|
+
export declare class BunSqliteStore implements Store {
|
|
4
|
+
db: any;
|
|
5
|
+
tableName: string;
|
|
6
|
+
constructor(db: any, tableName?: string);
|
|
7
|
+
getSessionById(sessionId: string): any;
|
|
8
|
+
createSession(sessionId: string, initialData: SessionData): void;
|
|
9
|
+
deleteSession(sessionId: string): void;
|
|
10
|
+
persistSessionData(sessionId: string, sessionData: SessionData): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export class BunSqliteStore {
|
|
2
|
+
constructor(db, tableName = 'sessions') {
|
|
3
|
+
Object.defineProperty(this, "db", {
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true,
|
|
7
|
+
value: void 0
|
|
8
|
+
});
|
|
9
|
+
Object.defineProperty(this, "tableName", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: void 0
|
|
14
|
+
});
|
|
15
|
+
this.db = db;
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
const query = db.query(`CREATE TABLE IF NOT EXISTS ${tableName} (id TEXT PRIMARY KEY, data TEXT)`);
|
|
18
|
+
query.run();
|
|
19
|
+
}
|
|
20
|
+
getSessionById(sessionId) {
|
|
21
|
+
const query = this.db.query(`SELECT data FROM ${this.tableName} WHERE id = $id`);
|
|
22
|
+
const result = query.get({ $id: sessionId });
|
|
23
|
+
if (result) {
|
|
24
|
+
return JSON.parse(result.data);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
createSession(sessionId, initialData) {
|
|
31
|
+
const query = this.db.query(`INSERT INTO ${this.tableName} (id, data) VALUES ($id, $data)`);
|
|
32
|
+
query.run({ $id: sessionId, $data: JSON.stringify(initialData) });
|
|
33
|
+
}
|
|
34
|
+
deleteSession(sessionId) {
|
|
35
|
+
const query = this.db.query(`DELETE FROM ${this.tableName} WHERE id = $id`);
|
|
36
|
+
query.run({ $id: sessionId });
|
|
37
|
+
}
|
|
38
|
+
persistSessionData(sessionId, sessionData) {
|
|
39
|
+
const query = this.db.query(`UPDATE ${this.tableName} SET data = $data WHERE id = $id`);
|
|
40
|
+
query.run({ $id: sessionId, $data: JSON.stringify(sessionData) });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Store from '../Store.js';
|
|
2
|
+
import { SessionData } from '../../Session.js';
|
|
3
|
+
export declare class CloudflareD1Store implements Store {
|
|
4
|
+
db: any;
|
|
5
|
+
tableName: string;
|
|
6
|
+
constructor(tableName?: string);
|
|
7
|
+
getSessionById(sessionId?: string | undefined): Promise<any>;
|
|
8
|
+
createSession(sessionId: string, initialData: SessionData): Promise<void>;
|
|
9
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
10
|
+
persistSessionData(sessionId: string, sessionData: SessionData): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class CloudflareD1Store {
|
|
2
|
+
constructor(tableName = 'sessions') {
|
|
3
|
+
Object.defineProperty(this, "db", {
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true,
|
|
7
|
+
value: void 0
|
|
8
|
+
});
|
|
9
|
+
Object.defineProperty(this, "tableName", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value: void 0
|
|
14
|
+
});
|
|
15
|
+
this.tableName = tableName;
|
|
16
|
+
}
|
|
17
|
+
async getSessionById(sessionId) {
|
|
18
|
+
const session = await this.db.prepare(`SELECT data FROM ${this.tableName} WHERE id = ?`)
|
|
19
|
+
.bind(sessionId)
|
|
20
|
+
.first('data');
|
|
21
|
+
if (session) {
|
|
22
|
+
return JSON.parse(session);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async createSession(sessionId, initialData) {
|
|
29
|
+
await this.db.prepare(`INSERT INTO ${this.tableName} (id, data) VALUES (?, ?)`).bind(sessionId, JSON.stringify(initialData)).run();
|
|
30
|
+
}
|
|
31
|
+
async deleteSession(sessionId) {
|
|
32
|
+
await this.db.prepare(`DELETE FROM ${this.tableName} WHERE id = ?`).bind(sessionId).run();
|
|
33
|
+
}
|
|
34
|
+
async persistSessionData(sessionId, sessionData) {
|
|
35
|
+
await this.db.prepare(`UPDATE ${this.tableName} SET data = ? WHERE id = ?`).bind(JSON.stringify(sessionData), sessionId).run();
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"module": "./esm/mod.js",
|
|
3
3
|
"main": "./script/mod.js",
|
|
4
4
|
"name": "hono-sessions",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.1",
|
|
6
6
|
"description": "Cookie-based sessions for Hono web framework",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
".": {
|
|
17
17
|
"import": "./esm/mod.js",
|
|
18
18
|
"require": "./script/mod.js"
|
|
19
|
+
},
|
|
20
|
+
"./bun-sqlite-store": {
|
|
21
|
+
"import": "./esm/src/store/bun/BunSqliteStore.js",
|
|
22
|
+
"require": "./script/src/store/bun/BunSqliteStore.js"
|
|
23
|
+
},
|
|
24
|
+
"./cloudflare-d1-store": {
|
|
25
|
+
"import": "./esm/src/store/cloudflare/CloudflareD1Store.js",
|
|
26
|
+
"require": "./script/src/store/cloudflare/CloudflareD1Store.js"
|
|
19
27
|
}
|
|
20
28
|
},
|
|
21
29
|
"dependencies": {
|
package/script/src/Middleware.js
CHANGED
|
@@ -37,8 +37,13 @@ function sessionMiddleware(options) {
|
|
|
37
37
|
session_data = await store.getSession(c);
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
try {
|
|
41
|
+
sid = (encryptionKey ? await (0, mod_js_1.decrypt)(encryptionKey, sessionCookie) : sessionCookie);
|
|
42
|
+
session_data = await store.getSessionById(sid);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
createNewSession = true;
|
|
46
|
+
}
|
|
42
47
|
}
|
|
43
48
|
if (session_data) {
|
|
44
49
|
session.setCache(session_data);
|
|
@@ -10,7 +10,7 @@ declare class CookieStore {
|
|
|
10
10
|
cookieOptions: CookieOptions | undefined;
|
|
11
11
|
sessionCookieName: string;
|
|
12
12
|
constructor(options?: CookieStoreOptions);
|
|
13
|
-
getSession(c: Context): Promise<
|
|
13
|
+
getSession(c: Context): Promise<SessionData | null>;
|
|
14
14
|
createSession(c: Context, initial_data: SessionData): Promise<void>;
|
|
15
15
|
deleteSession(c: Context): Promise<void>;
|
|
16
16
|
persistSessionData(c: Context, session_data: SessionData): Promise<void>;
|
|
@@ -27,12 +27,23 @@ class CookieStore {
|
|
|
27
27
|
this.sessionCookieName = options?.sessionCookieName || 'session';
|
|
28
28
|
}
|
|
29
29
|
async getSession(c) {
|
|
30
|
-
let
|
|
30
|
+
let session_data_raw;
|
|
31
31
|
const sessionCookie = (0, deps_js_1.getCookie)(c, this.sessionCookieName);
|
|
32
32
|
if (this.encryptionKey && sessionCookie) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
// Decrypt cookie string. If decryption fails, return null
|
|
34
|
+
try {
|
|
35
|
+
session_data_raw = (await (0, mod_js_1.decrypt)(this.encryptionKey, sessionCookie));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
// Parse session object from cookie string and return result. If fails, return null
|
|
41
|
+
try {
|
|
42
|
+
const session_data = JSON.parse(session_data_raw);
|
|
43
|
+
return session_data;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
49
|
else {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Store from '../Store.js';
|
|
2
|
+
import { SessionData } from '../../Session.js';
|
|
3
|
+
export declare class BunSqliteStore implements Store {
|
|
4
|
+
db: any;
|
|
5
|
+
tableName: string;
|
|
6
|
+
constructor(db: any, tableName?: string);
|
|
7
|
+
getSessionById(sessionId: string): any;
|
|
8
|
+
createSession(sessionId: string, initialData: SessionData): void;
|
|
9
|
+
deleteSession(sessionId: string): void;
|
|
10
|
+
persistSessionData(sessionId: string, sessionData: SessionData): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BunSqliteStore = void 0;
|
|
4
|
+
class BunSqliteStore {
|
|
5
|
+
constructor(db, tableName = 'sessions') {
|
|
6
|
+
Object.defineProperty(this, "db", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "tableName", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
this.db = db;
|
|
19
|
+
this.tableName = tableName;
|
|
20
|
+
const query = db.query(`CREATE TABLE IF NOT EXISTS ${tableName} (id TEXT PRIMARY KEY, data TEXT)`);
|
|
21
|
+
query.run();
|
|
22
|
+
}
|
|
23
|
+
getSessionById(sessionId) {
|
|
24
|
+
const query = this.db.query(`SELECT data FROM ${this.tableName} WHERE id = $id`);
|
|
25
|
+
const result = query.get({ $id: sessionId });
|
|
26
|
+
if (result) {
|
|
27
|
+
return JSON.parse(result.data);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
createSession(sessionId, initialData) {
|
|
34
|
+
const query = this.db.query(`INSERT INTO ${this.tableName} (id, data) VALUES ($id, $data)`);
|
|
35
|
+
query.run({ $id: sessionId, $data: JSON.stringify(initialData) });
|
|
36
|
+
}
|
|
37
|
+
deleteSession(sessionId) {
|
|
38
|
+
const query = this.db.query(`DELETE FROM ${this.tableName} WHERE id = $id`);
|
|
39
|
+
query.run({ $id: sessionId });
|
|
40
|
+
}
|
|
41
|
+
persistSessionData(sessionId, sessionData) {
|
|
42
|
+
const query = this.db.query(`UPDATE ${this.tableName} SET data = $data WHERE id = $id`);
|
|
43
|
+
query.run({ $id: sessionId, $data: JSON.stringify(sessionData) });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.BunSqliteStore = BunSqliteStore;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Store from '../Store.js';
|
|
2
|
+
import { SessionData } from '../../Session.js';
|
|
3
|
+
export declare class CloudflareD1Store implements Store {
|
|
4
|
+
db: any;
|
|
5
|
+
tableName: string;
|
|
6
|
+
constructor(tableName?: string);
|
|
7
|
+
getSessionById(sessionId?: string | undefined): Promise<any>;
|
|
8
|
+
createSession(sessionId: string, initialData: SessionData): Promise<void>;
|
|
9
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
10
|
+
persistSessionData(sessionId: string, sessionData: SessionData): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudflareD1Store = void 0;
|
|
4
|
+
class CloudflareD1Store {
|
|
5
|
+
constructor(tableName = 'sessions') {
|
|
6
|
+
Object.defineProperty(this, "db", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: void 0
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "tableName", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
this.tableName = tableName;
|
|
19
|
+
}
|
|
20
|
+
async getSessionById(sessionId) {
|
|
21
|
+
const session = await this.db.prepare(`SELECT data FROM ${this.tableName} WHERE id = ?`)
|
|
22
|
+
.bind(sessionId)
|
|
23
|
+
.first('data');
|
|
24
|
+
if (session) {
|
|
25
|
+
return JSON.parse(session);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async createSession(sessionId, initialData) {
|
|
32
|
+
await this.db.prepare(`INSERT INTO ${this.tableName} (id, data) VALUES (?, ?)`).bind(sessionId, JSON.stringify(initialData)).run();
|
|
33
|
+
}
|
|
34
|
+
async deleteSession(sessionId) {
|
|
35
|
+
await this.db.prepare(`DELETE FROM ${this.tableName} WHERE id = ?`).bind(sessionId).run();
|
|
36
|
+
}
|
|
37
|
+
async persistSessionData(sessionId, sessionData) {
|
|
38
|
+
await this.db.prepare(`UPDATE ${this.tableName} SET data = ? WHERE id = ?`).bind(JSON.stringify(sessionData), sessionId).run();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.CloudflareD1Store = CloudflareD1Store;
|