@logto/next 1.1.2 → 2.0.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.
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var client = require('../src/client.cjs');
6
+ var index = require('./iron-session-edge/index.cjs');
7
+ var NodeClient = require('@logto/node');
8
+
9
+ class LogtoClient extends client.default {
10
+ constructor(config) {
11
+ super(config, {
12
+ withIronSessionApiRoute: index.withIronSessionApiRoute,
13
+ withIronSessionSsr: index.withIronSessionSsr,
14
+ });
15
+ }
16
+ }
17
+
18
+ Object.defineProperty(exports, 'ReservedScope', {
19
+ enumerable: true,
20
+ get: function () { return NodeClient.ReservedScope; }
21
+ });
22
+ Object.defineProperty(exports, 'UserScope', {
23
+ enumerable: true,
24
+ get: function () { return NodeClient.UserScope; }
25
+ });
26
+ exports.default = LogtoClient;
@@ -0,0 +1,7 @@
1
+ import BaseClient from '../src/client';
2
+ import type { LogtoNextConfig } from '../src/types.js';
3
+ export { ReservedScope, UserScope } from '@logto/node';
4
+ export type { LogtoContext, InteractionMode } from '@logto/node';
5
+ export default class LogtoClient extends BaseClient {
6
+ constructor(config: LogtoNextConfig);
7
+ }
@@ -0,0 +1,14 @@
1
+ import LogtoNextBaseClient from '../src/client.js';
2
+ import { withIronSessionApiRoute, withIronSessionSsr } from './iron-session-edge/index.js';
3
+ export { ReservedScope, UserScope } from '@logto/node';
4
+
5
+ class LogtoClient extends LogtoNextBaseClient {
6
+ constructor(config) {
7
+ super(config, {
8
+ withIronSessionApiRoute,
9
+ withIronSessionSsr,
10
+ });
11
+ }
12
+ }
13
+
14
+ export { LogtoClient as default };
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ function getPropertyDescriptorForRequestSession(session) {
6
+ return {
7
+ enumerable: true,
8
+ get() {
9
+ return session;
10
+ },
11
+ set(value) {
12
+ const keys = Object.keys(value);
13
+ const currentKeys = Object.keys(session);
14
+ for (const key of currentKeys) {
15
+ if (!keys.includes(key)) {
16
+ /* eslint-disable @typescript-eslint/no-dynamic-delete */
17
+ /* eslint-disable @silverhand/fp/no-delete */
18
+ // @ts-expect-error See comment in IronSessionData interface
19
+ delete session[key];
20
+ /* eslint-enable @silverhand/fp/no-delete */
21
+ /* eslint-enable @typescript-eslint/no-dynamic-delete */
22
+ }
23
+ }
24
+ for (const key of keys) {
25
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
26
+ /* eslint-disable @silverhand/fp/no-mutation */
27
+ // @ts-expect-error See comment in IronSessionData interface
28
+ session[key] = value[key];
29
+ /* eslint-enable @silverhand/fp/no-mutation */
30
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
31
+ }
32
+ },
33
+ };
34
+ }
35
+
36
+ exports.default = getPropertyDescriptorForRequestSession;
@@ -0,0 +1,2 @@
1
+ import type { IronSession } from 'iron-session';
2
+ export default function getPropertyDescriptorForRequestSession(session: IronSession): PropertyDescriptor;
@@ -0,0 +1,32 @@
1
+ function getPropertyDescriptorForRequestSession(session) {
2
+ return {
3
+ enumerable: true,
4
+ get() {
5
+ return session;
6
+ },
7
+ set(value) {
8
+ const keys = Object.keys(value);
9
+ const currentKeys = Object.keys(session);
10
+ for (const key of currentKeys) {
11
+ if (!keys.includes(key)) {
12
+ /* eslint-disable @typescript-eslint/no-dynamic-delete */
13
+ /* eslint-disable @silverhand/fp/no-delete */
14
+ // @ts-expect-error See comment in IronSessionData interface
15
+ delete session[key];
16
+ /* eslint-enable @silverhand/fp/no-delete */
17
+ /* eslint-enable @typescript-eslint/no-dynamic-delete */
18
+ }
19
+ }
20
+ for (const key of keys) {
21
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
22
+ /* eslint-disable @silverhand/fp/no-mutation */
23
+ // @ts-expect-error See comment in IronSessionData interface
24
+ session[key] = value[key];
25
+ /* eslint-enable @silverhand/fp/no-mutation */
26
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
27
+ }
28
+ },
29
+ };
30
+ }
31
+
32
+ export { getPropertyDescriptorForRequestSession as default };
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var edge = require('iron-session/edge');
4
+ var getPropertyDescriptorForRequestSession = require('./get-property-descriptor-for-request-session.cjs');
5
+
6
+ function withIronSessionApiRoute(handler, options) {
7
+ return async (request, response) => {
8
+ const sessionOptions = options instanceof Function ? await options(request, response) : options;
9
+ const session = await edge.getIronSession(request, response, sessionOptions);
10
+ // We define req.session as being enumerable (so console.log(req) shows it)
11
+ // and we also want to allow people to do:
12
+ // req.session = { admin: true }; or req.session = {...req.session, admin: true};
13
+ // req.session.save();
14
+ // eslint-disable-next-line @silverhand/fp/no-mutating-methods
15
+ Object.defineProperty(request, 'session', getPropertyDescriptorForRequestSession.default(session));
16
+ return handler(request, response);
17
+ };
18
+ }
19
+ function withIronSessionSsr(handler, options) {
20
+ return async (context) => {
21
+ const sessionOptions = options instanceof Function ? await options(context.req, context.res) : options;
22
+ const session = await edge.getIronSession(context.req, context.res, sessionOptions);
23
+ // eslint-disable-next-line @silverhand/fp/no-mutating-methods
24
+ Object.defineProperty(context.req, 'session', getPropertyDescriptorForRequestSession.default(session));
25
+ return handler(context);
26
+ };
27
+ }
28
+
29
+ exports.withIronSessionApiRoute = withIronSessionApiRoute;
30
+ exports.withIronSessionSsr = withIronSessionSsr;
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import type { IncomingMessage, ServerResponse } from 'http';
3
+ import type { IronSessionOptions } from 'iron-session';
4
+ import type { NextApiHandler, GetServerSidePropsContext, GetServerSidePropsResult, NextApiRequest, NextApiResponse } from 'next';
5
+ type GetIronSessionApiOptions = (request: NextApiRequest, response: NextApiResponse) => Promise<IronSessionOptions> | IronSessionOptions;
6
+ export declare function withIronSessionApiRoute(handler: NextApiHandler, options: IronSessionOptions | GetIronSessionApiOptions): NextApiHandler;
7
+ type GetIronSessionSsrOptions = (request: IncomingMessage, response: ServerResponse) => Promise<IronSessionOptions> | IronSessionOptions;
8
+ export declare function withIronSessionSsr<P extends Record<string, unknown> = Record<string, unknown>>(handler: (context: GetServerSidePropsContext) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>>, options: IronSessionOptions | GetIronSessionSsrOptions): (context: GetServerSidePropsContext) => Promise<GetServerSidePropsResult<P>>;
9
+ export {};
@@ -0,0 +1,27 @@
1
+ import { getIronSession } from 'iron-session/edge';
2
+ import getPropertyDescriptorForRequestSession from './get-property-descriptor-for-request-session.js';
3
+
4
+ function withIronSessionApiRoute(handler, options) {
5
+ return async (request, response) => {
6
+ const sessionOptions = options instanceof Function ? await options(request, response) : options;
7
+ const session = await getIronSession(request, response, sessionOptions);
8
+ // We define req.session as being enumerable (so console.log(req) shows it)
9
+ // and we also want to allow people to do:
10
+ // req.session = { admin: true }; or req.session = {...req.session, admin: true};
11
+ // req.session.save();
12
+ // eslint-disable-next-line @silverhand/fp/no-mutating-methods
13
+ Object.defineProperty(request, 'session', getPropertyDescriptorForRequestSession(session));
14
+ return handler(request, response);
15
+ };
16
+ }
17
+ function withIronSessionSsr(handler, options) {
18
+ return async (context) => {
19
+ const sessionOptions = options instanceof Function ? await options(context.req, context.res) : options;
20
+ const session = await getIronSession(context.req, context.res, sessionOptions);
21
+ // eslint-disable-next-line @silverhand/fp/no-mutating-methods
22
+ Object.defineProperty(context.req, 'session', getPropertyDescriptorForRequestSession(session));
23
+ return handler(context);
24
+ };
25
+ }
26
+
27
+ export { withIronSessionApiRoute, withIronSessionSsr };
@@ -3,17 +3,17 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var NodeClient = require('@logto/node');
6
- var next = require('iron-session/next');
7
- var storage = require('./storage.js');
6
+ var storage = require('./storage.cjs');
8
7
 
9
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
9
 
11
10
  var NodeClient__default = /*#__PURE__*/_interopDefault(NodeClient);
12
11
 
13
- class LogtoClient {
14
- constructor(config) {
12
+ class LogtoNextBaseClient {
13
+ constructor(config, adapters) {
15
14
  this.config = config;
16
- this.handleSignIn = (redirectUri = `${this.config.baseUrl}/api/logto/sign-in-callback`, interactionMode) => next.withIronSessionApiRoute(async (request, response) => {
15
+ this.adapters = adapters;
16
+ this.handleSignIn = (redirectUri = `${this.config.baseUrl}/api/logto/sign-in-callback`, interactionMode) => this.adapters.withIronSessionApiRoute(async (request, response) => {
17
17
  const nodeClient = this.createNodeClient(request);
18
18
  await nodeClient.signIn(redirectUri, interactionMode);
19
19
  await this.storage?.save();
@@ -21,7 +21,7 @@ class LogtoClient {
21
21
  response.redirect(this.navigateUrl);
22
22
  }
23
23
  }, this.ironSessionConfigs);
24
- this.handleSignInCallback = (redirectTo = this.config.baseUrl) => next.withIronSessionApiRoute(async (request, response) => {
24
+ this.handleSignInCallback = (redirectTo = this.config.baseUrl) => this.adapters.withIronSessionApiRoute(async (request, response) => {
25
25
  const nodeClient = this.createNodeClient(request);
26
26
  if (request.url) {
27
27
  await nodeClient.handleSignInCallback(`${this.config.baseUrl}${request.url}`);
@@ -29,7 +29,7 @@ class LogtoClient {
29
29
  response.redirect(redirectTo);
30
30
  }
31
31
  }, this.ironSessionConfigs);
32
- this.handleSignOut = (redirectUri = this.config.baseUrl) => next.withIronSessionApiRoute(async (request, response) => {
32
+ this.handleSignOut = (redirectUri = this.config.baseUrl) => this.adapters.withIronSessionApiRoute(async (request, response) => {
33
33
  const nodeClient = this.createNodeClient(request);
34
34
  await nodeClient.signOut(redirectUri);
35
35
  request.session.destroy();
@@ -60,13 +60,13 @@ class LogtoClient {
60
60
  }
61
61
  response.status(404).end();
62
62
  };
63
- this.withLogtoApiRoute = (handler, config = {}) => next.withIronSessionApiRoute(async (request, response) => {
63
+ this.withLogtoApiRoute = (handler, config = {}) => this.adapters.withIronSessionApiRoute(async (request, response) => {
64
64
  const user = await this.getLogtoUserFromRequest(request, config);
65
65
  // eslint-disable-next-line @silverhand/fp/no-mutating-methods
66
66
  Object.defineProperty(request, 'user', { enumerable: true, get: () => user });
67
67
  return handler(request, response);
68
68
  }, this.ironSessionConfigs);
69
- this.withLogtoSsr = (handler, configs = {}) => next.withIronSessionSsr(async (context) => {
69
+ this.withLogtoSsr = (handler, configs = {}) => this.adapters.withIronSessionSsr(async (context) => {
70
70
  const user = await this.getLogtoUserFromRequest(context.req, configs);
71
71
  // eslint-disable-next-line @silverhand/fp/no-mutating-methods
72
72
  Object.defineProperty(context.req, 'user', { enumerable: true, get: () => user });
@@ -98,12 +98,4 @@ class LogtoClient {
98
98
  }
99
99
  }
100
100
 
101
- Object.defineProperty(exports, 'ReservedScope', {
102
- enumerable: true,
103
- get: function () { return NodeClient.ReservedScope; }
104
- });
105
- Object.defineProperty(exports, 'UserScope', {
106
- enumerable: true,
107
- get: function () { return NodeClient.UserScope; }
108
- });
109
- exports.default = LogtoClient;
101
+ exports.default = LogtoNextBaseClient;
@@ -1,13 +1,12 @@
1
1
  import type { GetContextParameters, InteractionMode } from '@logto/node';
2
2
  import type { GetServerSidePropsContext, GetServerSidePropsResult, NextApiHandler } from 'next';
3
- import type { LogtoNextConfig } from './types';
4
- export { ReservedScope, UserScope } from '@logto/node';
5
- export type { LogtoContext, InteractionMode } from '@logto/node';
6
- export default class LogtoClient {
3
+ import type { Adapters, LogtoNextConfig } from './types';
4
+ export default class LogtoNextBaseClient {
7
5
  private readonly config;
6
+ private readonly adapters;
8
7
  private navigateUrl?;
9
8
  private storage?;
10
- constructor(config: LogtoNextConfig);
9
+ constructor(config: LogtoNextConfig, adapters: Adapters);
11
10
  handleSignIn: (redirectUri?: string, interactionMode?: InteractionMode) => NextApiHandler;
12
11
  handleSignInCallback: (redirectTo?: string) => NextApiHandler;
13
12
  handleSignOut: (redirectUri?: string) => NextApiHandler;
@@ -1,12 +1,11 @@
1
1
  import NodeClient from '@logto/node';
2
- export { ReservedScope, UserScope } from '@logto/node';
3
- import { withIronSessionApiRoute, withIronSessionSsr } from 'iron-session/next';
4
- import NextStorage from './storage.mjs';
2
+ import NextStorage from './storage.js';
5
3
 
6
- class LogtoClient {
7
- constructor(config) {
4
+ class LogtoNextBaseClient {
5
+ constructor(config, adapters) {
8
6
  this.config = config;
9
- this.handleSignIn = (redirectUri = `${this.config.baseUrl}/api/logto/sign-in-callback`, interactionMode) => withIronSessionApiRoute(async (request, response) => {
7
+ this.adapters = adapters;
8
+ this.handleSignIn = (redirectUri = `${this.config.baseUrl}/api/logto/sign-in-callback`, interactionMode) => this.adapters.withIronSessionApiRoute(async (request, response) => {
10
9
  const nodeClient = this.createNodeClient(request);
11
10
  await nodeClient.signIn(redirectUri, interactionMode);
12
11
  await this.storage?.save();
@@ -14,7 +13,7 @@ class LogtoClient {
14
13
  response.redirect(this.navigateUrl);
15
14
  }
16
15
  }, this.ironSessionConfigs);
17
- this.handleSignInCallback = (redirectTo = this.config.baseUrl) => withIronSessionApiRoute(async (request, response) => {
16
+ this.handleSignInCallback = (redirectTo = this.config.baseUrl) => this.adapters.withIronSessionApiRoute(async (request, response) => {
18
17
  const nodeClient = this.createNodeClient(request);
19
18
  if (request.url) {
20
19
  await nodeClient.handleSignInCallback(`${this.config.baseUrl}${request.url}`);
@@ -22,7 +21,7 @@ class LogtoClient {
22
21
  response.redirect(redirectTo);
23
22
  }
24
23
  }, this.ironSessionConfigs);
25
- this.handleSignOut = (redirectUri = this.config.baseUrl) => withIronSessionApiRoute(async (request, response) => {
24
+ this.handleSignOut = (redirectUri = this.config.baseUrl) => this.adapters.withIronSessionApiRoute(async (request, response) => {
26
25
  const nodeClient = this.createNodeClient(request);
27
26
  await nodeClient.signOut(redirectUri);
28
27
  request.session.destroy();
@@ -53,13 +52,13 @@ class LogtoClient {
53
52
  }
54
53
  response.status(404).end();
55
54
  };
56
- this.withLogtoApiRoute = (handler, config = {}) => withIronSessionApiRoute(async (request, response) => {
55
+ this.withLogtoApiRoute = (handler, config = {}) => this.adapters.withIronSessionApiRoute(async (request, response) => {
57
56
  const user = await this.getLogtoUserFromRequest(request, config);
58
57
  // eslint-disable-next-line @silverhand/fp/no-mutating-methods
59
58
  Object.defineProperty(request, 'user', { enumerable: true, get: () => user });
60
59
  return handler(request, response);
61
60
  }, this.ironSessionConfigs);
62
- this.withLogtoSsr = (handler, configs = {}) => withIronSessionSsr(async (context) => {
61
+ this.withLogtoSsr = (handler, configs = {}) => this.adapters.withIronSessionSsr(async (context) => {
63
62
  const user = await this.getLogtoUserFromRequest(context.req, configs);
64
63
  // eslint-disable-next-line @silverhand/fp/no-mutating-methods
65
64
  Object.defineProperty(context.req, 'user', { enumerable: true, get: () => user });
@@ -91,4 +90,4 @@ class LogtoClient {
91
90
  }
92
91
  }
93
92
 
94
- export { LogtoClient as default };
93
+ export { LogtoNextBaseClient as default };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var next = require('iron-session/next');
6
+ var client = require('./client.cjs');
7
+ var NodeClient = require('@logto/node');
8
+
9
+ class LogtoClient extends client.default {
10
+ constructor(config) {
11
+ super(config, {
12
+ withIronSessionApiRoute: next.withIronSessionApiRoute,
13
+ withIronSessionSsr: next.withIronSessionSsr,
14
+ });
15
+ }
16
+ }
17
+
18
+ Object.defineProperty(exports, 'ReservedScope', {
19
+ enumerable: true,
20
+ get: function () { return NodeClient.ReservedScope; }
21
+ });
22
+ Object.defineProperty(exports, 'UserScope', {
23
+ enumerable: true,
24
+ get: function () { return NodeClient.UserScope; }
25
+ });
26
+ exports.default = LogtoClient;
@@ -0,0 +1,7 @@
1
+ import LogtoNextBaseClient from './client.js';
2
+ import type { LogtoNextConfig } from './types.js';
3
+ export { ReservedScope, UserScope } from '@logto/node';
4
+ export type { LogtoContext, InteractionMode } from '@logto/node';
5
+ export default class LogtoClient extends LogtoNextBaseClient {
6
+ constructor(config: LogtoNextConfig);
7
+ }
@@ -0,0 +1,14 @@
1
+ import { withIronSessionApiRoute, withIronSessionSsr } from 'iron-session/next';
2
+ import LogtoNextBaseClient from './client.js';
3
+ export { ReservedScope, UserScope } from '@logto/node';
4
+
5
+ class LogtoClient extends LogtoNextBaseClient {
6
+ constructor(config) {
7
+ super(config, {
8
+ withIronSessionApiRoute,
9
+ withIronSessionSsr,
10
+ });
11
+ }
12
+ }
13
+
14
+ export { LogtoClient as default };
@@ -1,5 +1,6 @@
1
1
  import type { LogtoConfig } from '@logto/node';
2
2
  import type { IronSession } from 'iron-session';
3
+ import type { withIronSessionApiRoute, withIronSessionSsr } from 'iron-session/next';
3
4
  import type { NextApiRequest } from 'next';
4
5
  export type NextRequestWithIronSession = NextApiRequest & {
5
6
  session: IronSession;
@@ -17,3 +18,7 @@ export type LogtoNextConfig = LogtoConfig & {
17
18
  cookieSecure: boolean;
18
19
  baseUrl: string;
19
20
  };
21
+ export type Adapters = {
22
+ withIronSessionApiRoute: typeof withIronSessionApiRoute;
23
+ withIronSessionSsr: typeof withIronSessionSsr;
24
+ };
package/package.json CHANGED
@@ -1,14 +1,22 @@
1
1
  {
2
2
  "name": "@logto/next",
3
- "version": "1.1.2",
4
- "source": "./src/index.ts",
5
- "main": "./lib/index.js",
3
+ "version": "2.0.0",
4
+ "type": "module",
5
+ "main": "./lib/src/index.cjs",
6
+ "module": "./lib/src/index.js",
7
+ "types": "./lib/src/index.d.ts",
6
8
  "exports": {
7
- "require": "./lib/index.js",
8
- "import": "./lib/index.mjs"
9
+ ".": {
10
+ "require": "./lib/src/index.cjs",
11
+ "import": "./lib/src/index.js",
12
+ "types": "./lib/src/index.d.ts"
13
+ },
14
+ "./edge": {
15
+ "require": "./lib/edge/index.cjs",
16
+ "import": "./lib/edge/index.js",
17
+ "types": "./lib/edge/index.d.ts"
18
+ }
9
19
  },
10
- "module": "./lib/index.mjs",
11
- "types": "./lib/index.d.ts",
12
20
  "files": [
13
21
  "lib"
14
22
  ],
@@ -18,25 +26,14 @@
18
26
  "url": "https://github.com/logto-io/js.git",
19
27
  "directory": "packages/next"
20
28
  },
21
- "scripts": {
22
- "dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
23
- "precommit": "lint-staged",
24
- "check": "tsc --noEmit",
25
- "build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
26
- "lint": "eslint --ext .ts src",
27
- "test": "jest",
28
- "test:coverage": "jest --silent --coverage",
29
- "prepack": "pnpm test"
30
- },
31
29
  "dependencies": {
32
- "@logto/node": "^1.1.2",
33
- "iron-session": "^6.1.3"
30
+ "@logto/node": "^2.0.0",
31
+ "iron-session": "^6.3.1"
34
32
  },
35
33
  "devDependencies": {
36
- "@jest/types": "^29.5.0",
37
- "@silverhand/eslint-config": "^2.0.0",
38
- "@silverhand/ts-config": "^1.0.0",
39
- "@silverhand/ts-config-react": "^2.0.0",
34
+ "@silverhand/eslint-config": "^3.0.1",
35
+ "@silverhand/ts-config": "^3.0.0",
36
+ "@silverhand/ts-config-react": "^3.0.0",
40
37
  "@swc/core": "^1.3.50",
41
38
  "@swc/jest": "^0.2.24",
42
39
  "@types/jest": "^29.5.0",
@@ -56,19 +53,22 @@
56
53
  "next": ">=12"
57
54
  },
58
55
  "eslintConfig": {
59
- "extends": "@silverhand"
56
+ "extends": "@silverhand",
57
+ "rules": {
58
+ "unicorn/prefer-node-protocol": "off"
59
+ }
60
60
  },
61
61
  "prettier": "@silverhand/eslint-config/.prettierrc",
62
62
  "publishConfig": {
63
63
  "access": "public"
64
64
  },
65
- "targets": {
66
- "main": {
67
- "context": "node",
68
- "engines": {
69
- "node": ">=18.12.0"
70
- }
71
- }
72
- },
73
- "gitHead": "9e9a8b0887ef67baa7c3c564590bb06e7801d03e"
74
- }
65
+ "scripts": {
66
+ "dev:tsc": "tsc -p tsconfig.build.json -w --preserveWatchOutput",
67
+ "precommit": "lint-staged",
68
+ "check": "tsc --noEmit",
69
+ "build": "rm -rf lib/ && tsc -p tsconfig.build.json --noEmit && rollup -c",
70
+ "lint": "eslint --ext .ts src",
71
+ "test": "node test.cjs && jest",
72
+ "test:coverage": "node test.cjs && jest --silent --coverage"
73
+ }
74
+ }
File without changes
File without changes
File without changes
File without changes