@adonisjs/session 7.0.0-10 → 7.0.0-11

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.
@@ -53,8 +53,8 @@ export default class SessionProvider {
53
53
  });
54
54
  const edge = await this.getEdge();
55
55
  if (edge) {
56
- const { edgePluginAdonisJSSession } = await import('../src/edge_plugin_adonisjs_session.js');
57
- edge.use(edgePluginAdonisJSSession);
56
+ const { edgePluginSession } = await import('../src/plugins/edge.js');
57
+ edge.use(edgePluginSession);
58
58
  }
59
59
  }
60
60
  }
@@ -1,5 +1,4 @@
1
- import type { CookieClient } from '@adonisjs/core/http';
2
- import type { SessionConfig, SessionData, SessionDriverContract } from './types/main.js';
1
+ import type { SessionData, SessionDriverContract } from './types/main.js';
3
2
  /**
4
3
  * Session client exposes the API to set session data as a client
5
4
  */
@@ -9,27 +8,33 @@ export declare class SessionClient {
9
8
  * Session key for setting flash messages
10
9
  */
11
10
  flashKey: string;
12
- constructor(config: SessionConfig, driver: SessionDriverContract, cookieClient: CookieClient);
13
11
  /**
14
- * Load session data from the driver
12
+ * Session to use when no explicit session id is
13
+ * defined
15
14
  */
16
- load(cookies: Record<string, any>, sessionId?: string): Promise<{
17
- sessionId: string;
18
- session: SessionData;
19
- flashMessages: SessionData;
20
- }>;
15
+ sessionId: string;
16
+ constructor(driver: SessionDriverContract);
21
17
  /**
22
- * Commits the session data to the session store and returns
23
- * the session id and cookie name for it to be accessible
24
- * by the server
18
+ * Merge session data
25
19
  */
26
- commit(values: SessionData | null, flashMessages: SessionData | null, sessionId?: string): Promise<{
27
- sessionId: string;
28
- signedSessionId: string;
29
- cookieName: string;
30
- }>;
20
+ merge(values: SessionData): this;
31
21
  /**
32
- * Clear the session store
22
+ * Merge flash messages
33
23
  */
34
- forget(sessionId?: string): Promise<void>;
24
+ flash(values: SessionData): this;
25
+ /**
26
+ * Commits data to the session store.
27
+ */
28
+ commit(): Promise<void>;
29
+ /**
30
+ * Destroys the session data with the store
31
+ */
32
+ destroy(sessionId?: string): Promise<void>;
33
+ /**
34
+ * Loads session data from the session store
35
+ */
36
+ load(sessionId?: string): Promise<{
37
+ values: any;
38
+ flashMessages: any;
39
+ }>;
35
40
  }
@@ -7,75 +7,79 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { cuid } from '@adonisjs/core/helpers';
10
+ import debug from './debug.js';
10
11
  import { Store } from './store.js';
11
12
  /**
12
13
  * Session client exposes the API to set session data as a client
13
14
  */
14
15
  export class SessionClient {
15
16
  /**
16
- * Session configuration
17
+ * Data store
17
18
  */
18
- #config;
19
+ #store = new Store({});
20
+ /**
21
+ * Flash messages store
22
+ */
23
+ #flashMessagesStore = new Store({});
19
24
  /**
20
25
  * The session driver to use for reading and writing session data
21
26
  */
22
27
  #driver;
23
28
  /**
24
- * Cookie client contract to sign and unsign cookies
29
+ * Session key for setting flash messages
25
30
  */
26
- #cookieClient;
31
+ flashKey = '__flash__';
27
32
  /**
28
33
  * Session to use when no explicit session id is
29
34
  * defined
30
35
  */
31
- #sessionId = cuid();
36
+ sessionId = cuid();
37
+ constructor(driver) {
38
+ this.#driver = driver;
39
+ }
32
40
  /**
33
- * Session key for setting flash messages
41
+ * Merge session data
34
42
  */
35
- flashKey = '__flash__';
36
- constructor(config, driver, cookieClient) {
37
- this.#config = config;
38
- this.#driver = driver;
39
- this.#cookieClient = cookieClient;
43
+ merge(values) {
44
+ this.#store.merge(values);
45
+ return this;
40
46
  }
41
47
  /**
42
- * Load session data from the driver
48
+ * Merge flash messages
43
49
  */
44
- async load(cookies, sessionId) {
45
- const sessionIdCookie = cookies[this.#config.cookieName];
46
- const sessId = sessionId || sessionIdCookie ? sessionIdCookie.value : this.#sessionId;
47
- const contents = await this.#driver.read(sessId);
48
- const store = new Store(contents);
49
- const flashMessages = store.pull(this.flashKey, null);
50
- return {
51
- sessionId: sessId,
52
- session: store.all(),
53
- flashMessages,
54
- };
50
+ flash(values) {
51
+ this.#flashMessagesStore.merge(values);
52
+ return this;
55
53
  }
56
54
  /**
57
- * Commits the session data to the session store and returns
58
- * the session id and cookie name for it to be accessible
59
- * by the server
55
+ * Commits data to the session store.
60
56
  */
61
- async commit(values, flashMessages, sessionId) {
62
- const sessId = sessionId || this.#sessionId;
63
- /**
64
- * Persist session data to the store, alongside flash messages
65
- */
66
- if (values || flashMessages) {
67
- await this.#driver.write(sessId, Object.assign({ [this.flashKey]: flashMessages }, values));
57
+ async commit() {
58
+ if (!this.#flashMessagesStore.isEmpty) {
59
+ this.#store.set(this.flashKey, this.#flashMessagesStore.toJSON());
60
+ }
61
+ debug('committing session data during api request');
62
+ if (!this.#store.isEmpty) {
63
+ this.#driver.write(this.sessionId, this.#store.toJSON());
68
64
  }
69
- return {
70
- sessionId: sessId,
71
- signedSessionId: this.#cookieClient.sign(this.#config.cookieName, sessId),
72
- cookieName: this.#config.cookieName,
73
- };
74
65
  }
75
66
  /**
76
- * Clear the session store
67
+ * Destroys the session data with the store
77
68
  */
78
- async forget(sessionId) {
79
- await this.#driver.destroy(sessionId || this.#sessionId);
69
+ async destroy(sessionId) {
70
+ debug('destroying session data during api request');
71
+ this.#driver.destroy(sessionId || this.sessionId);
72
+ }
73
+ /**
74
+ * Loads session data from the session store
75
+ */
76
+ async load(sessionId) {
77
+ const contents = await this.#driver.read(sessionId || this.sessionId);
78
+ const store = new Store(contents);
79
+ const flashMessages = store.pull(this.flashKey, {});
80
+ return {
81
+ values: store.all(),
82
+ flashMessages,
83
+ };
80
84
  }
81
85
  }
@@ -1,4 +1,3 @@
1
- import type { HttpContext } from '@adonisjs/core/http';
2
1
  import type { SessionDriversList } from './types/main.js';
3
2
  /**
4
3
  * A global collection of session drivers
@@ -16,7 +15,7 @@ declare class SessionDriversCollection {
16
15
  /**
17
16
  * Creates the driver instance with config
18
17
  */
19
- create<Name extends keyof SessionDriversList>(name: Name, config: Parameters<SessionDriversList[Name]>[0], ctx: HttpContext): ReturnType<SessionDriversList[Name]>;
18
+ create<Name extends keyof SessionDriversList>(name: Name, ...args: Parameters<SessionDriversList[Name]>): ReturnType<SessionDriversList[Name]>;
20
19
  }
21
20
  declare const sessionDriversList: SessionDriversCollection;
22
21
  export default sessionDriversList;
@@ -26,12 +26,12 @@ class SessionDriversCollection {
26
26
  /**
27
27
  * Creates the driver instance with config
28
28
  */
29
- create(name, config, ctx) {
29
+ create(name, ...args) {
30
30
  const driverFactory = this.list[name];
31
31
  if (!driverFactory) {
32
32
  throw new RuntimeException(`Unknown session driver "${String(name)}". Make sure the driver is registered`);
33
33
  }
34
- return driverFactory(config, ctx);
34
+ return driverFactory(args[0], args[1]);
35
35
  }
36
36
  }
37
37
  const sessionDriversList = new SessionDriversCollection();
@@ -3,4 +3,4 @@ import type { PluginFn } from 'edge.js/types';
3
3
  * The edge plugin for AdonisJS Session adds tags to read
4
4
  * flash messages
5
5
  */
6
- export declare const edgePluginAdonisJSSession: PluginFn<undefined>;
6
+ export declare const edgePluginSession: PluginFn<undefined>;
@@ -6,12 +6,12 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
- import debug from './debug.js';
9
+ import debug from '../debug.js';
10
10
  /**
11
11
  * The edge plugin for AdonisJS Session adds tags to read
12
12
  * flash messages
13
13
  */
14
- export const edgePluginAdonisJSSession = (edge) => {
14
+ export const edgePluginSession = (edge) => {
15
15
  debug('registering session tags with edge');
16
16
  edge.registerTag({
17
17
  tagName: 'flashMessage',
@@ -0,0 +1,75 @@
1
+ import type { PluginFn } from '@japa/runner/types';
2
+ import type { ApplicationService } from '@adonisjs/core/types';
3
+ import { SessionClient } from '../../client.js';
4
+ import type { SessionData } from '../../types/main.js';
5
+ declare module '@japa/api-client' {
6
+ interface ApiRequest {
7
+ sessionClient: SessionClient;
8
+ /**
9
+ * Make HTTP request along with the provided session data
10
+ */
11
+ withSession(values: SessionData): this;
12
+ /**
13
+ * Make HTTP request along with the provided session flash
14
+ * messages.
15
+ */
16
+ withFlashMessages(values: SessionData): this;
17
+ }
18
+ interface ApiResponse {
19
+ sessionBag: {
20
+ values: SessionData;
21
+ flashMessages: SessionData;
22
+ };
23
+ /**
24
+ * Get session data from the HTTP response
25
+ */
26
+ session(key?: string): any;
27
+ /**
28
+ * Get flash messages from the HTTP response
29
+ */
30
+ flashMessages(): SessionData;
31
+ /**
32
+ * Get flash messages for a specific key from the HTTP response
33
+ */
34
+ flashMessage(key: string): SessionData;
35
+ /**
36
+ * Assert session key-value pair exists
37
+ */
38
+ assertSession(key: string, value?: any): void;
39
+ /**
40
+ * Assert key is missing in session store
41
+ */
42
+ assertSessionMissing(key: string): void;
43
+ /**
44
+ * Assert flash message key-value pair exists
45
+ */
46
+ assertFlashMessage(key: string, value?: any): void;
47
+ /**
48
+ * Assert key is missing flash messages store
49
+ */
50
+ assertFlashMissing(key: string): void;
51
+ /**
52
+ * Assert flash messages has validation errors for
53
+ * the given field
54
+ */
55
+ assertHasValidationError(field: string): void;
56
+ /**
57
+ * Assert flash messages does not have validation errors
58
+ * for the given field
59
+ */
60
+ assertDoesNotHaveValidationError(field: string): void;
61
+ /**
62
+ * Assert error message for a given field
63
+ */
64
+ assertValidationError(field: string, message: string): void;
65
+ /**
66
+ * Assert all error messages for a given field
67
+ */
68
+ assertValidationErrors(field: string, messages: string[]): void;
69
+ }
70
+ }
71
+ /**
72
+ * Hooks AdonisJS Session with the Japa API Client
73
+ * plugin
74
+ */
75
+ export declare const sessionApiClient: (app: ApplicationService) => PluginFn;
@@ -0,0 +1,145 @@
1
+ /*
2
+ * @adonisjs/session
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import lodash from '@poppinss/utils/lodash';
10
+ import { RuntimeException } from '@poppinss/utils';
11
+ import { ApiClient, ApiRequest, ApiResponse } from '@japa/api-client';
12
+ import { SessionClient } from '../../client.js';
13
+ import { registerSessionDriver } from '../../helpers.js';
14
+ import sessionDriversList from '../../drivers_collection.js';
15
+ /**
16
+ * Hooks AdonisJS Session with the Japa API Client
17
+ * plugin
18
+ */
19
+ export const sessionApiClient = (app) => {
20
+ const pluginFn = async function () {
21
+ const config = app.config.get('session');
22
+ /**
23
+ * Disallow usage of driver other than memory during testing
24
+ */
25
+ if (config.driver !== 'memory') {
26
+ throw new RuntimeException(`Cannot use session driver "${config.driver}" during testing. Switch to memory driver`);
27
+ }
28
+ /**
29
+ * Register the memory driver if not already registered
30
+ */
31
+ await registerSessionDriver(app, 'memory');
32
+ /**
33
+ * Stick an singleton session client to APIRequest. The session
34
+ * client is used to keep a track of session data we have
35
+ * to send during the request.
36
+ */
37
+ ApiRequest.getter('sessionClient', function () {
38
+ return new SessionClient(sessionDriversList.create('memory', config));
39
+ }, true);
40
+ /**
41
+ * Define session data
42
+ */
43
+ ApiRequest.macro('withSession', function (data) {
44
+ this.sessionClient.merge(data);
45
+ return this;
46
+ });
47
+ /**
48
+ * Define flash messages
49
+ */
50
+ ApiRequest.macro('withFlashMessages', function (data) {
51
+ this.sessionClient.flash(data);
52
+ return this;
53
+ });
54
+ /**
55
+ * Get session data
56
+ */
57
+ ApiResponse.macro('session', function (key) {
58
+ return key ? lodash.get(this.sessionBag.values, key) : this.sessionBag.values;
59
+ });
60
+ /**
61
+ * Get flash messages
62
+ */
63
+ ApiResponse.macro('flashMessages', function () {
64
+ return this.sessionBag.flashMessages;
65
+ });
66
+ ApiResponse.macro('flashMessage', function (key) {
67
+ return lodash.get(this.sessionBag.flashMessages, key);
68
+ });
69
+ /**
70
+ * Response session assertions
71
+ */
72
+ ApiResponse.macro('assertSession', function (key, value) {
73
+ this.assert.property(this.session(), key);
74
+ if (value !== undefined) {
75
+ this.assert.deepEqual(this.session(key), value);
76
+ }
77
+ });
78
+ ApiResponse.macro('assertSessionMissing', function (key) {
79
+ this.assert.notProperty(this.session(), key);
80
+ });
81
+ ApiResponse.macro('assertFlashMessage', function (key, value) {
82
+ this.assert.property(this.flashMessages(), key);
83
+ if (value !== undefined) {
84
+ this.assert.deepEqual(this.flashMessage(key), value);
85
+ }
86
+ });
87
+ ApiResponse.macro('assertFlashMissing', function (key) {
88
+ this.assert.notProperty(this.flashMessages(), key);
89
+ });
90
+ ApiResponse.macro('assertHasValidationError', function (field) {
91
+ this.assert.property(this.flashMessage('errors'), field);
92
+ });
93
+ ApiResponse.macro('assertDoesNotHaveValidationError', function (field) {
94
+ this.assert.notProperty(this.flashMessage('errors'), field);
95
+ });
96
+ ApiResponse.macro('assertValidationError', function (field, message) {
97
+ this.assert.include(this.flashMessage('errors')?.[field] || [], message);
98
+ });
99
+ ApiResponse.macro('assertValidationErrors', function (field, messages) {
100
+ this.assert.deepEqual(this.flashMessage('errors')?.[field] || [], messages);
101
+ });
102
+ /**
103
+ * We define the hook using the "request.setup" method because we
104
+ * want to allow other Japa hooks to mutate the session store
105
+ * without running into race conditions
106
+ */
107
+ ApiClient.onRequest((request) => {
108
+ request.setup(async () => {
109
+ /**
110
+ * Set cookie
111
+ */
112
+ request.withCookie(config.cookieName, request.sessionClient.sessionId);
113
+ /**
114
+ * Persist data
115
+ */
116
+ await request.sessionClient.commit();
117
+ /**
118
+ * Cleanup if request fails
119
+ */
120
+ return async (error) => {
121
+ if (error) {
122
+ await request.sessionClient.destroy();
123
+ }
124
+ };
125
+ });
126
+ request.teardown(async (response) => {
127
+ const sessionId = response.cookie(config.cookieName);
128
+ /**
129
+ * Reading session data from the response cookie
130
+ */
131
+ response.sessionBag = sessionId
132
+ ? await response.request.sessionClient.load(sessionId.value)
133
+ : {
134
+ values: {},
135
+ flashMessages: {},
136
+ };
137
+ /**
138
+ * Cleanup state
139
+ */
140
+ await request.sessionClient.destroy(sessionId?.value);
141
+ });
142
+ });
143
+ };
144
+ return pluginFn;
145
+ };
@@ -0,0 +1,36 @@
1
+ import type { PluginFn } from '@japa/runner/types';
2
+ import type { ApplicationService } from '@adonisjs/core/types';
3
+ import type { CookieOptions as AdonisCookieOptions } from '@adonisjs/core/types/http';
4
+ import { SessionClient } from '../../client.js';
5
+ import type { SessionData } from '../../types/main.js';
6
+ declare module 'playwright' {
7
+ interface BrowserContext {
8
+ sessionClient: SessionClient;
9
+ /**
10
+ * Initiate session. The session id cookie will be defined
11
+ * if missing
12
+ */
13
+ initiateSession(options?: Partial<AdonisCookieOptions>): Promise<void>;
14
+ /**
15
+ * Returns data from the session store
16
+ */
17
+ getSession(): Promise<any>;
18
+ /**
19
+ * Returns data from the session store
20
+ */
21
+ getFlashMessages(): Promise<any>;
22
+ /**
23
+ * Set session data
24
+ */
25
+ setSession(values: SessionData): Promise<void>;
26
+ /**
27
+ * Set flash messages
28
+ */
29
+ setFlashMessages(values: SessionData): Promise<void>;
30
+ }
31
+ }
32
+ /**
33
+ * Hooks AdonisJS Session with the Japa API Client
34
+ * plugin
35
+ */
36
+ export declare const sessionBrowserClient: (app: ApplicationService) => PluginFn;
@@ -0,0 +1,119 @@
1
+ /*
2
+ * @adonisjs/session
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import { RuntimeException } from '@poppinss/utils';
10
+ import { decoratorsCollection } from '@japa/browser-client';
11
+ import { SessionClient } from '../../client.js';
12
+ import { registerSessionDriver } from '../../helpers.js';
13
+ import sessionDriversList from '../../drivers_collection.js';
14
+ /**
15
+ * Transforming AdonisJS same site option to playwright
16
+ * same site option.
17
+ */
18
+ function transformSameSiteOption(sameSite) {
19
+ if (!sameSite) {
20
+ return;
21
+ }
22
+ if (sameSite === true || sameSite === 'strict') {
23
+ return 'Strict';
24
+ }
25
+ if (sameSite === 'lax') {
26
+ return 'Lax';
27
+ }
28
+ if (sameSite === 'none') {
29
+ return 'None';
30
+ }
31
+ }
32
+ /**
33
+ * Transforming AdonisJS session config to playwright cookie options.
34
+ */
35
+ function getSessionCookieOptions(config, cookieOptions) {
36
+ const options = { ...config.cookie, ...cookieOptions };
37
+ return {
38
+ ...options,
39
+ expires: undefined,
40
+ sameSite: transformSameSiteOption(options.sameSite),
41
+ };
42
+ }
43
+ /**
44
+ * Hooks AdonisJS Session with the Japa API Client
45
+ * plugin
46
+ */
47
+ export const sessionBrowserClient = (app) => {
48
+ const pluginFn = async function () {
49
+ const config = app.config.get('session');
50
+ /**
51
+ * Disallow usage of driver other than memory during testing
52
+ */
53
+ if (config.driver !== 'memory') {
54
+ throw new RuntimeException(`Cannot use session driver "${config.driver}" during testing. Switch to memory driver`);
55
+ }
56
+ /**
57
+ * Register the memory driver if not already registered
58
+ */
59
+ await registerSessionDriver(app, 'memory');
60
+ decoratorsCollection.register({
61
+ context(context) {
62
+ /**
63
+ * Reference to session client per browser context
64
+ */
65
+ context.sessionClient = new SessionClient(sessionDriversList.create('memory', config));
66
+ /**
67
+ * Initiating session store
68
+ */
69
+ context.initiateSession = async function (options) {
70
+ const sessionId = await context.getCookie(config.cookieName);
71
+ if (sessionId) {
72
+ context.sessionClient.sessionId = sessionId;
73
+ return;
74
+ }
75
+ await context.setCookie(config.cookieName, context.sessionClient.sessionId, getSessionCookieOptions(config, options));
76
+ };
77
+ /**
78
+ * Returns session data
79
+ */
80
+ context.getSession = async function () {
81
+ await context.initiateSession();
82
+ const sessionData = await context.sessionClient.load();
83
+ return sessionData.values;
84
+ };
85
+ /**
86
+ * Returns flash messages from the data store
87
+ */
88
+ context.getFlashMessages = async function () {
89
+ await context.initiateSession();
90
+ const sessionData = await context.sessionClient.load();
91
+ return sessionData.flashMessages;
92
+ };
93
+ /**
94
+ * Set session data
95
+ */
96
+ context.setSession = async function (values) {
97
+ await context.initiateSession();
98
+ context.sessionClient.merge(values);
99
+ await context.sessionClient.commit();
100
+ };
101
+ /**
102
+ * Set flash messages
103
+ */
104
+ context.setFlashMessages = async function (values) {
105
+ await context.initiateSession();
106
+ context.sessionClient.flash(values);
107
+ await context.sessionClient.commit();
108
+ };
109
+ /**
110
+ * Destroy session when context is closed
111
+ */
112
+ context.on('close', async function () {
113
+ await context.sessionClient.destroy();
114
+ });
115
+ },
116
+ });
117
+ };
118
+ return pluginFn;
119
+ };
@@ -102,5 +102,5 @@ export interface SessionDriversList {
102
102
  file: (config: SessionConfig, ctx: HttpContext) => FileDriver;
103
103
  cookie: (config: SessionConfig, ctx: HttpContext) => CookieDriver;
104
104
  redis: (config: SessionConfig, ctx: HttpContext) => RedisDriver;
105
- memory: (config: SessionConfig, ctx: HttpContext) => MemoryDriver;
105
+ memory: (config: SessionConfig, ctx?: HttpContext) => MemoryDriver;
106
106
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@adonisjs/session",
3
3
  "description": "Session provider for AdonisJS",
4
- "version": "7.0.0-10",
4
+ "version": "7.0.0-11",
5
5
  "engines": {
6
6
  "node": ">=18.16.0"
7
7
  },
@@ -22,6 +22,9 @@
22
22
  "./factories": "./build/factories/main.js",
23
23
  "./session_provider": "./build/providers/session_provider.js",
24
24
  "./session_middleware": "./build/src/session_middleware.js",
25
+ "./plugins/edge": "./build/src/plugins/edge.js",
26
+ "./plugins/api_client": "./build/src/plugins/japa/api_client.js",
27
+ "./plugins/browser_client": "./build/src/plugins/japa/browser_client.js",
25
28
  "./client": "./build/src/client.js",
26
29
  "./types": "./build/src/types.js"
27
30
  },
@@ -55,8 +58,8 @@
55
58
  "@japa/plugin-adonisjs": "^2.0.0-1",
56
59
  "@japa/runner": "^3.0.0-6",
57
60
  "@japa/snapshot": "^2.0.0-1",
58
- "@swc/core": "^1.3.78",
59
- "@types/node": "^20.5.1",
61
+ "@swc/core": "1.3.82",
62
+ "@types/node": "^20.6.0",
60
63
  "@types/set-cookie-parser": "^2.4.3",
61
64
  "@types/supertest": "^2.0.12",
62
65
  "@vinejs/vine": "^1.6.0",
@@ -65,11 +68,12 @@
65
68
  "cross-env": "^7.0.3",
66
69
  "del-cli": "^5.0.0",
67
70
  "edge.js": "^6.0.0-8",
68
- "eslint": "^8.47.0",
71
+ "eslint": "^8.49.0",
72
+ "get-port": "^7.0.0",
69
73
  "github-label-sync": "^2.3.1",
70
74
  "husky": "^8.0.3",
71
75
  "np": "^8.0.4",
72
- "playwright": "^1.37.1",
76
+ "playwright": "^1.38.0",
73
77
  "prettier": "^3.0.2",
74
78
  "set-cookie-parser": "^2.6.0",
75
79
  "supertest": "^6.3.3",
@@ -82,6 +86,8 @@
82
86
  "peerDependencies": {
83
87
  "@adonisjs/core": "^6.1.5-22",
84
88
  "@adonisjs/redis": "^8.0.0-10",
89
+ "@japa/api-client": "^2.0.0-0",
90
+ "@japa/browser-client": "^2.0.0-3",
85
91
  "edge.js": "^6.0.0-8"
86
92
  },
87
93
  "peerDependenciesMeta": {
@@ -90,6 +96,12 @@
90
96
  },
91
97
  "edge.js": {
92
98
  "optional": true
99
+ },
100
+ "@japa/api-client": {
101
+ "optional": true
102
+ },
103
+ "@japa/browser-client": {
104
+ "optional": true
93
105
  }
94
106
  },
95
107
  "author": "virk,adonisjs",