@logto/node 3.0.3 → 3.1.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.
@@ -3,18 +3,28 @@ import { type CookieSerializeOptions } from 'cookie';
3
3
  import { PromiseQueue } from './promise-queue.js';
4
4
  import { type SessionData } from './session.js';
5
5
  type Nullable<T> = T | null;
6
- export type CookieConfig = {
7
- /** The encryption key to encrypt the session data. It should be a random string. */
8
- encryptionKey: string;
9
- /** The name of the cookie key. Default to `logtoCookies`. */
6
+ export type CookieConfigBase = {
10
7
  cookieKey?: string;
11
- /** Set to true in https */
12
8
  isSecure?: boolean;
13
- getCookie: (name: string) => string | undefined;
9
+ getCookie: (name: string) => Promise<string | undefined> | string | undefined;
14
10
  setCookie: (name: string, value: string, options: CookieSerializeOptions & {
15
11
  path: string;
16
- }) => void;
12
+ }) => Promise<void> | void;
13
+ };
14
+ export type SessionWrapper = {
15
+ wrap: (data: SessionData, key: string) => Promise<string>;
16
+ unwrap: (value: string, key: string) => Promise<SessionData>;
17
17
  };
18
+ export type CookieConfig = CookieConfigBase & ({
19
+ /** Required when using default session wrapper */
20
+ encryptionKey: string;
21
+ sessionWrapper?: never;
22
+ } | {
23
+ /** Optional when custom sessionWrapper is provided */
24
+ encryptionKey?: string;
25
+ /** Custom session wrapper can be used to implement external storage solutions */
26
+ sessionWrapper: SessionWrapper;
27
+ });
18
28
  /**
19
29
  * A storage that persists data in cookies with encryption.
20
30
  */
@@ -31,6 +41,12 @@ export declare class CookieStorage implements Storage<PersistKey> {
31
41
  get data(): SessionData;
32
42
  protected sessionData: SessionData;
33
43
  protected saveQueue: PromiseQueue;
44
+ /**
45
+ * Handles the wrapping and unwrapping of session data.
46
+ * Can be provided via config or defaults to using wrapSession/unwrapSession functions.
47
+ * Users can implement custom storage solutions by providing their own sessionWrapper.
48
+ */
49
+ protected sessionWrapper: SessionWrapper;
34
50
  constructor(config: CookieConfig);
35
51
  init(): Promise<void>;
36
52
  getItem(key: PersistKey): Promise<Nullable<string>>;
@@ -1,5 +1,5 @@
1
1
  import { PromiseQueue } from './promise-queue.js';
2
- import { unwrapSession, wrapSession } from './session.js';
2
+ import { wrapSession, unwrapSession } from './session.js';
3
3
 
4
4
  /**
5
5
  * A storage that persists data in cookies with encryption.
@@ -24,13 +24,17 @@ class CookieStorage {
24
24
  this.config = config;
25
25
  this.sessionData = {};
26
26
  this.saveQueue = new PromiseQueue();
27
- if (!config.encryptionKey) {
28
- throw new TypeError('The `encryptionKey` string is required for `CookieStorage`');
27
+ if (!config.sessionWrapper && !config.encryptionKey) {
28
+ throw new TypeError('Either `sessionWrapper` or `encryptionKey` must be provided for `CookieStorage`');
29
29
  }
30
+ this.sessionWrapper = config.sessionWrapper ?? {
31
+ wrap: wrapSession,
32
+ unwrap: unwrapSession,
33
+ };
30
34
  }
31
35
  async init() {
32
- const { encryptionKey } = this.config;
33
- this.sessionData = await unwrapSession(this.config.getCookie(this.cookieKey) ?? '', encryptionKey);
36
+ const { encryptionKey = '' } = this.config;
37
+ this.sessionData = await this.sessionWrapper.unwrap((await this.config.getCookie(this.cookieKey)) ?? '', encryptionKey);
34
38
  }
35
39
  async getItem(key) {
36
40
  return this.sessionData[key] ?? null;
@@ -52,9 +56,9 @@ class CookieStorage {
52
56
  return this.saveQueue.enqueue(async () => this.write());
53
57
  }
54
58
  async write(data = this.sessionData) {
55
- const { encryptionKey } = this.config;
56
- const value = await wrapSession(data, encryptionKey);
57
- this.config.setCookie(this.cookieKey, value, this.cookieOptions);
59
+ const { encryptionKey = '' } = this.config;
60
+ const value = await this.sessionWrapper.wrap(data, encryptionKey);
61
+ await this.config.setCookie(this.cookieKey, value, this.cookieOptions);
58
62
  }
59
63
  }
60
64
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logto/node",
3
- "version": "3.0.3",
3
+ "version": "3.1.1",
4
4
  "type": "module",
5
5
  "module": "./lib/src/index.js",
6
6
  "types": "./lib/src/index.d.ts",
@@ -30,19 +30,19 @@
30
30
  "dependencies": {
31
31
  "@silverhand/essentials": "^2.9.2",
32
32
  "js-base64": "^3.7.4",
33
- "@logto/client": "^3.0.3"
33
+ "@logto/client": "^3.0.4"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@silverhand/eslint-config": "^6.0.1",
37
37
  "@silverhand/ts-config": "^6.0.0",
38
38
  "@types/cookie": "^0.6.0",
39
39
  "@types/node": "^22.0.0",
40
- "@vitest/coverage-v8": "^1.6.0",
40
+ "@vitest/coverage-v8": "^2.1.9",
41
41
  "eslint": "^8.57.0",
42
42
  "lint-staged": "^15.0.0",
43
43
  "prettier": "^3.0.0",
44
44
  "typescript": "^5.3.3",
45
- "vitest": "^1.6.0"
45
+ "vitest": "^2.1.9"
46
46
  },
47
47
  "eslintConfig": {
48
48
  "extends": "@silverhand"