Skip to content

Commit

Permalink
feat: add custom prefix for session key
Browse files Browse the repository at this point in the history
  • Loading branch information
KnorpelSenf committed Nov 13, 2024
1 parent bcbdd4d commit 181f04d
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/convenience/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ export interface SessionOptions<S, C extends Context = Context> {
* session data.
*/
initial?: () => S;
/**
* A optional prefix to prepend to the session key after it was generated.
*
* This makes it easier to store session data under a namespace. You can
* technically achieve the same functionality by returning an already
* prefixed key from `getSessionKey`. This option is merely more convenient,
* as it does not require you to think about session key generation.
*/
prefix?: string;
/**
* This option lets you generate your own session keys per context object.
* The session key determines how to map the different session objects to
Expand Down Expand Up @@ -220,15 +229,17 @@ export function session<S, C extends Context>(
function strictSingleSession<S, C extends Context>(
options: SessionOptions<S, C>,
): MiddlewareFn<C & SessionFlavor<S>> {
const { initial, storage, getSessionKey, custom } = fillDefaults(options);
const { initial, storage, prefix, getSessionKey, custom } = fillDefaults(
options,
);
return async (ctx, next) => {
const propSession = new PropertySession<SessionFlavor<S>, "session">(
storage,
ctx,
"session",
initial,
);
const key = await getSessionKey(ctx);
const key = prefix + await getSessionKey(ctx);
await propSession.init(key, { custom, lazy: false });
await next(); // no catch: do not write back if middleware throws
await propSession.finish();
Expand All @@ -244,15 +255,16 @@ function strictMultiSession<S, C extends Context>(
return async (ctx, next) => {
ctx.session = {} as S;
const propSessions = await Promise.all(props.map(async (prop) => {
const { initial, storage, getSessionKey, custom } = defaults[prop];
const { initial, storage, prefix, getSessionKey, custom } =
defaults[prop];
const s = new PropertySession(
// @ts-expect-error cannot express that the storage works for a concrete prop
storage,
ctx.session,
prop,
initial,
);
const key = await getSessionKey(ctx);
const key = prefix + await getSessionKey(ctx);
await s.init(key, { custom, lazy: false });
return s;
}));
Expand Down Expand Up @@ -300,7 +312,9 @@ export function lazySession<S, C extends Context>(
if (options.type !== undefined && options.type !== "single") {
throw new Error("Cannot use lazy multi sessions!");
}
const { initial, storage, getSessionKey, custom } = fillDefaults(options);
const { initial, storage, prefix, getSessionKey, custom } = fillDefaults(
options,
);
return async (ctx, next) => {
const propSession = new PropertySession(
// @ts-expect-error suppress promise nature of values
Expand All @@ -309,7 +323,7 @@ export function lazySession<S, C extends Context>(
"session",
initial,
);
const key = await getSessionKey(ctx);
const key = prefix + await getSessionKey(ctx);
await propSession.init(key, { custom, lazy: true });
await next(); // no catch: do not write back if middleware throws
await propSession.finish();
Expand Down Expand Up @@ -424,15 +438,20 @@ class PropertySession<O extends {}, P extends keyof O> {
}

function fillDefaults<S, C extends Context>(opts: SessionOptions<S, C> = {}) {
let { getSessionKey = defaultGetSessionKey, initial, storage } = opts;
let {
prefix = "",
getSessionKey = defaultGetSessionKey,
initial,
storage,
} = opts;
if (storage == null) {
debug(
"Storing session data in memory, all data will be lost when the bot restarts.",
);
storage = new MemorySessionStorage<S>();
}
const custom = getSessionKey !== defaultGetSessionKey;
return { initial, storage, getSessionKey, custom };
return { initial, storage, prefix, getSessionKey, custom };
}

/** Stores session data per chat by default */
Expand Down

0 comments on commit 181f04d

Please sign in to comment.