@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.
- package/build/providers/session_provider.js +2 -2
- package/build/src/client.d.ts +24 -19
- package/build/src/client.js +45 -41
- package/build/src/drivers_collection.d.ts +1 -2
- package/build/src/drivers_collection.js +2 -2
- package/build/src/{edge_plugin_adonisjs_session.d.ts → plugins/edge.d.ts} +1 -1
- package/build/src/{edge_plugin_adonisjs_session.js → plugins/edge.js} +2 -2
- package/build/src/plugins/japa/api_client.d.ts +75 -0
- package/build/src/plugins/japa/api_client.js +145 -0
- package/build/src/plugins/japa/browser_client.d.ts +36 -0
- package/build/src/plugins/japa/browser_client.js +119 -0
- package/build/src/types/main.d.ts +1 -1
- package/package.json +17 -5
|
@@ -53,8 +53,8 @@ export default class SessionProvider {
|
|
|
53
53
|
});
|
|
54
54
|
const edge = await this.getEdge();
|
|
55
55
|
if (edge) {
|
|
56
|
-
const {
|
|
57
|
-
edge.use(
|
|
56
|
+
const { edgePluginSession } = await import('../src/plugins/edge.js');
|
|
57
|
+
edge.use(edgePluginSession);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
}
|
package/build/src/client.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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
|
-
*
|
|
12
|
+
* Session to use when no explicit session id is
|
|
13
|
+
* defined
|
|
15
14
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
session: SessionData;
|
|
19
|
-
flashMessages: SessionData;
|
|
20
|
-
}>;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
constructor(driver: SessionDriverContract);
|
|
21
17
|
/**
|
|
22
|
-
*
|
|
23
|
-
* the session id and cookie name for it to be accessible
|
|
24
|
-
* by the server
|
|
18
|
+
* Merge session data
|
|
25
19
|
*/
|
|
26
|
-
|
|
27
|
-
sessionId: string;
|
|
28
|
-
signedSessionId: string;
|
|
29
|
-
cookieName: string;
|
|
30
|
-
}>;
|
|
20
|
+
merge(values: SessionData): this;
|
|
31
21
|
/**
|
|
32
|
-
*
|
|
22
|
+
* Merge flash messages
|
|
33
23
|
*/
|
|
34
|
-
|
|
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
|
}
|
package/build/src/client.js
CHANGED
|
@@ -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
|
-
*
|
|
17
|
+
* Data store
|
|
17
18
|
*/
|
|
18
|
-
#
|
|
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
|
-
*
|
|
29
|
+
* Session key for setting flash messages
|
|
25
30
|
*/
|
|
26
|
-
|
|
31
|
+
flashKey = '__flash__';
|
|
27
32
|
/**
|
|
28
33
|
* Session to use when no explicit session id is
|
|
29
34
|
* defined
|
|
30
35
|
*/
|
|
31
|
-
|
|
36
|
+
sessionId = cuid();
|
|
37
|
+
constructor(driver) {
|
|
38
|
+
this.#driver = driver;
|
|
39
|
+
}
|
|
32
40
|
/**
|
|
33
|
-
*
|
|
41
|
+
* Merge session data
|
|
34
42
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this
|
|
38
|
-
this.#driver = driver;
|
|
39
|
-
this.#cookieClient = cookieClient;
|
|
43
|
+
merge(values) {
|
|
44
|
+
this.#store.merge(values);
|
|
45
|
+
return this;
|
|
40
46
|
}
|
|
41
47
|
/**
|
|
42
|
-
*
|
|
48
|
+
* Merge flash messages
|
|
43
49
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
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(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
|
|
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
|
-
*
|
|
67
|
+
* Destroys the session data with the store
|
|
77
68
|
*/
|
|
78
|
-
async
|
|
79
|
-
|
|
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,
|
|
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,
|
|
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(
|
|
34
|
+
return driverFactory(args[0], args[1]);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
const sessionDriversList = new SessionDriversCollection();
|
|
@@ -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 '
|
|
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
|
|
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
|
|
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-
|
|
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": "
|
|
59
|
-
"@types/node": "^20.
|
|
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.
|
|
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.
|
|
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",
|