hono-sessions 0.2.4 → 0.3.0
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 +17 -2
- 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/package.json +5 -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/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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)
|
|
@@ -125,6 +125,21 @@ import { sessionMiddleware, CookieStore, Session } from 'https://deno.land/x/hon
|
|
|
125
125
|
Deno.serve(app.fetch)
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### Bun
|
|
129
|
+
```ts
|
|
130
|
+
import { Hono } from 'hono'
|
|
131
|
+
import { sessionMiddleware, CookieStore, Session } from 'hono-sessions'
|
|
132
|
+
|
|
133
|
+
// Same as CF Workers, however instead of:
|
|
134
|
+
// export default app
|
|
135
|
+
// use:
|
|
136
|
+
|
|
137
|
+
export default {
|
|
138
|
+
port: 3000,
|
|
139
|
+
fetch: app.fetch
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
128
143
|
## Contributing
|
|
129
144
|
|
|
130
145
|
This package is built Deno-first, so you'll need to have Deno installed in your development environment. See their [website](https://deno.com/) for installation instructions specific to your platform.
|
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
|
+
}
|
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.0",
|
|
6
6
|
"description": "Cookie-based sessions for Hono web framework",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -16,6 +16,10 @@
|
|
|
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"
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
25
|
"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;
|