UNPKG

@smartsamurai/krapi-sdk

Version:

KRAPI TypeScript SDK - Easy-to-use client SDK for connecting to self-hosted KRAPI servers (like Appwrite SDK)

306 lines (287 loc) 11.2 kB
/** * System Adapter * * Unifies SystemHttpClient and SystemService behind a common interface. */ import { SystemHttpClient, SystemSettings as HttpClientSystemSettings } from "../../http-clients/system-http-client"; import { SystemService } from "../../system-service"; import { SystemInfo } from "../../types"; import { createAdapterInitError } from "./error-handler"; type Mode = "client" | "server"; /** * Transform service SystemSettings (snake_case) to HTTP client SystemSettings (camelCase) */ function transformServiceToHttpSettings( serviceData: unknown ): HttpClientSystemSettings { if (!serviceData || typeof serviceData !== "object") { return {} as HttpClientSystemSettings; } const data = serviceData as Record<string, unknown>; const general = (data.general as Record<string, unknown>) || {}; const security = (data.security as Record<string, unknown>) || {}; const email = (data.email as Record<string, unknown>) || {}; const database = (data.database as Record<string, unknown>) || {}; return { general: { siteName: (typeof general.site_name === "string" ? general.site_name : "") || (typeof general.siteName === "string" ? general.siteName : ""), siteUrl: (typeof general.site_url === "string" ? general.site_url : "") || (typeof general.siteUrl === "string" ? general.siteUrl : ""), adminEmail: (typeof general.admin_email === "string" ? general.admin_email : "") || (typeof general.adminEmail === "string" ? general.adminEmail : ""), timezone: (typeof general.timezone === "string" ? general.timezone : "UTC") || "UTC", defaultLanguage: (typeof general.default_language === "string" ? general.default_language : "en") || (typeof general.defaultLanguage === "string" ? general.defaultLanguage : "en"), }, security: { requireTwoFactor: typeof security.require_two_factor === "boolean" ? security.require_two_factor : typeof security.requireTwoFactor === "boolean" ? security.requireTwoFactor : false, sessionTimeout: typeof security.session_timeout === "number" ? security.session_timeout : typeof security.sessionTimeout === "number" ? security.sessionTimeout : 3600, passwordMinLength: typeof security.password_min_length === "number" ? security.password_min_length : typeof security.passwordMinLength === "number" ? security.passwordMinLength : 8, passwordRequireUppercase: typeof security.password_require_uppercase === "boolean" ? security.password_require_uppercase : typeof security.passwordRequireUppercase === "boolean" ? security.passwordRequireUppercase : false, passwordRequireNumbers: typeof security.password_require_numbers === "boolean" ? security.password_require_numbers : typeof security.passwordRequireNumbers === "boolean" ? security.passwordRequireNumbers : false, passwordRequireSymbols: typeof security.password_require_symbols === "boolean" ? security.password_require_symbols : typeof security.passwordRequireSymbols === "boolean" ? security.passwordRequireSymbols : false, maxLoginAttempts: typeof security.max_login_attempts === "number" ? security.max_login_attempts : typeof security.maxLoginAttempts === "number" ? security.maxLoginAttempts : 5, }, email: { smtpHost: (typeof email.smtp_host === "string" ? email.smtp_host : "") || (typeof email.smtpHost === "string" ? email.smtpHost : ""), smtpPort: typeof email.smtp_port === "number" ? email.smtp_port : typeof email.smtpPort === "number" ? email.smtpPort : 587, smtpUsername: (typeof email.smtp_username === "string" ? email.smtp_username : "") || (typeof email.smtpUsername === "string" ? email.smtpUsername : ""), smtpPassword: (typeof email.smtp_password === "string" ? email.smtp_password : "") || (typeof email.smtpPassword === "string" ? email.smtpPassword : ""), smtpSecure: typeof email.smtp_secure === "boolean" ? email.smtp_secure : typeof email.smtpSecure === "boolean" ? email.smtpSecure : false, fromEmail: (typeof email.from_email === "string" ? email.from_email : "") || (typeof email.fromEmail === "string" ? email.fromEmail : ""), fromName: (typeof email.from_name === "string" ? email.from_name : "") || (typeof email.fromName === "string" ? email.fromName : ""), }, database: { connectionPoolSize: typeof database.connection_pool_size === "number" ? database.connection_pool_size : typeof database.connectionPoolSize === "number" ? database.connectionPoolSize : 10, queryTimeout: typeof database.query_timeout === "number" ? database.query_timeout : typeof database.queryTimeout === "number" ? database.queryTimeout : 30000, enableQueryLogging: typeof database.enable_query_logging === "boolean" ? database.enable_query_logging : typeof database.enableQueryLogging === "boolean" ? database.enableQueryLogging : false, backupSchedule: (typeof database.backup_schedule === "string" ? database.backup_schedule : "0 0 * * *") || (typeof database.backupSchedule === "string" ? database.backupSchedule : "0 0 * * *"), backupRetentionDays: typeof database.backup_retention_days === "number" ? database.backup_retention_days : typeof database.backupRetentionDays === "number" ? database.backupRetentionDays : 30, }, }; } /** * Transform HTTP client SystemSettings (camelCase) to service SystemSettings (snake_case) * Note: Service SystemSettings has a different structure, so we use Record<string, unknown> */ function transformHttpToServiceSettings( settings: Partial<HttpClientSystemSettings> ): Partial<Record<string, unknown>> { const serviceSettings: Record<string, unknown> = {}; if (settings.general) { serviceSettings.general = { site_name: settings.general.siteName, site_url: settings.general.siteUrl, admin_email: settings.general.adminEmail, timezone: settings.general.timezone, default_language: settings.general.defaultLanguage, }; } if (settings.security) { serviceSettings.security = { require_two_factor: settings.security.requireTwoFactor, session_timeout: settings.security.sessionTimeout, password_min_length: settings.security.passwordMinLength, password_require_uppercase: settings.security.passwordRequireUppercase, password_require_numbers: settings.security.passwordRequireNumbers, password_require_symbols: settings.security.passwordRequireSymbols, max_login_attempts: settings.security.maxLoginAttempts, }; } if (settings.email) { serviceSettings.email = { smtp_host: settings.email.smtpHost, smtp_port: settings.email.smtpPort, smtp_username: settings.email.smtpUsername, smtp_password: settings.email.smtpPassword, smtp_secure: settings.email.smtpSecure, from_email: settings.email.fromEmail, from_name: settings.email.fromName, }; } if (settings.database) { serviceSettings.database = { connection_pool_size: settings.database.connectionPoolSize, query_timeout: settings.database.queryTimeout, enable_query_logging: settings.database.enableQueryLogging, backup_schedule: settings.database.backupSchedule, backup_retention_days: settings.database.backupRetentionDays, }; } return serviceSettings; } export class SystemAdapter { private mode: Mode; private httpClient: SystemHttpClient | undefined; private service: SystemService | undefined; constructor(mode: Mode, httpClient?: SystemHttpClient, service?: SystemService) { this.mode = mode; this.httpClient = httpClient; this.service = service; } async getInfo(): Promise<SystemInfo> { if (this.mode === "client") { if (!this.httpClient) { throw createAdapterInitError("HTTP client", this.mode); } const response = await this.httpClient.getSystemInfo(); const info = (response.data as unknown as SystemInfo) || ({} as SystemInfo); // Ensure version is always present if (!info.version) { (info as unknown as Record<string, unknown>).version = "unknown"; } return info; } else { if (!this.service) { throw createAdapterInitError("System service", this.mode); } const response = await this.service.getSystemInfo(); const info = (response.data || {}) as SystemInfo; // Ensure version is always present - use package.json version or default if (!info.version) { (info as unknown as Record<string, unknown>).version = process.env.npm_package_version || "1.0.0"; } return info; } } async getSettings(): Promise<HttpClientSystemSettings> { if (this.mode === "client") { if (!this.httpClient) { throw createAdapterInitError("HTTP client", this.mode); } const response = await this.httpClient.getSettings(); return response.data || ({} as HttpClientSystemSettings); } else { if (!this.service) { throw createAdapterInitError("System service", this.mode); } const result = await this.service.getSettings(); // Transform service SystemSettings to HTTP client SystemSettings format const serviceData = result.data; if (!serviceData) { return {} as HttpClientSystemSettings; } return transformServiceToHttpSettings(serviceData); } } async updateSettings(settings: Partial<HttpClientSystemSettings>): Promise<HttpClientSystemSettings> { if (this.mode === "client") { if (!this.httpClient) { throw createAdapterInitError("HTTP client", this.mode); } const response = await this.httpClient.updateSettings(settings); return response.data || ({} as HttpClientSystemSettings); } else { if (!this.service) { throw createAdapterInitError("System service", this.mode); } // Transform HTTP client SystemSettings to service format const serviceSettings = transformHttpToServiceSettings(settings); const result = await this.service.updateSettings(serviceSettings); // Transform back to HTTP client format const resultData = result.data; if (!resultData) { return {} as HttpClientSystemSettings; } return transformServiceToHttpSettings(resultData); } } }