mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-26 06:44:58 +00:00
code: dbal,session,sessions (7 files)
This commit is contained in:
31
dbal/ts/src/core/entities/session/clean-expired.ts
Normal file
31
dbal/ts/src/core/entities/session/clean-expired.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @file clean-expired.ts
|
||||
* @description Clean expired sessions operation
|
||||
*/
|
||||
import type { Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* Clean up expired sessions
|
||||
* @returns Number of sessions removed
|
||||
*/
|
||||
export async function cleanExpiredSessions(store: InMemoryStore): Promise<Result<number>> {
|
||||
const now = new Date();
|
||||
const expiredIds: string[] = [];
|
||||
|
||||
for (const [id, session] of store.sessions) {
|
||||
if (session.expiresAt < now) {
|
||||
expiredIds.push(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const id of expiredIds) {
|
||||
const session = store.sessions.get(id);
|
||||
if (session) {
|
||||
store.sessionTokens.delete(session.token);
|
||||
store.sessions.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
return { success: true, data: expiredIds.length };
|
||||
}
|
||||
39
dbal/ts/src/core/entities/session/create-session.ts
Normal file
39
dbal/ts/src/core/entities/session/create-session.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file create-session.ts
|
||||
* @description Create session operation
|
||||
*/
|
||||
import type { Session, CreateSessionInput, Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* Create a new session in the store
|
||||
*/
|
||||
export async function createSession(
|
||||
store: InMemoryStore,
|
||||
input: CreateSessionInput
|
||||
): Promise<Result<Session>> {
|
||||
if (!input.userId) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'User ID required' } };
|
||||
}
|
||||
if (!store.users.has(input.userId)) {
|
||||
return { success: false, error: { code: 'NOT_FOUND', message: 'User not found' } };
|
||||
}
|
||||
if (input.ttlSeconds <= 0) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'TTL must be positive' } };
|
||||
}
|
||||
|
||||
const session: Session = {
|
||||
id: store.generateId('session'),
|
||||
userId: input.userId,
|
||||
token: store.generateToken(),
|
||||
expiresAt: new Date(Date.now() + input.ttlSeconds * 1000),
|
||||
ipAddress: input.ipAddress ?? '',
|
||||
userAgent: input.userAgent ?? '',
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
store.sessions.set(session.id, session);
|
||||
store.sessionTokens.set(session.token, session.id);
|
||||
|
||||
return { success: true, data: session };
|
||||
}
|
||||
25
dbal/ts/src/core/entities/session/delete-session.ts
Normal file
25
dbal/ts/src/core/entities/session/delete-session.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file delete-session.ts
|
||||
* @description Delete session operation
|
||||
*/
|
||||
import type { Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* Delete a session by ID (logout)
|
||||
*/
|
||||
export async function deleteSession(store: InMemoryStore, id: string): Promise<Result<boolean>> {
|
||||
if (!id) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'ID required' } };
|
||||
}
|
||||
|
||||
const session = store.sessions.get(id);
|
||||
if (!session) {
|
||||
return { success: false, error: { code: 'NOT_FOUND', message: `Session not found: ${id}` } };
|
||||
}
|
||||
|
||||
store.sessionTokens.delete(session.token);
|
||||
store.sessions.delete(id);
|
||||
|
||||
return { success: true, data: true };
|
||||
}
|
||||
34
dbal/ts/src/core/entities/session/extend-session.ts
Normal file
34
dbal/ts/src/core/entities/session/extend-session.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file extend-session.ts
|
||||
* @description Extend session expiration operation
|
||||
*/
|
||||
import type { Session, Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* Extend a session's expiration time
|
||||
*/
|
||||
export async function extendSession(
|
||||
store: InMemoryStore,
|
||||
id: string,
|
||||
additionalSeconds: number
|
||||
): Promise<Result<Session>> {
|
||||
if (!id) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'ID required' } };
|
||||
}
|
||||
if (additionalSeconds <= 0) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'Additional seconds must be positive' } };
|
||||
}
|
||||
|
||||
const session = store.sessions.get(id);
|
||||
if (!session) {
|
||||
return { success: false, error: { code: 'NOT_FOUND', message: `Session not found: ${id}` } };
|
||||
}
|
||||
|
||||
if (session.expiresAt < new Date()) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'Cannot extend expired session' } };
|
||||
}
|
||||
|
||||
session.expiresAt = new Date(session.expiresAt.getTime() + additionalSeconds * 1000);
|
||||
return { success: true, data: session };
|
||||
}
|
||||
38
dbal/ts/src/core/entities/session/get-session.ts
Normal file
38
dbal/ts/src/core/entities/session/get-session.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file get-session.ts
|
||||
* @description Get session operations
|
||||
*/
|
||||
import type { Session, Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* Get a session by ID
|
||||
*/
|
||||
export async function getSession(store: InMemoryStore, id: string): Promise<Result<Session>> {
|
||||
if (!id) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'ID required' } };
|
||||
}
|
||||
|
||||
const session = store.sessions.get(id);
|
||||
if (!session) {
|
||||
return { success: false, error: { code: 'NOT_FOUND', message: `Session not found: ${id}` } };
|
||||
}
|
||||
|
||||
return { success: true, data: session };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session by token
|
||||
*/
|
||||
export async function getSessionByToken(store: InMemoryStore, token: string): Promise<Result<Session>> {
|
||||
if (!token) {
|
||||
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'Token required' } };
|
||||
}
|
||||
|
||||
const id = store.sessionTokens.get(token);
|
||||
if (!id) {
|
||||
return { success: false, error: { code: 'NOT_FOUND', message: 'Session not found' } };
|
||||
}
|
||||
|
||||
return getSession(store, id);
|
||||
}
|
||||
10
dbal/ts/src/core/entities/session/index.ts
Normal file
10
dbal/ts/src/core/entities/session/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @file index.ts
|
||||
* @description Barrel export for session operations
|
||||
*/
|
||||
export { createSession } from './create-session';
|
||||
export { getSession, getSessionByToken } from './get-session';
|
||||
export { extendSession } from './extend-session';
|
||||
export { deleteSession } from './delete-session';
|
||||
export { listSessions } from './list-sessions';
|
||||
export { cleanExpiredSessions } from './clean-expired';
|
||||
36
dbal/ts/src/core/entities/session/list-sessions.ts
Normal file
36
dbal/ts/src/core/entities/session/list-sessions.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file list-sessions.ts
|
||||
* @description List sessions with filtering
|
||||
*/
|
||||
import type { Session, ListOptions, Result } from '../types';
|
||||
import type { InMemoryStore } from '../store/in-memory-store';
|
||||
|
||||
/**
|
||||
* List sessions with filtering and pagination
|
||||
*/
|
||||
export async function listSessions(
|
||||
store: InMemoryStore,
|
||||
options: ListOptions = {}
|
||||
): Promise<Result<Session[]>> {
|
||||
const { filter = {}, page = 1, limit = 20 } = options;
|
||||
const now = new Date();
|
||||
|
||||
let sessions = Array.from(store.sessions.values());
|
||||
|
||||
// Apply filters
|
||||
if (filter.userId !== undefined) {
|
||||
sessions = sessions.filter((s) => s.userId === filter.userId);
|
||||
}
|
||||
if (filter.activeOnly) {
|
||||
sessions = sessions.filter((s) => s.expiresAt > now);
|
||||
}
|
||||
|
||||
// Sort by created_at descending (newest first)
|
||||
sessions.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
||||
|
||||
// Apply pagination
|
||||
const start = (page - 1) * limit;
|
||||
const paginated = sessions.slice(start, start + limit);
|
||||
|
||||
return { success: true, data: paginated };
|
||||
}
|
||||
Reference in New Issue
Block a user