@strapi/utils
Version:
Shared utilities for the Strapi packages
1 lines • 3.84 kB
Source Map (JSON)
{"version":3,"file":"sessions.mjs","sources":["../src/sessions.ts"],"sourcesContent":["import { getDeviceName } from './user-agent';\n\nexport interface SessionEntryLike {\n sessionId: string;\n deviceId?: string;\n createdAt?: Date | string | null;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface SanitizedSessionEntry {\n id: string;\n deviceId?: string;\n deviceName?: string;\n current: boolean;\n loginAt?: string;\n lastActiveAt?: string;\n}\n\nexport interface SessionDisplayEntry {\n current: boolean;\n lastActiveAt?: string;\n}\n\n/**\n * Sanitizes a session record for client consumption (active devices UI/API).\n * Never includes tokens or internal database identifiers.\n */\nexport const sanitizeSessionEntry = (\n session: SessionEntryLike,\n currentSessionId?: string\n): SanitizedSessionEntry => {\n const metadata = session.metadata ?? {};\n\n return {\n id: session.sessionId,\n deviceId: session.deviceId,\n deviceName: typeof metadata.deviceName === 'string' ? metadata.deviceName : undefined,\n current: Boolean(currentSessionId) && session.sessionId === currentSessionId,\n loginAt: typeof metadata.loginAt === 'string' ? metadata.loginAt : undefined,\n // The active record is re-created on each rotation, so its creation time is the\n // best available \"last used\" signal without an extra write per request.\n lastActiveAt: session.createdAt ? new Date(session.createdAt).toISOString() : undefined,\n };\n};\n\n/**\n * Builds origin-defined session metadata from generic request context fields.\n */\nexport const buildSessionMetadata = (params: {\n userAgent?: string | null;\n loginAt?: string;\n}): Record<string, unknown> => {\n const deviceName = getDeviceName(params.userAgent);\n\n return {\n loginAt: params.loginAt ?? new Date().toISOString(),\n ...(deviceName ? { deviceName } : {}),\n };\n};\n\n/**\n * Sorts sessions for display: current session first, then most recently used.\n */\nexport const sortSessionsForDisplay = <T extends SessionDisplayEntry>(sessions: T[]): T[] =>\n [...sessions].sort((a, b) => {\n if (a.current !== b.current) {\n return a.current ? -1 : 1;\n }\n\n return (b.lastActiveAt ?? '').localeCompare(a.lastActiveAt ?? '');\n });\n"],"names":["sanitizeSessionEntry","session","currentSessionId","metadata","id","sessionId","deviceId","deviceName","undefined","current","Boolean","loginAt","lastActiveAt","createdAt","Date","toISOString","buildSessionMetadata","params","getDeviceName","userAgent","sortSessionsForDisplay","sessions","sort","a","b","localeCompare"],"mappings":";;AAuBA;;;AAGC,IACM,MAAMA,oBAAAA,GAAuB,CAClCC,OAAAA,EACAC,gBAAAA,GAAAA;AAEA,IAAA,MAAMC,QAAAA,GAAWF,OAAAA,CAAQE,QAAQ,IAAI,EAAC;IAEtC,OAAO;AACLC,QAAAA,EAAAA,EAAIH,QAAQI,SAAS;AACrBC,QAAAA,QAAAA,EAAUL,QAAQK,QAAQ;AAC1BC,QAAAA,UAAAA,EAAY,OAAOJ,QAAAA,CAASI,UAAU,KAAK,QAAA,GAAWJ,QAAAA,CAASI,UAAU,GAAGC,SAAAA;AAC5EC,QAAAA,OAAAA,EAASC,OAAAA,CAAQR,gBAAAA,CAAAA,IAAqBD,OAAAA,CAAQI,SAAS,KAAKH,gBAAAA;AAC5DS,QAAAA,OAAAA,EAAS,OAAOR,QAAAA,CAASQ,OAAO,KAAK,QAAA,GAAWR,QAAAA,CAASQ,OAAO,GAAGH,SAAAA;;;QAGnEI,YAAAA,EAAcX,OAAAA,CAAQY,SAAS,GAAG,IAAIC,KAAKb,OAAAA,CAAQY,SAAS,CAAA,CAAEE,WAAW,EAAA,GAAKP;AAChF,KAAA;AACF;AAEA;;IAGO,MAAMQ,oBAAAA,GAAuB,CAACC,MAAAA,GAAAA;IAInC,MAAMV,UAAAA,GAAaW,aAAAA,CAAcD,MAAAA,CAAOE,SAAS,CAAA;IAEjD,OAAO;AACLR,QAAAA,OAAAA,EAASM,MAAAA,CAAON,OAAO,IAAI,IAAIG,OAAOC,WAAW,EAAA;AACjD,QAAA,GAAIR,UAAAA,GAAa;AAAEA,YAAAA;AAAW,SAAA,GAAI;AACpC,KAAA;AACF;AAEA;;AAEC,IACM,MAAMa,sBAAAA,GAAyB,CAAgCC,QAAAA,GACpE;AAAIA,QAAAA,GAAAA;KAAS,CAACC,IAAI,CAAC,CAACC,CAAAA,EAAGC,CAAAA,GAAAA;AACrB,QAAA,IAAID,CAAAA,CAAEd,OAAO,KAAKe,CAAAA,CAAEf,OAAO,EAAE;AAC3B,YAAA,OAAOc,CAAAA,CAAEd,OAAO,GAAG,EAAC,GAAI,CAAA;AAC1B,QAAA;QAEA,OAAQe,CAAAA,CAAAA,CAAEZ,YAAY,IAAI,EAAC,EAAGa,aAAa,CAACF,CAAAA,CAAEX,YAAY,IAAI,EAAA,CAAA;IAChE,CAAA;;;;"}