Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 75x 75x 75x 75x 75x 107x 107x 107x 107x 107x 107x 107x 107x 75x 75x | /**
* Session Storage Factory
*
* Creates and configures the appropriate storage backend based on configuration.
*/
import { SessionStorageBackend, StorageConfig } from "./types";
import { MemoryStorageBackend } from "./memory";
import { FileStorageBackend } from "./file";
import { PostgreSQLStorageBackend } from "./postgresql";
import { logger } from "../../logger";
/**
* Create a storage backend based on configuration
*
* Configuration can come from:
* 1. Explicit StorageConfig object
* 2. Environment variables
*
* Environment variables:
* - OAUTH_STORAGE_TYPE: "memory" | "file" | "postgresql" (default: "memory")
* - OAUTH_STORAGE_FILE_PATH: Path for file storage (default: ./data/oauth-sessions.json)
* - OAUTH_STORAGE_POSTGRESQL_URL: PostgreSQL connection string
* - OAUTH_STORAGE_TABLE_PREFIX: PostgreSQL table prefix (default: "oauth_")
*/
export function createStorageBackend(config?: StorageConfig): SessionStorageBackend {
// Use config if provided, otherwise read from environment
const storageType = config?.type ?? getEnvStorageType();
switch (storageType) {
case "file":
return createFileBackend(config);
case "postgresql":
return createPostgreSQLBackend();
case "memory":
default:
return createMemoryBackend();
}
}
function getEnvStorageType(): "memory" | "file" | "postgresql" {
const type = process.env.OAUTH_STORAGE_TYPE?.toLowerCase();
Iif (type === "file" || type === "postgresql") {
return type;
}
return "memory";
}
function createMemoryBackend(): MemoryStorageBackend {
logger.info("Using in-memory session storage (sessions will be lost on restart)");
return new MemoryStorageBackend();
}
function createFileBackend(config?: StorageConfig): FileStorageBackend {
const filePath =
config?.file?.path ?? process.env.OAUTH_STORAGE_FILE_PATH ?? "./data/oauth-sessions.json";
const saveInterval =
config?.file?.saveInterval ?? parseInt(process.env.OAUTH_STORAGE_SAVE_INTERVAL ?? "30000", 10);
const prettyPrint =
config?.file?.prettyPrint ?? process.env.OAUTH_STORAGE_PRETTY_PRINT === "true";
logger.info({ filePath, saveInterval }, "Using file-based session storage");
return new FileStorageBackend({
filePath,
saveInterval,
prettyPrint,
});
}
function createPostgreSQLBackend(): PostgreSQLStorageBackend {
// Prisma uses OAUTH_STORAGE_POSTGRESQL_URL or DATABASE_URL from environment
const connectionString = process.env.OAUTH_STORAGE_POSTGRESQL_URL ?? process.env.DATABASE_URL;
if (!connectionString) {
throw new Error(
"PostgreSQL storage requires a connection string. " +
"Set OAUTH_STORAGE_POSTGRESQL_URL or DATABASE_URL environment variable"
);
}
logger.info("Using PostgreSQL session storage (via Prisma)");
return new PostgreSQLStorageBackend();
}
/**
* Get storage type from environment or config
*/
export function getStorageType(config?: StorageConfig): "memory" | "file" | "postgresql" {
return config?.type ?? getEnvStorageType();
}
/**
* Validate storage configuration
*/
export function validateStorageConfig(config?: StorageConfig): string[] {
const errors: string[] = [];
const type = getStorageType(config);
if (type === "postgresql") {
// Prisma uses OAUTH_STORAGE_POSTGRESQL_URL or DATABASE_URL
const connectionString = process.env.OAUTH_STORAGE_POSTGRESQL_URL ?? process.env.DATABASE_URL;
if (!connectionString) {
errors.push(
"PostgreSQL storage requires OAUTH_STORAGE_POSTGRESQL_URL or DATABASE_URL environment variable"
);
}
}
if (type === "file") {
const filePath = config?.file?.path ?? process.env.OAUTH_STORAGE_FILE_PATH;
// File path is optional - defaults to ./data/oauth-sessions.json
if (filePath) {
// Basic path validation
if (filePath.includes("..")) {
errors.push("File storage path must not contain '..'");
}
}
}
return errors;
}
|