@adonisjs/session 8.0.0-next.0 → 8.0.0-next.2
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/commands/commands.json +1 -0
- package/build/commands/main.d.ts +4 -0
- package/build/commands/main.js +36 -0
- package/build/commands/make_session_table.d.ts +9 -0
- package/build/commands/make_session_table.js +13 -0
- package/build/cookie--JOJxrtW.js +31 -0
- package/build/database-vbrhCOPd.js +86 -0
- package/build/debug-BZVg83L1.js +3 -0
- package/build/dynamodb-BFVgTQSf.js +72 -0
- package/build/factories/main.js +27 -45
- package/build/file-BBU02j4z.js +71 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +7 -25
- package/build/main-kn40V-hF.js +2 -0
- package/build/make/migration/sessions.stub +26 -0
- package/build/providers/session_provider.d.ts +2 -1
- package/build/providers/session_provider.js +34 -48
- package/build/redis-D8D9UtiD.js +91 -0
- package/build/session-C9DdRahS.js +215 -0
- package/build/session-Cb9-DoMh.js +139 -0
- package/build/session_collection-CvS5yIq6.js +31 -0
- package/build/session_middleware-gegOBxmm.js +27 -0
- package/build/src/client.js +38 -7
- package/build/src/debug.d.ts +1 -1
- package/build/src/define_config.d.ts +14 -6
- package/build/src/errors.d.ts +9 -0
- package/build/src/plugins/edge.d.ts +5 -1
- package/build/src/plugins/edge.js +74 -124
- package/build/src/plugins/japa/api_client.js +76 -96
- package/build/src/plugins/japa/browser_client.js +58 -81
- package/build/src/session.d.ts +12 -0
- package/build/src/session_collection.d.ts +81 -0
- package/build/src/session_middleware.js +5 -9
- package/build/src/stores/database.d.ts +70 -0
- package/build/src/stores/memory.d.ts +19 -2
- package/build/src/stores/redis.d.ts +15 -2
- package/build/src/types.d.ts +62 -8
- package/build/src/types.js +1 -0
- package/build/values_store-CvR1Sn37.js +78 -0
- package/package.json +65 -42
- package/build/chunk-DFXWYDMY.js +0 -62
- package/build/chunk-HAD4PFFM.js +0 -229
- package/build/chunk-MVBWJOEG.js +0 -187
- package/build/chunk-SBOMJK4T.js +0 -14
- package/build/chunk-SHD6OX52.js +0 -488
- package/build/chunk-Y566BNUT.js +0 -113
- package/build/cookie-YBBGLCO5.js +0 -88
- package/build/dynamodb-PLZABBFD.js +0 -153
- package/build/file-CCJ5ESE2.js +0 -151
- package/build/redis-NXJWWWVB.js +0 -89
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { t as debug_default } from "./debug-BZVg83L1.js";
|
|
2
|
+
import string from "@adonisjs/core/helpers/string";
|
|
3
|
+
import { MessageBuilder } from "@adonisjs/core/helpers";
|
|
4
|
+
var RedisStore = class {
|
|
5
|
+
#connection;
|
|
6
|
+
#ttlSeconds;
|
|
7
|
+
constructor(connection, age) {
|
|
8
|
+
this.#connection = connection;
|
|
9
|
+
this.#ttlSeconds = string.seconds.parse(age);
|
|
10
|
+
debug_default("initiating redis store");
|
|
11
|
+
}
|
|
12
|
+
#processSessionResult(options) {
|
|
13
|
+
if (!options.contents) return {
|
|
14
|
+
session: null,
|
|
15
|
+
isInvalid: true
|
|
16
|
+
};
|
|
17
|
+
const data = this.#parseSessionData(options.contents, options.sessionId);
|
|
18
|
+
if (!data) return {
|
|
19
|
+
session: null,
|
|
20
|
+
isInvalid: true
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
session: {
|
|
24
|
+
id: options.sessionId,
|
|
25
|
+
data
|
|
26
|
+
},
|
|
27
|
+
isInvalid: false
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async #fetchSessionContents(sessionIds) {
|
|
31
|
+
const pipeline = this.#connection.pipeline();
|
|
32
|
+
sessionIds.forEach((sessionId) => pipeline.get(sessionId));
|
|
33
|
+
return (await pipeline.exec())?.map((result) => result[1]) ?? [];
|
|
34
|
+
}
|
|
35
|
+
async #cleanupInvalidSessions(userId, invalidSessionIds) {
|
|
36
|
+
if (invalidSessionIds.length === 0) return;
|
|
37
|
+
await this.#connection.srem(this.#getTagKey(userId), ...invalidSessionIds);
|
|
38
|
+
}
|
|
39
|
+
#getTagKey(userId) {
|
|
40
|
+
return `session_tag:${userId}`;
|
|
41
|
+
}
|
|
42
|
+
#parseSessionData(contents, sessionId) {
|
|
43
|
+
try {
|
|
44
|
+
return new MessageBuilder().verify(contents, sessionId);
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async read(sessionId) {
|
|
50
|
+
debug_default("redis store: reading session data %s", sessionId);
|
|
51
|
+
const contents = await this.#connection.get(sessionId);
|
|
52
|
+
if (!contents) return null;
|
|
53
|
+
try {
|
|
54
|
+
return new MessageBuilder().verify(contents, sessionId);
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async write(sessionId, values) {
|
|
60
|
+
debug_default("redis store: writing session data %s, %O", sessionId, values);
|
|
61
|
+
const message = new MessageBuilder().build(values, void 0, sessionId);
|
|
62
|
+
await this.#connection.setex(sessionId, this.#ttlSeconds, message);
|
|
63
|
+
}
|
|
64
|
+
async destroy(sessionId) {
|
|
65
|
+
debug_default("redis store: destroying session data %s", sessionId);
|
|
66
|
+
await this.#connection.del(sessionId);
|
|
67
|
+
}
|
|
68
|
+
async touch(sessionId) {
|
|
69
|
+
debug_default("redis store: touching session data %s", sessionId);
|
|
70
|
+
await this.#connection.expire(sessionId, this.#ttlSeconds);
|
|
71
|
+
}
|
|
72
|
+
async tag(sessionId, userId) {
|
|
73
|
+
debug_default("redis store: tagging session %s with user %s", sessionId, userId);
|
|
74
|
+
await this.#connection.sadd(this.#getTagKey(userId), sessionId);
|
|
75
|
+
}
|
|
76
|
+
async tagged(userId) {
|
|
77
|
+
debug_default("redis store: getting sessions tagged with user %s", userId);
|
|
78
|
+
const sessionIds = await this.#connection.smembers(this.#getTagKey(userId));
|
|
79
|
+
if (sessionIds.length === 0) return [];
|
|
80
|
+
const contents = await this.#fetchSessionContents(sessionIds);
|
|
81
|
+
const results = sessionIds.map((sessionId, index) => this.#processSessionResult({
|
|
82
|
+
sessionId,
|
|
83
|
+
contents: contents[index]
|
|
84
|
+
}));
|
|
85
|
+
const validSessions = results.filter((r) => r.session !== null).map((r) => r.session);
|
|
86
|
+
const invalidSessionIds = results.map((result, index) => result.isInvalid ? sessionIds[index] : null).filter((id) => id !== null);
|
|
87
|
+
await this.#cleanupInvalidSessions(userId, invalidSessionIds);
|
|
88
|
+
return validSessions;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
export { RedisStore };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { t as debug_default } from "./debug-BZVg83L1.js";
|
|
2
|
+
import { n as ValuesStore, t as ReadOnlyValuesStore } from "./values_store-CvR1Sn37.js";
|
|
3
|
+
import "node:module";
|
|
4
|
+
import { createError } from "@adonisjs/core/exceptions";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import Macroable from "@poppinss/macroable";
|
|
7
|
+
import lodash from "@poppinss/utils/lodash";
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __export = (all, symbols) => {
|
|
10
|
+
let target = {};
|
|
11
|
+
for (var name in all) __defProp(target, name, {
|
|
12
|
+
get: all[name],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
if (symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
+
return target;
|
|
17
|
+
};
|
|
18
|
+
var errors_exports = /* @__PURE__ */ __export({
|
|
19
|
+
E_SESSION_NOT_MUTABLE: () => E_SESSION_NOT_MUTABLE,
|
|
20
|
+
E_SESSION_NOT_READY: () => E_SESSION_NOT_READY,
|
|
21
|
+
E_SESSION_TAGGING_NOT_SUPPORTED: () => E_SESSION_TAGGING_NOT_SUPPORTED
|
|
22
|
+
});
|
|
23
|
+
const E_SESSION_NOT_MUTABLE = createError("Session store is in readonly mode and cannot be mutated", "E_SESSION_NOT_MUTABLE", 500);
|
|
24
|
+
const E_SESSION_NOT_READY = createError("Session store has not been initiated. Make sure you have registered the session middleware", "E_SESSION_NOT_READY", 500);
|
|
25
|
+
const E_SESSION_TAGGING_NOT_SUPPORTED = createError("Session store does not support tagging. Use memory, redis, or database store instead", "E_SESSION_TAGGING_NOT_SUPPORTED", 500);
|
|
26
|
+
var Session = class extends Macroable {
|
|
27
|
+
#store;
|
|
28
|
+
#emitter;
|
|
29
|
+
#ctx;
|
|
30
|
+
#readonly = false;
|
|
31
|
+
#valuesStore;
|
|
32
|
+
#sessionId;
|
|
33
|
+
#sessionIdFromCookie;
|
|
34
|
+
responseFlashMessages = new ValuesStore({});
|
|
35
|
+
flashMessages = new ValuesStore({});
|
|
36
|
+
flashKey = "__flash__";
|
|
37
|
+
get sessionId() {
|
|
38
|
+
return this.#sessionId;
|
|
39
|
+
}
|
|
40
|
+
get fresh() {
|
|
41
|
+
return this.#sessionIdFromCookie === void 0;
|
|
42
|
+
}
|
|
43
|
+
get readonly() {
|
|
44
|
+
return this.#readonly;
|
|
45
|
+
}
|
|
46
|
+
get initiated() {
|
|
47
|
+
return !!this.#valuesStore;
|
|
48
|
+
}
|
|
49
|
+
get hasRegeneratedSession() {
|
|
50
|
+
return !!(this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId);
|
|
51
|
+
}
|
|
52
|
+
get isEmpty() {
|
|
53
|
+
return this.#valuesStore?.isEmpty ?? true;
|
|
54
|
+
}
|
|
55
|
+
get hasBeenModified() {
|
|
56
|
+
return this.#valuesStore?.hasBeenModified ?? false;
|
|
57
|
+
}
|
|
58
|
+
constructor(config, storeFactory, emitter, ctx) {
|
|
59
|
+
super();
|
|
60
|
+
this.config = config;
|
|
61
|
+
this.#ctx = ctx;
|
|
62
|
+
this.#emitter = emitter;
|
|
63
|
+
this.#store = storeFactory(ctx, config);
|
|
64
|
+
this.#sessionIdFromCookie = ctx.request.cookie(config.cookieName, void 0);
|
|
65
|
+
this.#sessionId = this.#sessionIdFromCookie || randomUUID();
|
|
66
|
+
}
|
|
67
|
+
#getFlashStore(mode) {
|
|
68
|
+
if (!this.#valuesStore) throw new E_SESSION_NOT_READY();
|
|
69
|
+
if (mode === "write" && this.readonly) throw new E_SESSION_NOT_MUTABLE();
|
|
70
|
+
return this.responseFlashMessages;
|
|
71
|
+
}
|
|
72
|
+
#getValuesStore(mode) {
|
|
73
|
+
if (!this.#valuesStore) throw new E_SESSION_NOT_READY();
|
|
74
|
+
if (mode === "write" && this.readonly) throw new E_SESSION_NOT_MUTABLE();
|
|
75
|
+
return this.#valuesStore;
|
|
76
|
+
}
|
|
77
|
+
async initiate(readonly) {
|
|
78
|
+
if (this.#valuesStore) return;
|
|
79
|
+
debug_default("initiating session (readonly: %s)", readonly);
|
|
80
|
+
this.#readonly = readonly;
|
|
81
|
+
this.#valuesStore = new ValuesStore(await this.#store.read(this.#sessionId));
|
|
82
|
+
if (this.has(this.flashKey)) {
|
|
83
|
+
debug_default("reading flash data");
|
|
84
|
+
if (this.#readonly) this.flashMessages.update(this.get(this.flashKey, null));
|
|
85
|
+
else this.flashMessages.update(this.pull(this.flashKey, null));
|
|
86
|
+
}
|
|
87
|
+
if ("view" in this.#ctx) this.#ctx.view.share({
|
|
88
|
+
session: new ReadOnlyValuesStore(this.#valuesStore.all()),
|
|
89
|
+
flashMessages: new ReadOnlyValuesStore(this.flashMessages.all()),
|
|
90
|
+
old: function(key, defaultValue) {
|
|
91
|
+
return this.flashMessages.get(key, defaultValue);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
this.#emitter.emit("session:initiated", { session: this });
|
|
95
|
+
}
|
|
96
|
+
put(key, value) {
|
|
97
|
+
this.#getValuesStore("write").set(key, value);
|
|
98
|
+
}
|
|
99
|
+
has(key) {
|
|
100
|
+
return this.#getValuesStore("read").has(key);
|
|
101
|
+
}
|
|
102
|
+
get(key, defaultValue) {
|
|
103
|
+
return this.#getValuesStore("read").get(key, defaultValue);
|
|
104
|
+
}
|
|
105
|
+
all() {
|
|
106
|
+
return this.#getValuesStore("read").all();
|
|
107
|
+
}
|
|
108
|
+
forget(key) {
|
|
109
|
+
return this.#getValuesStore("write").unset(key);
|
|
110
|
+
}
|
|
111
|
+
pull(key, defaultValue) {
|
|
112
|
+
return this.#getValuesStore("write").pull(key, defaultValue);
|
|
113
|
+
}
|
|
114
|
+
increment(key, steps = 1) {
|
|
115
|
+
return this.#getValuesStore("write").increment(key, steps);
|
|
116
|
+
}
|
|
117
|
+
decrement(key, steps = 1) {
|
|
118
|
+
return this.#getValuesStore("write").decrement(key, steps);
|
|
119
|
+
}
|
|
120
|
+
clear() {
|
|
121
|
+
return this.#getValuesStore("write").clear();
|
|
122
|
+
}
|
|
123
|
+
flash(key, value) {
|
|
124
|
+
if (typeof key === "string") {
|
|
125
|
+
if (value) this.#getFlashStore("write").set(key, value);
|
|
126
|
+
} else this.#getFlashStore("write").merge(key);
|
|
127
|
+
}
|
|
128
|
+
flashErrors(errorsCollection) {
|
|
129
|
+
this.flash({ errorsBag: errorsCollection });
|
|
130
|
+
}
|
|
131
|
+
flashValidationErrors(error, withInput = true) {
|
|
132
|
+
const errorsBag = error.messages.reduce((result, message) => {
|
|
133
|
+
if (result[message.field]) result[message.field].push(message.message);
|
|
134
|
+
else result[message.field] = [message.message];
|
|
135
|
+
return result;
|
|
136
|
+
}, {});
|
|
137
|
+
if (withInput) this.flashExcept([
|
|
138
|
+
"_csrf",
|
|
139
|
+
"_method",
|
|
140
|
+
"password",
|
|
141
|
+
"password_confirmation"
|
|
142
|
+
]);
|
|
143
|
+
let summary = "The form could not be saved. Please check the errors below.";
|
|
144
|
+
if ("i18n" in this.#ctx) summary = this.#ctx.i18n.t(`errors.${error.code}`, { count: error.messages.length }, summary);
|
|
145
|
+
this.flashErrors({ [String(error.code)]: summary });
|
|
146
|
+
this.flash("inputErrorsBag", errorsBag);
|
|
147
|
+
}
|
|
148
|
+
flashAll() {
|
|
149
|
+
return this.#getFlashStore("write").set("input", this.#ctx.request.original());
|
|
150
|
+
}
|
|
151
|
+
flashExcept(keys) {
|
|
152
|
+
this.#getFlashStore("write").set("input", lodash.omit(this.#ctx.request.original(), keys));
|
|
153
|
+
}
|
|
154
|
+
flashOnly(keys) {
|
|
155
|
+
this.#getFlashStore("write").set("input", lodash.pick(this.#ctx.request.original(), keys));
|
|
156
|
+
}
|
|
157
|
+
reflash() {
|
|
158
|
+
this.#getFlashStore("write").set("reflashed", this.flashMessages.all());
|
|
159
|
+
}
|
|
160
|
+
reflashOnly(keys) {
|
|
161
|
+
this.#getFlashStore("write").set("reflashed", lodash.pick(this.flashMessages.all(), keys));
|
|
162
|
+
}
|
|
163
|
+
reflashExcept(keys) {
|
|
164
|
+
this.#getFlashStore("write").set("reflashed", lodash.omit(this.flashMessages.all(), keys));
|
|
165
|
+
}
|
|
166
|
+
async tag(userId) {
|
|
167
|
+
if (!("tag" in this.#store)) throw new E_SESSION_TAGGING_NOT_SUPPORTED();
|
|
168
|
+
await this.#store.tag(this.#sessionId, userId);
|
|
169
|
+
}
|
|
170
|
+
regenerate() {
|
|
171
|
+
this.#sessionId = randomUUID();
|
|
172
|
+
}
|
|
173
|
+
async commit() {
|
|
174
|
+
if (!this.#valuesStore || this.readonly) return;
|
|
175
|
+
if (!this.responseFlashMessages.isEmpty) {
|
|
176
|
+
const { input, reflashed, ...others } = this.responseFlashMessages.all();
|
|
177
|
+
this.put(this.flashKey, {
|
|
178
|
+
...reflashed,
|
|
179
|
+
...input,
|
|
180
|
+
...others
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
debug_default("committing session data");
|
|
184
|
+
this.#ctx.response.cookie(this.config.cookieName, this.#sessionId, this.config.cookie);
|
|
185
|
+
if (this.isEmpty) {
|
|
186
|
+
if (this.#sessionIdFromCookie) await this.#store.destroy(this.#sessionIdFromCookie);
|
|
187
|
+
this.#emitter.emit("session:committed", { session: this });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (!this.hasBeenModified) {
|
|
191
|
+
if (this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId) {
|
|
192
|
+
await this.#store.destroy(this.#sessionIdFromCookie);
|
|
193
|
+
await this.#store.write(this.#sessionId, this.#valuesStore.toJSON());
|
|
194
|
+
this.#emitter.emit("session:migrated", {
|
|
195
|
+
fromSessionId: this.#sessionIdFromCookie,
|
|
196
|
+
toSessionId: this.sessionId,
|
|
197
|
+
session: this
|
|
198
|
+
});
|
|
199
|
+
} else await this.#store.touch(this.#sessionId);
|
|
200
|
+
this.#emitter.emit("session:committed", { session: this });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (this.#sessionIdFromCookie && this.#sessionIdFromCookie !== this.#sessionId) {
|
|
204
|
+
await this.#store.destroy(this.#sessionIdFromCookie);
|
|
205
|
+
await this.#store.write(this.#sessionId, this.#valuesStore.toJSON());
|
|
206
|
+
this.#emitter.emit("session:migrated", {
|
|
207
|
+
fromSessionId: this.#sessionIdFromCookie,
|
|
208
|
+
toSessionId: this.sessionId,
|
|
209
|
+
session: this
|
|
210
|
+
});
|
|
211
|
+
} else await this.#store.write(this.#sessionId, this.#valuesStore.toJSON());
|
|
212
|
+
this.#emitter.emit("session:committed", { session: this });
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
export { E_SESSION_TAGGING_NOT_SUPPORTED as n, errors_exports as r, Session as t };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { t as stubsRoot } from "./main-kn40V-hF.js";
|
|
2
|
+
import { t as debug_default } from "./debug-BZVg83L1.js";
|
|
3
|
+
import { InvalidArgumentsException, RuntimeException } from "@adonisjs/core/exceptions";
|
|
4
|
+
import { configProvider } from "@adonisjs/core";
|
|
5
|
+
import string from "@adonisjs/core/helpers/string";
|
|
6
|
+
async function configure(command) {
|
|
7
|
+
const codemods = await command.createCodemods();
|
|
8
|
+
await codemods.makeUsingStub(stubsRoot, "config/session.stub", {});
|
|
9
|
+
await codemods.defineEnvVariables({ SESSION_DRIVER: "cookie" });
|
|
10
|
+
await codemods.defineEnvValidations({
|
|
11
|
+
variables: { SESSION_DRIVER: `Env.schema.enum(['cookie', 'memory'] as const)` },
|
|
12
|
+
leadingComment: "Variables for configuring session package"
|
|
13
|
+
});
|
|
14
|
+
await codemods.registerMiddleware("router", [{ path: "@adonisjs/session/session_middleware" }]);
|
|
15
|
+
await codemods.updateRcFile((rcFile) => {
|
|
16
|
+
rcFile.addProvider("@adonisjs/session/session_provider");
|
|
17
|
+
rcFile.addCommand("@adonisjs/session/commands");
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
var MemoryStore = class MemoryStore {
|
|
21
|
+
static sessions = /* @__PURE__ */ new Map();
|
|
22
|
+
static tags = /* @__PURE__ */ new Map();
|
|
23
|
+
read(sessionId) {
|
|
24
|
+
return MemoryStore.sessions.get(sessionId) || null;
|
|
25
|
+
}
|
|
26
|
+
write(sessionId, values) {
|
|
27
|
+
MemoryStore.sessions.set(sessionId, values);
|
|
28
|
+
}
|
|
29
|
+
destroy(sessionId) {
|
|
30
|
+
MemoryStore.sessions.delete(sessionId);
|
|
31
|
+
MemoryStore.tags.delete(sessionId);
|
|
32
|
+
}
|
|
33
|
+
touch(_) {}
|
|
34
|
+
tag(sessionId, userId) {
|
|
35
|
+
MemoryStore.tags.set(sessionId, userId);
|
|
36
|
+
}
|
|
37
|
+
tagged(userId) {
|
|
38
|
+
const sessions = [];
|
|
39
|
+
for (const [sessionId, tagUserId] of MemoryStore.tags) {
|
|
40
|
+
if (tagUserId !== userId) continue;
|
|
41
|
+
const data = MemoryStore.sessions.get(sessionId);
|
|
42
|
+
if (data) sessions.push({
|
|
43
|
+
id: sessionId,
|
|
44
|
+
data
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return sessions;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function defineConfig(config) {
|
|
51
|
+
debug_default("processing session config %O", config);
|
|
52
|
+
if (!config.store) throw new InvalidArgumentsException("Missing \"store\" property inside the session config");
|
|
53
|
+
const { stores: stores$1, cookie, ...rest } = {
|
|
54
|
+
enabled: true,
|
|
55
|
+
age: "2h",
|
|
56
|
+
cookieName: "adonis_session",
|
|
57
|
+
clearWithBrowser: false,
|
|
58
|
+
...config
|
|
59
|
+
};
|
|
60
|
+
const cookieOptions = { ...cookie };
|
|
61
|
+
if (!rest.clearWithBrowser) {
|
|
62
|
+
cookieOptions.maxAge = string.seconds.parse(rest.age);
|
|
63
|
+
debug_default("computing maxAge \"%s\" for session id cookie", cookieOptions.maxAge);
|
|
64
|
+
} else {
|
|
65
|
+
cookieOptions.maxAge = void 0;
|
|
66
|
+
cookieOptions.expires = void 0;
|
|
67
|
+
}
|
|
68
|
+
return configProvider.create(async (app) => {
|
|
69
|
+
const storesNames = Object.keys(config.stores);
|
|
70
|
+
const storesList = { memory: () => new MemoryStore() };
|
|
71
|
+
for (let storeName of storesNames) {
|
|
72
|
+
const store = config.stores[storeName];
|
|
73
|
+
if (typeof store === "function") storesList[storeName] = store;
|
|
74
|
+
else storesList[storeName] = await store.resolver(app);
|
|
75
|
+
}
|
|
76
|
+
const transformedConfig = {
|
|
77
|
+
...rest,
|
|
78
|
+
cookie: cookieOptions,
|
|
79
|
+
stores: storesList
|
|
80
|
+
};
|
|
81
|
+
debug_default("transformed session config %O", transformedConfig);
|
|
82
|
+
return transformedConfig;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const stores = {
|
|
86
|
+
file: (config) => {
|
|
87
|
+
return configProvider.create(async () => {
|
|
88
|
+
const { FileStore } = await import("./file-BBU02j4z.js");
|
|
89
|
+
return (_, sessionConfig) => {
|
|
90
|
+
return new FileStore(config, sessionConfig.age);
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
redis: (config) => {
|
|
95
|
+
return configProvider.create(async (app) => {
|
|
96
|
+
const { RedisStore } = await import("./redis-D8D9UtiD.js");
|
|
97
|
+
const redis = await app.container.make("redis");
|
|
98
|
+
return (_, sessionConfig) => {
|
|
99
|
+
return new RedisStore(redis.connection(config.connection), sessionConfig.age);
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
cookie: () => {
|
|
104
|
+
return configProvider.create(async () => {
|
|
105
|
+
const { CookieStore } = await import("./cookie--JOJxrtW.js");
|
|
106
|
+
return (ctx, sessionConfig) => {
|
|
107
|
+
return new CookieStore(sessionConfig.cookie, ctx);
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
dynamodb: (config) => {
|
|
112
|
+
return configProvider.create(async () => {
|
|
113
|
+
const { DynamoDBStore } = await import("./dynamodb-BFVgTQSf.js");
|
|
114
|
+
const { DynamoDBClient } = await import("@aws-sdk/client-dynamodb");
|
|
115
|
+
const client = "clientConfig" in config ? new DynamoDBClient(config.clientConfig) : config.client;
|
|
116
|
+
return (_, sessionConfig) => {
|
|
117
|
+
return new DynamoDBStore(client, sessionConfig.age, {
|
|
118
|
+
tableName: config.tableName,
|
|
119
|
+
keyAttribute: config.keyAttribute
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
database: (config) => {
|
|
125
|
+
return configProvider.create(async (app) => {
|
|
126
|
+
const { DatabaseStore } = await import("./database-vbrhCOPd.js");
|
|
127
|
+
const db = await app.container.make("lucid.db");
|
|
128
|
+
const connectionName = config?.connectionName || db.primaryConnectionName;
|
|
129
|
+
if (!db.manager.has(connectionName)) throw new RuntimeException(`Invalid database connection "${connectionName}" referenced in session config`);
|
|
130
|
+
return (_, sessionConfig) => {
|
|
131
|
+
return new DatabaseStore(db.connection(connectionName), sessionConfig.age, {
|
|
132
|
+
tableName: config?.tableName,
|
|
133
|
+
gcProbability: config?.gcProbability
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
export { stores as n, configure as r, defineConfig as t };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { n as E_SESSION_TAGGING_NOT_SUPPORTED } from "./session-C9DdRahS.js";
|
|
2
|
+
import { t as debug_default } from "./debug-BZVg83L1.js";
|
|
3
|
+
var SessionCollection = class {
|
|
4
|
+
#store;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
const storeFactory = config.stores[config.store];
|
|
7
|
+
this.#store = storeFactory(null, config);
|
|
8
|
+
}
|
|
9
|
+
supportsTagging() {
|
|
10
|
+
return "tag" in this.#store && "tagged" in this.#store;
|
|
11
|
+
}
|
|
12
|
+
async get(sessionId) {
|
|
13
|
+
debug_default("session collection: getting session data %s", sessionId);
|
|
14
|
+
return this.#store.read(sessionId);
|
|
15
|
+
}
|
|
16
|
+
async destroy(sessionId) {
|
|
17
|
+
debug_default("session collection: destroying session %s", sessionId);
|
|
18
|
+
return this.#store.destroy(sessionId);
|
|
19
|
+
}
|
|
20
|
+
async tag(sessionId, userId) {
|
|
21
|
+
debug_default("session collection: tagging session %s with user %s", sessionId, userId);
|
|
22
|
+
if (!this.supportsTagging()) throw new E_SESSION_TAGGING_NOT_SUPPORTED();
|
|
23
|
+
return this.#store.tag(sessionId, userId);
|
|
24
|
+
}
|
|
25
|
+
async tagged(userId) {
|
|
26
|
+
debug_default("session collection: getting sessions tagged with user %s", userId);
|
|
27
|
+
if (!this.supportsTagging()) throw new E_SESSION_TAGGING_NOT_SUPPORTED();
|
|
28
|
+
return this.#store.tagged(userId);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
export { SessionCollection as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { t as Session } from "./session-C9DdRahS.js";
|
|
2
|
+
import { ExceptionHandler } from "@adonisjs/core/http";
|
|
3
|
+
const originalErrorHandler = ExceptionHandler.prototype.renderValidationErrorAsHTML;
|
|
4
|
+
ExceptionHandler.macro("renderValidationErrorAsHTML", async function(error, ctx) {
|
|
5
|
+
if (ctx.session) {
|
|
6
|
+
const withInput = ctx.request.header("X-Inertia") ? false : true;
|
|
7
|
+
ctx.session.flashValidationErrors(error, withInput);
|
|
8
|
+
ctx.response.redirect("back", true);
|
|
9
|
+
} else return originalErrorHandler(error, ctx);
|
|
10
|
+
});
|
|
11
|
+
var SessionMiddleware = class {
|
|
12
|
+
#config;
|
|
13
|
+
#emitter;
|
|
14
|
+
constructor(config, emitter) {
|
|
15
|
+
this.#config = config;
|
|
16
|
+
this.#emitter = emitter;
|
|
17
|
+
}
|
|
18
|
+
async handle(ctx, next) {
|
|
19
|
+
if (!this.#config.enabled) return next();
|
|
20
|
+
ctx.session = new Session(this.#config, this.#config.stores[this.#config.store], this.#emitter, ctx);
|
|
21
|
+
await ctx.session.initiate(false);
|
|
22
|
+
const response = await next();
|
|
23
|
+
await ctx.session.commit();
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export { SessionMiddleware as t };
|
package/build/src/client.js
CHANGED
|
@@ -1,8 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { t as debug_default } from "../debug-BZVg83L1.js";
|
|
2
|
+
import { n as ValuesStore } from "../values_store-CvR1Sn37.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
var SessionClient = class {
|
|
5
|
+
#valuesStore = new ValuesStore({});
|
|
6
|
+
#flashMessagesStore = new ValuesStore({});
|
|
7
|
+
#store;
|
|
8
|
+
flashKey = "__flash__";
|
|
9
|
+
sessionId = randomUUID();
|
|
10
|
+
constructor(store) {
|
|
11
|
+
this.#store = store;
|
|
12
|
+
}
|
|
13
|
+
merge(values) {
|
|
14
|
+
this.#valuesStore.merge(values);
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
flash(values) {
|
|
18
|
+
this.#flashMessagesStore.merge(values);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
async commit() {
|
|
22
|
+
if (!this.#flashMessagesStore.isEmpty) this.#valuesStore.set(this.flashKey, this.#flashMessagesStore.toJSON());
|
|
23
|
+
debug_default("committing session data during api request");
|
|
24
|
+
if (!this.#valuesStore.isEmpty) this.#store.write(this.sessionId, this.#valuesStore.toJSON());
|
|
25
|
+
}
|
|
26
|
+
async destroy(sessionId) {
|
|
27
|
+
debug_default("destroying session data during api request");
|
|
28
|
+
this.#store.destroy(sessionId || this.sessionId);
|
|
29
|
+
}
|
|
30
|
+
async load(sessionId) {
|
|
31
|
+
const store = new ValuesStore(await this.#store.read(sessionId || this.sessionId));
|
|
32
|
+
const flashMessages = store.pull(this.flashKey, {});
|
|
33
|
+
return {
|
|
34
|
+
values: store.all(),
|
|
35
|
+
flashMessages
|
|
36
|
+
};
|
|
37
|
+
}
|
|
8
38
|
};
|
|
39
|
+
export { SessionClient };
|
package/build/src/debug.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("util").DebugLogger;
|
|
1
|
+
declare const _default: import("node:util").DebugLogger;
|
|
2
2
|
export default _default;
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import type { ConfigProvider } from '@adonisjs/core/types';
|
|
2
2
|
import type { CookieOptions } from '@adonisjs/core/types/http';
|
|
3
|
-
import type { SessionConfig, FileStoreConfig, RedisStoreConfig, SessionStoreFactory, DynamoDBStoreConfig } from './types.ts';
|
|
3
|
+
import type { SessionConfig, FileStoreConfig, RedisStoreConfig, SessionStoreFactory, DynamoDBStoreConfig, DatabaseStoreConfig } from './types.ts';
|
|
4
|
+
type ConfigInput<KnownStores extends Record<string, SessionStoreFactory | ConfigProvider<SessionStoreFactory>>> = Partial<SessionConfig> & {
|
|
5
|
+
store: keyof KnownStores | 'memory';
|
|
6
|
+
stores: KnownStores;
|
|
7
|
+
/**
|
|
8
|
+
* Whether to clear the session cookie when the browser is closed.
|
|
9
|
+
* When true, creates a session cookie that expires on browser close.
|
|
10
|
+
* Note: Persisted session data continues to exist until it expires.
|
|
11
|
+
*/
|
|
12
|
+
clearWithBrowser?: boolean;
|
|
13
|
+
cookie?: Omit<Partial<CookieOptions>, 'maxAge' | 'expires'>;
|
|
14
|
+
};
|
|
4
15
|
/**
|
|
5
16
|
* Resolved session configuration with all stores resolved
|
|
6
17
|
*/
|
|
7
18
|
type ResolvedConfig<KnownStores extends Record<string, SessionStoreFactory>> = SessionConfig & {
|
|
8
19
|
store: keyof KnownStores;
|
|
9
20
|
stores: KnownStores;
|
|
10
|
-
cookie: Partial<CookieOptions>;
|
|
11
21
|
};
|
|
12
22
|
/**
|
|
13
23
|
* Defines and validates session configuration with store setup.
|
|
@@ -29,10 +39,7 @@ type ResolvedConfig<KnownStores extends Record<string, SessionStoreFactory>> = S
|
|
|
29
39
|
* }
|
|
30
40
|
* })
|
|
31
41
|
*/
|
|
32
|
-
export declare function defineConfig<KnownStores extends Record<string, SessionStoreFactory | ConfigProvider<SessionStoreFactory>>>(config:
|
|
33
|
-
store: keyof KnownStores | 'memory';
|
|
34
|
-
stores: KnownStores;
|
|
35
|
-
}): ConfigProvider<ResolvedConfig<{
|
|
42
|
+
export declare function defineConfig<KnownStores extends Record<string, SessionStoreFactory | ConfigProvider<SessionStoreFactory>>>(config: ConfigInput<KnownStores>): ConfigProvider<ResolvedConfig<{
|
|
36
43
|
[K in keyof KnownStores]: SessionStoreFactory;
|
|
37
44
|
}>>;
|
|
38
45
|
/**
|
|
@@ -59,5 +66,6 @@ export declare const stores: {
|
|
|
59
66
|
redis: (config: RedisStoreConfig) => ConfigProvider<SessionStoreFactory>;
|
|
60
67
|
cookie: () => ConfigProvider<SessionStoreFactory>;
|
|
61
68
|
dynamodb: (config: DynamoDBStoreConfig) => ConfigProvider<SessionStoreFactory>;
|
|
69
|
+
database: (config?: DatabaseStoreConfig) => ConfigProvider<SessionStoreFactory>;
|
|
62
70
|
};
|
|
63
71
|
export {};
|
package/build/src/errors.d.ts
CHANGED
|
@@ -22,3 +22,12 @@ export declare const E_SESSION_NOT_MUTABLE: new (args?: any, options?: ErrorOpti
|
|
|
22
22
|
* session.put('key', 'value') // Works fine
|
|
23
23
|
*/
|
|
24
24
|
export declare const E_SESSION_NOT_READY: new (args?: any, options?: ErrorOptions) => import("@adonisjs/core/exceptions").Exception;
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when attempting to use tagging features with a store that doesn't support it.
|
|
27
|
+
* Only Memory, Redis, and Database stores support session tagging.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // This will throw E_SESSION_TAGGING_NOT_SUPPORTED when using cookie store
|
|
31
|
+
* const sessions = await sessionCollection.tagged(userId)
|
|
32
|
+
*/
|
|
33
|
+
export declare const E_SESSION_TAGGING_NOT_SUPPORTED: new (args?: any, options?: ErrorOptions) => import("@adonisjs/core/exceptions").Exception;
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import type { PluginFn } from 'edge.js/types';
|
|
2
2
|
/**
|
|
3
3
|
* The edge plugin for AdonisJS Session adds template tags to read flash messages.
|
|
4
|
-
* Provides @flashMessage, @inputError, @error, and
|
|
4
|
+
* Provides @flashMessage, @inputError, @error, and \@errors tags for templates.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
|
+
* ```ts
|
|
7
8
|
* // Register the plugin with Edge
|
|
8
9
|
* import { edgePluginSession } from '@adonisjs/session/plugins/edge'
|
|
9
10
|
* edge.use(edgePluginSession)
|
|
11
|
+
* ```
|
|
10
12
|
*
|
|
13
|
+
* ```edge
|
|
11
14
|
* // Use in templates
|
|
12
15
|
* @flashMessage('success')
|
|
13
16
|
* <div class="alert alert-success">{{ $message }}</div>
|
|
14
17
|
* @end
|
|
18
|
+
* ```
|
|
15
19
|
*/
|
|
16
20
|
export declare const edgePluginSession: PluginFn<undefined>;
|