@scayle/h3-session 0.4.2 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @scayle/h3-session
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Cookie metadata is no longer saved in the session store. Previously, `h3-session` stored a copy of the cookie settings in the session store alongside the session data. This has been changed and now only the session data itself is stored. The cookie settings can still be read and manipulated from the `Session` object.
8
+
9
+ ### Patch Changes
10
+
11
+ - Removed dependency `zod@^3.23.8`
12
+ - Replace regex used for cookie parsing
13
+
3
14
  ## 0.4.2
4
15
 
5
16
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -41,7 +41,7 @@ declare class UnstorageSessionStore implements SessionStore {
41
41
  * Get the session with the specified session ID
42
42
  * @param sid the un-prefixed session ID
43
43
  */
44
- get(sid: string): Promise<RawSession | undefined>;
44
+ get(sid: string): Promise<SessionDataT | undefined>;
45
45
  /**
46
46
  * Save the session with the specified session ID
47
47
  * If the session has expired (has a TTL <= 0) it is deleted.
@@ -62,7 +62,7 @@ declare class UnstorageSessionStore implements SessionStore {
62
62
  /**
63
63
  * Fetch all saved sessions.
64
64
  */
65
- all(): Promise<RawSession[]>;
65
+ all(): Promise<SessionDataT[]>;
66
66
  /**
67
67
  * Returns the number of saved sessions
68
68
  */
@@ -84,9 +84,7 @@ type SessionCookie = SessionCookieOptions & {
84
84
  };
85
85
  interface SessionDataT {
86
86
  }
87
- type RawSession = SessionDataT & {
88
- cookie?: SessionCookieOptions;
89
- };
87
+ type RawSession = SessionDataT;
90
88
  interface SessionStore {
91
89
  all?: () => Promise<RawSession[]>;
92
90
  destroy: (sid: string) => Promise<void>;
@@ -128,6 +126,13 @@ declare module 'h3' {
128
126
  * @param secrets an array of secret strings to verify with
129
127
  */
130
128
  declare function unsignCookie(value: string, secrets: string[]): Promise<string | false>;
129
+ /**
130
+ * Creates a signed cookie value in the format `s:[value].[signature]`
131
+ * @param value
132
+ * @param secret
133
+ */
134
+ declare function signCookie(value: string, secret: string): Promise<string>;
135
+ declare function validateConfig(config: H3SessionOptions): void;
131
136
  /**
132
137
  * Attach a session to an H3Event
133
138
  * @param event
@@ -135,4 +140,4 @@ declare function unsignCookie(value: string, secrets: string[]): Promise<string
135
140
  */
136
141
  declare function useSession(event: H3Event, config: H3SessionOptions): Promise<void>;
137
142
 
138
- export { type RawSession, Session, type SessionCookie, type SessionCookieOptions, type SessionDataT, type SessionMethods, type SessionStore, UnstorageSessionStore, unsignCookie, useSession };
143
+ export { type H3SessionOptions, type RawSession, Session, type SessionCookie, type SessionCookieOptions, type SessionDataT, type SessionMethods, type SessionStore, UnstorageSessionStore, signCookie, unsignCookie, useSession, validateConfig };
package/dist/index.d.ts CHANGED
@@ -41,7 +41,7 @@ declare class UnstorageSessionStore implements SessionStore {
41
41
  * Get the session with the specified session ID
42
42
  * @param sid the un-prefixed session ID
43
43
  */
44
- get(sid: string): Promise<RawSession | undefined>;
44
+ get(sid: string): Promise<SessionDataT | undefined>;
45
45
  /**
46
46
  * Save the session with the specified session ID
47
47
  * If the session has expired (has a TTL <= 0) it is deleted.
@@ -62,7 +62,7 @@ declare class UnstorageSessionStore implements SessionStore {
62
62
  /**
63
63
  * Fetch all saved sessions.
64
64
  */
65
- all(): Promise<RawSession[]>;
65
+ all(): Promise<SessionDataT[]>;
66
66
  /**
67
67
  * Returns the number of saved sessions
68
68
  */
@@ -84,9 +84,7 @@ type SessionCookie = SessionCookieOptions & {
84
84
  };
85
85
  interface SessionDataT {
86
86
  }
87
- type RawSession = SessionDataT & {
88
- cookie?: SessionCookieOptions;
89
- };
87
+ type RawSession = SessionDataT;
90
88
  interface SessionStore {
91
89
  all?: () => Promise<RawSession[]>;
92
90
  destroy: (sid: string) => Promise<void>;
@@ -128,6 +126,13 @@ declare module 'h3' {
128
126
  * @param secrets an array of secret strings to verify with
129
127
  */
130
128
  declare function unsignCookie(value: string, secrets: string[]): Promise<string | false>;
129
+ /**
130
+ * Creates a signed cookie value in the format `s:[value].[signature]`
131
+ * @param value
132
+ * @param secret
133
+ */
134
+ declare function signCookie(value: string, secret: string): Promise<string>;
135
+ declare function validateConfig(config: H3SessionOptions): void;
131
136
  /**
132
137
  * Attach a session to an H3Event
133
138
  * @param event
@@ -135,4 +140,4 @@ declare function unsignCookie(value: string, secrets: string[]): Promise<string
135
140
  */
136
141
  declare function useSession(event: H3Event, config: H3SessionOptions): Promise<void>;
137
142
 
138
- export { type RawSession, Session, type SessionCookie, type SessionCookieOptions, type SessionDataT, type SessionMethods, type SessionStore, UnstorageSessionStore, unsignCookie, useSession };
143
+ export { type H3SessionOptions, type RawSession, Session, type SessionCookie, type SessionCookieOptions, type SessionDataT, type SessionMethods, type SessionStore, UnstorageSessionStore, signCookie, unsignCookie, useSession, validateConfig };
package/dist/index.mjs CHANGED
@@ -2,7 +2,6 @@ import { Buffer } from 'node:buffer';
2
2
  import { getCookie, setCookie } from 'h3';
3
3
  import { defu } from 'defu';
4
4
  import { subtle, randomUUID } from 'uncrypto';
5
- import { z } from 'zod';
6
5
 
7
6
  class Session {
8
7
  #id;
@@ -21,7 +20,7 @@ class Session {
21
20
  return this.#id;
22
21
  }
23
22
  async save() {
24
- await this.#store.set(this.#id, { ...this.data, cookie: this.cookie });
23
+ await this.#store.set(this.#id, this.data);
25
24
  }
26
25
  async reload() {
27
26
  this.data = await this.#store.get(this.#id) ?? (await this.#generate()).data;
@@ -39,15 +38,6 @@ class Session {
39
38
  }
40
39
  }
41
40
 
42
- const CookieSchema = z.object({
43
- domain: z.string().optional(),
44
- expires: z.coerce.date().optional(),
45
- httpOnly: z.boolean().optional(),
46
- maxAge: z.number().optional(),
47
- path: z.string().optional(),
48
- sameSite: z.enum(["lax", "none", "strict"]).or(z.boolean()).optional(),
49
- secure: z.boolean().optional()
50
- });
51
41
  class UnstorageSessionStore {
52
42
  storage;
53
43
  prefix;
@@ -70,13 +60,6 @@ class UnstorageSessionStore {
70
60
  */
71
61
  async get(sid) {
72
62
  const item = await this.storage.getItem(this.getKey(sid));
73
- if (item && item.cookie) {
74
- try {
75
- item.cookie = CookieSchema.parse(item.cookie);
76
- } catch {
77
- delete item.cookie;
78
- }
79
- }
80
63
  return item ?? void 0;
81
64
  }
82
65
  /**
@@ -144,12 +127,26 @@ class UnstorageSessionStore {
144
127
  }
145
128
  }
146
129
 
130
+ const signatureLength = 43;
131
+ function parseCookieValue(value) {
132
+ if (value.length < signatureLength + 3) {
133
+ return void 0;
134
+ }
135
+ const separatorIndex = value.length - signatureLength - 1;
136
+ if (value.charAt(0) !== "s" || value.charAt(1) !== ":" || value.charAt(separatorIndex) !== ".") {
137
+ return void 0;
138
+ }
139
+ return [
140
+ value.substring(2, separatorIndex),
141
+ value.substring(separatorIndex + 1)
142
+ ];
143
+ }
147
144
  async function unsignCookie(value, secrets) {
148
- const matches = /s:([^.]*)\.(.*)/.exec(value);
145
+ const matches = parseCookieValue(value);
149
146
  if (!matches) {
150
147
  return false;
151
148
  }
152
- const [, message, signature] = matches;
149
+ const [message, signature] = matches;
153
150
  const encoder = new TextEncoder();
154
151
  const messageUint8Array = encoder.encode(message);
155
152
  const signatureUint8Array = Uint8Array.from(Buffer.from(signature, "base64"));
@@ -175,6 +172,12 @@ async function unsignCookie(value, secrets) {
175
172
  return false;
176
173
  }
177
174
  async function signCookie(value, secret) {
175
+ if (!value) {
176
+ throw new Error("[h3-session] No value was provided!");
177
+ }
178
+ if (!secret) {
179
+ throw new Error("[h3-session] No secret was provided!");
180
+ }
178
181
  const encoder = new TextEncoder();
179
182
  const messageUint8Array = encoder.encode(value);
180
183
  const keyUint8Array = encoder.encode(secret);
@@ -273,4 +276,4 @@ async function useSession(event, config) {
273
276
  event.context.sessionStore = store;
274
277
  }
275
278
 
276
- export { Session, UnstorageSessionStore, unsignCookie, useSession };
279
+ export { Session, UnstorageSessionStore, signCookie, unsignCookie, useSession, validateConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/h3-session",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Persistent sessions for h3",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -22,7 +22,11 @@
22
22
  "format": "dprint check",
23
23
  "format:fix": "dprint fmt",
24
24
  "lint": "eslint . --format gitlab",
25
- "lint:fix": "eslint . --fix"
25
+ "lint:fix": "eslint . --fix",
26
+ "test": "vitest run",
27
+ "test:ci": "vitest --run --coverage --reporter=default --reporter=junit --outputFile=./junit.xml",
28
+ "test:watch": "vitest watch",
29
+ "typecheck": "tsc --noEmit -p tsconfig.json"
26
30
  },
27
31
  "peerDependencies": {
28
32
  "h3": "^1.10.0"
@@ -30,8 +34,7 @@
30
34
  "dependencies": {
31
35
  "defu": "^6.1.4",
32
36
  "uncrypto": "^0.1.3",
33
- "unstorage": "^1.10.2",
34
- "zod": "^3.23.8"
37
+ "unstorage": "^1.10.2"
35
38
  },
36
39
  "devDependencies": {
37
40
  "@arethetypeswrong/cli": "0.17.1",
@@ -41,7 +44,8 @@
41
44
  "eslint-formatter-gitlab": "5.1.0",
42
45
  "h3": "1.13.0",
43
46
  "typescript": "5.6.3",
44
- "unbuild": "3.0.1"
47
+ "unbuild": "3.0.1",
48
+ "vitest": "2.1.8"
45
49
  },
46
50
  "volta": {
47
51
  "node": "22.12.0"