@scayle/h3-session 0.5.1 → 0.6.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/CHANGELOG.md +12 -0
- package/LICENSE +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +43 -16
- package/package.json +22 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @scayle/h3-session
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Disallow setting `name`, `path` or `domain` on the session cookie. Setting these properties would result in a new cookie rather than updating the existing cookie. It is now blocked to prevent unexpected behavior.
|
|
8
|
+
|
|
9
|
+
## 0.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [Performance] Reduce the calls to `importKey` to improve performance.
|
|
14
|
+
|
|
3
15
|
## 0.5.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/LICENSE
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -140,4 +140,5 @@ declare function validateConfig(config: H3SessionOptions): void;
|
|
|
140
140
|
*/
|
|
141
141
|
declare function useSession(event: H3Event, config: H3SessionOptions): Promise<void>;
|
|
142
142
|
|
|
143
|
-
export {
|
|
143
|
+
export { Session, UnstorageSessionStore, signCookie, unsignCookie, useSession, validateConfig };
|
|
144
|
+
export type { H3SessionOptions, RawSession, SessionCookie, SessionCookieOptions, SessionDataT, SessionMethods, SessionStore };
|
package/dist/index.d.ts
CHANGED
|
@@ -140,4 +140,5 @@ declare function validateConfig(config: H3SessionOptions): void;
|
|
|
140
140
|
*/
|
|
141
141
|
declare function useSession(event: H3Event, config: H3SessionOptions): Promise<void>;
|
|
142
142
|
|
|
143
|
-
export {
|
|
143
|
+
export { Session, UnstorageSessionStore, signCookie, unsignCookie, useSession, validateConfig };
|
|
144
|
+
export type { H3SessionOptions, RawSession, SessionCookie, SessionCookieOptions, SessionDataT, SessionMethods, SessionStore };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,41 @@ import { getCookie, setCookie } from 'h3';
|
|
|
3
3
|
import { defu } from 'defu';
|
|
4
4
|
import { subtle, randomUUID } from 'uncrypto';
|
|
5
5
|
|
|
6
|
+
const _signKeys = {};
|
|
7
|
+
async function getCryptoSignKey(secret) {
|
|
8
|
+
if (_signKeys[secret]) {
|
|
9
|
+
return _signKeys[secret];
|
|
10
|
+
}
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
const keyUint8Array = encoder.encode(secret);
|
|
13
|
+
const cryptoKey = await subtle.importKey(
|
|
14
|
+
"raw",
|
|
15
|
+
keyUint8Array,
|
|
16
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
17
|
+
false,
|
|
18
|
+
["sign"]
|
|
19
|
+
);
|
|
20
|
+
_signKeys[secret] = cryptoKey;
|
|
21
|
+
return cryptoKey;
|
|
22
|
+
}
|
|
23
|
+
const _verifyKeys = {};
|
|
24
|
+
async function getCryptoVerifyKey(secret) {
|
|
25
|
+
if (_verifyKeys[secret]) {
|
|
26
|
+
return _verifyKeys[secret];
|
|
27
|
+
}
|
|
28
|
+
const encoder = new TextEncoder();
|
|
29
|
+
const keyUint8Array = encoder.encode(secret);
|
|
30
|
+
const cryptoKey = await subtle.importKey(
|
|
31
|
+
"raw",
|
|
32
|
+
keyUint8Array,
|
|
33
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
34
|
+
false,
|
|
35
|
+
["verify"]
|
|
36
|
+
);
|
|
37
|
+
_verifyKeys[secret] = cryptoKey;
|
|
38
|
+
return cryptoKey;
|
|
39
|
+
}
|
|
40
|
+
|
|
6
41
|
class Session {
|
|
7
42
|
#id;
|
|
8
43
|
#store;
|
|
@@ -152,14 +187,7 @@ async function unsignCookie(value, secrets) {
|
|
|
152
187
|
const messageUint8Array = encoder.encode(message);
|
|
153
188
|
const signatureUint8Array = Uint8Array.from(Buffer.from(signature, "base64"));
|
|
154
189
|
for (let i = 0; i < secrets.length; i++) {
|
|
155
|
-
const
|
|
156
|
-
const cryptoKey = await subtle.importKey(
|
|
157
|
-
"raw",
|
|
158
|
-
keyUint8Array,
|
|
159
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
160
|
-
false,
|
|
161
|
-
["verify"]
|
|
162
|
-
);
|
|
190
|
+
const cryptoKey = await getCryptoVerifyKey(secrets[i]);
|
|
163
191
|
const result = await subtle.verify(
|
|
164
192
|
"HMAC",
|
|
165
193
|
cryptoKey,
|
|
@@ -181,14 +209,7 @@ async function signCookie(value, secret) {
|
|
|
181
209
|
}
|
|
182
210
|
const encoder = new TextEncoder();
|
|
183
211
|
const messageUint8Array = encoder.encode(value);
|
|
184
|
-
const
|
|
185
|
-
const cryptoKey = await subtle.importKey(
|
|
186
|
-
"raw",
|
|
187
|
-
keyUint8Array,
|
|
188
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
189
|
-
false,
|
|
190
|
-
["sign"]
|
|
191
|
-
);
|
|
212
|
+
const cryptoKey = await getCryptoSignKey(secret);
|
|
192
213
|
const signature = await subtle.sign("HMAC", cryptoKey, messageUint8Array);
|
|
193
214
|
const b64Signature = Buffer.from(signature).toString("base64").replace(/=+$/, "");
|
|
194
215
|
return `s:${value}.${b64Signature}`;
|
|
@@ -201,6 +222,7 @@ function validateConfig(config) {
|
|
|
201
222
|
throw new Error("[h3-session] Session secret is required!");
|
|
202
223
|
}
|
|
203
224
|
}
|
|
225
|
+
const uniqueCookieAttributes = /* @__PURE__ */ new Set(["name", "path", "domain"]);
|
|
204
226
|
async function useSession(event, config) {
|
|
205
227
|
if (event.context.session) {
|
|
206
228
|
return;
|
|
@@ -240,6 +262,11 @@ async function useSession(event, config) {
|
|
|
240
262
|
await cookie.setSessionId(sid);
|
|
241
263
|
return new Proxy(cookie, {
|
|
242
264
|
set(target, property, value) {
|
|
265
|
+
if (uniqueCookieAttributes.has(property)) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
`[h3-session] Cannot change ${property} on a session cookie!`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
243
270
|
target[property] = value;
|
|
244
271
|
setCookie(event, sessionConfig.name, signedCookie, cookie);
|
|
245
272
|
return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scayle/h3-session",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Persistent sessions for h3",
|
|
5
5
|
"author": "SCAYLE Commerce Engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
"access": "public",
|
|
9
9
|
"registry": "https://registry.npmjs.org/"
|
|
10
10
|
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"url": "git+https://github.com/scayle/h3-session.git"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"h3",
|
|
16
|
+
"session"
|
|
17
|
+
],
|
|
11
18
|
"exports": {
|
|
12
19
|
".": "./dist/index.mjs"
|
|
13
20
|
},
|
|
@@ -21,10 +28,11 @@
|
|
|
21
28
|
"verify-packaging": "attw --pack . --profile esm-only",
|
|
22
29
|
"format": "dprint check",
|
|
23
30
|
"format:fix": "dprint fmt",
|
|
24
|
-
"lint": "eslint .
|
|
31
|
+
"lint": "eslint .",
|
|
32
|
+
"lint:ci": "eslint . --format gitlab",
|
|
25
33
|
"lint:fix": "eslint . --fix",
|
|
26
34
|
"test": "vitest run",
|
|
27
|
-
"test:ci": "vitest --run --coverage --reporter=default --reporter=junit --outputFile=./junit.xml",
|
|
35
|
+
"test:ci": "vitest --run --coverage --reporter=default --reporter=junit --outputFile=./coverage/junit.xml",
|
|
28
36
|
"test:watch": "vitest watch",
|
|
29
37
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
30
38
|
},
|
|
@@ -37,18 +45,18 @@
|
|
|
37
45
|
"unstorage": "^1.10.2"
|
|
38
46
|
},
|
|
39
47
|
"devDependencies": {
|
|
40
|
-
"@arethetypeswrong/cli": "0.17.
|
|
41
|
-
"@scayle/eslint-config-storefront": "4.
|
|
42
|
-
"cookie-es": "
|
|
43
|
-
"dprint": "0.
|
|
44
|
-
"eslint": "9.
|
|
45
|
-
"eslint-formatter-gitlab": "
|
|
46
|
-
"h3": "1.
|
|
47
|
-
"typescript": "5.
|
|
48
|
-
"unbuild": "3.
|
|
49
|
-
"vitest": "
|
|
48
|
+
"@arethetypeswrong/cli": "0.17.4",
|
|
49
|
+
"@scayle/eslint-config-storefront": "4.5.0",
|
|
50
|
+
"cookie-es": "2.0.0",
|
|
51
|
+
"dprint": "0.49.1",
|
|
52
|
+
"eslint": "9.25.1",
|
|
53
|
+
"eslint-formatter-gitlab": "6.0.0",
|
|
54
|
+
"h3": "1.15.1",
|
|
55
|
+
"typescript": "5.8.3",
|
|
56
|
+
"unbuild": "3.5.0",
|
|
57
|
+
"vitest": "3.1.2"
|
|
50
58
|
},
|
|
51
59
|
"volta": {
|
|
52
|
-
"node": "22.
|
|
60
|
+
"node": "22.14.0"
|
|
53
61
|
}
|
|
54
62
|
}
|