jax-hono 1.0.2 → 1.0.3
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/bin/jax.js +0 -0
- package/index.ts +2 -0
- package/middleware/jwt.ts +30 -25
- package/package.json +5 -4
- package/plugins/session/index.ts +84 -18
- package/types/config.ts +3 -7
package/bin/jax.js
CHANGED
|
File without changes
|
package/index.ts
CHANGED
package/middleware/jwt.ts
CHANGED
|
@@ -1,62 +1,67 @@
|
|
|
1
|
-
import config from
|
|
2
|
-
import jwt from
|
|
3
|
-
import type { Context, MiddlewareHandler, Next } from
|
|
1
|
+
import config from "../config";
|
|
2
|
+
import jwt from "jsonwebtoken";
|
|
3
|
+
import type { Context, MiddlewareHandler, Next } from "hono";
|
|
4
4
|
|
|
5
|
-
type JwtAuthOptions<
|
|
5
|
+
type JwtAuthOptions<
|
|
6
|
+
TPayload extends Record<string, any> = Record<string, any>,
|
|
7
|
+
> = {
|
|
6
8
|
secretSuffix: string;
|
|
7
9
|
stateKey: string;
|
|
8
10
|
validate?: (payload: TPayload, c: Context) => boolean | Promise<boolean>;
|
|
9
11
|
resolveState?: (payload: TPayload, c: Context) => unknown | Promise<unknown>;
|
|
10
12
|
};
|
|
11
13
|
|
|
12
|
-
function createJwtAuth<
|
|
13
|
-
|
|
14
|
-
): MiddlewareHandler {
|
|
14
|
+
function createJwtAuth<
|
|
15
|
+
TPayload extends Record<string, any> = Record<string, any>,
|
|
16
|
+
>(options: JwtAuthOptions<TPayload>): MiddlewareHandler {
|
|
15
17
|
return async (c, next) => {
|
|
16
|
-
const session = c.get('session');
|
|
17
|
-
const sessionData = session.get(options.stateKey);
|
|
18
|
+
// const session = c.get('session');
|
|
19
|
+
// const sessionData = session.get(options.stateKey);
|
|
18
20
|
|
|
19
|
-
if (sessionData) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
21
|
+
// if (sessionData) {
|
|
22
|
+
// c.state[options.stateKey] = sessionData;
|
|
23
|
+
// await next();
|
|
24
|
+
// }
|
|
24
25
|
|
|
25
26
|
const token = getAuthorizationToken(c);
|
|
26
27
|
|
|
27
28
|
if (!token) {
|
|
28
|
-
return c.json({ code: 401, msg:
|
|
29
|
+
return c.json({ code: 401, msg: "请先登录" });
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
try {
|
|
32
33
|
const payload = jwt.verify(
|
|
33
34
|
token,
|
|
34
|
-
(config as any).jwt.secret + options.secretSuffix
|
|
35
|
+
(config as any).jwt.secret + options.secretSuffix,
|
|
35
36
|
) as TPayload;
|
|
36
|
-
const valid = options.validate
|
|
37
|
+
const valid = options.validate
|
|
38
|
+
? await options.validate(payload, c)
|
|
39
|
+
: true;
|
|
37
40
|
|
|
38
41
|
if (!valid) {
|
|
39
|
-
return c.json({ code: 401, msg:
|
|
42
|
+
return c.json({ code: 401, msg: "请重新登录" });
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
const stateValue = options.resolveState
|
|
45
|
+
const stateValue = options.resolveState
|
|
46
|
+
? await options.resolveState(payload, c)
|
|
47
|
+
: payload;
|
|
43
48
|
|
|
44
49
|
if (!stateValue) {
|
|
45
|
-
return c.json({ code: 401, msg:
|
|
50
|
+
return c.json({ code: 401, msg: "请重新登录" });
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
c.state[options.stateKey] = stateValue;
|
|
49
54
|
|
|
50
55
|
await next();
|
|
51
56
|
} catch {
|
|
52
|
-
return c.json({ code: 401, msg:
|
|
57
|
+
return c.json({ code: 401, msg: "请重新登录" });
|
|
53
58
|
}
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
function createOptionalAuth(auth: MiddlewareHandler): MiddlewareHandler {
|
|
58
63
|
return async (c, next) => {
|
|
59
|
-
if (!c.req.header(
|
|
64
|
+
if (!c.req.header("authorization")) {
|
|
60
65
|
await next();
|
|
61
66
|
return;
|
|
62
67
|
}
|
|
@@ -66,10 +71,10 @@ function createOptionalAuth(auth: MiddlewareHandler): MiddlewareHandler {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
function getAuthorizationToken(c: Context) {
|
|
69
|
-
const authorization = c.req.header(
|
|
74
|
+
const authorization = c.req.header("authorization") ?? "";
|
|
70
75
|
|
|
71
|
-
return authorization.startsWith(
|
|
72
|
-
? authorization.slice(
|
|
76
|
+
return authorization.startsWith("Bearer ")
|
|
77
|
+
? authorization.slice("Bearer ".length)
|
|
73
78
|
: authorization;
|
|
74
79
|
}
|
|
75
80
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jax-hono",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Lightweight framework layer on top of Hono, built for Bun",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -82,10 +82,10 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@hono/session": "^0.2.1",
|
|
85
|
-
"cac": "^7.0.0"
|
|
86
|
-
"hono": "^4.12.27"
|
|
85
|
+
"cac": "^7.0.0"
|
|
87
86
|
},
|
|
88
87
|
"peerDependencies": {
|
|
88
|
+
"hono": "^4.12.27",
|
|
89
89
|
"dayjs": "*",
|
|
90
90
|
"deepmerge": "^4.3.1",
|
|
91
91
|
"dotenv": "^17.4.2",
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
"dayjs": "^1.11.21",
|
|
99
99
|
"deepmerge": "^4.3.1",
|
|
100
100
|
"dotenv": "^17.4.2",
|
|
101
|
+
"hono": "^4.12.27",
|
|
101
102
|
"jsonwebtoken": "^9.0.3",
|
|
102
103
|
"minimist": "^1.2.8",
|
|
103
104
|
"mongoose": "^8.24.1"
|
|
@@ -117,4 +118,4 @@
|
|
|
117
118
|
"bun": ">=1.0.0"
|
|
118
119
|
},
|
|
119
120
|
"license": "MIT"
|
|
120
|
-
}
|
|
121
|
+
}
|
package/plugins/session/index.ts
CHANGED
|
@@ -1,20 +1,86 @@
|
|
|
1
|
-
import { useSession, useSessionStorage } from '@hono/session'
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import { definePlugin } from '../define'
|
|
1
|
+
import { useSession, useSessionStorage } from '@hono/session';
|
|
2
|
+
import type { Session, SessionData, SessionOptions, Storage } from '@hono/session';
|
|
3
|
+
import type { Context } from 'hono';
|
|
4
|
+
import { definePlugin } from '../define';
|
|
5
|
+
|
|
6
|
+
export type JaxSessionData = SessionData;
|
|
7
|
+
|
|
8
|
+
export type SessionStorageFactory<Data extends SessionData = JaxSessionData> = (
|
|
9
|
+
c: Context
|
|
10
|
+
) => Storage<Data>;
|
|
11
|
+
|
|
12
|
+
export type SessionPluginOptions<Data extends SessionData = JaxSessionData> =
|
|
13
|
+
SessionOptions<Data> & {
|
|
14
|
+
/**
|
|
15
|
+
* Optional backing storage. When omitted, @hono/session keeps session data
|
|
16
|
+
* inside the encrypted cookie.
|
|
17
|
+
*/
|
|
18
|
+
storage?: Storage<Data> | SessionStorageFactory<Data>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
declare module 'hono' {
|
|
22
|
+
interface ContextVariableMap {
|
|
23
|
+
session: Session<JaxSessionData>;
|
|
24
|
+
sessionStorage?: Storage<JaxSessionData>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_SESSION_DURATION = {
|
|
29
|
+
// 会话的有效时间以秒为单位。超过该时间后,会话将失效,需要重新认证才能继续使用。
|
|
30
|
+
absolute: 60 * 60 * 24 * 7 // 7天
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const DEFAULT_SESSION_OPTIONS: SessionPluginOptions = {
|
|
34
|
+
secret: 'jax-session',
|
|
35
|
+
duration: DEFAULT_SESSION_DURATION
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function isSessionPluginOptions(options: unknown): options is SessionPluginOptions {
|
|
39
|
+
return Boolean(options && typeof options === 'object' && !Array.isArray(options));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function resolveSessionOptions(config: unknown, options: unknown): SessionPluginOptions {
|
|
43
|
+
const configOptions = readConfigSessionOptions(config);
|
|
44
|
+
const pluginOptions = isSessionPluginOptions(options) ? options : {};
|
|
45
|
+
const duration: NonNullable<SessionPluginOptions['duration']> = {
|
|
46
|
+
absolute: DEFAULT_SESSION_DURATION.absolute,
|
|
47
|
+
...configOptions.duration,
|
|
48
|
+
...pluginOptions.duration
|
|
49
|
+
};
|
|
50
|
+
const { storage, ...sessionOptions } = {
|
|
51
|
+
...DEFAULT_SESSION_OPTIONS,
|
|
52
|
+
...configOptions,
|
|
53
|
+
...pluginOptions,
|
|
54
|
+
duration
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
...sessionOptions,
|
|
59
|
+
storage
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function readConfigSessionOptions(config: unknown): SessionPluginOptions {
|
|
64
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const session = (config as { session?: unknown }).session;
|
|
69
|
+
|
|
70
|
+
return isSessionPluginOptions(session) ? session : {};
|
|
71
|
+
}
|
|
5
72
|
|
|
6
73
|
export default definePlugin({
|
|
7
|
-
setup(ctx) {
|
|
8
|
-
ctx.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
})
|
|
74
|
+
setup(ctx, options) {
|
|
75
|
+
const { storage, ...sessionOptions } = resolveSessionOptions(ctx.config, options);
|
|
76
|
+
|
|
77
|
+
if (storage) {
|
|
78
|
+
ctx.app.use(useSessionStorage(storage));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ctx.app.use(useSession(sessionOptions));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export type { Session, SessionData, SessionOptions, Storage };
|
|
86
|
+
export { useSession, useSessionStorage };
|
package/types/config.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
+
import type { SessionPluginOptions } from '../plugins/session';
|
|
2
|
+
|
|
1
3
|
export type JaxConfig = {
|
|
2
4
|
rootDir: string;
|
|
3
5
|
port: number;
|
|
4
6
|
env: string;
|
|
5
7
|
|
|
6
|
-
session?:
|
|
7
|
-
secret?: string;
|
|
8
|
-
duration?: {
|
|
9
|
-
absolute: number;
|
|
10
|
-
inactivity?: number;
|
|
11
|
-
};
|
|
12
|
-
};
|
|
8
|
+
session?: SessionPluginOptions;
|
|
13
9
|
};
|