yt-transcript-strapi-plugin 0.1.0 → 0.1.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.
@@ -975,6 +975,26 @@ const controller = ({ strapi }) => ({
975
975
  ctx.body = { data: transcript2 };
976
976
  }
977
977
  });
978
+ const SESSION_TIMEOUT_MS = 4 * 60 * 60 * 1e3;
979
+ function isSessionExpired(session) {
980
+ return Date.now() - session.createdAt > SESSION_TIMEOUT_MS;
981
+ }
982
+ function cleanupExpiredSessions(plugin, strapi) {
983
+ let cleaned = 0;
984
+ for (const [sessionId, session] of plugin.sessions.entries()) {
985
+ if (isSessionExpired(session)) {
986
+ try {
987
+ session.server.close();
988
+ } catch {
989
+ }
990
+ plugin.sessions.delete(sessionId);
991
+ cleaned++;
992
+ }
993
+ }
994
+ if (cleaned > 0) {
995
+ strapi.log.debug(`[yt-transcript-mcp] Cleaned up ${cleaned} expired sessions`);
996
+ }
997
+ }
978
998
  const mcpController = ({ strapi }) => ({
979
999
  /**
980
1000
  * Handle MCP requests (POST, GET, DELETE)
@@ -991,17 +1011,41 @@ const mcpController = ({ strapi }) => ({
991
1011
  };
992
1012
  return;
993
1013
  }
994
- const strapiToken = ctx.state.strapiToken;
1014
+ if (Math.random() < 0.01) {
1015
+ cleanupExpiredSessions(plugin, strapi);
1016
+ }
995
1017
  try {
996
- const sessionId = ctx.request.headers["mcp-session-id"] || node_crypto.randomUUID();
997
- let session = plugin.sessions.get(sessionId);
1018
+ const requestedSessionId = ctx.request.headers["mcp-session-id"];
1019
+ let session = requestedSessionId ? plugin.sessions.get(requestedSessionId) : null;
1020
+ if (session && isSessionExpired(session)) {
1021
+ strapi.log.debug(`[yt-transcript-mcp] Session expired, removing: ${requestedSessionId}`);
1022
+ try {
1023
+ session.server.close();
1024
+ } catch {
1025
+ }
1026
+ plugin.sessions.delete(requestedSessionId);
1027
+ session = null;
1028
+ }
1029
+ if (requestedSessionId && !session) {
1030
+ ctx.status = 400;
1031
+ ctx.body = {
1032
+ jsonrpc: "2.0",
1033
+ error: {
1034
+ code: -32e3,
1035
+ message: "Session expired or invalid. Please reinitialize the connection."
1036
+ },
1037
+ id: null
1038
+ };
1039
+ return;
1040
+ }
998
1041
  if (!session) {
1042
+ const sessionId = node_crypto.randomUUID();
999
1043
  const server = plugin.createMcpServer();
1000
1044
  const transport = new streamableHttp_js.StreamableHTTPServerTransport({
1001
1045
  sessionIdGenerator: () => sessionId
1002
1046
  });
1003
1047
  await server.connect(transport);
1004
- session = { server, transport, createdAt: Date.now(), strapiToken };
1048
+ session = { server, transport, createdAt: Date.now(), strapiToken: ctx.state.strapiToken };
1005
1049
  plugin.sessions.set(sessionId, session);
1006
1050
  strapi.log.debug(`[yt-transcript-mcp] New session created: ${sessionId} (auth: ${ctx.state.authMethod})`);
1007
1051
  }
@@ -974,6 +974,26 @@ const controller = ({ strapi }) => ({
974
974
  ctx.body = { data: transcript2 };
975
975
  }
976
976
  });
977
+ const SESSION_TIMEOUT_MS = 4 * 60 * 60 * 1e3;
978
+ function isSessionExpired(session) {
979
+ return Date.now() - session.createdAt > SESSION_TIMEOUT_MS;
980
+ }
981
+ function cleanupExpiredSessions(plugin, strapi) {
982
+ let cleaned = 0;
983
+ for (const [sessionId, session] of plugin.sessions.entries()) {
984
+ if (isSessionExpired(session)) {
985
+ try {
986
+ session.server.close();
987
+ } catch {
988
+ }
989
+ plugin.sessions.delete(sessionId);
990
+ cleaned++;
991
+ }
992
+ }
993
+ if (cleaned > 0) {
994
+ strapi.log.debug(`[yt-transcript-mcp] Cleaned up ${cleaned} expired sessions`);
995
+ }
996
+ }
977
997
  const mcpController = ({ strapi }) => ({
978
998
  /**
979
999
  * Handle MCP requests (POST, GET, DELETE)
@@ -990,17 +1010,41 @@ const mcpController = ({ strapi }) => ({
990
1010
  };
991
1011
  return;
992
1012
  }
993
- const strapiToken = ctx.state.strapiToken;
1013
+ if (Math.random() < 0.01) {
1014
+ cleanupExpiredSessions(plugin, strapi);
1015
+ }
994
1016
  try {
995
- const sessionId = ctx.request.headers["mcp-session-id"] || randomUUID();
996
- let session = plugin.sessions.get(sessionId);
1017
+ const requestedSessionId = ctx.request.headers["mcp-session-id"];
1018
+ let session = requestedSessionId ? plugin.sessions.get(requestedSessionId) : null;
1019
+ if (session && isSessionExpired(session)) {
1020
+ strapi.log.debug(`[yt-transcript-mcp] Session expired, removing: ${requestedSessionId}`);
1021
+ try {
1022
+ session.server.close();
1023
+ } catch {
1024
+ }
1025
+ plugin.sessions.delete(requestedSessionId);
1026
+ session = null;
1027
+ }
1028
+ if (requestedSessionId && !session) {
1029
+ ctx.status = 400;
1030
+ ctx.body = {
1031
+ jsonrpc: "2.0",
1032
+ error: {
1033
+ code: -32e3,
1034
+ message: "Session expired or invalid. Please reinitialize the connection."
1035
+ },
1036
+ id: null
1037
+ };
1038
+ return;
1039
+ }
997
1040
  if (!session) {
1041
+ const sessionId = randomUUID();
998
1042
  const server = plugin.createMcpServer();
999
1043
  const transport = new StreamableHTTPServerTransport({
1000
1044
  sessionIdGenerator: () => sessionId
1001
1045
  });
1002
1046
  await server.connect(transport);
1003
- session = { server, transport, createdAt: Date.now(), strapiToken };
1047
+ session = { server, transport, createdAt: Date.now(), strapiToken: ctx.state.strapiToken };
1004
1048
  plugin.sessions.set(sessionId, session);
1005
1049
  strapi.log.debug(`[yt-transcript-mcp] New session created: ${sessionId} (auth: ${ctx.state.authMethod})`);
1006
1050
  }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.1.0",
2
+ "version": "0.1.2",
3
3
  "keywords": [
4
4
  "yt-transcript-strapi-plugin",
5
5
  "youtube",