@sonicjs-cms/core 2.13.0 → 2.14.0
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.
- package/dist/{chunk-IYFSNRZN.js → chunk-23DP6TO5.js} +13 -10
- package/dist/chunk-23DP6TO5.js.map +1 -0
- package/dist/{chunk-DB2GJJTM.js → chunk-AFGOH2F6.js} +3 -3
- package/dist/{chunk-DB2GJJTM.js.map → chunk-AFGOH2F6.js.map} +1 -1
- package/dist/{chunk-HVTSE2SF.cjs → chunk-DRWSHIFG.cjs} +102 -99
- package/dist/chunk-DRWSHIFG.cjs.map +1 -0
- package/dist/{chunk-CO4B5EYF.js → chunk-GAVTTYMC.js} +3 -3
- package/dist/{chunk-CO4B5EYF.js.map → chunk-GAVTTYMC.js.map} +1 -1
- package/dist/{chunk-3VAKUFNQ.js → chunk-JKNKO6LA.js} +22 -5
- package/dist/chunk-JKNKO6LA.js.map +1 -0
- package/dist/{chunk-SER23XI4.cjs → chunk-KZ2MFGET.cjs} +22 -5
- package/dist/chunk-KZ2MFGET.cjs.map +1 -0
- package/dist/{chunk-XCP5GCBE.cjs → chunk-YULUPQZV.cjs} +3 -3
- package/dist/{chunk-XCP5GCBE.cjs.map → chunk-YULUPQZV.cjs.map} +1 -1
- package/dist/{chunk-EGUDIX6Q.cjs → chunk-YYMPHM3I.cjs} +4 -4
- package/dist/{chunk-EGUDIX6Q.cjs.map → chunk-YYMPHM3I.cjs.map} +1 -1
- package/dist/index.cjs +853 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +763 -9
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +28 -28
- package/dist/middleware.js +2 -2
- package/dist/migrations-F7KVA74T.cjs +13 -0
- package/dist/{migrations-GMHTJI7D.cjs.map → migrations-F7KVA74T.cjs.map} +1 -1
- package/dist/migrations-WKONKRN7.js +4 -0
- package/dist/{migrations-IVFIDOSO.js.map → migrations-WKONKRN7.js.map} +1 -1
- package/dist/{plugin-bootstrap-DVGLQrcO.d.cts → plugin-bootstrap-BGwBraaN.d.cts} +1 -0
- package/dist/{plugin-bootstrap-CZ1GDum7.d.ts → plugin-bootstrap-Drns7X9w.d.ts} +1 -0
- package/dist/routes.cjs +27 -27
- package/dist/routes.js +4 -4
- package/dist/services.cjs +2 -2
- package/dist/services.d.cts +1 -1
- package/dist/services.d.ts +1 -1
- package/dist/services.js +1 -1
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-3VAKUFNQ.js.map +0 -1
- package/dist/chunk-HVTSE2SF.cjs.map +0 -1
- package/dist/chunk-IYFSNRZN.js.map +0 -1
- package/dist/chunk-SER23XI4.cjs.map +0 -1
- package/dist/migrations-GMHTJI7D.cjs +0 -13
- package/dist/migrations-IVFIDOSO.js +0 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugins/core-plugins/database-tools-plugin/services/database-service.ts","../src/templates/pages/admin-database-table.template.ts","../src/plugins/core-plugins/database-tools-plugin/admin-routes.ts","../src/plugins/core-plugins/seed-data-plugin/services/seed-data-service.ts","../src/plugins/core-plugins/seed-data-plugin/admin-routes.ts","../src/plugins/core-plugins/email-plugin/index.ts","../src/plugins/core-plugins/otp-login-plugin/otp-service.ts","../src/plugins/core-plugins/otp-login-plugin/email-templates.ts","../src/plugins/core-plugins/otp-login-plugin/index.ts","../src/plugins/core-plugins/oauth-providers/oauth-service.ts","../src/plugins/core-plugins/oauth-providers/index.ts","../src/plugins/core-plugins/ai-search-plugin/services/embedding.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/chunking.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/custom-rag.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/ai-search.ts","../src/plugins/core-plugins/ai-search-plugin/services/indexer.ts","../src/plugins/core-plugins/ai-search-plugin/components/settings-page.ts","../src/plugins/core-plugins/ai-search-plugin/routes/admin.ts","../src/plugins/core-plugins/ai-search-plugin/routes/api.ts","../src/plugins/core-plugins/ai-search-plugin/manifest.json","../src/plugins/core-plugins/ai-search-plugin/index.ts","../src/plugins/available/magic-link-auth/index.ts","../src/plugins/core-plugins/security-audit-plugin/types.ts","../src/plugins/core-plugins/security-audit-plugin/services/security-audit-service.ts","../src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts","../src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts","../src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts","../src/plugins/core-plugins/security-audit-plugin/routes/admin.ts","../src/plugins/core-plugins/security-audit-plugin/services/brute-force-detector.ts","../src/plugins/core-plugins/security-audit-plugin/routes/api.ts","../src/plugins/core-plugins/security-audit-plugin/middleware/audit-middleware.ts","../src/plugins/core-plugins/security-audit-plugin/index.ts","../src/middleware/plugin-menu.ts","../src/plugins/cache/services/cache-config.ts","../src/plugins/cache/services/cache.ts","../src/plugins/cache/services/event-bus.ts","../src/plugins/cache/services/cache-invalidation.ts","../src/plugins/cache/services/cache-warming.ts","../src/templates/pages/admin-cache.template.ts","../src/plugins/cache/routes.ts","../src/plugins/cache/index.ts","../src/assets/favicon.ts","../src/app.ts","../src/db/index.ts","../src/index.ts"],"names":["init_admin_layout_catalyst_template","escapeHtml","renderAdminLayoutCatalyst","router","Hono","requireAuth","PluginBuilder","plugin","z","SettingsService","emailPlugin","AuthManager","setCookie","getCookie","jwt","content","collections","renderAdminLayout","api_default","DEFAULT_SETTINGS","formatTimestamp","severityBadge","eventTypeBadge","adminRoutes","PluginService","apiRoutes","getSettings","isPluginActive","logPromise","media","renderConfirmationDialog","getConfirmationDialogScript","totalRequests","app","getCoreVersion","metricsMiddleware","bootstrapMiddleware","securityHeadersMiddleware","csrfProtection","api_media_default","api_system_default","admin_api_default","adminCollectionsRoutes","adminFormsRoutes","adminSettingsRoutes","public_forms_default","admin_content_default","adminMediaRoutes","userProfilesPlugin","adminPluginRoutes","adminLogsRoutes","userRoutes","auth_default","test_cleanup_default","setAppInstance","d1","drizzle","schema_exports","package_default"],"mappings":"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","file":"index.cjs","sourcesContent":["import { D1Database } from '@cloudflare/workers-types'\n\nexport interface TruncateResult {\n success: boolean\n message: string\n tablesCleared: string[]\n adminUserPreserved: boolean\n errors?: string[]\n}\n\nexport interface DatabaseStats {\n tables: Array<{\n name: string\n rowCount: number\n }>\n totalRows: number\n}\n\nexport interface TableData {\n tableName: string\n columns: string[]\n rows: any[]\n totalRows: number\n}\n\nexport class DatabaseToolsService {\n constructor(private db: D1Database) {}\n\n /**\n * Get database statistics\n */\n async getDatabaseStats(): Promise<DatabaseStats> {\n const tables = await this.getTables()\n const stats: DatabaseStats = {\n tables: [],\n totalRows: 0\n }\n\n for (const tableName of tables) {\n try {\n const result = await this.db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).first()\n const rowCount = (result?.count as number) || 0\n \n stats.tables.push({\n name: tableName,\n rowCount\n })\n stats.totalRows += rowCount\n } catch (error) {\n // Skip tables that can't be counted (might be views or system tables)\n console.warn(`Could not count rows in table ${tableName}:`, error)\n }\n }\n\n return stats\n }\n\n /**\n * Get all tables in the database\n */\n private async getTables(): Promise<string[]> {\n const result = await this.db.prepare(`\n SELECT name FROM sqlite_master \n WHERE type='table' \n AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `).all()\n\n return result.results?.map((row: any) => row.name) || []\n }\n\n /**\n * Truncate all data except admin user\n */\n async truncateAllData(adminEmail: string): Promise<TruncateResult> {\n const errors: string[] = []\n const tablesCleared: string[] = []\n let adminUserPreserved = false\n\n try {\n // First, preserve the admin user data\n const adminUser = await this.db.prepare(\n 'SELECT * FROM users WHERE email = ? AND role = ?'\n ).bind(adminEmail, 'admin').first()\n\n if (!adminUser) {\n return {\n success: false,\n message: 'Admin user not found. Operation cancelled for safety.',\n tablesCleared: [],\n adminUserPreserved: false,\n errors: ['Admin user not found']\n }\n }\n\n // Define tables to truncate (excluding system tables)\n const tablesToTruncate = [\n 'content',\n 'content_versions', \n 'content_workflow_status',\n 'collections',\n 'media',\n 'sessions',\n 'notifications',\n 'api_tokens',\n 'workflow_history',\n 'scheduled_content',\n 'faqs',\n 'faq_categories',\n 'plugins',\n 'plugin_settings',\n 'email_templates',\n 'email_themes'\n ]\n\n // Check which tables exist\n const existingTables = await this.getTables()\n const tablesToClear = tablesToTruncate.filter(table => \n existingTables.includes(table)\n )\n\n // Clear all data except users table\n for (const tableName of tablesToClear) {\n try {\n await this.db.prepare(`DELETE FROM ${tableName}`).run()\n tablesCleared.push(tableName)\n } catch (error) {\n errors.push(`Failed to clear table ${tableName}: ${error}`)\n console.error(`Error clearing table ${tableName}:`, error)\n }\n }\n\n // Clear users table but preserve admin\n try {\n await this.db.prepare('DELETE FROM users WHERE email != ? OR role != ?')\n .bind(adminEmail, 'admin').run()\n \n // Verify admin user still exists\n const verifyAdmin = await this.db.prepare(\n 'SELECT id FROM users WHERE email = ? AND role = ?'\n ).bind(adminEmail, 'admin').first()\n\n adminUserPreserved = !!verifyAdmin\n tablesCleared.push('users (non-admin)')\n } catch (error) {\n errors.push(`Failed to clear non-admin users: ${error}`)\n console.error('Error clearing non-admin users:', error)\n }\n\n // Reset auto-increment counters if supported\n try {\n await this.db.prepare('DELETE FROM sqlite_sequence').run()\n } catch (error) {\n // sqlite_sequence might not exist, ignore\n }\n\n const message = errors.length > 0 \n ? `Truncation completed with ${errors.length} errors. ${tablesCleared.length} tables cleared.`\n : `Successfully truncated database. ${tablesCleared.length} tables cleared.`\n\n return {\n success: errors.length === 0,\n message,\n tablesCleared,\n adminUserPreserved,\n errors: errors.length > 0 ? errors : undefined\n }\n\n } catch (error) {\n return {\n success: false,\n message: `Database truncation failed: ${error}`,\n tablesCleared,\n adminUserPreserved,\n errors: [String(error)]\n }\n }\n }\n\n /**\n * Create a backup of current data (simplified version)\n */\n async createBackup(): Promise<{ success: boolean; message: string; backupId?: string }> {\n try {\n const backupId = `backup_${Date.now()}`\n const stats = await this.getDatabaseStats()\n \n // In a real implementation, this would export data to a file or cloud storage\n // For now, we'll just log the stats and return success\n console.log(`Backup ${backupId} created with ${stats.totalRows} total rows`)\n \n return {\n success: true,\n message: `Backup created successfully (${stats.totalRows} rows)`,\n backupId\n }\n } catch (error) {\n return {\n success: false,\n message: `Backup failed: ${error}`\n }\n }\n }\n\n /**\n * Get table data with optional pagination and sorting\n */\n async getTableData(\n tableName: string,\n limit: number = 100,\n offset: number = 0,\n sortColumn?: string,\n sortDirection: 'asc' | 'desc' = 'asc'\n ): Promise<TableData> {\n try {\n // Validate table name to prevent SQL injection\n const tables = await this.getTables()\n if (!tables.includes(tableName)) {\n throw new Error(`Table ${tableName} not found`)\n }\n\n // Get column names\n const pragmaResult = await this.db.prepare(`PRAGMA table_info(${tableName})`).all()\n const columns = pragmaResult.results?.map((col: any) => col.name) || []\n\n // Validate sort column if provided\n if (sortColumn && !columns.includes(sortColumn)) {\n sortColumn = undefined\n }\n\n // Get total row count\n const countResult = await this.db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).first()\n const totalRows = (countResult?.count as number) || 0\n\n // Build query with optional sorting\n let query = `SELECT * FROM ${tableName}`\n if (sortColumn) {\n query += ` ORDER BY ${sortColumn} ${sortDirection.toUpperCase()}`\n }\n query += ` LIMIT ${limit} OFFSET ${offset}`\n\n // Get paginated data\n const dataResult = await this.db.prepare(query).all()\n\n return {\n tableName,\n columns,\n rows: dataResult.results || [],\n totalRows\n }\n } catch (error) {\n throw new Error(`Failed to fetch table data: ${error}`)\n }\n }\n\n /**\n * Validate database integrity\n */\n async validateDatabase(): Promise<{ valid: boolean; issues: string[] }> {\n const issues: string[] = []\n\n try {\n // Check critical tables exist\n const requiredTables = ['users', 'content', 'collections']\n const existingTables = await this.getTables()\n\n for (const table of requiredTables) {\n if (!existingTables.includes(table)) {\n issues.push(`Critical table missing: ${table}`)\n }\n }\n\n // Check admin user exists\n const adminCount = await this.db.prepare(\n 'SELECT COUNT(*) as count FROM users WHERE role = ?'\n ).bind('admin').first()\n\n if ((adminCount?.count as number) === 0) {\n issues.push('No admin users found')\n }\n\n // Run SQLite integrity check\n try {\n const integrityResult = await this.db.prepare('PRAGMA integrity_check').first()\n if (integrityResult && (integrityResult as any).integrity_check !== 'ok') {\n issues.push(`Database integrity check failed: ${(integrityResult as any).integrity_check}`)\n }\n } catch (error) {\n issues.push(`Could not run integrity check: ${error}`)\n }\n\n } catch (error) {\n issues.push(`Validation error: ${error}`)\n }\n\n return {\n valid: issues.length === 0,\n issues\n }\n }\n}","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\n\nexport interface DatabaseTablePageData {\n user?: {\n name: string\n email: string\n role: string\n }\n tableName: string\n columns: string[]\n rows: any[]\n totalRows: number\n currentPage: number\n pageSize: number\n sortColumn?: string\n sortDirection?: 'asc' | 'desc'\n}\n\nexport function renderDatabaseTablePage(data: DatabaseTablePageData): string {\n const totalPages = Math.ceil(data.totalRows / data.pageSize)\n const startRow = (data.currentPage - 1) * data.pageSize + 1\n const endRow = Math.min(data.currentPage * data.pageSize, data.totalRows)\n\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <div class=\"flex items-center space-x-3\">\n <a\n href=\"/admin/settings/database-tools\"\n class=\"inline-flex items-center text-sm/6 text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300\"\n >\n <svg class=\"w-5 h-5 mr-1\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\"/>\n </svg>\n Back to Database Tools\n </a>\n </div>\n <h1 class=\"mt-2 text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Table: ${data.tableName}</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Showing ${startRow.toLocaleString()} - ${endRow.toLocaleString()} of ${data.totalRows.toLocaleString()} rows\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 flex items-center space-x-3\">\n <div class=\"flex items-center space-x-2\">\n <label for=\"pageSize\" class=\"text-sm font-medium text-zinc-700 dark:text-zinc-300\">\n Rows per page:\n </label>\n <select\n id=\"pageSize\"\n onchange=\"changePageSize(this.value)\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm cursor-pointer\"\n >\n <option value=\"10\" ${data.pageSize === 10 ? 'selected' : ''}>10</option>\n <option value=\"20\" ${data.pageSize === 20 ? 'selected' : ''}>20</option>\n <option value=\"50\" ${data.pageSize === 50 ? 'selected' : ''}>50</option>\n <option value=\"100\" ${data.pageSize === 100 ? 'selected' : ''}>100</option>\n <option value=\"200\" ${data.pageSize === 200 ? 'selected' : ''}>200</option>\n </select>\n </div>\n <button\n onclick=\"refreshTableData()\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n </div>\n </div>\n\n <!-- Table Card -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <!-- Table -->\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-950/10 dark:divide-white/10\">\n <thead class=\"bg-zinc-50 dark:bg-white/5\">\n <tr>\n ${data.columns.map(col => `\n <th\n scope=\"col\"\n class=\"px-4 py-3.5 text-left text-xs font-semibold text-zinc-950 dark:text-white uppercase tracking-wider cursor-pointer hover:bg-zinc-100 dark:hover:bg-white/10 transition-colors\"\n onclick=\"sortTable('${col}')\"\n >\n <div class=\"flex items-center space-x-1\">\n <span>${col}</span>\n ${data.sortColumn === col ? `\n <svg class=\"w-4 h-4 ${data.sortDirection === 'asc' ? '' : 'rotate-180'}\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 15l7-7 7 7\"/>\n </svg>\n ` : `\n <svg class=\"w-4 h-4 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\"/>\n </svg>\n `}\n </div>\n </th>\n `).join('')}\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-950/5 dark:divide-white/5\">\n ${data.rows.length > 0\n ? data.rows.map((row, idx) => `\n <tr class=\"${idx % 2 === 0 ? 'bg-white dark:bg-zinc-900' : 'bg-zinc-50 dark:bg-zinc-900/50'}\">\n ${data.columns.map(col => `\n <td class=\"px-4 py-3 text-sm text-zinc-700 dark:text-zinc-300 whitespace-nowrap max-w-xs overflow-hidden text-ellipsis\" title=\"${escapeHtml(String(row[col] ?? ''))}\">\n ${formatCellValue(row[col])}\n </td>\n `).join('')}\n </tr>\n `).join('')\n : `\n <tr>\n <td colspan=\"${data.columns.length}\" class=\"px-4 py-12 text-center text-sm text-zinc-500 dark:text-zinc-400\">\n <svg class=\"w-12 h-12 mx-auto mb-4 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4\"/>\n </svg>\n <p>No data in this table</p>\n </td>\n </tr>\n `\n }\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n ${totalPages > 1 ? `\n <div class=\"flex items-center justify-between border-t border-zinc-950/10 dark:border-white/10 bg-zinc-50 dark:bg-zinc-900/50 px-4 py-3 sm:px-6\">\n <div class=\"flex flex-1 justify-between sm:hidden\">\n <button\n onclick=\"goToPage(${data.currentPage - 1})\"\n ${data.currentPage === 1 ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-lg px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-100 dark:hover:bg-zinc-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Previous\n </button>\n <button\n onclick=\"goToPage(${data.currentPage + 1})\"\n ${data.currentPage === totalPages ? 'disabled' : ''}\n class=\"relative ml-3 inline-flex items-center rounded-lg px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-100 dark:hover:bg-zinc-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n </button>\n </div>\n <div class=\"hidden sm:flex sm:flex-1 sm:items-center sm:justify-between\">\n <div>\n <p class=\"text-sm text-zinc-700 dark:text-zinc-300\">\n Page <span class=\"font-medium\">${data.currentPage}</span> of <span class=\"font-medium\">${totalPages}</span>\n </p>\n </div>\n <div>\n <nav class=\"isolate inline-flex -space-x-px rounded-lg shadow-sm\" aria-label=\"Pagination\">\n <button\n onclick=\"goToPage(${data.currentPage - 1})\"\n ${data.currentPage === 1 ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-l-lg px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 focus:z-20 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <span class=\"sr-only\">Previous</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n ${generatePageNumbers(data.currentPage, totalPages)}\n\n <button\n onclick=\"goToPage(${data.currentPage + 1})\"\n ${data.currentPage === totalPages ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-r-lg px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 focus:z-20 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <span class=\"sr-only\">Next</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n </nav>\n </div>\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n\n <script>\n const currentTableName = '${data.tableName}';\n let currentPage = ${data.currentPage};\n let currentPageSize = ${data.pageSize};\n let currentSort = '${data.sortColumn || ''}';\n let currentSortDir = '${data.sortDirection || 'asc'}';\n\n function goToPage(page) {\n if (page < 1 || page > ${totalPages}) return;\n const params = new URLSearchParams();\n params.set('page', page);\n params.set('pageSize', currentPageSize);\n if (currentSort) {\n params.set('sort', currentSort);\n params.set('dir', currentSortDir);\n }\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function sortTable(column) {\n let newDir = 'asc';\n if (currentSort === column && currentSortDir === 'asc') {\n newDir = 'desc';\n }\n\n const params = new URLSearchParams();\n params.set('page', '1');\n params.set('pageSize', currentPageSize);\n params.set('sort', column);\n params.set('dir', newDir);\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function changePageSize(newSize) {\n const params = new URLSearchParams();\n params.set('page', '1');\n params.set('pageSize', newSize);\n if (currentSort) {\n params.set('sort', currentSort);\n params.set('dir', currentSortDir);\n }\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function refreshTableData() {\n window.location.reload();\n }\n\n function formatCellValue(value) {\n if (value === null || value === undefined) {\n return '<span class=\"text-zinc-400 dark:text-zinc-500 italic\">null</span>';\n }\n if (typeof value === 'boolean') {\n return \\`<span class=\"px-2 py-0.5 rounded text-xs font-medium \\${value ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400'}\">\\${value}</span>\\`;\n }\n if (typeof value === 'object') {\n return '<span class=\"text-xs font-mono text-zinc-600 dark:text-zinc-400\">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? '...' : '') + '</span>';\n }\n const str = String(value);\n if (str.length > 100) {\n return escapeHtml(str.substring(0, 100)) + '...';\n }\n return escapeHtml(str);\n }\n\n function escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return String(text).replace(/[&<>\"']/g, m => map[m]);\n }\n </script>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: `Table: ${data.tableName}`,\n pageTitle: `Database: ${data.tableName}`,\n currentPath: `/admin/database-tools/tables/${data.tableName}`,\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction generatePageNumbers(currentPage: number, totalPages: number): string {\n const pages: number[] = []\n const maxVisible = 7\n\n if (totalPages <= maxVisible) {\n for (let i = 1; i <= totalPages; i++) {\n pages.push(i)\n }\n } else {\n if (currentPage <= 4) {\n for (let i = 1; i <= 5; i++) pages.push(i)\n pages.push(-1) // ellipsis\n pages.push(totalPages)\n } else if (currentPage >= totalPages - 3) {\n pages.push(1)\n pages.push(-1) // ellipsis\n for (let i = totalPages - 4; i <= totalPages; i++) pages.push(i)\n } else {\n pages.push(1)\n pages.push(-1) // ellipsis\n for (let i = currentPage - 1; i <= currentPage + 1; i++) pages.push(i)\n pages.push(-1) // ellipsis\n pages.push(totalPages)\n }\n }\n\n return pages.map(page => {\n if (page === -1) {\n return `\n <span class=\"relative inline-flex items-center px-4 py-2 text-sm font-semibold text-zinc-700 dark:text-zinc-300 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700\">\n ...\n </span>\n `\n }\n\n const isActive = page === currentPage\n return `\n <button\n onclick=\"goToPage(${page})\"\n class=\"relative inline-flex items-center px-4 py-2 text-sm font-semibold ${\n isActive\n ? 'z-10 bg-indigo-600 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'\n : 'text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800'\n }\"\n >\n ${page}\n </button>\n `\n }).join('')\n}\n\nfunction escapeHtml(text: string): string {\n const map: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }\n return String(text).replace(/[&<>\"']/g, m => map[m] || m)\n}\n\nfunction formatCellValue(value: any): string {\n if (value === null || value === undefined) {\n return '<span class=\"text-zinc-400 dark:text-zinc-500 italic\">null</span>'\n }\n if (typeof value === 'boolean') {\n return `<span class=\"px-2 py-0.5 rounded text-xs font-medium ${value ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400'}\">${value}</span>`\n }\n if (typeof value === 'object') {\n return '<span class=\"text-xs font-mono text-zinc-600 dark:text-zinc-400\">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? '...' : '') + '</span>'\n }\n const str = String(value)\n if (str.length > 100) {\n return escapeHtml(str.substring(0, 100)) + '...'\n }\n return escapeHtml(str)\n}\n","import { Hono } from 'hono'\nimport { DatabaseToolsService } from './services/database-service'\nimport { renderDatabaseTablePage, DatabaseTablePageData } from '../../../templates/pages/admin-database-table.template'\nimport { requireAuth } from '../../../middleware'\n\ntype Bindings = {\n DB: D1Database\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n }\n}\n\nexport function createDatabaseToolsAdminRoutes() {\n const router = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n // Apply authentication middleware\n router.use('*', requireAuth())\n\n // Get database statistics\n router.get('/api/stats', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const stats = await service.getDatabaseStats()\n\n return c.json({\n success: true,\n data: stats\n })\n } catch (error) {\n console.error('Error fetching database stats:', error)\n return c.json({ \n success: false, \n error: 'Failed to fetch database statistics' \n }, 500)\n }\n })\n\n // Truncate all data except admin user\n router.post('/api/truncate', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const body = await c.req.json()\n const { confirmText } = body\n\n // Require confirmation text for safety\n if (confirmText !== 'TRUNCATE ALL DATA') {\n return c.json({\n success: false,\n error: 'Invalid confirmation text. Operation cancelled.'\n }, 400)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const result = await service.truncateAllData(user.email)\n\n return c.json({\n success: result.success,\n message: result.message,\n data: {\n tablesCleared: result.tablesCleared,\n adminUserPreserved: result.adminUserPreserved,\n errors: result.errors\n }\n })\n } catch (error) {\n console.error('Error truncating database:', error)\n return c.json({ \n success: false, \n error: 'Failed to truncate database' \n }, 500)\n }\n })\n\n // Create backup\n router.post('/api/backup', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const result = await service.createBackup()\n\n return c.json({\n success: result.success,\n message: result.message,\n data: {\n backupId: result.backupId\n }\n })\n } catch (error) {\n console.error('Error creating backup:', error)\n return c.json({ \n success: false, \n error: 'Failed to create backup' \n }, 500)\n }\n })\n\n // Validate database\n router.get('/api/validate', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const validation = await service.validateDatabase()\n\n return c.json({\n success: true,\n data: validation\n })\n } catch (error) {\n console.error('Error validating database:', error)\n return c.json({\n success: false,\n error: 'Failed to validate database'\n }, 500)\n }\n })\n\n // Get table data (API endpoint)\n router.get('/api/tables/:tableName', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const tableName = c.req.param('tableName')\n const limit = parseInt(c.req.query('limit') || '100')\n const offset = parseInt(c.req.query('offset') || '0')\n const sortColumn = c.req.query('sort')\n const sortDirection = (c.req.query('dir') || 'asc') as 'asc' | 'desc'\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const tableData = await service.getTableData(tableName, limit, offset, sortColumn, sortDirection)\n\n return c.json({\n success: true,\n data: tableData\n })\n } catch (error) {\n console.error('Error fetching table data:', error)\n return c.json({\n success: false,\n error: `Failed to fetch table data: ${error}`\n }, 500)\n }\n })\n\n // View table data page\n router.get('/tables/:tableName', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.redirect('/admin/login')\n }\n\n const tableName = c.req.param('tableName')\n const page = parseInt(c.req.query('page') || '1')\n const pageSize = parseInt(c.req.query('pageSize') || '20')\n const sortColumn = c.req.query('sort')\n const sortDirection = (c.req.query('dir') || 'asc') as 'asc' | 'desc'\n\n const offset = (page - 1) * pageSize\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const tableData = await service.getTableData(tableName, pageSize, offset, sortColumn, sortDirection)\n\n const pageData: DatabaseTablePageData = {\n user: {\n name: user.email.split('@')[0] || 'Unknown',\n email: user.email,\n role: user.role\n },\n tableName: tableData.tableName,\n columns: tableData.columns,\n rows: tableData.rows,\n totalRows: tableData.totalRows,\n currentPage: page,\n pageSize: pageSize,\n sortColumn: sortColumn,\n sortDirection: sortDirection\n }\n\n return c.html(renderDatabaseTablePage(pageData))\n } catch (error) {\n console.error('Error rendering table page:', error)\n return c.text(`Error: ${error}`, 500)\n }\n })\n\n return router\n}","import type { D1Database } from '@cloudflare/workers-types'\n\nexport class SeedDataService {\n constructor(private db: D1Database) {}\n\n // First names for generating realistic users\n private firstNames = [\n 'Emma', 'Liam', 'Olivia', 'Noah', 'Ava', 'Ethan', 'Sophia', 'Mason',\n 'Isabella', 'William', 'Mia', 'James', 'Charlotte', 'Benjamin', 'Amelia',\n 'Lucas', 'Harper', 'Henry', 'Evelyn', 'Alexander'\n ]\n\n // Last names for generating realistic users\n private lastNames = [\n 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',\n 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson',\n 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin'\n ]\n\n // Content titles for blog posts\n private blogTitles = [\n 'Getting Started with Modern Web Development',\n 'The Future of JavaScript Frameworks',\n 'Building Scalable Applications with Microservices',\n 'Understanding TypeScript: A Complete Guide',\n 'Best Practices for API Design',\n 'Introduction to Cloud Computing',\n 'Mastering Git and Version Control',\n 'The Art of Code Review',\n 'Performance Optimization Techniques',\n 'Security Best Practices for Web Apps',\n 'Exploring Serverless Architecture',\n 'Database Design Fundamentals',\n 'Testing Strategies for Modern Apps',\n 'CI/CD Pipeline Implementation',\n 'Mobile-First Development Approach'\n ]\n\n // Content titles for pages\n private pageTitles = [\n 'About Us', 'Contact', 'Privacy Policy', 'Terms of Service',\n 'FAQ', 'Our Team', 'Careers', 'Press Kit',\n 'Support', 'Documentation', 'Pricing', 'Features'\n ]\n\n // Content titles for products\n private productTitles = [\n 'Premium Wireless Headphones',\n 'Smart Watch Pro',\n 'Laptop Stand Adjustable',\n 'Mechanical Keyboard RGB',\n 'HD Webcam 4K',\n 'USB-C Hub 7-in-1',\n 'Portable SSD 1TB',\n 'Wireless Mouse Ergonomic',\n 'Monitor 27\" 4K',\n 'Desk Lamp LED',\n 'Phone Case Premium',\n 'Tablet Stand Aluminum',\n 'Cable Management Kit',\n 'Power Bank 20000mAh',\n 'Bluetooth Speaker Portable'\n ]\n\n // Content for generating blog posts\n private blogContent = [\n 'This comprehensive guide covers everything you need to know about modern development practices and tools.',\n 'Learn the fundamentals and advanced concepts that will help you build better applications.',\n 'Discover the latest trends and best practices used by industry professionals.',\n 'A deep dive into the technologies and methodologies shaping the future of software development.',\n 'Practical tips and real-world examples to improve your development workflow.',\n 'Explore cutting-edge techniques and proven strategies for building robust applications.',\n 'Master the essential skills needed to excel in modern software development.',\n 'An in-depth look at the tools and frameworks that power today\\'s web applications.',\n 'Step-by-step instructions and expert insights for developers of all levels.',\n 'Understanding the core principles that drive successful software projects.'\n ]\n\n // Generate a random ID\n private generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n }\n\n // Generate a slug from a title\n private generateSlug(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '')\n }\n\n // Generate random date within the last year\n private randomDate(): Date {\n const now = new Date()\n const yearAgo = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate())\n const randomTime = yearAgo.getTime() + Math.random() * (now.getTime() - yearAgo.getTime())\n return new Date(randomTime)\n }\n\n // Create 20 example users\n async createUsers(): Promise<number> {\n const roles = ['admin', 'editor', 'author', 'viewer']\n // const hashedPassword = await bcrypt.hash('password123', 10)\n const hashedPassword = 'password123' // TODO: Use actual bcrypt hash\n\n let count = 0\n for (let i = 0; i < 20; i++) {\n const firstName = this.firstNames[Math.floor(Math.random() * this.firstNames.length)] || 'John'\n const lastName = this.lastNames[Math.floor(Math.random() * this.lastNames.length)] || 'Doe'\n const username = `${firstName.toLowerCase()}${lastName.toLowerCase()}${i}`\n const email = `${username}@example.com`\n const createdAt = this.randomDate()\n const createdAtTimestamp = Math.floor(createdAt.getTime() / 1000)\n\n const stmt = this.db.prepare(`\n INSERT INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, last_login_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await stmt.bind(\n this.generateId(),\n email,\n username,\n firstName,\n lastName,\n hashedPassword,\n roles[Math.floor(Math.random() * roles.length)],\n Math.random() > 0.1 ? 1 : 0, // 90% active\n Math.random() > 0.3 ? createdAtTimestamp : null,\n createdAtTimestamp,\n createdAtTimestamp\n ).run()\n\n count++\n }\n\n return count\n }\n\n // Create 200 content items across different types\n async createContent(): Promise<number> {\n // Get all users and collections\n const usersStmt = this.db.prepare('SELECT * FROM users')\n const { results: allUsers } = await usersStmt.all()\n\n const collectionsStmt = this.db.prepare('SELECT * FROM collections')\n const { results: allCollections } = await collectionsStmt.all()\n\n if (!allUsers || allUsers.length === 0) {\n throw new Error('No users found. Please create users first.')\n }\n\n if (!allCollections || allCollections.length === 0) {\n throw new Error('No collections found. Please create collections first.')\n }\n\n const statuses = ['draft', 'published', 'archived']\n\n // Create 200 content items\n let count = 0\n for (let i = 0; i < 200; i++) {\n const collection: any = allCollections[Math.floor(Math.random() * allCollections.length)]\n const author: any = allUsers[Math.floor(Math.random() * allUsers.length)]\n const status = statuses[Math.floor(Math.random() * statuses.length)]\n\n let title: string\n let contentData: any\n\n // Generate content based on collection type\n if (collection.name === 'blog_posts' || collection.name.includes('blog')) {\n title = this.blogTitles[Math.floor(Math.random() * this.blogTitles.length)] || 'Untitled Blog Post'\n contentData = {\n body: this.blogContent[Math.floor(Math.random() * this.blogContent.length)] || 'Blog content here',\n excerpt: 'A brief introduction to this article that provides an overview of the main topics covered.',\n tags: this.generateTags(),\n featured: Math.random() > 0.7\n }\n } else if (collection.name === 'pages' || collection.name.includes('page')) {\n title = this.pageTitles[Math.floor(Math.random() * this.pageTitles.length)] || 'Untitled Page'\n contentData = {\n body: 'This is a standard page with important information about our services and policies.',\n template: 'default',\n showInMenu: Math.random() > 0.5\n }\n } else if (collection.name === 'products' || collection.name.includes('product')) {\n title = this.productTitles[Math.floor(Math.random() * this.productTitles.length)] || 'Untitled Product'\n contentData = {\n description: 'High-quality product with excellent features and great value for money.',\n price: (Math.random() * 500 + 10).toFixed(2),\n sku: `SKU-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n inStock: Math.random() > 0.2,\n rating: (Math.random() * 2 + 3).toFixed(1) // 3.0 - 5.0\n }\n } else {\n // Generic content\n title = `${collection.display_name || collection.name} Item ${i + 1}`\n contentData = {\n description: 'This is a sample content item with generic data.',\n value: Math.floor(Math.random() * 1000)\n }\n }\n\n const slug = `${this.generateSlug(title)}-${i}`\n const createdAt = this.randomDate()\n const createdAtTimestamp = Math.floor(createdAt.getTime() / 1000)\n const publishedAtTimestamp = status === 'published' ? createdAtTimestamp : null\n\n const stmt = this.db.prepare(`\n INSERT INTO content (id, collection_id, slug, title, data, status, published_at, author_id, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await stmt.bind(\n this.generateId(),\n collection.id,\n slug,\n `${title} ${i}`,\n JSON.stringify(contentData),\n status,\n publishedAtTimestamp,\n author.id,\n createdAtTimestamp,\n createdAtTimestamp\n ).run()\n\n count++\n }\n\n return count\n }\n\n // Generate random tags for blog posts\n private generateTags(): string[] {\n const allTags = [\n 'tutorial', 'guide', 'javascript', 'typescript', 'web-dev',\n 'backend', 'frontend', 'best-practices', 'security', 'performance',\n 'testing', 'deployment', 'cloud', 'database', 'api'\n ]\n\n const numTags = Math.floor(Math.random() * 4) + 1 // 1-4 tags\n const shuffled = allTags.sort(() => 0.5 - Math.random())\n return shuffled.slice(0, numTags)\n }\n\n // Seed all data\n async seedAll(): Promise<{ users: number; content: number }> {\n const userCount = await this.createUsers()\n const contentCount = await this.createContent()\n\n return {\n users: userCount,\n content: contentCount\n }\n }\n\n // Clear all seed data (optional cleanup method)\n async clearSeedData(): Promise<void> {\n // Delete content first (due to foreign key constraints)\n const deleteContentStmt = this.db.prepare('DELETE FROM content')\n await deleteContentStmt.run()\n\n // Delete users (but keep admin users)\n const deleteUsersStmt = this.db.prepare(\n \"DELETE FROM users WHERE role != 'admin'\"\n )\n await deleteUsersStmt.run()\n }\n}\n","import { Hono } from 'hono'\nimport { SeedDataService } from './services/seed-data-service'\n\ntype Bindings = {\n DB: D1Database\n}\n\nexport function createSeedDataAdminRoutes() {\n const routes = new Hono<{ Bindings: Bindings }>()\n\n // Get seed data status/info\n routes.get('/', async (c) => {\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <title>Seed Data - SonicJS Admin</title>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #f5f5f5;\n padding: 2rem;\n }\n .container {\n max-width: 800px;\n margin: 0 auto;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n padding: 2rem;\n }\n h1 {\n color: #333;\n margin-bottom: 1rem;\n font-size: 2rem;\n }\n .description {\n color: #666;\n margin-bottom: 2rem;\n line-height: 1.6;\n }\n .card {\n background: #f9f9f9;\n border-radius: 6px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n }\n .card h2 {\n color: #333;\n font-size: 1.25rem;\n margin-bottom: 0.75rem;\n }\n .card p {\n color: #666;\n line-height: 1.6;\n margin-bottom: 1rem;\n }\n .card ul {\n color: #666;\n margin-left: 1.5rem;\n margin-bottom: 1rem;\n }\n .card li {\n margin-bottom: 0.5rem;\n }\n button {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n font-size: 1rem;\n cursor: pointer;\n transition: background 0.2s;\n }\n button:hover {\n background: #2563eb;\n }\n button:disabled {\n background: #94a3b8;\n cursor: not-allowed;\n }\n .danger {\n background: #ef4444;\n }\n .danger:hover {\n background: #dc2626;\n }\n .warning {\n background: #f59e0b;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n }\n .success {\n background: #10b981;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n display: none;\n }\n .error {\n background: #ef4444;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n display: none;\n }\n .loading {\n display: none;\n margin-left: 1rem;\n }\n .back-link {\n display: inline-block;\n margin-bottom: 1rem;\n color: #3b82f6;\n text-decoration: none;\n font-size: 0.9rem;\n }\n .back-link:hover {\n text-decoration: underline;\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <a href=\"/admin/plugins/seed-data\" class=\"back-link\">← Back to Plugin Settings</a>\n <h1>🌱 Seed Data Generator</h1>\n <p class=\"description\">\n Generate realistic example data for testing and development. This will create 20 users and 200 content items with realistic data.\n </p>\n\n <div class=\"warning\">\n <strong>⚠️ Warning:</strong> This will create new data in your database. Make sure you're not running this in production!\n </div>\n\n <div class=\"success\" id=\"successMessage\"></div>\n <div class=\"error\" id=\"errorMessage\"></div>\n\n <div class=\"card\">\n <h2>What will be created?</h2>\n <ul>\n <li><strong>20 Users:</strong> With realistic names, emails, and various roles (admin, editor, author, viewer)</li>\n <li><strong>200 Content Items:</strong> Including blog posts, pages, and products with realistic titles and data</li>\n <li><strong>All passwords:</strong> Set to \"password123\" for testing</li>\n <li><strong>Random dates:</strong> Created within the last year</li>\n <li><strong>Various statuses:</strong> Draft, published, and archived content</li>\n </ul>\n </div>\n\n <div class=\"card\">\n <h2>Generate Seed Data</h2>\n <p>Click the button below to generate example data. This may take a few moments.</p>\n <button id=\"seedButton\" onclick=\"generateSeedData()\">\n Generate Data\n <span class=\"loading\" id=\"loading\">...</span>\n </button>\n </div>\n\n <div class=\"card\">\n <h2>Clear Seed Data</h2>\n <p>Remove all users and content from the database (except admin users).</p>\n <button class=\"danger\" id=\"clearButton\" onclick=\"clearSeedData()\">\n Clear All Data\n <span class=\"loading\" id=\"clearLoading\">...</span>\n </button>\n </div>\n </div>\n\n <script>\n async function generateSeedData() {\n const button = document.getElementById('seedButton');\n const loading = document.getElementById('loading');\n const success = document.getElementById('successMessage');\n const error = document.getElementById('errorMessage');\n\n button.disabled = true;\n loading.style.display = 'inline';\n success.style.display = 'none';\n error.style.display = 'none';\n\n try {\n const response = await fetch('/admin/seed-data/generate', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n const data = await response.json();\n\n if (response.ok) {\n success.textContent = \\`✅ Successfully created \\${data.users} users and \\${data.content} content items!\\`;\n success.style.display = 'block';\n } else {\n throw new Error(data.error || 'Failed to generate seed data');\n }\n } catch (err) {\n error.textContent = \\`❌ Error: \\${err.message}\\`;\n error.style.display = 'block';\n } finally {\n button.disabled = false;\n loading.style.display = 'none';\n }\n }\n\n async function clearSeedData() {\n if (!confirm('Are you sure you want to clear all data? This cannot be undone!')) {\n return;\n }\n\n const button = document.getElementById('clearButton');\n const loading = document.getElementById('clearLoading');\n const success = document.getElementById('successMessage');\n const error = document.getElementById('errorMessage');\n\n button.disabled = true;\n loading.style.display = 'inline';\n success.style.display = 'none';\n error.style.display = 'none';\n\n try {\n const response = await fetch('/admin/seed-data/clear', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n const data = await response.json();\n\n if (response.ok) {\n success.textContent = '✅ Successfully cleared all seed data!';\n success.style.display = 'block';\n } else {\n throw new Error(data.error || 'Failed to clear seed data');\n }\n } catch (err) {\n error.textContent = \\`❌ Error: \\${err.message}\\`;\n error.style.display = 'block';\n } finally {\n button.disabled = false;\n loading.style.display = 'none';\n }\n }\n </script>\n </body>\n </html>\n `\n return c.html(html)\n })\n\n // Generate seed data\n routes.post('/generate', async (c) => {\n try {\n const db = c.env.DB\n const seedService = new SeedDataService(db)\n\n const result = await seedService.seedAll()\n\n return c.json({\n success: true,\n users: result.users,\n content: result.content\n })\n } catch (error: any) {\n return c.json({\n success: false,\n error: error.message\n }, 500)\n }\n })\n\n // Clear seed data\n routes.post('/clear', async (c) => {\n try {\n const db = c.env.DB\n const seedService = new SeedDataService(db)\n\n await seedService.clearSeedData()\n\n return c.json({\n success: true\n })\n } catch (error: any) {\n return c.json({\n success: false,\n error: error.message\n }, 500)\n }\n })\n\n return routes\n}\n","/**\n * Email Plugin\n *\n * Send transactional emails using Resend\n * Handles registration, verification, password reset, and one-time codes\n */\n\nimport { Hono } from 'hono'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\n\nexport function createEmailPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'email',\n version: '1.0.0-beta.1',\n description: 'Send transactional emails using Resend'\n })\n\n // Add plugin metadata\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // Create the Email Settings route (POST only - GET is handled by generic plugin settings page)\n const emailRoutes = new Hono()\n\n // Note: Admin UI is now handled by the generic plugin settings page\n // with custom component at admin-plugin-settings.template.ts\n\n // POST endpoint for saving settings\n emailRoutes.post('/settings', async (c: any) => {\n try {\n const body = await c.req.json()\n const db = c.env.DB\n\n // Update plugin settings in database\n await db.prepare(`\n UPDATE plugins\n SET settings = ?,\n updated_at = unixepoch()\n WHERE id = 'email'\n `).bind(JSON.stringify(body)).run()\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error saving email settings:', error)\n return c.json({ success: false, error: 'Failed to save settings' }, 500)\n }\n })\n\n // POST endpoint for test email\n emailRoutes.post('/test', async (c: any) => {\n try {\n const db = c.env.DB\n const body = await c.req.json()\n\n // Load settings from database\n const plugin = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'email'\n `).first() as { settings: string | null } | null\n\n if (!plugin?.settings) {\n return c.json({\n success: false,\n error: 'Email settings not configured. Please save your settings first.'\n }, 400)\n }\n\n const settings = JSON.parse(plugin.settings)\n\n // Validate required settings\n if (!settings.apiKey || !settings.fromEmail || !settings.fromName) {\n return c.json({\n success: false,\n error: 'Missing required settings. Please configure API Key, From Email, and From Name.'\n }, 400)\n }\n\n // Use provided email or fallback to fromEmail\n const toEmail = body.toEmail || settings.fromEmail\n\n // Validate email format\n if (!toEmail.match(/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/)) {\n return c.json({\n success: false,\n error: 'Invalid email address format'\n }, 400)\n }\n\n // Send test email via Resend API\n const response = await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${settings.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n from: `${settings.fromName} <${settings.fromEmail}>`,\n to: [toEmail],\n subject: 'Test Email from SonicJS',\n html: `\n <div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n <h1 style=\"color: #667eea;\">Test Email Successful! 🎉</h1>\n <p>This is a test email from your SonicJS Email plugin.</p>\n <p><strong>Configuration:</strong></p>\n <ul>\n <li>From: ${settings.fromName} <${settings.fromEmail}></li>\n <li>Reply-To: ${settings.replyTo || 'Not set'}</li>\n <li>Sent at: ${new Date().toISOString()}</li>\n </ul>\n <p>Your email settings are working correctly!</p>\n </div>\n `,\n reply_to: settings.replyTo || settings.fromEmail\n })\n })\n\n const data = await response.json() as any\n\n if (!response.ok) {\n console.error('Resend API error:', data)\n return c.json({\n success: false,\n error: data.message || 'Failed to send test email. Check your API key and domain verification.'\n }, response.status)\n }\n\n return c.json({\n success: true,\n message: `Test email sent successfully to ${toEmail}`,\n emailId: data.id\n })\n\n } catch (error: any) {\n console.error('Test email error:', error)\n return c.json({\n success: false,\n error: error.message || 'An error occurred while sending test email'\n }, 500)\n }\n })\n\n // Register the route\n builder.addRoute('/admin/plugins/email', emailRoutes, {\n description: 'Email plugin settings',\n requiresAuth: true,\n priority: 80\n })\n\n // Add menu item (points to generic plugin settings page)\n builder.addMenuItem('Email', '/admin/plugins/email', {\n icon: 'envelope',\n order: 80,\n permissions: ['email:manage']\n })\n\n // Add lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ Email plugin activated')\n },\n\n deactivate: async () => {\n console.info('❌ Email plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\n// Export the plugin instance\nexport const emailPlugin = createEmailPlugin()\n","/**\n * OTP Service\n * Handles OTP code generation, verification, and management\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\nexport interface OTPSettings {\n codeLength: number\n codeExpiryMinutes: number\n maxAttempts: number\n rateLimitPerHour: number\n allowNewUserRegistration: boolean\n logoUrl?: string\n}\n\nexport interface OTPCode {\n id: string\n user_email: string\n code: string\n expires_at: number\n used: number\n used_at: number | null\n ip_address: string | null\n user_agent: string | null\n attempts: number\n created_at: number\n}\n\nexport class OTPService {\n constructor(private db: D1Database) {}\n\n /**\n * Generate a secure random OTP code\n */\n generateCode(length: number = 6): string {\n const digits = '0123456789'\n let code = ''\n\n for (let i = 0; i < length; i++) {\n const randomValues = new Uint8Array(1)\n crypto.getRandomValues(randomValues)\n const randomValue = randomValues[0] ?? 0\n code += digits[randomValue % digits.length]\n }\n\n return code\n }\n\n /**\n * Create and store a new OTP code\n */\n async createOTPCode(\n email: string,\n settings: OTPSettings,\n ipAddress?: string,\n userAgent?: string\n ): Promise<OTPCode> {\n const code = this.generateCode(settings.codeLength)\n const id = crypto.randomUUID()\n const now = Date.now()\n const expiresAt = now + (settings.codeExpiryMinutes * 60 * 1000)\n\n const otpCode: OTPCode = {\n id,\n user_email: email.toLowerCase(),\n code,\n expires_at: expiresAt,\n used: 0,\n used_at: null,\n ip_address: ipAddress || null,\n user_agent: userAgent || null,\n attempts: 0,\n created_at: now\n }\n\n await this.db.prepare(`\n INSERT INTO otp_codes (\n id, user_email, code, expires_at, used, used_at,\n ip_address, user_agent, attempts, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n otpCode.id,\n otpCode.user_email,\n otpCode.code,\n otpCode.expires_at,\n otpCode.used,\n otpCode.used_at,\n otpCode.ip_address,\n otpCode.user_agent,\n otpCode.attempts,\n otpCode.created_at\n ).run()\n\n return otpCode\n }\n\n /**\n * Verify an OTP code\n */\n async verifyCode(\n email: string,\n code: string,\n settings: OTPSettings\n ): Promise<{ valid: boolean; attemptsRemaining?: number; error?: string }> {\n const normalizedEmail = email.toLowerCase()\n const now = Date.now()\n\n // Find the most recent unused code for this email\n const otpCode = await this.db.prepare(`\n SELECT * FROM otp_codes\n WHERE user_email = ? AND code = ? AND used = 0\n ORDER BY created_at DESC\n LIMIT 1\n `).bind(normalizedEmail, code).first() as OTPCode | null\n\n if (!otpCode) {\n return { valid: false, error: 'Invalid or expired code' }\n }\n\n // Check if expired\n if (now > otpCode.expires_at) {\n return { valid: false, error: 'Code has expired' }\n }\n\n // Check attempts\n if (otpCode.attempts >= settings.maxAttempts) {\n return { valid: false, error: 'Maximum attempts exceeded' }\n }\n\n // Code is valid - mark as used\n await this.db.prepare(`\n UPDATE otp_codes\n SET used = 1, used_at = ?, attempts = attempts + 1\n WHERE id = ?\n `).bind(now, otpCode.id).run()\n\n return { valid: true }\n }\n\n /**\n * Increment failed attempt count\n */\n async incrementAttempts(email: string, code: string): Promise<number> {\n const normalizedEmail = email.toLowerCase()\n\n const result = await this.db.prepare(`\n UPDATE otp_codes\n SET attempts = attempts + 1\n WHERE user_email = ? AND code = ? AND used = 0\n RETURNING attempts\n `).bind(normalizedEmail, code).first() as { attempts: number } | null\n\n return result?.attempts || 0\n }\n\n /**\n * Check rate limiting\n */\n async checkRateLimit(email: string, settings: OTPSettings): Promise<boolean> {\n const normalizedEmail = email.toLowerCase()\n const oneHourAgo = Date.now() - (60 * 60 * 1000)\n\n const result = await this.db.prepare(`\n SELECT COUNT(*) as count\n FROM otp_codes\n WHERE user_email = ? AND created_at > ?\n `).bind(normalizedEmail, oneHourAgo).first() as { count: number } | null\n\n const count = result?.count || 0\n return count < settings.rateLimitPerHour\n }\n\n /**\n * Get recent OTP requests for activity log\n */\n async getRecentRequests(limit: number = 50): Promise<OTPCode[]> {\n const result = await this.db.prepare(`\n SELECT * FROM otp_codes\n ORDER BY created_at DESC\n LIMIT ?\n `).bind(limit).all()\n\n const rows = (result.results || []) as Record<string, unknown>[]\n return rows.map(row => this.mapRowToOTP(row))\n }\n\n /**\n * Clean up expired codes (for maintenance)\n */\n async cleanupExpiredCodes(): Promise<number> {\n const now = Date.now()\n\n const result = await this.db.prepare(`\n DELETE FROM otp_codes\n WHERE expires_at < ? OR (used = 1 AND used_at < ?)\n `).bind(now, now - (30 * 24 * 60 * 60 * 1000)).run() // Keep used codes for 30 days\n\n return result.meta.changes || 0\n }\n\n private mapRowToOTP(row: Record<string, unknown>): OTPCode {\n return {\n id: String(row.id),\n user_email: String(row.user_email),\n code: String(row.code),\n expires_at: Number(row.expires_at ?? Date.now()),\n used: Number(row.used ?? 0),\n used_at: row.used_at === null || row.used_at === undefined ? null : Number(row.used_at),\n ip_address: typeof row.ip_address === 'string' ? row.ip_address : null,\n user_agent: typeof row.user_agent === 'string' ? row.user_agent : null,\n attempts: Number(row.attempts ?? 0),\n created_at: Number(row.created_at ?? Date.now())\n }\n }\n\n /**\n * Get OTP statistics\n */\n async getStats(days: number = 7): Promise<{\n total: number\n successful: number\n failed: number\n expired: number\n }> {\n const since = Date.now() - (days * 24 * 60 * 60 * 1000)\n\n const stats = await this.db.prepare(`\n SELECT\n COUNT(*) as total,\n SUM(CASE WHEN used = 1 THEN 1 ELSE 0 END) as successful,\n SUM(CASE WHEN attempts >= 3 AND used = 0 THEN 1 ELSE 0 END) as failed,\n SUM(CASE WHEN expires_at < ? AND used = 0 THEN 1 ELSE 0 END) as expired\n FROM otp_codes\n WHERE created_at > ?\n `).bind(Date.now(), since).first() as any\n\n return {\n total: stats?.total || 0,\n successful: stats?.successful || 0,\n failed: stats?.failed || 0,\n expired: stats?.expired || 0\n }\n }\n}\n","/**\n * OTP Email Templates\n * HTML and plain text templates for OTP codes\n */\n\nexport interface OTPEmailData {\n code: string\n expiryMinutes: number\n codeLength: number\n maxAttempts: number\n email: string\n ipAddress?: string\n timestamp: string\n appName: string\n logoUrl?: string\n}\n\nexport function renderOTPEmailHTML(data: OTPEmailData): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Your Login Code</title>\n</head>\n<body style=\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f5f5f5;\">\n\n <div style=\"background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);\">\n\n ${data.logoUrl ? `\n <div style=\"text-align: center; padding: 30px 20px 20px;\">\n <img src=\"${data.logoUrl}\" alt=\"Logo\" style=\"max-width: 150px; height: auto;\">\n </div>\n ` : ''}\n\n <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 30px; text-align: center;\">\n <h1 style=\"margin: 0 0 10px 0; font-size: 32px; font-weight: 600;\">Your Login Code</h1>\n <p style=\"margin: 0; opacity: 0.95; font-size: 16px;\">Enter this code to sign in to ${data.appName}</p>\n </div>\n\n <div style=\"padding: 40px 30px;\">\n <div style=\"background: #f8f9fa; border: 2px dashed #667eea; border-radius: 12px; padding: 30px; text-align: center; margin: 0 0 30px 0;\">\n <div style=\"font-size: 56px; font-weight: bold; letter-spacing: 12px; color: #667eea; font-family: 'Courier New', Courier, monospace; line-height: 1;\">\n ${data.code}\n </div>\n </div>\n\n <div style=\"background: #fff3cd; border-left: 4px solid #ffc107; padding: 16px 20px; margin: 0 0 30px 0; border-radius: 6px;\">\n <p style=\"margin: 0; font-size: 14px; color: #856404;\">\n <strong>⚠️ This code expires in ${data.expiryMinutes} minutes</strong>\n </p>\n </div>\n\n <div style=\"margin: 0 0 30px 0;\">\n <h3 style=\"color: #333; margin: 0 0 15px 0; font-size: 18px;\">Quick Tips:</h3>\n <ul style=\"color: #666; font-size: 14px; line-height: 1.8; margin: 0; padding-left: 20px;\">\n <li>Enter the code exactly as shown (${data.codeLength} digits)</li>\n <li>The code can only be used once</li>\n <li>You have ${data.maxAttempts} attempts to enter the correct code</li>\n <li>Request a new code if this one expires</li>\n </ul>\n </div>\n\n <div style=\"background: #e8f4ff; border-radius: 8px; padding: 20px; margin: 0 0 30px 0;\">\n <p style=\"margin: 0 0 10px 0; font-size: 14px; color: #0066cc; font-weight: 600;\">\n 🔒 Security Notice\n </p>\n <p style=\"margin: 0; font-size: 13px; color: #004080; line-height: 1.6;\">\n Never share this code with anyone. ${data.appName} will never ask you for this code via phone, email, or social media.\n </p>\n </div>\n </div>\n\n <div style=\"border-top: 1px solid #eee; padding: 30px; background: #f8f9fa;\">\n <p style=\"margin: 0 0 15px 0; font-size: 14px; color: #666; text-align: center;\">\n <strong>Didn't request this code?</strong><br>\n Someone may have entered your email by mistake. You can safely ignore this email.\n </p>\n\n <div style=\"text-align: center; color: #999; font-size: 12px; line-height: 1.6;\">\n <p style=\"margin: 5px 0;\">This email was sent to ${data.email}</p>\n ${data.ipAddress ? `<p style=\"margin: 5px 0;\">IP Address: ${data.ipAddress}</p>` : ''}\n <p style=\"margin: 5px 0;\">Time: ${data.timestamp}</p>\n </div>\n </div>\n\n </div>\n\n <div style=\"text-align: center; padding: 20px; color: #999; font-size: 12px;\">\n <p style=\"margin: 0;\">© ${new Date().getFullYear()} ${data.appName}. All rights reserved.</p>\n </div>\n\n</body>\n</html>`\n}\n\nexport function renderOTPEmailText(data: OTPEmailData): string {\n return `Your Login Code for ${data.appName}\n\nYour one-time verification code is:\n\n${data.code}\n\nThis code expires in ${data.expiryMinutes} minutes.\n\nQuick Tips:\n• Enter the code exactly as shown (${data.codeLength} digits)\n• The code can only be used once\n• You have ${data.maxAttempts} attempts to enter the correct code\n• Request a new code if this one expires\n\nSecurity Notice:\nNever share this code with anyone. ${data.appName} will never ask you for this code via phone, email, or social media.\n\nDidn't request this code?\nSomeone may have entered your email by mistake. You can safely ignore this email.\n\n---\nThis email was sent to ${data.email}\n${data.ipAddress ? `IP Address: ${data.ipAddress}` : ''}\nTime: ${data.timestamp}\n\n© ${new Date().getFullYear()} ${data.appName}. All rights reserved.`\n}\n\nexport function renderOTPEmail(data: OTPEmailData): { html: string; text: string } {\n return {\n html: renderOTPEmailHTML(data),\n text: renderOTPEmailText(data)\n }\n}\n","/**\n * OTP Login Plugin\n *\n * Passwordless authentication via email one-time codes\n * Users receive a secure 6-digit code to sign in without passwords\n */\n\nimport { Hono } from 'hono'\nimport { setCookie } from 'hono/cookie'\nimport { z } from 'zod'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\nimport { OTPService, type OTPSettings } from './otp-service'\nimport { renderOTPEmail } from './email-templates'\nimport { AuthManager } from '../../../middleware'\nimport { SettingsService } from '../../../services/settings'\n\n// Validation schemas\nconst otpRequestSchema = z.object({\n email: z.string().email('Valid email is required')\n})\n\nconst otpVerifySchema = z.object({\n email: z.string().email('Valid email is required'),\n code: z.string().min(4).max(8)\n})\n\n// Default settings (site name comes from general settings)\nconst DEFAULT_SETTINGS: OTPSettings = {\n codeLength: 6,\n codeExpiryMinutes: 10,\n maxAttempts: 3,\n rateLimitPerHour: 5,\n allowNewUserRegistration: false\n}\n\nexport function createOTPLoginPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'otp-login',\n version: '1.0.0-beta.1',\n description: 'Passwordless authentication via email one-time codes'\n })\n\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // ==================== API Routes ====================\n\n const otpAPI = new Hono()\n\n // POST /auth/otp/request - Request OTP code\n otpAPI.post('/request', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB\n const otpService = new OTPService(db)\n\n // Load plugin settings from database\n let settings: OTPSettings = { ...DEFAULT_SETTINGS }\n const pluginRow = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'otp-login'\n `).first() as { settings: string | null } | null\n if (pluginRow?.settings) {\n try {\n const savedSettings = JSON.parse(pluginRow.settings)\n settings = { ...DEFAULT_SETTINGS, ...savedSettings }\n } catch (e) {\n console.warn('Failed to parse OTP plugin settings, using defaults')\n }\n }\n\n // Get site name from general settings\n const settingsService = new SettingsService(db)\n const generalSettings = await settingsService.getGeneralSettings()\n const siteName = generalSettings.siteName\n\n // Check rate limiting\n const canRequest = await otpService.checkRateLimit(normalizedEmail, settings)\n if (!canRequest) {\n return c.json({\n error: 'Too many requests. Please try again in an hour.'\n }, 429)\n }\n\n // Check if user exists\n const user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n if (!user && !settings.allowNewUserRegistration) {\n // Don't reveal if user exists or not (security)\n return c.json({\n message: 'If an account exists for this email, you will receive a verification code shortly.',\n expiresIn: settings.codeExpiryMinutes * 60\n })\n }\n\n if (user && !user.is_active) {\n return c.json({\n error: 'This account has been deactivated.'\n }, 403)\n }\n\n // Get IP and user agent\n const ipAddress = c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown'\n const userAgent = c.req.header('user-agent') || 'unknown'\n\n // Create OTP code\n const otpCode = await otpService.createOTPCode(\n normalizedEmail,\n settings,\n ipAddress,\n userAgent\n )\n\n // Send email via Email plugin\n try {\n const isDevMode = c.env.ENVIRONMENT === 'development'\n\n if (isDevMode) {\n console.log(`[DEV] OTP Code for ${normalizedEmail}: ${otpCode.code}`)\n }\n\n // Prepare email content\n const emailContent = renderOTPEmail({\n code: otpCode.code,\n expiryMinutes: settings.codeExpiryMinutes,\n codeLength: settings.codeLength,\n maxAttempts: settings.maxAttempts,\n email: normalizedEmail,\n ipAddress,\n timestamp: new Date().toISOString(),\n appName: siteName,\n logoUrl: settings.logoUrl || ''\n })\n\n // Load email plugin settings from database\n // Note: We don't check status='active' because the email plugin's\n // settings UI works regardless of status, so we follow the same pattern\n const emailPlugin = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'email'\n `).first() as { settings: string | null } | null\n\n if (emailPlugin?.settings) {\n const emailSettings = JSON.parse(emailPlugin.settings)\n\n if (emailSettings.apiKey && emailSettings.fromEmail && emailSettings.fromName) {\n // Send email via Resend API\n const emailResponse = await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${emailSettings.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n from: `${emailSettings.fromName} <${emailSettings.fromEmail}>`,\n to: [normalizedEmail],\n subject: `Your login code for ${siteName}`,\n html: emailContent.html,\n text: emailContent.text,\n reply_to: emailSettings.replyTo || emailSettings.fromEmail\n })\n })\n\n if (!emailResponse.ok) {\n const errorData = await emailResponse.json() as { message?: string }\n console.error('Failed to send OTP email via Resend:', errorData)\n // Don't expose error to user for security - just log it\n }\n } else {\n console.warn('Email plugin is not fully configured (missing apiKey, fromEmail, or fromName)')\n }\n } else {\n console.warn('Email plugin is not active or has no settings configured')\n }\n\n const response: any = {\n message: 'If an account exists for this email, you will receive a verification code shortly.',\n expiresIn: settings.codeExpiryMinutes * 60\n }\n\n // In development, include the code\n if (isDevMode) {\n response.dev_code = otpCode.code\n }\n\n return c.json(response)\n } catch (emailError) {\n console.error('Error sending OTP email:', emailError)\n return c.json({\n error: 'Failed to send verification code. Please try again.'\n }, 500)\n }\n } catch (error) {\n console.error('OTP request error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // POST /auth/otp/verify - Verify OTP code\n otpAPI.post('/verify', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpVerifySchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email, code } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB\n const otpService = new OTPService(db)\n\n // Load plugin settings from database\n let settings = { ...DEFAULT_SETTINGS }\n const pluginRow = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'otp-login'\n `).first() as { settings: string | null } | null\n if (pluginRow?.settings) {\n try {\n const savedSettings = JSON.parse(pluginRow.settings)\n settings = { ...DEFAULT_SETTINGS, ...savedSettings }\n } catch (e) {\n console.warn('Failed to parse OTP plugin settings, using defaults')\n }\n }\n\n // Verify the code\n const verification = await otpService.verifyCode(normalizedEmail, code, settings)\n\n if (!verification.valid) {\n // Increment attempts on failure\n await otpService.incrementAttempts(normalizedEmail, code)\n\n return c.json({\n error: verification.error || 'Invalid code',\n attemptsRemaining: verification.attemptsRemaining\n }, 401)\n }\n\n // Code is valid - get user\n let user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n if (!user && settings.allowNewUserRegistration) {\n // Auto-create new user on first OTP verification\n const userId = crypto.randomUUID()\n const now = Date.now()\n const username = normalizedEmail.split('@')[0] + '_' + userId.slice(0, 6)\n\n await db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, is_active, email_verified, created_at, updated_at\n ) VALUES (?, ?, ?, '', '', NULL, 'viewer', 1, 1, ?, ?)\n `).bind(userId, normalizedEmail, username, now, now).run()\n\n user = { id: userId, email: normalizedEmail, role: 'viewer', is_active: 1 }\n }\n\n if (!user) {\n return c.json({\n error: 'User not found'\n }, 404)\n }\n\n if (!user.is_active) {\n return c.json({\n error: 'Account is deactivated'\n }, 403)\n }\n\n // Generate JWT token\n const token = await AuthManager.generateToken(user.id, user.email, user.role, (c.env as any).JWT_SECRET)\n\n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n\n return c.json({\n success: true,\n user: {\n id: user.id,\n email: user.email,\n role: user.role\n },\n token,\n message: 'Authentication successful'\n })\n } catch (error) {\n console.error('OTP verify error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // POST /auth/otp/resend - Resend OTP code\n otpAPI.post('/resend', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n // Reuse the request endpoint logic\n return otpAPI.fetch(\n new Request(c.req.url.replace('/resend', '/request'), {\n method: 'POST',\n headers: c.req.raw.headers,\n body: JSON.stringify({ email: validation.data.email })\n }),\n c.env\n )\n } catch (error) {\n console.error('OTP resend error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // Register API routes\n builder.addRoute('/auth/otp', otpAPI, {\n description: 'OTP authentication endpoints',\n requiresAuth: false,\n priority: 100\n })\n\n // Note: Admin UI is now handled by the generic plugin settings page\n // with custom component at admin-plugin-settings.template.ts\n\n // Add menu item (points to generic plugin settings page)\n builder.addMenuItem('OTP Login', '/admin/plugins/otp-login', {\n icon: 'key',\n order: 85,\n permissions: ['otp:manage']\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ OTP Login plugin activated')\n },\n deactivate: async () => {\n console.info('❌ OTP Login plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\nexport const otpLoginPlugin = createOTPLoginPlugin()\n","/**\n * OAuth Service\n * Handles OAuth2 authorization code flow, token exchange, and user info fetching.\n * Provider-agnostic — each provider is a simple config object.\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\n// ─── Provider Configuration ─────────────────────────────────────────────────\n\nexport interface OAuthProviderConfig {\n id: string\n name: string\n authorizeUrl: string\n tokenUrl: string\n userInfoUrl: string\n scopes: string[]\n /** Map provider profile JSON to a normalized user profile */\n mapProfile: (profile: Record<string, any>) => OAuthUserProfile\n}\n\nexport interface OAuthUserProfile {\n providerAccountId: string\n email: string\n name: string\n avatar?: string\n}\n\nexport interface OAuthPluginSettings {\n providers: Record<string, {\n clientId: string\n clientSecret: string\n enabled: boolean\n }>\n}\n\n// ─── Built-in Providers ─────────────────────────────────────────────────────\n\nexport const GITHUB_PROVIDER: OAuthProviderConfig = {\n id: 'github',\n name: 'GitHub',\n authorizeUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n userInfoUrl: 'https://api.github.com/user',\n scopes: ['read:user', 'user:email'],\n mapProfile: (profile) => ({\n providerAccountId: String(profile.id),\n email: profile.email || '',\n name: profile.name || profile.login || '',\n avatar: profile.avatar_url || undefined\n })\n}\n\nexport const GOOGLE_PROVIDER: OAuthProviderConfig = {\n id: 'google',\n name: 'Google',\n authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n userInfoUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n scopes: ['openid', 'email', 'profile'],\n mapProfile: (profile) => ({\n providerAccountId: String(profile.id),\n email: profile.email || '',\n name: profile.name || '',\n avatar: profile.picture || undefined\n })\n}\n\nexport const BUILT_IN_PROVIDERS: Record<string, OAuthProviderConfig> = {\n github: GITHUB_PROVIDER,\n google: GOOGLE_PROVIDER\n}\n\n// ─── OAuth Account DB Record ────────────────────────────────────────────────\n\nexport interface OAuthAccount {\n id: string\n user_id: string\n provider: string\n provider_account_id: string\n access_token: string | null\n refresh_token: string | null\n token_expires_at: number | null\n profile_data: string | null\n created_at: number\n updated_at: number\n}\n\n// ─── OAuth Service ──────────────────────────────────────────────────────────\n\nexport class OAuthService {\n constructor(private db: D1Database) {}\n\n /**\n * Build the authorization redirect URL for a provider.\n */\n buildAuthorizeUrl(\n provider: OAuthProviderConfig,\n clientId: string,\n redirectUri: string,\n state: string\n ): string {\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n scope: provider.scopes.join(' '),\n state\n })\n\n // Google requires access_type for refresh tokens\n if (provider.id === 'google') {\n params.set('access_type', 'offline')\n params.set('prompt', 'consent')\n }\n\n return `${provider.authorizeUrl}?${params.toString()}`\n }\n\n /**\n * Exchange authorization code for tokens using native fetch.\n */\n async exchangeCode(\n provider: OAuthProviderConfig,\n clientId: string,\n clientSecret: string,\n code: string,\n redirectUri: string\n ): Promise<{ access_token: string; refresh_token?: string; expires_in?: number }> {\n const body: Record<string, string> = {\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri,\n grant_type: 'authorization_code'\n }\n\n const response = await fetch(provider.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Accept': 'application/json'\n },\n body: new URLSearchParams(body).toString()\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Token exchange failed (${response.status}): ${errorText}`)\n }\n\n const data = await response.json() as Record<string, any>\n\n if (data.error) {\n throw new Error(`Token exchange error: ${data.error_description || data.error}`)\n }\n\n return {\n access_token: data.access_token,\n refresh_token: data.refresh_token,\n expires_in: data.expires_in ? Number(data.expires_in) : undefined\n }\n }\n\n /**\n * Fetch user profile from the provider's userinfo endpoint.\n */\n async fetchUserProfile(\n provider: OAuthProviderConfig,\n accessToken: string\n ): Promise<OAuthUserProfile> {\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${accessToken}`,\n 'Accept': 'application/json'\n }\n\n // GitHub uses a different auth header format\n if (provider.id === 'github') {\n headers['Authorization'] = `token ${accessToken}`\n }\n\n const response = await fetch(provider.userInfoUrl, { headers })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch user profile (${response.status})`)\n }\n\n const profile = await response.json() as Record<string, any>\n\n // For GitHub, email may not be in the profile — fetch from /user/emails\n if (provider.id === 'github' && !profile.email) {\n const emailResponse = await fetch('https://api.github.com/user/emails', {\n headers: {\n 'Authorization': `token ${accessToken}`,\n 'Accept': 'application/json'\n }\n })\n\n if (emailResponse.ok) {\n const emails = await emailResponse.json() as Array<{ email: string; primary: boolean; verified: boolean }>\n const primaryEmail = emails.find(e => e.primary && e.verified)\n if (primaryEmail) {\n profile.email = primaryEmail.email\n }\n }\n }\n\n return provider.mapProfile(profile)\n }\n\n // ─── Database Operations ────────────────────────────────────────────────\n\n /**\n * Find an existing OAuth account link.\n */\n async findOAuthAccount(\n provider: string,\n providerAccountId: string\n ): Promise<OAuthAccount | null> {\n return await this.db.prepare(`\n SELECT * FROM oauth_accounts\n WHERE provider = ? AND provider_account_id = ?\n `).bind(provider, providerAccountId).first() as OAuthAccount | null\n }\n\n /**\n * Find all OAuth accounts for a user.\n */\n async findUserOAuthAccounts(userId: string): Promise<OAuthAccount[]> {\n const result = await this.db.prepare(`\n SELECT * FROM oauth_accounts WHERE user_id = ?\n `).bind(userId).all()\n return (result.results || []) as unknown as OAuthAccount[]\n }\n\n /**\n * Create a new OAuth account link.\n */\n async createOAuthAccount(params: {\n userId: string\n provider: string\n providerAccountId: string\n accessToken: string\n refreshToken?: string\n tokenExpiresAt?: number\n profileData?: string\n }): Promise<OAuthAccount> {\n const id = crypto.randomUUID()\n const now = Date.now()\n\n await this.db.prepare(`\n INSERT INTO oauth_accounts (\n id, user_id, provider, provider_account_id,\n access_token, refresh_token, token_expires_at,\n profile_data, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n id,\n params.userId,\n params.provider,\n params.providerAccountId,\n params.accessToken,\n params.refreshToken || null,\n params.tokenExpiresAt || null,\n params.profileData || null,\n now,\n now\n ).run()\n\n return {\n id,\n user_id: params.userId,\n provider: params.provider,\n provider_account_id: params.providerAccountId,\n access_token: params.accessToken,\n refresh_token: params.refreshToken || null,\n token_expires_at: params.tokenExpiresAt || null,\n profile_data: params.profileData || null,\n created_at: now,\n updated_at: now\n }\n }\n\n /**\n * Update tokens for an existing OAuth account.\n */\n async updateOAuthTokens(\n id: string,\n accessToken: string,\n refreshToken?: string,\n tokenExpiresAt?: number\n ): Promise<void> {\n await this.db.prepare(`\n UPDATE oauth_accounts\n SET access_token = ?, refresh_token = ?, token_expires_at = ?, updated_at = ?\n WHERE id = ?\n `).bind(accessToken, refreshToken || null, tokenExpiresAt || null, Date.now(), id).run()\n }\n\n /**\n * Unlink an OAuth account from a user (only if they have another auth method).\n */\n async unlinkOAuthAccount(userId: string, provider: string): Promise<boolean> {\n // Check user has a password or another OAuth link before unlinking\n const user = await this.db.prepare(`\n SELECT password_hash FROM users WHERE id = ?\n `).bind(userId).first() as { password_hash: string | null } | null\n\n const otherLinks = await this.db.prepare(`\n SELECT COUNT(*) as count FROM oauth_accounts\n WHERE user_id = ? AND provider != ?\n `).bind(userId, provider).first() as { count: number } | null\n\n const hasPassword = !!user?.password_hash\n const hasOtherLinks = (otherLinks?.count || 0) > 0\n\n if (!hasPassword && !hasOtherLinks) {\n return false // Cannot unlink the only auth method\n }\n\n await this.db.prepare(`\n DELETE FROM oauth_accounts WHERE user_id = ? AND provider = ?\n `).bind(userId, provider).run()\n\n return true\n }\n\n /**\n * Find a user by email.\n */\n async findUserByEmail(email: string): Promise<{\n id: string\n email: string\n role: string\n is_active: number\n first_name: string\n last_name: string\n } | null> {\n return await this.db.prepare(`\n SELECT id, email, role, is_active, first_name, last_name\n FROM users WHERE email = ?\n `).bind(email.toLowerCase()).first() as any\n }\n\n /**\n * Create a new user from an OAuth profile.\n */\n async createUserFromOAuth(profile: OAuthUserProfile): Promise<string> {\n const id = crypto.randomUUID()\n const now = Date.now()\n const email = profile.email.toLowerCase()\n const nameParts = (profile.name || email.split('@')[0] || 'User').split(' ')\n const firstName = nameParts[0] || 'User'\n const lastName = nameParts.slice(1).join(' ') || ''\n const username = email.split('@')[0] || id.substring(0, 8)\n\n // Check for username collision and append random suffix if needed\n const existing = await this.db.prepare(\n 'SELECT id FROM users WHERE username = ?'\n ).bind(username).first()\n\n const finalUsername = existing\n ? `${username}-${id.substring(0, 6)}`\n : username\n\n await this.db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, avatar, is_active, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, NULL, 'viewer', ?, 1, ?, ?)\n `).bind(\n id, email, finalUsername, firstName, lastName,\n profile.avatar || null, now, now\n ).run()\n\n return id\n }\n\n /**\n * Generate a cryptographically random state parameter for CSRF protection.\n */\n generateState(): string {\n const bytes = new Uint8Array(32)\n crypto.getRandomValues(bytes)\n return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')\n }\n}\n","/**\n * OAuth Providers Plugin\n *\n * OAuth2/OIDC social login support for SonicJS.\n * Phase 1: Core OAuth2 authorization code flow with GitHub and Google providers.\n *\n * Routes:\n * GET /auth/oauth/:provider → Redirect to provider authorization\n * GET /auth/oauth/:provider/callback → Handle OAuth callback\n * POST /auth/oauth/link → Link OAuth provider to logged-in account\n * POST /auth/oauth/unlink → Unlink OAuth provider from account\n * GET /auth/oauth/accounts → List linked OAuth accounts for current user\n */\n\nimport { Hono } from 'hono'\nimport { setCookie, getCookie } from 'hono/cookie'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '../../types'\nimport {\n OAuthService,\n BUILT_IN_PROVIDERS,\n type OAuthPluginSettings,\n type OAuthProviderConfig\n} from './oauth-service'\nimport { AuthManager } from '../../../middleware'\n\nconst STATE_COOKIE_NAME = 'oauth_state'\nconst STATE_COOKIE_MAX_AGE = 600 // 10 minutes\n\nexport function createOAuthProvidersPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'oauth-providers',\n version: '1.0.0-beta.1',\n description: 'OAuth2/OIDC social login with GitHub, Google, and more'\n })\n\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // ==================== Helper Functions ====================\n\n function getCallbackUrl(c: any, provider: string): string {\n const proto = c.req.header('x-forwarded-proto') || 'https'\n const host = c.req.header('host') || 'localhost'\n return `${proto}://${host}/auth/oauth/${provider}/callback`\n }\n\n async function loadSettings(db: any): Promise<OAuthPluginSettings | null> {\n const row = await db.prepare(\n `SELECT settings FROM plugins WHERE id = 'oauth-providers'`\n ).first() as { settings: string | null } | null\n\n if (!row?.settings) return null\n\n try {\n return JSON.parse(row.settings) as OAuthPluginSettings\n } catch {\n return null\n }\n }\n\n function getProviderCredentials(\n settings: OAuthPluginSettings | null,\n providerId: string\n ): { clientId: string; clientSecret: string } | null {\n if (!settings?.providers?.[providerId]) return null\n const p = settings.providers[providerId]\n if (!p.enabled || !p.clientId || !p.clientSecret) return null\n return { clientId: p.clientId, clientSecret: p.clientSecret }\n }\n\n // ==================== API Routes ====================\n\n const oauthAPI = new Hono()\n\n // GET /auth/oauth/:provider — Redirect to provider authorization\n oauthAPI.get('/:provider', async (c: any) => {\n try {\n const providerId = c.req.param('provider')\n const providerConfig = BUILT_IN_PROVIDERS[providerId]\n\n if (!providerConfig) {\n return c.json({ error: `Unknown OAuth provider: ${providerId}` }, 400)\n }\n\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, providerId)\n\n if (!creds) {\n return c.json({\n error: `OAuth provider \"${providerId}\" is not configured or not enabled`\n }, 400)\n }\n\n const oauthService = new OAuthService(db)\n const state = oauthService.generateState()\n const redirectUri = getCallbackUrl(c, providerId)\n\n // Store state in a cookie for CSRF validation on callback\n setCookie(c, STATE_COOKIE_NAME, state, {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax', // Lax required for OAuth redirect flow\n maxAge: STATE_COOKIE_MAX_AGE,\n path: '/auth/oauth'\n })\n\n const authorizeUrl = oauthService.buildAuthorizeUrl(\n providerConfig,\n creds.clientId,\n redirectUri,\n state\n )\n\n return c.redirect(authorizeUrl)\n } catch (error) {\n console.error('OAuth authorize error:', error)\n return c.json({ error: 'Failed to initiate OAuth flow' }, 500)\n }\n })\n\n // GET /auth/oauth/:provider/callback — Handle OAuth callback\n oauthAPI.get('/:provider/callback', async (c: any) => {\n try {\n const providerId = c.req.param('provider')\n const providerConfig = BUILT_IN_PROVIDERS[providerId]\n\n if (!providerConfig) {\n return c.redirect('/auth/login?error=Unknown OAuth provider')\n }\n\n // Validate state (CSRF protection)\n const stateParam = c.req.query('state')\n const stateCookie = getCookie(c, STATE_COOKIE_NAME)\n\n if (!stateParam || !stateCookie || stateParam !== stateCookie) {\n return c.redirect('/auth/login?error=Invalid OAuth state. Please try again.')\n }\n\n // Clear the state cookie\n setCookie(c, STATE_COOKIE_NAME, '', {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax',\n maxAge: 0,\n path: '/auth/oauth'\n })\n\n // Check for error from provider\n const errorParam = c.req.query('error')\n if (errorParam) {\n const errorDesc = c.req.query('error_description') || errorParam\n return c.redirect(`/auth/login?error=${encodeURIComponent(errorDesc)}`)\n }\n\n const code = c.req.query('code')\n if (!code) {\n return c.redirect('/auth/login?error=No authorization code received')\n }\n\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, providerId)\n\n if (!creds) {\n return c.redirect('/auth/login?error=OAuth provider not configured')\n }\n\n const oauthService = new OAuthService(db)\n const redirectUri = getCallbackUrl(c, providerId)\n\n // Exchange code for tokens\n const tokens = await oauthService.exchangeCode(\n providerConfig,\n creds.clientId,\n creds.clientSecret,\n code,\n redirectUri\n )\n\n // Fetch user profile from provider\n const profile = await oauthService.fetchUserProfile(providerConfig, tokens.access_token)\n\n if (!profile.email) {\n return c.redirect('/auth/login?error=Could not retrieve email from OAuth provider. Please ensure your email is public or grant email permission.')\n }\n\n const tokenExpiresAt = tokens.expires_in\n ? Date.now() + (tokens.expires_in * 1000)\n : null\n\n // Check if this OAuth account is already linked to a user\n const existingOAuth = await oauthService.findOAuthAccount(providerId, profile.providerAccountId)\n\n if (existingOAuth) {\n // Existing OAuth link — update tokens and log in\n await oauthService.updateOAuthTokens(\n existingOAuth.id,\n tokens.access_token,\n tokens.refresh_token,\n tokenExpiresAt ?? undefined\n )\n\n // Fetch user to generate JWT\n const user = await db.prepare(\n 'SELECT id, email, role, is_active FROM users WHERE id = ?'\n ).bind(existingOAuth.user_id).first() as any\n\n if (!user || !user.is_active) {\n return c.redirect('/auth/login?error=Account is deactivated')\n }\n\n const jwt = await AuthManager.generateToken(\n user.id, user.email, user.role,\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n }\n\n // No existing OAuth link — check if user exists by email\n const existingUser = await oauthService.findUserByEmail(profile.email)\n\n if (existingUser) {\n if (!existingUser.is_active) {\n return c.redirect('/auth/login?error=Account is deactivated')\n }\n\n // Link OAuth to existing account\n await oauthService.createOAuthAccount({\n userId: existingUser.id,\n provider: providerId,\n providerAccountId: profile.providerAccountId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n tokenExpiresAt: tokenExpiresAt ?? undefined,\n profileData: JSON.stringify(profile)\n })\n\n const jwt = await AuthManager.generateToken(\n existingUser.id, existingUser.email, existingUser.role,\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n }\n\n // Brand new user — create account from OAuth profile\n const newUserId = await oauthService.createUserFromOAuth(profile)\n\n await oauthService.createOAuthAccount({\n userId: newUserId,\n provider: providerId,\n providerAccountId: profile.providerAccountId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n tokenExpiresAt: tokenExpiresAt ?? undefined,\n profileData: JSON.stringify(profile)\n })\n\n const jwt = await AuthManager.generateToken(\n newUserId, profile.email.toLowerCase(), 'viewer',\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n\n } catch (error) {\n console.error('OAuth callback error:', error)\n const message = error instanceof Error ? error.message : 'OAuth authentication failed'\n return c.redirect(`/auth/login?error=${encodeURIComponent(message)}`)\n }\n })\n\n // POST /auth/oauth/link — Link an OAuth provider to the current logged-in user\n oauthAPI.post('/link', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const body = await c.req.json()\n const { provider } = body\n\n if (!provider || !BUILT_IN_PROVIDERS[provider]) {\n return c.json({ error: 'Invalid provider' }, 400)\n }\n\n // Redirect the user to the OAuth flow — the callback will auto-link\n // since the user already exists by email\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, provider)\n\n if (!creds) {\n return c.json({ error: `OAuth provider \"${provider}\" is not configured` }, 400)\n }\n\n const oauthService = new OAuthService(db)\n const state = oauthService.generateState()\n const redirectUri = getCallbackUrl(c, provider)\n\n setCookie(c, STATE_COOKIE_NAME, state, {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax',\n maxAge: STATE_COOKIE_MAX_AGE,\n path: '/auth/oauth'\n })\n\n const authorizeUrl = oauthService.buildAuthorizeUrl(\n BUILT_IN_PROVIDERS[provider]!,\n creds.clientId,\n redirectUri,\n state\n )\n\n return c.json({ redirectUrl: authorizeUrl })\n } catch (error) {\n console.error('OAuth link error:', error)\n return c.json({ error: 'Failed to initiate account linking' }, 500)\n }\n })\n\n // POST /auth/oauth/unlink — Unlink an OAuth provider from the current user\n oauthAPI.post('/unlink', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const body = await c.req.json()\n const { provider } = body\n\n if (!provider) {\n return c.json({ error: 'Provider is required' }, 400)\n }\n\n const db = c.env.DB\n const oauthService = new OAuthService(db)\n const success = await oauthService.unlinkOAuthAccount(user.userId, provider)\n\n if (!success) {\n return c.json({\n error: 'Cannot unlink the only authentication method. Set a password first.'\n }, 400)\n }\n\n return c.json({ success: true, message: `${provider} account unlinked` })\n } catch (error) {\n console.error('OAuth unlink error:', error)\n return c.json({ error: 'Failed to unlink account' }, 500)\n }\n })\n\n // GET /auth/oauth/accounts — List linked OAuth accounts for current user\n oauthAPI.get('/accounts', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const db = c.env.DB\n const oauthService = new OAuthService(db)\n const accounts = await oauthService.findUserOAuthAccounts(user.userId)\n\n return c.json({\n accounts: accounts.map(a => ({\n provider: a.provider,\n providerAccountId: a.provider_account_id,\n linkedAt: a.created_at\n }))\n })\n } catch (error) {\n console.error('OAuth accounts error:', error)\n return c.json({ error: 'Failed to fetch linked accounts' }, 500)\n }\n })\n\n // Register routes\n builder.addRoute('/auth/oauth', oauthAPI, {\n description: 'OAuth2 social login endpoints',\n requiresAuth: false,\n priority: 100\n })\n\n // Add menu item for admin settings\n builder.addMenuItem('OAuth Providers', '/admin/plugins/oauth-providers', {\n icon: 'shield',\n order: 86,\n permissions: ['oauth:manage']\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ OAuth Providers plugin activated')\n },\n deactivate: async () => {\n console.info('❌ OAuth Providers plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\nexport const oauthProvidersPlugin = createOAuthProvidersPlugin()\n","/**\n * Embedding Service\n * Generates embeddings using Cloudflare Workers AI\n */\n\nexport class EmbeddingService {\n constructor(private ai: any) {}\n\n /**\n * Generate embedding for a single text\n */\n async generateEmbedding(text: string): Promise<number[]> {\n try {\n // Use Cloudflare Workers AI embedding model\n // @cf/baai/bge-base-en-v1.5 produces 768-dimensional vectors\n const response = await this.ai.run('@cf/baai/bge-base-en-v1.5', {\n text: this.preprocessText(text)\n })\n\n // Extract embedding vector\n if (response.data && response.data.length > 0) {\n return response.data[0]\n }\n\n throw new Error('No embedding data returned')\n } catch (error) {\n console.error('[EmbeddingService] Error generating embedding:', error)\n throw error\n }\n }\n\n /**\n * Generate embeddings for multiple texts (batch processing)\n */\n async generateBatch(texts: string[]): Promise<number[][]> {\n try {\n // Process in smaller batches to avoid rate limits\n const batchSize = 10\n const batches: string[][] = []\n \n for (let i = 0; i < texts.length; i += batchSize) {\n batches.push(texts.slice(i, i + batchSize))\n }\n\n const allEmbeddings: number[][] = []\n\n for (const batch of batches) {\n const batchEmbeddings = await Promise.all(\n batch.map(text => this.generateEmbedding(text))\n )\n allEmbeddings.push(...batchEmbeddings)\n }\n\n return allEmbeddings\n } catch (error) {\n console.error('[EmbeddingService] Error generating batch embeddings:', error)\n throw error\n }\n }\n\n /**\n * Preprocess text before generating embedding\n * - Trim whitespace\n * - Limit length to avoid token limits\n * - Remove special characters that might cause issues\n */\n private preprocessText(text: string): string {\n if (!text) return ''\n\n // Trim and normalize whitespace\n let processed = text.trim().replace(/\\s+/g, ' ')\n\n // Limit to ~8000 characters (rough token limit)\n if (processed.length > 8000) {\n processed = processed.substring(0, 8000)\n }\n\n return processed\n }\n\n /**\n * Calculate cosine similarity between two embeddings\n */\n cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error('Embeddings must have same dimensions')\n }\n\n let dotProduct = 0\n let normA = 0\n let normB = 0\n\n for (let i = 0; i < a.length; i++) {\n const aVal = a[i] ?? 0\n const bVal = b[i] ?? 0\n dotProduct += aVal * bVal\n normA += aVal * aVal\n normB += bVal * bVal\n }\n\n return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB))\n }\n}\n","/**\n * Chunking Service\n * Splits content into optimal chunks for embedding and search\n */\n\nexport interface ContentChunk {\n id: string\n content_id: string\n collection_id: string\n title: string\n text: string\n chunk_index: number\n metadata: Record<string, any>\n}\n\nexport class ChunkingService {\n // Default chunk size (in approximate tokens)\n private readonly CHUNK_SIZE = 500\n private readonly CHUNK_OVERLAP = 50\n\n /**\n * Chunk a single content item\n */\n chunkContent(\n contentId: string,\n collectionId: string,\n title: string,\n data: any,\n metadata: Record<string, any> = {}\n ): ContentChunk[] {\n // Extract all text from content\n const text = this.extractText(data)\n \n if (!text || text.trim().length === 0) {\n console.warn(`[ChunkingService] No text found for content ${contentId}`)\n return []\n }\n\n // Split into chunks\n const textChunks = this.splitIntoChunks(text)\n\n // Create chunk objects\n return textChunks.map((chunkText, index) => ({\n id: `${contentId}_chunk_${index}`,\n content_id: contentId,\n collection_id: collectionId,\n title: title,\n text: chunkText,\n chunk_index: index,\n metadata: {\n ...metadata,\n total_chunks: textChunks.length\n }\n }))\n }\n\n /**\n * Chunk multiple content items\n */\n chunkContentBatch(items: Array<{\n id: string\n collection_id: string\n title: string\n data: any\n metadata?: Record<string, any>\n }>): ContentChunk[] {\n const allChunks: ContentChunk[] = []\n\n for (const item of items) {\n const chunks = this.chunkContent(\n item.id,\n item.collection_id,\n item.title,\n item.data,\n item.metadata\n )\n allChunks.push(...chunks)\n }\n\n return allChunks\n }\n\n /**\n * Extract all text from content data\n */\n private extractText(data: any): string {\n const parts: string[] = []\n\n // Common text fields\n if (data.title) parts.push(String(data.title))\n if (data.name) parts.push(String(data.name))\n if (data.description) parts.push(String(data.description))\n if (data.content) parts.push(String(data.content))\n if (data.body) parts.push(String(data.body))\n if (data.text) parts.push(String(data.text))\n if (data.summary) parts.push(String(data.summary))\n\n // Recursively extract from nested objects\n const extractRecursive = (obj: any): void => {\n if (typeof obj === 'string') {\n // Skip very short strings and URLs\n if (obj.length > 10 && !obj.startsWith('http')) {\n parts.push(obj)\n }\n } else if (Array.isArray(obj)) {\n obj.forEach(extractRecursive)\n } else if (obj && typeof obj === 'object') {\n // Skip certain keys\n const skipKeys = ['id', 'slug', 'url', 'image', 'thumbnail', 'metadata']\n \n Object.entries(obj).forEach(([key, value]) => {\n if (!skipKeys.includes(key.toLowerCase())) {\n extractRecursive(value)\n }\n })\n }\n }\n\n extractRecursive(data)\n\n return parts.join('\\n\\n').trim()\n }\n\n /**\n * Split text into overlapping chunks\n */\n private splitIntoChunks(text: string): string[] {\n // Split by words\n const words = text.split(/\\s+/)\n \n if (words.length <= this.CHUNK_SIZE) {\n return [text]\n }\n\n const chunks: string[] = []\n let startIndex = 0\n\n while (startIndex < words.length) {\n // Get chunk with overlap\n const endIndex = Math.min(startIndex + this.CHUNK_SIZE, words.length)\n const chunk = words.slice(startIndex, endIndex).join(' ')\n chunks.push(chunk)\n\n // Move forward by chunk size minus overlap\n startIndex += this.CHUNK_SIZE - this.CHUNK_OVERLAP\n\n // Ensure we don't create a tiny last chunk\n if (startIndex >= words.length - this.CHUNK_OVERLAP) {\n break\n }\n }\n\n return chunks\n }\n\n /**\n * Get optimal chunk size based on content type\n */\n getOptimalChunkSize(contentType: string): number {\n switch (contentType) {\n case 'blog_posts':\n case 'articles':\n return 600 // Larger chunks for long-form content\n case 'products':\n case 'pages':\n return 400 // Medium chunks for structured content\n case 'messages':\n case 'comments':\n return 200 // Small chunks for short content\n default:\n return this.CHUNK_SIZE\n }\n }\n}\n","/**\n * Custom RAG Service\n * Implements full RAG pipeline using Cloudflare Vectorize\n * \n * Fulfills GitHub Issue #362: Advanced search with Cloudflare Search\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\nimport { EmbeddingService } from './embedding.service'\nimport { ChunkingService, type ContentChunk } from './chunking.service'\nimport type { SearchQuery, SearchResponse, SearchResult, AISearchSettings } from '../types'\n\nexport class CustomRAGService {\n private embeddingService: EmbeddingService\n private chunkingService: ChunkingService\n\n constructor(\n private db: D1Database,\n private ai: any,\n private vectorize: any\n ) {\n this.embeddingService = new EmbeddingService(ai)\n this.chunkingService = new ChunkingService()\n }\n\n /**\n * Index all content from a collection\n */\n async indexCollection(collectionId: string): Promise<{\n total_items: number\n total_chunks: number\n indexed_chunks: number\n errors: number\n }> {\n console.log(`[CustomRAG] Starting indexing for collection: ${collectionId}`)\n \n try {\n // Get all published content from collection\n const { results: contentItems } = await this.db\n .prepare(`\n SELECT c.id, c.title, c.data, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.collection_id = ? AND c.status = 'published'\n `)\n .bind(collectionId)\n .all<{\n id: string\n title: string\n data: string\n collection_id: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n const totalItems = contentItems?.length || 0\n \n if (totalItems === 0) {\n console.log(`[CustomRAG] No content found in collection ${collectionId}`)\n return { total_items: 0, total_chunks: 0, indexed_chunks: 0, errors: 0 }\n }\n\n // Chunk all content\n const items = (contentItems || []).map(item => ({\n id: item.id,\n collection_id: item.collection_id,\n title: item.title || 'Untitled',\n data: typeof item.data === 'string' ? JSON.parse(item.data) : item.data,\n metadata: {\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at,\n author_id: item.author_id,\n collection_name: item.collection_name,\n collection_display_name: item.collection_display_name\n }\n }))\n\n const chunks = this.chunkingService.chunkContentBatch(items)\n const totalChunks = chunks.length\n\n console.log(`[CustomRAG] Generated ${totalChunks} chunks from ${totalItems} items`)\n\n // Generate embeddings in batches\n const embeddings = await this.embeddingService.generateBatch(\n chunks.map(c => `${c.title}\\n\\n${c.text}`)\n )\n\n console.log(`[CustomRAG] Generated ${embeddings.length} embeddings`)\n\n // Store in Vectorize\n let indexedChunks = 0\n let errors = 0\n const batchSize = 100\n\n for (let i = 0; i < chunks.length; i += batchSize) {\n const chunkBatch = chunks.slice(i, i + batchSize)\n const embeddingBatch = embeddings.slice(i, i + batchSize)\n\n try {\n await this.vectorize.upsert(\n chunkBatch.map((chunk, idx) => ({\n id: chunk.id,\n values: embeddingBatch[idx],\n metadata: {\n content_id: chunk.content_id,\n collection_id: chunk.collection_id,\n title: chunk.title,\n text: chunk.text.substring(0, 500), // Store snippet for display\n chunk_index: chunk.chunk_index,\n ...chunk.metadata\n }\n }))\n )\n\n indexedChunks += chunkBatch.length\n console.log(`[CustomRAG] Indexed batch ${i / batchSize + 1}: ${chunkBatch.length} chunks`)\n } catch (error) {\n console.error(`[CustomRAG] Error indexing batch ${i / batchSize + 1}:`, error)\n errors += chunkBatch.length\n }\n }\n\n console.log(`[CustomRAG] Indexing complete: ${indexedChunks}/${totalChunks} chunks indexed`)\n\n return {\n total_items: totalItems,\n total_chunks: totalChunks,\n indexed_chunks: indexedChunks,\n errors\n }\n } catch (error) {\n console.error(`[CustomRAG] Error indexing collection ${collectionId}:`, error)\n throw error\n }\n }\n\n /**\n * Search using RAG (semantic search with Vectorize)\n */\n async search(query: SearchQuery, settings: AISearchSettings): Promise<SearchResponse> {\n const startTime = Date.now()\n\n try {\n console.log(`[CustomRAG] Searching for: \"${query.query}\"`)\n\n // Generate query embedding\n const queryEmbedding = await this.embeddingService.generateEmbedding(query.query)\n\n // Build Vectorize query filters\n const filter: any = {}\n \n if (query.filters?.collections && query.filters.collections.length > 0) {\n filter.collection_id = { $in: query.filters.collections }\n } else if (settings.selected_collections.length > 0) {\n filter.collection_id = { $in: settings.selected_collections }\n }\n\n if (query.filters?.status && query.filters.status.length > 0) {\n filter.status = { $in: query.filters.status }\n }\n\n // Vectorize filters have issues, so we query without filter and manually filter results\n const vectorResults = await this.vectorize.query(queryEmbedding, {\n topK: 50, // Max allowed with returnMetadata: true\n returnMetadata: true\n })\n\n // Manually filter results by collection_id if filter exists\n let filteredMatches = vectorResults.matches || []\n if (filter.collection_id?.$in && Array.isArray(filter.collection_id.$in)) {\n const allowedCollections = filter.collection_id.$in\n filteredMatches = filteredMatches.filter((match: any) => \n allowedCollections.includes(match.metadata?.collection_id)\n )\n }\n\n // Apply status filter if exists\n if (filter.status?.$in && Array.isArray(filter.status.$in)) {\n const allowedStatuses = filter.status.$in\n filteredMatches = filteredMatches.filter((match: any) => \n allowedStatuses.includes(match.metadata?.status)\n )\n }\n\n // Limit to requested topK\n const topK = query.limit || settings.results_limit || 20\n filteredMatches = filteredMatches.slice(0, topK)\n\n // Replace matches with filtered results\n vectorResults.matches = filteredMatches\n\n if (!vectorResults.matches || vectorResults.matches.length === 0) {\n return {\n results: [],\n total: 0,\n query_time_ms: Date.now() - startTime,\n mode: 'ai'\n }\n }\n\n // Get unique content IDs\n const contentIds = [...new Set(\n vectorResults.matches.map((m: any) => m.metadata.content_id)\n )]\n\n // Fetch full content from D1\n const placeholders = contentIds.map(() => '?').join(',')\n const { results: contentItems } = await this.db\n .prepare(`\n SELECT c.id, c.title, c.slug, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.display_name as collection_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id IN (${placeholders})\n `)\n .bind(...contentIds)\n .all<{\n id: string\n title: string\n slug: string\n collection_id: string\n collection_name: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n }>()\n\n // Map results with relevance scores\n const searchResults: SearchResult[] = (contentItems || []).map(item => {\n // Find best matching chunk for this content\n const matchingChunks = vectorResults.matches.filter(\n (m: any) => m.metadata.content_id === item.id\n )\n \n const bestMatch = matchingChunks.reduce((best: any, current: any) => \n current.score > (best?.score || 0) ? current : best\n , null)\n\n return {\n id: item.id,\n title: item.title || 'Untitled',\n slug: item.slug || '',\n collection_id: item.collection_id,\n collection_name: item.collection_name,\n snippet: bestMatch?.metadata?.text || '',\n relevance_score: bestMatch?.score || 0,\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at\n }\n })\n\n // Sort by relevance score\n searchResults.sort((a, b) => (b.relevance_score || 0) - (a.relevance_score || 0))\n\n const queryTime = Date.now() - startTime\n console.log(`[CustomRAG] Search completed in ${queryTime}ms, ${searchResults.length} results`)\n\n return {\n results: searchResults,\n total: searchResults.length,\n query_time_ms: queryTime,\n mode: 'ai'\n }\n } catch (error) {\n console.error('[CustomRAG] Search error:', error)\n throw error\n }\n }\n\n /**\n * Update index for a single content item\n */\n async updateContentIndex(contentId: string): Promise<void> {\n try {\n // Get content item\n const content = await this.db\n .prepare(`\n SELECT c.id, c.title, c.data, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id = ?\n `)\n .bind(contentId)\n .first<{\n id: string\n title: string\n data: string\n collection_id: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n if (!content) {\n console.warn(`[CustomRAG] Content ${contentId} not found`)\n return\n }\n\n // If content is not published, remove from index\n if (content.status !== 'published') {\n await this.removeContentFromIndex(contentId)\n return\n }\n\n // Chunk content\n const chunks = this.chunkingService.chunkContent(\n content.id,\n content.collection_id,\n content.title || 'Untitled',\n typeof content.data === 'string' ? JSON.parse(content.data) : content.data,\n {\n status: content.status,\n created_at: content.created_at,\n updated_at: content.updated_at,\n author_id: content.author_id,\n collection_name: content.collection_name,\n collection_display_name: content.collection_display_name\n }\n )\n\n // Generate embeddings\n const embeddings = await this.embeddingService.generateBatch(\n chunks.map(c => `${c.title}\\n\\n${c.text}`)\n )\n\n // Update in Vectorize\n await this.vectorize.upsert(\n chunks.map((chunk, idx) => ({\n id: chunk.id,\n values: embeddings[idx],\n metadata: {\n content_id: chunk.content_id,\n collection_id: chunk.collection_id,\n title: chunk.title,\n text: chunk.text.substring(0, 500),\n chunk_index: chunk.chunk_index,\n ...chunk.metadata\n }\n }))\n )\n\n console.log(`[CustomRAG] Updated index for content ${contentId}: ${chunks.length} chunks`)\n } catch (error) {\n console.error(`[CustomRAG] Error updating index for ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Remove content from index\n */\n async removeContentFromIndex(contentId: string): Promise<void> {\n try {\n // Note: Vectorize doesn't have a bulk delete by metadata filter\n // We need to delete each chunk individually\n // In practice, we would track chunk IDs or use a different approach\n \n console.log(`[CustomRAG] Removing content ${contentId} from index`)\n \n // For now, we'll let stale chunks age out\n // A better approach would be to maintain a mapping in D1\n // TODO: Implement proper chunk tracking\n \n } catch (error) {\n console.error(`[CustomRAG] Error removing content ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Get search suggestions based on query\n */\n async getSuggestions(partialQuery: string, limit: number = 5): Promise<string[]> {\n try {\n // Generate embedding for partial query\n const queryEmbedding = await this.embeddingService.generateEmbedding(partialQuery)\n\n // Search for similar content titles\n const results = await this.vectorize.query(queryEmbedding, {\n topK: limit * 2, // Get more to filter\n returnMetadata: true\n })\n\n // Extract unique titles\n const suggestions = [...new Set(\n results.matches?.map((m: any) => m.metadata.title).filter(Boolean) || []\n )].slice(0, limit)\n\n return suggestions as string[]\n } catch (error) {\n console.error('[CustomRAG] Error getting suggestions:', error)\n return []\n }\n }\n\n /**\n * Check if Vectorize is available and configured\n */\n isAvailable(): boolean {\n return !!this.vectorize && !!this.ai\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type {\n AISearchSettings,\n SearchQuery,\n SearchResponse,\n SearchResult,\n CollectionInfo,\n NewCollectionNotification,\n} from '../types'\nimport { CustomRAGService } from './custom-rag.service'\n\n/**\n * AI Search Service\n * Handles search operations, settings management, and collection detection\n * Now uses Custom RAG with Vectorize for semantic search\n */\nexport class AISearchService {\n private customRAG?: CustomRAGService\n\n constructor(\n private db: D1Database,\n private ai?: any, // Workers AI for embeddings\n private vectorize?: any // Vectorize for vector search\n ) {\n // Initialize Custom RAG if bindings are available\n if (this.ai && this.vectorize) {\n this.customRAG = new CustomRAGService(db, ai, vectorize)\n console.log('[AISearchService] Custom RAG initialized')\n } else {\n console.log('[AISearchService] Custom RAG not available, using keyword search only')\n }\n }\n\n /**\n * Get plugin settings\n */\n async getSettings(): Promise<AISearchSettings | null> {\n try {\n const plugin = await this.db\n .prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`)\n .bind('ai-search')\n .first<{ settings: string | null }>()\n\n if (!plugin || !plugin.settings) {\n return this.getDefaultSettings()\n }\n\n return JSON.parse(plugin.settings) as AISearchSettings\n } catch (error) {\n console.error('Error fetching AI Search settings:', error)\n return this.getDefaultSettings()\n }\n }\n\n /**\n * Get default settings\n */\n getDefaultSettings(): AISearchSettings {\n return {\n enabled: true,\n ai_mode_enabled: true,\n selected_collections: [],\n dismissed_collections: [],\n autocomplete_enabled: true,\n cache_duration: 1,\n results_limit: 20,\n index_media: false,\n }\n }\n\n /**\n * Update plugin settings\n */\n async updateSettings(settings: Partial<AISearchSettings>): Promise<AISearchSettings> {\n const existing = await this.getSettings()\n const updated: AISearchSettings = {\n ...existing!,\n ...settings,\n }\n\n try {\n // Update plugin settings in plugins table\n await this.db\n .prepare(`\n UPDATE plugins\n SET settings = ?,\n updated_at = unixepoch()\n WHERE id = 'ai-search'\n `)\n .bind(JSON.stringify(updated))\n .run()\n\n return updated\n } catch (error) {\n console.error('Error updating AI Search settings:', error)\n throw error\n }\n }\n\n /**\n * Detect new collections that aren't indexed or dismissed\n */\n async detectNewCollections(): Promise<NewCollectionNotification[]> {\n try {\n // Get all collections (exclude test collections)\n // Note: D1 doesn't support parameterized LIKE, so we filter in JavaScript\n const collectionsStmt = this.db.prepare(\n 'SELECT id, name, display_name, description FROM collections WHERE is_active = 1'\n )\n const { results: allCollections } = await collectionsStmt.all<{\n id: number\n name: string\n display_name: string\n description?: string\n }>()\n \n // Filter out test collections (starts with test_, ends with _test, or is test_collection)\n const collections = (allCollections || []).filter(\n (col) => {\n if (!col.name) return false\n const name = col.name.toLowerCase()\n return !name.startsWith('test_') && \n !name.endsWith('_test') && \n name !== 'test_collection' &&\n !name.includes('_test_') &&\n name !== 'large_payload_test' &&\n name !== 'concurrent_test'\n }\n )\n\n // Get settings\n const settings = await this.getSettings()\n const selected = settings?.selected_collections || []\n const dismissed = settings?.dismissed_collections || []\n\n // Get item counts for each collection\n const notifications: NewCollectionNotification[] = []\n\n for (const collection of collections || []) {\n const collectionId = String(collection.id)\n\n // Skip if already selected or dismissed\n if (selected.includes(collectionId) || dismissed.includes(collectionId)) {\n continue\n }\n\n // Get item count\n const countStmt = this.db.prepare(\n 'SELECT COUNT(*) as count FROM content WHERE collection_id = ?'\n )\n const countResult = await countStmt.bind(collectionId).first<{ count: number }>()\n const itemCount = countResult?.count || 0\n\n notifications.push({\n collection: {\n id: collectionId,\n name: collection.name,\n display_name: collection.display_name,\n description: collection.description,\n item_count: itemCount,\n is_indexed: false,\n is_dismissed: false,\n is_new: true,\n },\n message: `New collection \"${collection.display_name}\" with ${itemCount} items available for indexing`,\n })\n }\n\n return notifications\n } catch (error) {\n console.error('Error detecting new collections:', error)\n return []\n }\n }\n\n /**\n * Get all collections with indexing status\n */\n async getAllCollections(): Promise<CollectionInfo[]> {\n try {\n // Get all collections (same query as content page)\n const collectionsStmt = this.db.prepare(\n 'SELECT id, name, display_name, description FROM collections WHERE is_active = 1 ORDER BY display_name'\n )\n const { results: allCollections } = await collectionsStmt.all<{\n id: string\n name: string\n display_name: string\n description?: string\n }>()\n \n console.log('[AISearchService.getAllCollections] Raw collections from DB:', allCollections?.length || 0)\n const firstCollection = allCollections?.[0]\n if (firstCollection) {\n console.log('[AISearchService.getAllCollections] Sample collection:', {\n id: firstCollection.id,\n name: firstCollection.name,\n display_name: firstCollection.display_name\n })\n }\n \n // No filtering needed - test collections are now properly cleaned up by E2E tests\n const collections = (allCollections || []).filter(\n (col) => col.id && col.name\n )\n \n console.log('[AISearchService.getAllCollections] After filtering test collections:', collections.length)\n console.log('[AISearchService.getAllCollections] Remaining collections:', collections.map(c => c.name).join(', '))\n\n // Get settings\n const settings = await this.getSettings()\n const selected = settings?.selected_collections || []\n const dismissed = settings?.dismissed_collections || []\n \n console.log('[AISearchService.getAllCollections] Settings:', {\n selected_count: selected.length,\n dismissed_count: dismissed.length,\n selected: selected\n })\n\n // Get item counts and indexing status\n const collectionInfos: CollectionInfo[] = []\n\n for (const collection of collections) {\n if (!collection.id || !collection.name) continue\n const collectionId = String(collection.id)\n \n if (!collectionId) {\n console.warn('[AISearchService] Skipping invalid collection:', collection)\n continue\n }\n\n // Get item count\n const countStmt = this.db.prepare(\n 'SELECT COUNT(*) as count FROM content WHERE collection_id = ?'\n )\n const countResult = await countStmt.bind(collectionId).first<{ count: number }>()\n const itemCount = countResult?.count || 0\n\n collectionInfos.push({\n id: collectionId,\n name: collection.name,\n display_name: collection.display_name || collection.name,\n description: collection.description,\n item_count: itemCount,\n is_indexed: selected.includes(collectionId),\n is_dismissed: dismissed.includes(collectionId),\n is_new: !selected.includes(collectionId) && !dismissed.includes(collectionId),\n })\n }\n \n console.log('[AISearchService.getAllCollections] Returning collectionInfos:', collectionInfos.length)\n const firstInfo = collectionInfos[0]\n if (collectionInfos.length > 0 && firstInfo) {\n console.log('[AISearchService.getAllCollections] First collectionInfo:', {\n id: firstInfo.id,\n name: firstInfo.name,\n display_name: firstInfo.display_name,\n item_count: firstInfo.item_count\n })\n }\n return collectionInfos\n } catch (error) {\n console.error('[AISearchService] Error fetching collections:', error)\n return []\n }\n }\n\n /**\n * Execute search query\n */\n async search(query: SearchQuery): Promise<SearchResponse> {\n const startTime = Date.now()\n const settings = await this.getSettings()\n\n if (!settings?.enabled) {\n return {\n results: [],\n total: 0,\n query_time_ms: 0,\n mode: query.mode,\n }\n }\n\n // Use AI Search if enabled and mode is 'ai'\n if (query.mode === 'ai' && settings.ai_mode_enabled && this.customRAG?.isAvailable()) {\n return this.searchAI(query, settings)\n }\n\n // Fallback to keyword search\n return this.searchKeyword(query, settings)\n }\n\n /**\n * AI-powered semantic search using Custom RAG\n */\n private async searchAI(query: SearchQuery, settings: AISearchSettings): Promise<SearchResponse> {\n const startTime = Date.now()\n \n try {\n if (!this.customRAG) {\n console.warn('[AISearchService] CustomRAG not available, falling back to keyword search')\n return this.searchKeyword(query, settings)\n }\n\n // Use Custom RAG for semantic search - pass the full query object and settings\n const result = await this.customRAG.search(query, settings)\n\n return result\n } catch (error) {\n console.error('[AISearchService] AI search error, falling back to keyword:', error)\n // Fallback to keyword search\n return this.searchKeyword(query, settings)\n }\n }\n\n /**\n * Traditional keyword search\n */\n private async searchKeyword(\n query: SearchQuery,\n settings: AISearchSettings\n ): Promise<SearchResponse> {\n const startTime = Date.now()\n\n try {\n const conditions: string[] = []\n const params: any[] = []\n\n // Search query\n if (query.query) {\n conditions.push('(c.title LIKE ? OR c.slug LIKE ? OR c.data LIKE ?)')\n const searchTerm = `%${query.query}%`\n params.push(searchTerm, searchTerm, searchTerm)\n }\n\n // Collection filter\n if (query.filters?.collections && query.filters.collections.length > 0) {\n const placeholders = query.filters.collections.map(() => '?').join(',')\n conditions.push(`c.collection_id IN (${placeholders})`)\n params.push(...query.filters.collections)\n } else if (settings.selected_collections.length > 0) {\n // Only search indexed collections\n const placeholders = settings.selected_collections.map(() => '?').join(',')\n conditions.push(`c.collection_id IN (${placeholders})`)\n params.push(...settings.selected_collections)\n }\n\n // Status filter\n if (query.filters?.status && query.filters.status.length > 0) {\n const placeholders = query.filters.status.map(() => '?').join(',')\n conditions.push(`c.status IN (${placeholders})`)\n params.push(...query.filters.status)\n } else {\n // Exclude deleted by default\n conditions.push(\"c.status != 'deleted'\")\n }\n\n // Date range filter\n if (query.filters?.dateRange) {\n const field = query.filters.dateRange.field || 'created_at'\n if (query.filters.dateRange.start) {\n conditions.push(`c.${field} >= ?`)\n params.push(query.filters.dateRange.start.getTime())\n }\n if (query.filters.dateRange.end) {\n conditions.push(`c.${field} <= ?`)\n params.push(query.filters.dateRange.end.getTime())\n }\n }\n\n // Author filter\n if (query.filters?.author) {\n conditions.push('c.author_id = ?')\n params.push(query.filters.author)\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n // Get total count\n const countStmt = this.db.prepare(`\n SELECT COUNT(*) as count \n FROM content c\n ${whereClause}\n `)\n const countResult = await countStmt.bind(...params).first<{ count: number }>()\n const total = countResult?.count || 0\n\n // Get results\n const limit = query.limit || settings.results_limit\n const offset = query.offset || 0\n\n const resultsStmt = this.db.prepare(`\n SELECT \n c.id, c.title, c.slug, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id, c.data,\n col.name as collection_name, col.display_name as collection_display_name,\n u.email as author_email\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n LEFT JOIN users u ON c.author_id = u.id\n ${whereClause}\n ORDER BY c.updated_at DESC\n LIMIT ? OFFSET ?\n `)\n\n const { results } = await resultsStmt.bind(...params, limit, offset).all<{\n id: string\n title: string\n slug: string\n collection_id: number\n collection_name: string\n collection_display_name: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n author_email?: string\n data: string\n }>()\n\n const searchResults: SearchResult[] = (results || []).map((row) => ({\n id: String(row.id),\n title: row.title || 'Untitled',\n slug: row.slug || '',\n collection_id: String(row.collection_id),\n collection_name: row.collection_display_name || row.collection_name,\n snippet: this.extractSnippet(row.data, query.query),\n status: row.status,\n created_at: Number(row.created_at),\n updated_at: Number(row.updated_at),\n author_name: row.author_email,\n }))\n\n const queryTime = Date.now() - startTime\n\n // Log search history\n await this.logSearch(query.query, query.mode, searchResults.length)\n\n return {\n results: searchResults,\n total,\n query_time_ms: queryTime,\n mode: query.mode,\n }\n } catch (error) {\n console.error('Keyword search error:', error)\n return {\n results: [],\n total: 0,\n query_time_ms: Date.now() - startTime,\n mode: query.mode,\n }\n }\n }\n\n /**\n * Extract snippet from content data\n */\n private extractSnippet(data: string, query: string): string {\n try {\n const parsed = typeof data === 'string' ? JSON.parse(data) : data\n const text = JSON.stringify(parsed).toLowerCase()\n const queryLower = query.toLowerCase()\n\n const index = text.indexOf(queryLower)\n if (index === -1) {\n // Return first 200 chars\n return JSON.stringify(parsed).substring(0, 200) + '...'\n }\n\n // Extract context around match\n const start = Math.max(0, index - 50)\n const end = Math.min(text.length, index + query.length + 50)\n return text.substring(start, end) + '...'\n } catch {\n return data.substring(0, 200) + '...'\n }\n }\n\n /**\n * Get search suggestions (autocomplete)\n */\n async getSearchSuggestions(partial: string): Promise<string[]> {\n try {\n const settings = await this.getSettings()\n if (!settings?.autocomplete_enabled) {\n return []\n }\n\n // If Custom RAG is available, use AI-powered suggestions\n if (this.customRAG?.isAvailable()) {\n try {\n const aiSuggestions = await this.customRAG.getSuggestions(partial, 5)\n if (aiSuggestions.length > 0) {\n return aiSuggestions\n }\n } catch (error) {\n console.error('[AISearchService] Error getting AI suggestions:', error)\n // Fall through to history-based suggestions\n }\n }\n\n // Fallback to history-based suggestions\n const stmt = this.db.prepare(`\n SELECT DISTINCT query \n FROM ai_search_history \n WHERE query LIKE ? \n ORDER BY created_at DESC \n LIMIT 10\n `)\n const { results } = await stmt.bind(`%${partial}%`).all<{ query: string }>()\n\n return (results || []).map((r) => r.query)\n } catch (error) {\n console.error('Error getting suggestions:', error)\n return []\n }\n }\n\n /**\n * Log search query to history\n */\n private async logSearch(query: string, mode: 'ai' | 'keyword', resultsCount: number): Promise<void> {\n try {\n const stmt = this.db.prepare(`\n INSERT INTO ai_search_history (query, mode, results_count, created_at)\n VALUES (?, ?, ?, ?)\n `)\n await stmt.bind(query, mode, resultsCount, Date.now()).run()\n } catch (error) {\n console.error('Error logging search:', error)\n }\n }\n\n /**\n * Get search analytics\n */\n async getSearchAnalytics(): Promise<{\n total_queries: number\n ai_queries: number\n keyword_queries: number\n popular_queries: Array<{ query: string; count: number }>\n average_query_time: number\n }> {\n try {\n // Total queries (last 30 days)\n const totalStmt = this.db.prepare(`\n SELECT COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n `)\n const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000\n const totalResult = await totalStmt.bind(thirtyDaysAgo).first<{ count: number }>()\n\n // AI vs Keyword breakdown\n const modeStmt = this.db.prepare(`\n SELECT mode, COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n GROUP BY mode\n `)\n const { results: modeResults } = await modeStmt.bind(thirtyDaysAgo).all<{\n mode: string\n count: number\n }>()\n\n const aiCount = modeResults?.find((r) => r.mode === 'ai')?.count || 0\n const keywordCount = modeResults?.find((r) => r.mode === 'keyword')?.count || 0\n\n // Popular queries\n const popularStmt = this.db.prepare(`\n SELECT query, COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n GROUP BY query \n ORDER BY count DESC \n LIMIT 10\n `)\n const { results: popularResults } = await popularStmt.bind(thirtyDaysAgo).all<{\n query: string\n count: number\n }>()\n\n return {\n total_queries: totalResult?.count || 0,\n ai_queries: aiCount,\n keyword_queries: keywordCount,\n popular_queries: (popularResults || []).map((r) => ({\n query: r.query,\n count: r.count,\n })),\n average_query_time: 0, // TODO: Track query times\n }\n } catch (error) {\n console.error('Error getting analytics:', error)\n return {\n total_queries: 0,\n ai_queries: 0,\n keyword_queries: 0,\n popular_queries: [],\n average_query_time: 0,\n }\n }\n }\n\n /**\n * Verify Custom RAG is available\n */\n verifyBinding(): boolean {\n return this.customRAG?.isAvailable() ?? false\n }\n\n /**\n * Get Custom RAG service instance (for indexer)\n */\n getCustomRAG(): CustomRAGService | undefined {\n return this.customRAG\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type { AISearchSettings, IndexStatus } from '../types'\nimport { CustomRAGService } from './custom-rag.service'\n\n/**\n * Index Manager Service\n * Handles indexing of content items using Custom RAG with Vectorize\n */\nexport class IndexManager {\n private customRAG?: CustomRAGService\n\n constructor(\n private db: D1Database,\n private ai?: any, // Workers AI for embeddings\n private vectorize?: any // Vectorize for vector search\n ) {\n // Initialize Custom RAG if bindings are available\n if (this.ai && this.vectorize) {\n this.customRAG = new CustomRAGService(db, ai, vectorize)\n console.log('[IndexManager] Custom RAG initialized')\n }\n }\n\n /**\n * Index all content items within a collection using Custom RAG\n */\n async indexCollection(collectionId: string): Promise<IndexStatus> {\n try {\n // Get collection info\n const collectionStmt = this.db.prepare(\n 'SELECT id, name, display_name FROM collections WHERE id = ?'\n )\n const collection = await collectionStmt.bind(collectionId).first<{\n id: string\n name: string\n display_name: string\n }>()\n\n if (!collection) {\n throw new Error(`Collection ${collectionId} not found`)\n }\n\n // Update status to indexing\n await this.updateIndexStatus(collectionId, {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: 0,\n indexed_items: 0,\n status: 'indexing',\n })\n\n // Use Custom RAG for indexing if available\n if (this.customRAG?.isAvailable()) {\n console.log(`[IndexManager] Using Custom RAG to index collection ${collectionId}`)\n \n const result = await this.customRAG.indexCollection(collectionId)\n\n const finalStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: result.total_items,\n indexed_items: result.indexed_chunks,\n last_sync_at: Date.now(),\n status: result.errors > 0 ? 'error' : 'completed',\n error_message: result.errors > 0 ? `${result.errors} errors during indexing` : undefined\n }\n\n await this.updateIndexStatus(collectionId, finalStatus)\n return finalStatus\n }\n\n // Fallback: No indexing without Custom RAG\n console.warn(`[IndexManager] Custom RAG not available, skipping indexing for ${collectionId}`)\n \n const fallbackStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: 0,\n indexed_items: 0,\n last_sync_at: Date.now(),\n status: 'completed',\n error_message: 'Custom RAG not available - using keyword search only'\n }\n\n await this.updateIndexStatus(collectionId, fallbackStatus)\n return fallbackStatus\n } catch (error) {\n console.error(`[IndexManager] Error indexing collection ${collectionId}:`, error)\n const errorStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: 'Unknown',\n total_items: 0,\n indexed_items: 0,\n status: 'error',\n error_message: error instanceof Error ? error.message : String(error),\n }\n await this.updateIndexStatus(collectionId, errorStatus)\n return errorStatus\n }\n }\n\n /**\n * Index a single content item\n */\n private async indexContentItem(\n item: {\n id: string\n title: string\n slug: string\n data: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n },\n collectionId: string\n ): Promise<void> {\n try {\n // Parse content data\n let parsedData: any = {}\n try {\n parsedData = typeof item.data === 'string' ? JSON.parse(item.data) : item.data\n } catch {\n parsedData = {}\n }\n\n // Prepare document for AI Search\n const document = {\n id: `content_${item.id}`,\n title: item.title || 'Untitled',\n slug: item.slug || '',\n content: this.extractSearchableText(parsedData),\n metadata: {\n collection_id: collectionId,\n collection_name: item.collection_name,\n collection_display_name: item.collection_display_name,\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at,\n author_id: item.author_id,\n },\n }\n\n // TODO: Call Cloudflare AI Search API to index document\n // await this.aiSearch.index(document)\n\n // For now, just log (actual implementation will use AI Search API)\n console.log(`Indexed content item: ${item.id}`)\n } catch (error) {\n console.error(`Error indexing content item ${item.id}:`, error)\n throw error\n }\n }\n\n /**\n * Extract searchable text from content data\n */\n private extractSearchableText(data: any): string {\n const parts: string[] = []\n\n // Add title if present\n if (data.title) parts.push(String(data.title))\n if (data.name) parts.push(String(data.name))\n\n // Add description/content fields\n if (data.description) parts.push(String(data.description))\n if (data.content) parts.push(String(data.content))\n if (data.body) parts.push(String(data.body))\n if (data.text) parts.push(String(data.text))\n\n // Add all string values from data\n const extractStrings = (obj: any): void => {\n if (typeof obj === 'string') {\n parts.push(obj)\n } else if (Array.isArray(obj)) {\n obj.forEach(extractStrings)\n } else if (obj && typeof obj === 'object') {\n Object.values(obj).forEach(extractStrings)\n }\n }\n\n extractStrings(data)\n\n return parts.join(' ')\n }\n\n /**\n * Update a single content item in the index\n */\n async updateIndex(collectionId: number, contentId: string): Promise<void> {\n try {\n // Get content item\n const stmt = this.db.prepare(`\n SELECT \n c.id, c.title, c.slug, c.data, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id = ? AND c.collection_id = ?\n `)\n const item = await stmt.bind(contentId, collectionId).first<{\n id: string\n title: string\n slug: string\n data: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n if (!item) {\n throw new Error(`Content item ${contentId} not found`)\n }\n\n // Re-index the item\n await this.indexContentItem(item, String(collectionId))\n\n // Update last sync time for collection\n const status = await this.getIndexStatus(String(collectionId))\n if (status) {\n await this.updateIndexStatus(String(collectionId), {\n ...status,\n last_sync_at: Date.now(),\n })\n }\n } catch (error) {\n console.error(`Error updating index for content ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Remove a content item from the index using Custom RAG\n */\n async removeFromIndex(collectionId: string, contentId: string): Promise<void> {\n try {\n if (this.customRAG?.isAvailable()) {\n console.log(`[IndexManager] Removing content ${contentId} from index`)\n await this.customRAG.removeContentFromIndex(contentId)\n } else {\n console.warn(`[IndexManager] Custom RAG not available, skipping removal for ${contentId}`)\n }\n } catch (error) {\n console.error(`[IndexManager] Error removing content ${contentId} from index:`, error)\n throw error\n }\n }\n\n /**\n * Get indexing status for a collection\n */\n async getIndexStatus(collectionId: string): Promise<IndexStatus | null> {\n try {\n const stmt = this.db.prepare(\n 'SELECT * FROM ai_search_index_meta WHERE collection_id = ?'\n )\n const result = await stmt.bind(collectionId).first<{\n id: number\n collection_id: string\n collection_name: string\n total_items: number\n indexed_items: number\n last_sync_at?: number\n status: string\n error_message?: string\n }>()\n\n if (!result) {\n return null\n }\n\n return {\n collection_id: String(result.collection_id),\n collection_name: result.collection_name,\n total_items: result.total_items,\n indexed_items: result.indexed_items,\n last_sync_at: result.last_sync_at,\n status: result.status as IndexStatus['status'],\n error_message: result.error_message,\n }\n } catch (error) {\n console.error(`Error getting index status for collection ${collectionId}:`, error)\n return null\n }\n }\n\n /**\n * Get indexing status for all collections\n */\n async getAllIndexStatus(): Promise<Record<string, IndexStatus>> {\n try {\n const stmt = this.db.prepare('SELECT * FROM ai_search_index_meta')\n const { results } = await stmt.all<{\n id: number\n collection_id: number\n collection_name: string\n total_items: number\n indexed_items: number\n last_sync_at?: number\n status: string\n error_message?: string\n }>()\n\n const statusMap: Record<string, IndexStatus> = {}\n\n for (const row of results || []) {\n const collectionId = String(row.collection_id)\n statusMap[collectionId] = {\n collection_id: collectionId,\n collection_name: row.collection_name,\n total_items: row.total_items,\n indexed_items: row.indexed_items,\n last_sync_at: row.last_sync_at,\n status: row.status as IndexStatus['status'],\n error_message: row.error_message,\n }\n }\n\n return statusMap\n } catch (error) {\n console.error('Error getting all index status:', error)\n return {}\n }\n }\n\n /**\n * Update index status in database\n */\n private async updateIndexStatus(collectionId: string, status: IndexStatus): Promise<void> {\n try {\n // Check if record exists\n const checkStmt = this.db.prepare(\n 'SELECT id FROM ai_search_index_meta WHERE collection_id = ?'\n )\n const existing = await checkStmt.bind(collectionId).first<{ id: number }>()\n\n if (existing) {\n // Update existing\n const stmt = this.db.prepare(`\n UPDATE ai_search_index_meta \n SET collection_name = ?,\n total_items = ?,\n indexed_items = ?,\n last_sync_at = ?,\n status = ?,\n error_message = ?\n WHERE collection_id = ?\n `)\n await stmt\n .bind(\n status.collection_name,\n status.total_items,\n status.indexed_items,\n status.last_sync_at || null,\n status.status,\n status.error_message || null,\n String(collectionId)\n )\n .run()\n } else {\n // Insert new\n const stmt = this.db.prepare(`\n INSERT INTO ai_search_index_meta (\n collection_id, collection_name, total_items, indexed_items,\n last_sync_at, status, error_message\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n await stmt\n .bind(\n String(status.collection_id),\n status.collection_name,\n status.total_items,\n status.indexed_items,\n status.last_sync_at || null,\n status.status,\n status.error_message || null\n )\n .run()\n }\n } catch (error) {\n console.error(`Error updating index status for collection ${collectionId}:`, error)\n throw error\n }\n }\n\n /**\n * Sync all selected collections\n */\n async syncAll(selectedCollections: string[]): Promise<void> {\n for (const collectionId of selectedCollections) {\n try {\n await this.indexCollection(collectionId)\n } catch (error) {\n console.error(`Error syncing collection ${collectionId}:`, error)\n }\n }\n }\n}\n","import { renderAdminLayout } from '../../../../templates/layouts/admin-layout-v2.template'\nimport type {\n AISearchSettings,\n CollectionInfo,\n IndexStatus,\n NewCollectionNotification,\n} from '../types'\n\ninterface SettingsPageData {\n settings: AISearchSettings | null\n collections: CollectionInfo[]\n newCollections: NewCollectionNotification[]\n indexStatus: Record<number, IndexStatus>\n analytics: {\n total_queries: number\n ai_queries: number\n keyword_queries: number\n popular_queries: Array<{ query: string; count: number }>\n average_query_time: number\n }\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderSettingsPage(data: SettingsPageData): string {\n const settings = data.settings || {\n enabled: false,\n ai_mode_enabled: true,\n selected_collections: [],\n dismissed_collections: [],\n autocomplete_enabled: true,\n cache_duration: 1,\n results_limit: 20,\n index_media: false,\n }\n\n // Ensure arrays exist\n const selectedCollections = Array.isArray(settings.selected_collections) ? settings.selected_collections : []\n const dismissedCollections = Array.isArray(settings.dismissed_collections) ? settings.dismissed_collections : []\n\n const enabled = settings.enabled === true\n const aiModeEnabled = settings.ai_mode_enabled !== false\n const autocompleteEnabled = settings.autocomplete_enabled !== false\n const indexMedia = settings.index_media === true\n\n const selectedCollectionIds = new Set(selectedCollections.map(id => String(id)))\n const dismissedCollectionIds = new Set(dismissedCollections.map(id => String(id)))\n\n // Ensure collections array exists\n const collections = Array.isArray(data.collections) ? data.collections : []\n\n // Debug: Log collections in template\n console.log('[SettingsPage Template] Collections received:', collections.length)\n if (collections.length > 0) {\n console.log('[SettingsPage Template] First collection:', collections[0])\n }\n\n const content = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6\">\n <!-- Header with Back Button -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">🔍 AI Search Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Configure advanced search with Cloudflare AI Search. Select collections to index and manage search preferences.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/plugins\" class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\"/>\n </svg>\n Back to Plugins\n </a>\n </div>\n </div>\n\n\n <!-- Main Settings Card -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 mb-6\">\n <form id=\"settingsForm\" class=\"space-y-6\">\n <!-- Enable Search Section -->\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">🔍 Search Settings</h2>\n <div class=\"space-y-3\">\n <div class=\"flex items-center gap-3 p-4 border border-indigo-200 bg-indigo-50 dark:bg-indigo-900/20 rounded-lg\">\n <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" ${enabled ? 'checked' : ''} class=\"w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div class=\"flex-1\">\n <label for=\"enabled\" class=\"text-base font-semibold text-zinc-900 dark:text-white select-none cursor-pointer block\">Enable AI Search</label>\n <p class=\"text-xs text-zinc-600 dark:text-zinc-400 mt-0.5\">Turn on advanced search capabilities across your content</p>\n </div>\n </div>\n\n <div class=\"flex items-center gap-3 p-4 border border-blue-200 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\n <input type=\"checkbox\" id=\"ai_mode_enabled\" name=\"ai_mode_enabled\" ${aiModeEnabled ? 'checked' : ''} class=\"w-5 h-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer\">\n <div class=\"flex-1\">\n <label for=\"ai_mode_enabled\" class=\"text-base font-semibold text-zinc-900 dark:text-white select-none cursor-pointer block\">🤖 AI/Semantic Search</label>\n <p class=\"text-xs text-zinc-600 dark:text-zinc-400 mt-0.5\">\n Enable natural language queries (requires Cloudflare Workers AI binding)\n <a href=\"https://developers.cloudflare.com/workers-ai/\" target=\"_blank\" class=\"text-blue-600 dark:text-blue-400 hover:underline ml-1\">→ Setup Guide</a>\n </p>\n <p class=\"text-xs text-amber-600 dark:text-amber-400 mt-1\">\n ⚠️ If AI binding unavailable, will fallback to keyword search\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <hr class=\"border-zinc-200 dark:border-zinc-800\">\n\n <!-- Collections Section -->\n <div>\n <div class=\"flex items-start justify-between mb-4\">\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white\">📚 Collections to Index</h2>\n <p class=\"text-sm text-zinc-600 dark:text-zinc-400 mt-1\">\n Select which content collections should be indexed and searchable. Only checked collections will be included in search results.\n </p>\n </div>\n </div>\n <div class=\"space-y-3 max-h-96 overflow-y-auto border-2 border-zinc-300 dark:border-zinc-700 rounded-lg p-4 bg-white dark:bg-zinc-800\" id=\"collections-list\">\n ${collections.length === 0\n ? '<p class=\"text-sm text-zinc-500 dark:text-zinc-400 p-4\">No collections available. Create collections first.</p>'\n : collections.map((collection) => {\n const collectionId = String(collection.id)\n const isChecked = selectedCollectionIds.has(collectionId)\n const isDismissed = dismissedCollectionIds.has(collectionId)\n const indexStatusMap: Record<string, any> = data.indexStatus || {}\n const status = indexStatusMap[collectionId]\n // Only show NEW badge if collection is new, not dismissed, and has never been indexed\n const isNew = collection.is_new === true && !isDismissed && !status\n // Only show status badge if collection is CHECKED and has status\n const statusBadge = (status && isChecked)\n ? `<span class=\"ml-2 px-2 py-1 text-xs rounded-full ${status.status === 'completed'\n ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'\n : status.status === 'indexing'\n ? 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300'\n : status.status === 'error'\n ? 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'\n : 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300'\n }\">${status.status}</span>`\n : ''\n\n return `<div class=\"flex items-start gap-3 p-3 rounded-lg border border-zinc-200 dark:border-zinc-700 ${isNew ? 'bg-blue-50 dark:bg-blue-900/10 border-blue-200 dark:border-blue-800' : 'hover:bg-zinc-50 dark:hover:bg-zinc-800'}\">\n <input\n type=\"checkbox\"\n id=\"collection_${collectionId}\"\n name=\"selected_collections\"\n value=\"${collectionId}\"\n ${isChecked ? 'checked' : ''}\n class=\"mt-1 w-5 h-5 text-indigo-600 bg-white border-gray-300 rounded focus:ring-indigo-500 focus:ring-2 cursor-pointer\"\n style=\"cursor: pointer; flex-shrink: 0;\"\n />\n <div class=\"flex-1 min-w-0\">\n <label for=\"collection_${collectionId}\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer flex items-center\">\n ${collection.display_name || collection.name || 'Unnamed Collection'}\n ${isNew ? '<span class=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300\">NEW</span>' : ''}\n ${statusBadge}\n </label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n ${collection.description || collection.name || 'No description'} • ${collection.item_count || 0} items\n ${status ? ` • ${status.indexed_items}/${status.total_items} indexed` : ''}\n </p>\n ${status && status.status === 'indexing'\n ? `<div class=\"mt-2 w-full bg-gray-200 rounded-full h-2 dark:bg-gray-700\">\n <div class=\"bg-blue-600 h-2 rounded-full\" style=\"width: ${(status.indexed_items / status.total_items) * 100}%\"></div>\n </div>`\n : ''}\n </div>\n ${isChecked ? `\n <button\n type=\"button\"\n onclick=\"reindexCollection('${collectionId}')\"\n class=\"px-3 py-1.5 text-xs font-medium text-white bg-indigo-600 hover:bg-indigo-700 rounded-md transition-colors flex items-center gap-1.5 whitespace-nowrap\"\n ${status && status.status === 'indexing' ? 'disabled' : ''}\n >\n <svg class=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n Re-index\n </button>\n ` : ''}\n </div>`\n }).join('')}\n </div>\n </div>\n\n <hr class=\"border-zinc-200 dark:border-zinc-800\">\n\n <!-- Advanced Options -->\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">⚙️ Advanced Options</h2>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"flex items-start gap-3 p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg\">\n <input type=\"checkbox\" id=\"autocomplete_enabled\" name=\"autocomplete_enabled\" ${autocompleteEnabled ? 'checked' : ''} class=\"mt-0.5 w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div>\n <label for=\"autocomplete_enabled\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer block\">Autocomplete Suggestions</label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">Show search suggestions as users type</p>\n </div>\n </div>\n\n <div class=\"flex items-start gap-3 p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg\">\n <input type=\"checkbox\" id=\"index_media\" name=\"index_media\" ${indexMedia ? 'checked' : ''} class=\"mt-0.5 w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div>\n <label for=\"index_media\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer block\">Index Media Metadata</label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">Include media files in search results</p>\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Cache Duration (hours)</label>\n <input type=\"number\" id=\"cache_duration\" name=\"cache_duration\" value=\"${settings.cache_duration || 1}\" min=\"0\" max=\"24\" class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-indigo-500\">\n </div>\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Results Per Page</label>\n <input type=\"number\" id=\"results_limit\" name=\"results_limit\" value=\"${settings.results_limit || 20}\" min=\"10\" max=\"100\" class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-indigo-500\">\n </div>\n </div>\n </div>\n\n <!-- Save Button -->\n <div class=\"flex items-center justify-between pt-4 border-t border-zinc-200 dark:border-zinc-800\">\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">\n 💡 Collections marked as <span class=\"px-1.5 py-0.5 text-xs font-medium rounded-full bg-blue-500 text-white\">NEW</span> haven't been indexed yet\n </p>\n <button type=\"submit\" class=\"inline-flex items-center justify-center rounded-lg bg-indigo-600 text-white px-6 py-2.5 text-sm font-semibold hover:bg-indigo-500 shadow-sm transition-colors\">\n 💾 Save Settings\n </button>\n </div>\n </form>\n </div>\n\n\n <!-- Search Analytics -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">📊 Search Analytics</h2>\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">Total Queries</div>\n <div class=\"text-2xl font-bold text-zinc-950 dark:text-white mt-1\">${data.analytics.total_queries}</div>\n </div>\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">AI Queries</div>\n <div class=\"text-2xl font-bold text-blue-600 dark:text-blue-400 mt-1\">${data.analytics.ai_queries}</div>\n </div>\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">Keyword Queries</div>\n <div class=\"text-2xl font-bold text-indigo-600 dark:text-indigo-400 mt-1\">${data.analytics.keyword_queries}</div>\n </div>\n </div>\n ${data.analytics.popular_queries.length > 0\n ? `\n <div>\n <h3 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-2\">Popular Searches</h3>\n <div class=\"space-y-1\">\n ${data.analytics.popular_queries.map(\n (item) => `\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-700 dark:text-zinc-300\">\"${item.query}\"</span>\n <span class=\"text-zinc-500 dark:text-zinc-400\">${item.count} times</span>\n </div>\n `\n ).join('')}\n </div>\n </div>\n `\n : '<p class=\"text-sm text-zinc-500 dark:text-zinc-400\">No search history yet.</p>'}\n </div>\n\n <!-- Success Message -->\n <div id=\"msg\" class=\"hidden fixed bottom-4 right-4 p-4 rounded-lg bg-green-50 text-green-900 border border-green-200 dark:bg-green-900/20 dark:text-green-100 dark:border-green-800 shadow-lg z-50\">\n <div class=\"flex items-center gap-2\">\n <span class=\"text-xl\">✅</span>\n <span class=\"font-semibold\">Settings Saved Successfully!</span>\n </div>\n </div>\n </div>\n <script>\n // Form submission with error handling\n document.getElementById('settingsForm').addEventListener('submit', async (e) => {\n e.preventDefault();\n console.log('[AI Search Client] Form submitted');\n \n try {\n const btn = e.submitter;\n btn.innerText = 'Saving...'; \n btn.disabled = true;\n \n const formData = new FormData(e.target);\n const selectedCollections = Array.from(formData.getAll('selected_collections')).map(String);\n \n const data = {\n enabled: document.getElementById('enabled').checked,\n ai_mode_enabled: document.getElementById('ai_mode_enabled').checked,\n selected_collections: selectedCollections,\n autocomplete_enabled: document.getElementById('autocomplete_enabled').checked,\n cache_duration: Number(formData.get('cache_duration')),\n results_limit: Number(formData.get('results_limit')),\n index_media: document.getElementById('index_media').checked,\n };\n \n console.log('[AI Search Client] Sending data:', data);\n console.log('[AI Search Client] Selected collections:', selectedCollections);\n \n const res = await fetch('/admin/plugins/ai-search', { \n method: 'POST', \n headers: {'Content-Type': 'application/json'}, \n body: JSON.stringify(data) \n });\n \n console.log('[AI Search Client] Response status:', res.status);\n \n if (res.ok) {\n const result = await res.json();\n console.log('[AI Search Client] Save successful:', result);\n document.getElementById('msg').classList.remove('hidden'); \n setTimeout(() => {\n document.getElementById('msg').classList.add('hidden');\n location.reload();\n }, 2000); \n } else {\n const error = await res.text();\n console.error('[AI Search Client] Save failed:', error);\n alert('Failed to save settings: ' + error);\n }\n \n btn.innerText = 'Save Settings'; \n btn.disabled = false;\n } catch (error) {\n console.error('[AI Search Client] Error:', error);\n alert('Error saving settings: ' + error.message);\n }\n });\n\n // Add collection to index\n async function addCollectionToIndex(collectionId) {\n const form = document.getElementById('settingsForm');\n const checkbox = document.getElementById('collection_' + collectionId);\n if (checkbox) {\n checkbox.checked = true;\n form.dispatchEvent(new Event('submit'));\n }\n }\n\n // Dismiss collection\n async function dismissCollection(collectionId) {\n const res = await fetch('/admin/plugins/ai-search', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify({\n dismissed_collections: [collectionId]\n })\n });\n if (res.ok) {\n location.reload();\n }\n }\n\n // Re-index collection\n async function reindexCollection(collectionId) {\n const res = await fetch('/admin/plugins/ai-search/api/reindex', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify({ collection_id: collectionId })\n });\n if (res.ok) {\n alert('Re-indexing started. Page will refresh in a moment.');\n setTimeout(() => location.reload(), 2000);\n } else {\n alert('Failed to start re-indexing. Please try again.');\n }\n }\n\n // Poll for index status updates\n setInterval(async () => {\n const res = await fetch('/admin/plugins/ai-search/api/status');\n if (res.ok) {\n const { data } = await res.json();\n // Update status indicators if needed\n // For now, just reload every 30 seconds if indexing is in progress\n const hasIndexing = Object.values(data).some((s) => s.status === 'indexing');\n if (hasIndexing) {\n location.reload();\n }\n }\n }, 30000);\n </script>\n `\n\n return renderAdminLayout({\n title: 'AI Search Settings',\n pageTitle: 'AI Search Settings',\n currentPath: '/admin/plugins/ai-search/settings',\n user: data.user,\n content: content\n })\n}\n","import { Hono } from 'hono'\nimport type { Bindings } from '../../../../app'\nimport { requireAuth } from '../../../../middleware'\nimport { AISearchService } from '../services/ai-search'\nimport { IndexManager } from '../services/indexer'\nimport { renderSettingsPage } from '../components/settings-page'\nimport type { AISearchSettings, SearchQuery } from '../types'\n\ntype Variables = {\n user: {\n id: number\n email: string\n role: string\n }\n}\n\nconst adminRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminRoutes.use('*', requireAuth())\n\n/**\n * GET /admin/plugins/ai-search\n * Render settings page\n */\nadminRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const ai = (c.env as any).AI // Workers AI for embeddings\n const vectorize = (c.env as any).VECTORIZE_INDEX // Vectorize for vector search\n\n const service = new AISearchService(db, ai, vectorize)\n const indexer = new IndexManager(db, ai, vectorize)\n\n // Get settings\n const settings = await service.getSettings()\n console.log('[AI Search Settings Route] Settings loaded:', !!settings)\n\n // Get all collections with status\n const collections = await service.getAllCollections()\n console.log('[AI Search Settings Route] Collections returned:', collections.length)\n \n // If no collections, try direct query\n if (collections.length === 0) {\n const directQuery = await db.prepare('SELECT id, name, display_name FROM collections WHERE is_active = 1').all()\n console.log('[AI Search Settings Route] Direct DB query found:', directQuery.results?.length || 0, 'collections')\n if (directQuery.results && directQuery.results.length > 0) {\n console.log('[AI Search Settings Route] Sample from DB:', directQuery.results[0])\n }\n } else if (collections.length > 0 && collections[0]) {\n console.log('[AI Search Settings Route] First collection:', {\n id: collections[0].id,\n name: collections[0].name,\n display_name: collections[0].display_name\n })\n }\n\n // Get new collections notifications\n const newCollections = await service.detectNewCollections()\n console.log('AI Search: New collections:', newCollections.length)\n\n // Get index status for all collections\n const indexStatus = await indexer.getAllIndexStatus()\n console.log('AI Search: Index status:', Object.keys(indexStatus).length)\n\n // Get analytics\n const analytics = await service.getSearchAnalytics()\n\n return c.html(\n renderSettingsPage({\n settings,\n collections: collections || [],\n newCollections: newCollections || [],\n indexStatus: indexStatus || {},\n analytics,\n user: {\n name: user.email,\n email: user.email,\n role: user.role,\n },\n })\n )\n } catch (error) {\n console.error('Error rendering AI Search settings:', error)\n return c.html(`<p>Error loading settings: ${error instanceof Error ? error.message : String(error)}</p>`, 500)\n }\n})\n\n/**\n * POST /admin/plugins/ai-search\n * Update settings\n */\nadminRoutes.post('/', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n const indexer = new IndexManager(db, ai, vectorize)\n\n const body = await c.req.json()\n console.log('[AI Search POST] Received body:', JSON.stringify(body, null, 2))\n\n // Get current settings\n const currentSettings = await service.getSettings()\n console.log('[AI Search POST] Current settings selected_collections:', currentSettings?.selected_collections)\n\n // Update settings\n const updatedSettings: Partial<AISearchSettings> = {\n enabled: body.enabled !== undefined ? Boolean(body.enabled) : currentSettings?.enabled,\n ai_mode_enabled: body.ai_mode_enabled !== undefined ? Boolean(body.ai_mode_enabled) : currentSettings?.ai_mode_enabled,\n selected_collections: Array.isArray(body.selected_collections) ? body.selected_collections.map(String) : (currentSettings?.selected_collections || []),\n dismissed_collections: Array.isArray(body.dismissed_collections) ? body.dismissed_collections.map(String) : (currentSettings?.dismissed_collections || []),\n autocomplete_enabled: body.autocomplete_enabled !== undefined ? Boolean(body.autocomplete_enabled) : currentSettings?.autocomplete_enabled,\n cache_duration: body.cache_duration ? Number(body.cache_duration) : currentSettings?.cache_duration,\n results_limit: body.results_limit ? Number(body.results_limit) : currentSettings?.results_limit,\n index_media: body.index_media !== undefined ? Boolean(body.index_media) : currentSettings?.index_media,\n }\n\n console.log('[AI Search POST] Updated settings selected_collections:', updatedSettings.selected_collections)\n\n // If collections changed, trigger indexing\n const collectionsChanged =\n JSON.stringify(updatedSettings.selected_collections) !==\n JSON.stringify(currentSettings?.selected_collections || [])\n\n const saved = await service.updateSettings(updatedSettings)\n console.log('[AI Search POST] Settings saved, selected_collections:', saved.selected_collections)\n\n // Start indexing if collections were added\n if (collectionsChanged && updatedSettings.selected_collections) {\n console.log('[AI Search POST] Collections changed, starting background indexing')\n // Start indexing in background (non-blocking) - must use waitUntil to ensure it completes\n c.executionCtx.waitUntil(\n indexer\n .syncAll(updatedSettings.selected_collections)\n .then(() => console.log('[AI Search POST] Background indexing completed'))\n .catch((error) => console.error('[AI Search POST] Background indexing error:', error))\n )\n }\n\n return c.json({ success: true, settings: saved })\n } catch (error) {\n console.error('Error updating AI Search settings:', error)\n return c.json({ error: 'Failed to update settings' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/settings\n * Get settings API endpoint\n */\nadminRoutes.get('/api/settings', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const settings = await service.getSettings()\n return c.json({ success: true, data: settings })\n } catch (error) {\n console.error('Error fetching settings:', error)\n return c.json({ error: 'Failed to fetch settings' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/new-collections\n * Get new collections that aren't indexed or dismissed\n */\nadminRoutes.get('/api/new-collections', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const notifications = await service.detectNewCollections()\n return c.json({ success: true, data: notifications })\n } catch (error) {\n console.error('Error detecting new collections:', error)\n return c.json({ error: 'Failed to detect new collections' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/status\n * Get indexing status\n */\nadminRoutes.get('/api/status', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const indexer = new IndexManager(db, ai, vectorize)\n\n const status = await indexer.getAllIndexStatus()\n return c.json({ success: true, data: status })\n } catch (error) {\n console.error('Error fetching index status:', error)\n return c.json({ error: 'Failed to fetch status' }, 500)\n }\n})\n\n/**\n * POST /admin/api/ai-search/reindex\n * Trigger re-indexing for a collection\n */\nadminRoutes.post('/api/reindex', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const indexer = new IndexManager(db, ai, vectorize)\n\n const body = await c.req.json()\n const collectionIdRaw: unknown = body.collection_id\n const collectionId = collectionIdRaw ? String(collectionIdRaw) : ''\n\n if (!collectionId || collectionId === 'undefined' || collectionId === 'null') {\n return c.json({ error: 'collection_id is required' }, 400)\n }\n\n // Start indexing in background - must use waitUntil to ensure it completes\n c.executionCtx.waitUntil(\n indexer\n .indexCollection(collectionId)\n .then(() => console.log(`[AI Search Reindex] Completed for collection ${collectionId}`))\n .catch((error) => console.error(`[AI Search Reindex] Error for collection ${collectionId}:`, error))\n )\n\n return c.json({ success: true, message: 'Re-indexing started' })\n } catch (error) {\n console.error('Error starting re-index:', error)\n return c.json({ error: 'Failed to start re-indexing' }, 500)\n }\n})\n\nexport default adminRoutes\n","import { Hono } from 'hono'\nimport type { Bindings } from '../../../../app'\nimport { AISearchService } from '../services/ai-search'\nimport type { SearchQuery } from '../types'\n\ntype Variables = {\n user?: {\n id: number\n email: string\n role: string\n }\n}\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n/**\n * POST /api/search\n * Execute search query\n */\napiRoutes.post('/', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const body = await c.req.json()\n\n const query: SearchQuery = {\n query: body.query || '',\n mode: body.mode || 'keyword',\n filters: body.filters || {},\n limit: body.limit ? Number(body.limit) : undefined,\n offset: body.offset ? Number(body.offset) : undefined,\n }\n\n // Convert date strings to Date objects if present\n if (query.filters?.dateRange) {\n if (typeof query.filters.dateRange.start === 'string') {\n query.filters.dateRange.start = new Date(query.filters.dateRange.start)\n }\n if (typeof query.filters.dateRange.end === 'string') {\n query.filters.dateRange.end = new Date(query.filters.dateRange.end)\n }\n }\n\n const results = await service.search(query)\n\n return c.json({\n success: true,\n data: results,\n })\n } catch (error) {\n console.error('Search error:', error)\n return c.json(\n {\n success: false,\n error: 'Search failed',\n message: error instanceof Error ? error.message : String(error),\n },\n 500\n )\n }\n})\n\n/**\n * GET /api/search/suggest\n * Get search suggestions (autocomplete)\n */\napiRoutes.get('/suggest', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const query = c.req.query('q') || ''\n\n if (!query || query.length < 2) {\n return c.json({ success: true, data: [] })\n }\n\n const suggestions = await service.getSearchSuggestions(query)\n\n return c.json({\n success: true,\n data: suggestions,\n })\n } catch (error) {\n console.error('Suggestions error:', error)\n return c.json(\n {\n success: false,\n error: 'Failed to get suggestions',\n },\n 500\n )\n }\n})\n\n/**\n * GET /admin/api/search/analytics\n * Get search analytics\n */\napiRoutes.get('/analytics', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const analytics = await service.getSearchAnalytics()\n\n return c.json({\n success: true,\n data: analytics,\n })\n } catch (error) {\n console.error('Analytics error:', error)\n return c.json(\n {\n success: false,\n error: 'Failed to get analytics',\n },\n 500\n )\n }\n})\n\nexport default apiRoutes\n","{\n \"id\": \"ai-search\",\n \"name\": \"AI Search\",\n \"description\": \"Advanced search with Cloudflare AI Search. Full-text search, semantic search, and advanced filtering across all content collections.\",\n \"version\": \"1.0.0\",\n \"author\": \"SonicJS\",\n \"category\": \"content\",\n \"icon\": \"magnifying-glass\",\n \"homepage\": \"https://developers.cloudflare.com/ai-search/\",\n \"repository\": \"https://github.com/sonicjs/sonicjs\",\n \"license\": \"MIT\",\n \"permissions\": [\"settings:write\", \"admin:access\", \"content:read\"],\n \"dependencies\": [],\n \"configSchema\": {\n \"enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable AI Search\",\n \"description\": \"Enable or disable AI Search functionality\",\n \"default\": true\n },\n \"ai_mode_enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable AI/Semantic Search\",\n \"description\": \"Enable AI-powered semantic search (requires Cloudflare Workers AI binding)\",\n \"default\": false\n },\n \"ai_provider\": {\n \"type\": \"string\",\n \"label\": \"AI Provider\",\n \"description\": \"Which AI service to use for semantic search\",\n \"default\": \"cloudflare\",\n \"enum\": [\"cloudflare\", \"keyword-only\"]\n },\n \"autocomplete_enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable Autocomplete\",\n \"description\": \"Show search suggestions as user types\",\n \"default\": true\n },\n \"cache_duration\": {\n \"type\": \"number\",\n \"label\": \"Cache Duration (hours)\",\n \"description\": \"How long to cache search results\",\n \"default\": 1,\n \"min\": 0,\n \"max\": 24\n },\n \"results_limit\": {\n \"type\": \"number\",\n \"label\": \"Results Per Page\",\n \"description\": \"Maximum number of results to show per page\",\n \"default\": 20,\n \"min\": 10,\n \"max\": 100\n },\n \"index_media\": {\n \"type\": \"boolean\",\n \"label\": \"Index Media Metadata\",\n \"description\": \"Include R2 media files in search index\",\n \"default\": false\n }\n },\n \"adminMenu\": {\n \"label\": \"AI Search\",\n \"icon\": \"magnifying-glass\",\n \"href\": \"/admin/plugins/ai-search\",\n \"parentId\": \"plugins\",\n \"order\": 50\n }\n}\n","import { PluginBuilder } from '../../sdk/plugin-builder'\nimport { AISearchService } from './services/ai-search'\nimport { IndexManager } from './services/indexer'\nimport adminRoutes from './routes/admin'\nimport apiRoutes from './routes/api'\nimport manifest from './manifest.json'\n\n/**\n * AI Search Plugin\n * \n * Provides advanced search capabilities using Cloudflare AI Search.\n * Features:\n * - Semantic/AI-powered search with natural language queries\n * - Traditional keyword search\n * - Full-text search across all content collections\n * - Advanced filtering (collections, dates, status, tags)\n * - Autocomplete suggestions\n * - Search analytics\n * - Dynamic collection discovery and indexing\n * \n * @example\n * ```typescript\n * import { AISearchService } from '@sonicjs-cms/core/plugins'\n * \n * const service = new AISearchService(db, aiSearch)\n * const results = await service.search({\n * query: 'blog posts about security',\n * mode: 'ai',\n * filters: { collections: [1, 2] }\n * })\n * ```\n */\n\nexport const aiSearchPlugin = new PluginBuilder({\n name: manifest.name,\n version: manifest.version,\n description: manifest.description,\n author: { name: manifest.author },\n})\n .metadata({\n description: manifest.description,\n author: { name: manifest.author },\n })\n .addService('aiSearch', AISearchService)\n .addService('indexManager', IndexManager)\n .addRoute('/admin/plugins/ai-search', adminRoutes as any)\n .addRoute('/api/search', apiRoutes as any)\n .build()\n\n// Export services and types for easy import\nexport { AISearchService } from './services/ai-search'\nexport { IndexManager } from './services/indexer'\nexport type {\n AISearchSettings,\n SearchQuery,\n SearchResponse,\n SearchResult,\n CollectionInfo,\n IndexStatus,\n} from './types'\n","/**\n * Magic Link Authentication Plugin\n *\n * Provides passwordless authentication via email magic links\n * Users receive a secure one-time link to sign in without passwords\n */\n\nimport { Hono } from 'hono'\nimport { z } from 'zod'\nimport type { Plugin, PluginContext } from '../../types'\nimport type { D1Database } from '@cloudflare/workers-types'\nimport { AuthManager } from '../../../middleware/auth'\n\nconst magicLinkRequestSchema = z.object({\n email: z.string().email('Valid email is required')\n})\n\nexport function createMagicLinkAuthPlugin(): Plugin {\n const magicLinkRoutes = new Hono()\n\n // Request a magic link\n magicLinkRoutes.post('/request', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = magicLinkRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB as D1Database\n\n // Check rate limiting\n const oneHourAgo = Date.now() - (60 * 60 * 1000)\n const recentLinks = await db.prepare(`\n SELECT COUNT(*) as count\n FROM magic_links\n WHERE user_email = ? AND created_at > ?\n `).bind(normalizedEmail, oneHourAgo).first() as any\n\n const rateLimitPerHour = 5 // TODO: Get from plugin settings\n if (recentLinks && recentLinks.count >= rateLimitPerHour) {\n return c.json({\n error: 'Too many requests. Please try again later.'\n }, 429)\n }\n\n // Check if user exists\n const user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n const allowNewUsers = false // TODO: Get from plugin settings\n\n if (!user && !allowNewUsers) {\n // Don't reveal if user exists or not for security\n return c.json({\n message: 'If an account exists for this email, you will receive a magic link shortly.'\n })\n }\n\n if (user && !user.is_active) {\n return c.json({\n error: 'This account has been deactivated.'\n }, 403)\n }\n\n // Generate secure token\n const token = crypto.randomUUID() + '-' + crypto.randomUUID()\n const tokenId = crypto.randomUUID()\n const linkExpiryMinutes = 15 // TODO: Get from plugin settings\n const expiresAt = Date.now() + (linkExpiryMinutes * 60 * 1000)\n\n // Store magic link\n await db.prepare(`\n INSERT INTO magic_links (\n id, user_email, token, expires_at, used, created_at, ip_address, user_agent\n ) VALUES (?, ?, ?, ?, 0, ?, ?, ?)\n `).bind(\n tokenId,\n normalizedEmail,\n token,\n expiresAt,\n Date.now(),\n c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown',\n c.req.header('user-agent') || 'unknown'\n ).run()\n\n // Generate magic link URL\n const baseUrl = new URL(c.req.url).origin\n const magicLink = `${baseUrl}/auth/magic-link/verify?token=${token}`\n\n // Send email via email plugin\n try {\n const emailPlugin = c.env.plugins?.get('email')\n if (emailPlugin && emailPlugin.sendEmail) {\n await emailPlugin.sendEmail({\n to: normalizedEmail,\n subject: 'Your Magic Link to Sign In',\n html: renderMagicLinkEmail(magicLink, linkExpiryMinutes)\n })\n } else {\n console.error('Email plugin not available')\n // In production, this should fail. For now, log the link for testing\n console.log(`Magic link for ${normalizedEmail}: ${magicLink}`)\n }\n } catch (error) {\n console.error('Failed to send magic link email:', error)\n return c.json({\n error: 'Failed to send email. Please try again later.'\n }, 500)\n }\n\n return c.json({\n message: 'If an account exists for this email, you will receive a magic link shortly.',\n // For development only - remove in production\n ...(c.env.ENVIRONMENT === 'development' && { dev_link: magicLink })\n })\n } catch (error) {\n console.error('Magic link request error:', error)\n return c.json({ error: 'Failed to process request' }, 500)\n }\n })\n\n // Verify magic link and sign in\n magicLinkRoutes.get('/verify', async (c: any) => {\n try {\n const token = c.req.query('token')\n\n if (!token) {\n return c.redirect('/auth/login?error=Invalid magic link')\n }\n\n const db = c.env.DB as D1Database\n\n // Find magic link\n const magicLink = await db.prepare(`\n SELECT * FROM magic_links\n WHERE token = ? AND used = 0\n `).bind(token).first() as any\n\n if (!magicLink) {\n return c.redirect('/auth/login?error=Invalid or expired magic link')\n }\n\n // Check expiration\n if (magicLink.expires_at < Date.now()) {\n return c.redirect('/auth/login?error=This magic link has expired')\n }\n\n // Get or create user\n let user = await db.prepare(`\n SELECT * FROM users WHERE email = ? AND is_active = 1\n `).bind(magicLink.user_email).first() as any\n\n const allowNewUsers = false // TODO: Get from plugin settings\n\n if (!user && allowNewUsers) {\n // Create new user\n const userId = crypto.randomUUID()\n const username = magicLink.user_email.split('@')[0]\n const now = Date.now()\n\n await db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, is_active, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, NULL, 'viewer', 1, ?, ?)\n `).bind(\n userId,\n magicLink.user_email,\n username,\n username,\n '',\n now,\n now\n ).run()\n\n user = {\n id: userId,\n email: magicLink.user_email,\n username,\n role: 'viewer'\n }\n } else if (!user) {\n return c.redirect('/auth/login?error=No account found for this email')\n }\n\n // Mark magic link as used\n await db.prepare(`\n UPDATE magic_links\n SET used = 1, used_at = ?\n WHERE id = ?\n `).bind(Date.now(), magicLink.id).run()\n\n // Generate JWT token\n const jwtToken = await AuthManager.generateToken(\n user.id,\n user.email,\n user.role,\n (c.env as any).JWT_SECRET\n )\n\n // Set auth cookie\n AuthManager.setAuthCookie(c, jwtToken)\n\n // Update last login\n await db.prepare(`\n UPDATE users SET last_login_at = ? WHERE id = ?\n `).bind(Date.now(), user.id).run()\n\n // Redirect to admin dashboard\n return c.redirect('/admin/dashboard?message=Successfully signed in')\n } catch (error) {\n console.error('Magic link verification error:', error)\n return c.redirect('/auth/login?error=Authentication failed')\n }\n })\n\n return {\n name: 'magic-link-auth',\n version: '1.0.0',\n description: 'Passwordless authentication via email magic links',\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n dependencies: ['email'],\n\n routes: [{\n path: '/auth/magic-link',\n handler: magicLinkRoutes,\n description: 'Magic link authentication endpoints',\n requiresAuth: false\n }],\n\n async install(context: PluginContext) {\n console.log('Installing magic-link-auth plugin...')\n // Migration is handled by plugin system\n },\n\n async activate(context: PluginContext) {\n console.log('Magic link authentication activated')\n console.log('Users can now sign in via /auth/magic-link/request')\n },\n\n async deactivate(context: PluginContext) {\n console.log('Magic link authentication deactivated')\n },\n\n async uninstall(context: PluginContext) {\n console.log('Uninstalling magic-link-auth plugin...')\n // Optionally clean up magic_links table\n // await context.db.prepare('DROP TABLE IF EXISTS magic_links').run()\n }\n }\n}\n\n/**\n * Render magic link email template\n */\nfunction renderMagicLinkEmail(magicLink: string, expiryMinutes: number): string {\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Your Magic Link</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .container {\n background: #ffffff;\n border-radius: 8px;\n padding: 40px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .header {\n text-align: center;\n margin-bottom: 30px;\n }\n .header h1 {\n color: #0ea5e9;\n margin: 0;\n font-size: 24px;\n }\n .content {\n margin-bottom: 30px;\n }\n .button {\n display: inline-block;\n padding: 14px 32px;\n background: linear-gradient(135deg, #0ea5e9 0%, #06b6d4 100%);\n color: #ffffff !important;\n text-decoration: none;\n border-radius: 6px;\n font-weight: 600;\n text-align: center;\n margin: 20px 0;\n }\n .button:hover {\n opacity: 0.9;\n }\n .expiry {\n color: #ef4444;\n font-size: 14px;\n margin-top: 20px;\n }\n .footer {\n margin-top: 40px;\n padding-top: 20px;\n border-top: 1px solid #e5e7eb;\n font-size: 12px;\n color: #6b7280;\n text-align: center;\n }\n .security-note {\n background: #fef3c7;\n border-left: 4px solid #f59e0b;\n padding: 12px 16px;\n margin-top: 20px;\n border-radius: 4px;\n font-size: 14px;\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>🔗 Your Magic Link</h1>\n </div>\n\n <div class=\"content\">\n <p>Hello!</p>\n <p>You requested a magic link to sign in to your account. Click the button below to continue:</p>\n\n <div style=\"text-align: center;\">\n <a href=\"${magicLink}\" class=\"button\">Sign In</a>\n </div>\n\n <p class=\"expiry\">⏰ This link expires in ${expiryMinutes} minutes</p>\n\n <div class=\"security-note\">\n <strong>Security Notice:</strong> If you didn't request this link, you can safely ignore this email.\n Someone may have entered your email address by mistake.\n </div>\n </div>\n\n <div class=\"footer\">\n <p>This is an automated email from SonicJS.</p>\n <p>For security, this link can only be used once.</p>\n </div>\n </div>\n </body>\n </html>\n `\n}\n\nexport default createMagicLinkAuthPlugin()\n","export type SecurityEventType =\n | 'login_success'\n | 'login_failure'\n | 'registration'\n | 'password_reset_request'\n | 'password_reset_complete'\n | 'account_lockout'\n | 'suspicious_activity'\n | 'logout'\n | 'permission_denied'\n\nexport type SecuritySeverity = 'info' | 'warning' | 'critical'\n\nexport interface SecurityEvent {\n id: string\n eventType: SecurityEventType\n severity: SecuritySeverity\n userId?: string | null\n email?: string | null\n ipAddress?: string | null\n userAgent?: string | null\n countryCode?: string | null\n requestPath?: string | null\n requestMethod?: string | null\n details?: Record<string, any> | null\n fingerprint?: string | null\n blocked: boolean\n createdAt: number\n}\n\nexport interface SecurityEventInsert {\n eventType: SecurityEventType\n severity?: SecuritySeverity\n userId?: string\n email?: string\n ipAddress?: string\n userAgent?: string\n countryCode?: string\n requestPath?: string\n requestMethod?: string\n details?: Record<string, any>\n fingerprint?: string\n blocked?: boolean\n}\n\nexport interface SecurityEventFilters {\n eventType?: SecurityEventType | SecurityEventType[]\n severity?: SecuritySeverity | SecuritySeverity[]\n email?: string\n ipAddress?: string\n search?: string\n startDate?: number\n endDate?: number\n blocked?: boolean\n page?: number\n limit?: number\n sortBy?: 'created_at' | 'event_type' | 'severity'\n sortOrder?: 'asc' | 'desc'\n}\n\nexport interface SecurityStats {\n totalEvents: number\n failedLogins24h: number\n failedLoginsTrend: number // percentage change vs prior 24h\n activeLockouts: number\n flaggedIPs: number\n eventsByType: Record<string, number>\n eventsBySeverity: Record<string, number>\n}\n\nexport interface TopIP {\n ipAddress: string\n countryCode: string | null\n failedAttempts: number\n lastSeen: number\n locked: boolean\n}\n\nexport interface HourlyBucket {\n hour: string\n count: number\n}\n\nexport interface SecurityAuditSettings {\n retention: {\n daysToKeep: number\n maxEvents: number\n autoPurge: boolean\n }\n bruteForce: {\n enabled: boolean\n maxFailedAttemptsPerIP: number\n maxFailedAttemptsPerEmail: number\n windowMinutes: number\n lockoutDurationMinutes: number\n alertThreshold: number\n }\n logging: {\n logSuccessfulLogins: boolean\n logLogouts: boolean\n logRegistrations: boolean\n logPasswordResets: boolean\n logPermissionDenied: boolean\n }\n}\n\nexport const DEFAULT_SETTINGS: SecurityAuditSettings = {\n retention: {\n daysToKeep: 90,\n maxEvents: 100000,\n autoPurge: true\n },\n bruteForce: {\n enabled: true,\n maxFailedAttemptsPerIP: 10,\n maxFailedAttemptsPerEmail: 5,\n windowMinutes: 15,\n lockoutDurationMinutes: 30,\n alertThreshold: 20\n },\n logging: {\n logSuccessfulLogins: true,\n logLogouts: true,\n logRegistrations: true,\n logPasswordResets: true,\n logPermissionDenied: true\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type {\n SecurityEvent,\n SecurityEventInsert,\n SecurityEventFilters,\n SecurityStats,\n TopIP,\n HourlyBucket,\n SecurityAuditSettings\n} from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nexport class SecurityAuditService {\n constructor(\n private db: D1Database,\n private settings: SecurityAuditSettings = DEFAULT_SETTINGS\n ) {}\n\n async logEvent(event: SecurityEventInsert): Promise<string> {\n const id = crypto.randomUUID()\n const now = Date.now()\n\n await this.db.prepare(`\n INSERT INTO security_events (id, event_type, severity, user_id, email, ip_address, user_agent, country_code, request_path, request_method, details, fingerprint, blocked, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n id,\n event.eventType,\n event.severity || 'info',\n event.userId || null,\n event.email || null,\n event.ipAddress || null,\n event.userAgent || null,\n event.countryCode || null,\n event.requestPath || null,\n event.requestMethod || null,\n event.details ? JSON.stringify(event.details) : null,\n event.fingerprint || null,\n event.blocked ? 1 : 0,\n now\n ).run()\n\n return id\n }\n\n async getEvents(filters: SecurityEventFilters = {}): Promise<{ events: SecurityEvent[], total: number }> {\n const conditions: string[] = []\n const params: any[] = []\n\n if (filters.eventType) {\n if (Array.isArray(filters.eventType)) {\n conditions.push(`event_type IN (${filters.eventType.map(() => '?').join(',')})`)\n params.push(...filters.eventType)\n } else {\n conditions.push('event_type = ?')\n params.push(filters.eventType)\n }\n }\n\n if (filters.severity) {\n if (Array.isArray(filters.severity)) {\n conditions.push(`severity IN (${filters.severity.map(() => '?').join(',')})`)\n params.push(...filters.severity)\n } else {\n conditions.push('severity = ?')\n params.push(filters.severity)\n }\n }\n\n if (filters.email) {\n conditions.push('email LIKE ?')\n params.push(`%${filters.email}%`)\n }\n\n if (filters.ipAddress) {\n conditions.push('ip_address LIKE ?')\n params.push(`%${filters.ipAddress}%`)\n }\n\n if (filters.search) {\n conditions.push('(email LIKE ? OR ip_address LIKE ? OR details LIKE ?)')\n params.push(`%${filters.search}%`, `%${filters.search}%`, `%${filters.search}%`)\n }\n\n if (filters.startDate) {\n conditions.push('created_at >= ?')\n params.push(filters.startDate)\n }\n\n if (filters.endDate) {\n conditions.push('created_at <= ?')\n params.push(filters.endDate)\n }\n\n if (filters.blocked !== undefined) {\n conditions.push('blocked = ?')\n params.push(filters.blocked ? 1 : 0)\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const sortBy = filters.sortBy || 'created_at'\n const sortOrder = filters.sortOrder || 'desc'\n const page = filters.page || 1\n const limit = filters.limit || 50\n const offset = (page - 1) * limit\n\n // Get total count\n const countResult = await this.db.prepare(\n `SELECT COUNT(*) as count FROM security_events ${where}`\n ).bind(...params).first<{ count: number }>()\n const total = countResult?.count || 0\n\n // Get page of results\n const results = await this.db.prepare(\n `SELECT * FROM security_events ${where} ORDER BY ${sortBy} ${sortOrder} LIMIT ? OFFSET ?`\n ).bind(...params, limit, offset).all()\n\n const events: SecurityEvent[] = (results.results || []).map((row: any) => ({\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }))\n\n return { events, total }\n }\n\n async getEvent(id: string): Promise<SecurityEvent | null> {\n const row = await this.db.prepare(\n 'SELECT * FROM security_events WHERE id = ?'\n ).bind(id).first<any>()\n\n if (!row) return null\n\n return {\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }\n }\n\n async getStats(): Promise<SecurityStats> {\n const now = Date.now()\n const h24 = now - 24 * 60 * 60 * 1000\n const h48 = now - 48 * 60 * 60 * 1000\n\n // Total events\n const totalResult = await this.db.prepare(\n 'SELECT COUNT(*) as count FROM security_events'\n ).first<{ count: number }>()\n\n // Failed logins last 24h\n const failed24hResult = await this.db.prepare(\n \"SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ?\"\n ).bind(h24).first<{ count: number }>()\n\n // Failed logins prior 24h (for trend)\n const failedPrior24hResult = await this.db.prepare(\n \"SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ? AND created_at < ?\"\n ).bind(h48, h24).first<{ count: number }>()\n\n const failed24h = failed24hResult?.count || 0\n const failedPrior24h = failedPrior24hResult?.count || 0\n const trend = failedPrior24h > 0\n ? Math.round(((failed24h - failedPrior24h) / failedPrior24h) * 100)\n : (failed24h > 0 ? 100 : 0)\n\n // Active lockouts (events in last lockout window)\n const lockoutWindow = now - (this.settings.bruteForce.lockoutDurationMinutes * 60 * 1000)\n const lockoutsResult = await this.db.prepare(\n \"SELECT COUNT(DISTINCT ip_address) as count FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?\"\n ).bind(lockoutWindow).first<{ count: number }>()\n\n // Flagged IPs (IPs with more than threshold failed attempts in window)\n const windowStart = now - (this.settings.bruteForce.windowMinutes * 60 * 1000)\n const flaggedResult = await this.db.prepare(\n `SELECT COUNT(*) as count FROM (\n SELECT ip_address FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY ip_address HAVING COUNT(*) >= ?\n )`\n ).bind(windowStart, this.settings.bruteForce.maxFailedAttemptsPerIP).first<{ count: number }>()\n\n // Events by type\n const typeResults = await this.db.prepare(\n 'SELECT event_type, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY event_type'\n ).bind(h24).all()\n\n const eventsByType: Record<string, number> = {}\n for (const row of (typeResults.results || []) as any[]) {\n eventsByType[row.event_type] = row.count\n }\n\n // Events by severity\n const severityResults = await this.db.prepare(\n 'SELECT severity, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY severity'\n ).bind(h24).all()\n\n const eventsBySeverity: Record<string, number> = {}\n for (const row of (severityResults.results || []) as any[]) {\n eventsBySeverity[row.severity] = row.count\n }\n\n return {\n totalEvents: totalResult?.count || 0,\n failedLogins24h: failed24h,\n failedLoginsTrend: trend,\n activeLockouts: lockoutsResult?.count || 0,\n flaggedIPs: flaggedResult?.count || 0,\n eventsByType,\n eventsBySeverity\n }\n }\n\n async getTopIPs(limit: number = 10): Promise<TopIP[]> {\n const now = Date.now()\n const h24 = now - 24 * 60 * 60 * 1000\n\n const results = await this.db.prepare(`\n SELECT\n ip_address,\n country_code,\n COUNT(*) as failed_attempts,\n MAX(created_at) as last_seen\n FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY ip_address\n ORDER BY failed_attempts DESC\n LIMIT ?\n `).bind(h24, limit).all()\n\n // Check which IPs are locked\n const lockoutWindow = now - (this.settings.bruteForce.lockoutDurationMinutes * 60 * 1000)\n const lockoutResults = await this.db.prepare(\n \"SELECT DISTINCT ip_address FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?\"\n ).bind(lockoutWindow).all()\n\n const lockedIPs = new Set((lockoutResults.results || []).map((r: any) => r.ip_address))\n\n return (results.results || []).map((row: any) => ({\n ipAddress: row.ip_address,\n countryCode: row.country_code,\n failedAttempts: row.failed_attempts,\n lastSeen: row.last_seen,\n locked: lockedIPs.has(row.ip_address)\n }))\n }\n\n async getHourlyTrend(hours: number = 24): Promise<HourlyBucket[]> {\n const now = Date.now()\n const start = now - hours * 60 * 60 * 1000\n\n // Build hourly buckets\n const buckets: HourlyBucket[] = []\n for (let i = 0; i < hours; i++) {\n const bucketStart = start + i * 60 * 60 * 1000\n const date = new Date(bucketStart)\n buckets.push({\n hour: `${date.getUTCHours().toString().padStart(2, '0')}:00`,\n count: 0\n })\n }\n\n const results = await this.db.prepare(`\n SELECT\n CAST((created_at - ?) / 3600000 AS INTEGER) as bucket,\n COUNT(*) as count\n FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY bucket\n ORDER BY bucket\n `).bind(start, start).all()\n\n for (const row of (results.results || []) as any[]) {\n const idx = row.bucket\n if (idx >= 0 && idx < buckets.length) {\n buckets[idx]!.count = row.count\n }\n }\n\n return buckets\n }\n\n async purgeOldEvents(daysToKeep?: number): Promise<number> {\n const days = daysToKeep || this.settings.retention.daysToKeep\n const cutoff = Date.now() - days * 24 * 60 * 60 * 1000\n\n const result = await this.db.prepare(\n 'DELETE FROM security_events WHERE created_at < ?'\n ).bind(cutoff).run()\n\n return (result.meta as any)?.changes || 0\n }\n\n async getRecentCriticalEvents(limit: number = 20): Promise<SecurityEvent[]> {\n const results = await this.db.prepare(\n \"SELECT * FROM security_events WHERE severity = 'critical' ORDER BY created_at DESC LIMIT ?\"\n ).bind(limit).all()\n\n return (results.results || []).map((row: any) => ({\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }))\n }\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityStats, TopIP, HourlyBucket, SecurityEvent } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface SecurityDashboardData {\n stats: SecurityStats\n topIPs: TopIP[]\n hourlyTrend: HourlyBucket[]\n recentCritical: SecurityEvent[]\n user?: BaseUser\n version?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nfunction formatTimestamp(ts: number): string {\n const date = new Date(ts)\n const now = Date.now()\n const diff = now - ts\n\n if (diff < 60000) return 'just now'\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`\n return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n}\n\nfunction severityBadge(severity: string): string {\n const colors: Record<string, string> = {\n info: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n warning: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n critical: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'\n }\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}\">${severity}</span>`\n}\n\nfunction eventTypeBadge(type: string): string {\n const labels: Record<string, string> = {\n login_success: 'Login OK',\n login_failure: 'Login Failed',\n registration: 'Registration',\n account_lockout: 'Lockout',\n suspicious_activity: 'Suspicious',\n logout: 'Logout',\n password_reset_request: 'Password Reset',\n permission_denied: 'Access Denied'\n }\n return labels[type] || type\n}\n\nfunction trendArrow(trend: number): string {\n if (trend > 0) return `<span class=\"text-red-500\">+${trend}%</span>`\n if (trend < 0) return `<span class=\"text-emerald-500\">${trend}%</span>`\n return `<span class=\"text-zinc-400\">0%</span>`\n}\n\nfunction renderBarChart(data: HourlyBucket[]): string {\n if (data.length === 0) return '<p class=\"text-zinc-500 text-sm\">No data available</p>'\n\n const max = Math.max(...data.map(d => d.count), 1)\n\n const bars = data.map(d => {\n const height = Math.max((d.count / max) * 100, 2)\n const color = d.count === 0\n ? 'bg-zinc-200 dark:bg-zinc-700'\n : d.count >= max * 0.75\n ? 'bg-red-500'\n : d.count >= max * 0.5\n ? 'bg-amber-500'\n : 'bg-cyan-500'\n return `\n <div class=\"flex flex-col items-center flex-1 min-w-0 group relative\">\n <div class=\"w-full flex flex-col items-center justify-end\" style=\"height: 120px\">\n <div class=\"absolute bottom-8 hidden group-hover:block bg-zinc-900 text-white text-xs rounded px-2 py-1 whitespace-nowrap z-10\">\n ${d.hour}: ${d.count} failed\n </div>\n <div class=\"${color} w-full max-w-[12px] rounded-t transition-all\" style=\"height: ${height}%\"></div>\n </div>\n <span class=\"text-[9px] text-zinc-400 mt-1 ${data.length > 12 ? 'hidden sm:block' : ''}\">${d.hour}</span>\n </div>\n `\n }).join('')\n\n return `<div class=\"flex items-end gap-px\">${bars}</div>`\n}\n\nexport function renderSecurityDashboard(data: SecurityDashboardData): string {\n const { stats, topIPs, hourlyTrend, recentCritical, user, version, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Dashboard</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Monitor login attempts, brute-force detection, and security events.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit/events\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n View Event Log\n </a>\n <a href=\"/api/security-audit/export?format=csv\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n Export CSV\n </a>\n </div>\n </div>\n\n <!-- Summary Cards -->\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-6\">\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Total Events</p>\n <p class=\"mt-2 text-3xl font-bold text-zinc-950 dark:text-white\">${stats.totalEvents.toLocaleString()}</p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Failed Logins (24h)</p>\n <p class=\"mt-2 text-3xl font-bold text-zinc-950 dark:text-white\">\n ${stats.failedLogins24h}\n <span class=\"ml-2 text-sm font-normal\">${trendArrow(stats.failedLoginsTrend)}</span>\n </p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Active Lockouts</p>\n <p class=\"mt-2 text-3xl font-bold ${stats.activeLockouts > 0 ? 'text-red-600 dark:text-red-400' : 'text-zinc-950 dark:text-white'}\">${stats.activeLockouts}</p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Flagged IPs</p>\n <p class=\"mt-2 text-3xl font-bold ${stats.flaggedIPs > 0 ? 'text-amber-600 dark:text-amber-400' : 'text-zinc-950 dark:text-white'}\">${stats.flaggedIPs}</p>\n </div>\n </div>\n\n <!-- Charts Row -->\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6\">\n <!-- Failed Login Trend -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-4\">Failed Login Attempts (24h)</h2>\n ${renderBarChart(hourlyTrend)}\n </div>\n\n <!-- Events by Type -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-4\">Events by Type (24h)</h2>\n <div class=\"space-y-3\">\n ${Object.entries(stats.eventsByType).length === 0\n ? '<p class=\"text-zinc-500 text-sm\">No events in the last 24 hours</p>'\n : Object.entries(stats.eventsByType)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => {\n const total = Object.values(stats.eventsByType).reduce((s, v) => s + v, 0)\n const pct = total > 0 ? Math.round((count / total) * 100) : 0\n return `\n <div>\n <div class=\"flex justify-between text-sm mb-1\">\n <span class=\"text-zinc-600 dark:text-zinc-300\">${eventTypeBadge(type)}</span>\n <span class=\"text-zinc-500 dark:text-zinc-400\">${count}</span>\n </div>\n <div class=\"w-full bg-zinc-100 dark:bg-zinc-800 rounded-full h-1.5\">\n <div class=\"h-1.5 rounded-full ${type === 'login_failure' ? 'bg-red-500' : type === 'login_success' ? 'bg-emerald-500' : 'bg-cyan-500'}\" style=\"width: ${pct}%\"></div>\n </div>\n </div>\n `\n }).join('')\n }\n </div>\n </div>\n </div>\n\n <!-- Top IPs and Recent Critical -->\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <!-- Top IPs -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n <div class=\"p-5 border-b border-zinc-100 dark:border-zinc-800\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white\">Top IPs by Failed Logins (24h)</h2>\n </div>\n ${topIPs.length === 0\n ? '<div class=\"p-5\"><p class=\"text-zinc-500 text-sm\">No failed login attempts</p></div>'\n : `<table class=\"min-w-full\">\n <thead>\n <tr class=\"border-b border-zinc-100 dark:border-zinc-800\">\n <th class=\"px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase\">IP Address</th>\n <th class=\"px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase\">Country</th>\n <th class=\"px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase\">Attempts</th>\n <th class=\"px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase\">Status</th>\n </tr>\n </thead>\n <tbody>\n ${topIPs.map(ip => `\n <tr class=\"border-b border-zinc-50 dark:border-zinc-800/50 hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <td class=\"px-5 py-3 text-sm font-mono text-zinc-900 dark:text-zinc-100\">${ip.ipAddress}</td>\n <td class=\"px-5 py-3 text-sm text-zinc-600 dark:text-zinc-400\">${ip.countryCode || '-'}</td>\n <td class=\"px-5 py-3 text-sm text-right font-semibold ${ip.failedAttempts >= 10 ? 'text-red-600 dark:text-red-400' : 'text-zinc-900 dark:text-zinc-100'}\">${ip.failedAttempts}</td>\n <td class=\"px-5 py-3 text-sm text-right\">\n ${ip.locked\n ? '<span class=\"inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400\">Locked</span>'\n : '<span class=\"inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400\">Active</span>'\n }\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>`\n }\n </div>\n\n <!-- Recent Critical Events -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n <div class=\"p-5 border-b border-zinc-100 dark:border-zinc-800\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white\">Recent Critical Events</h2>\n </div>\n ${recentCritical.length === 0\n ? '<div class=\"p-5\"><p class=\"text-zinc-500 text-sm\">No critical events</p></div>'\n : `<div class=\"divide-y divide-zinc-100 dark:divide-zinc-800\">\n ${recentCritical.slice(0, 10).map(event => `\n <div class=\"px-5 py-3 hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-2\">\n ${severityBadge(event.severity)}\n <span class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100\">${eventTypeBadge(event.eventType)}</span>\n </div>\n <span class=\"text-xs text-zinc-400\">${formatTimestamp(event.createdAt)}</span>\n </div>\n <div class=\"mt-1 text-xs text-zinc-500 dark:text-zinc-400\">\n ${event.ipAddress ? `IP: ${event.ipAddress}` : ''}\n ${event.email ? ` | ${event.email}` : ''}\n </div>\n </div>\n `).join('')}\n </div>`\n }\n </div>\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Dashboard',\n pageTitle: 'Security Dashboard',\n currentPath: '/admin/plugins/security-audit',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityEvent, SecurityEventFilters } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface EventLogPageData {\n events: SecurityEvent[]\n pagination: {\n currentPage: number\n totalPages: number\n totalItems: number\n itemsPerPage: number\n startItem: number\n endItem: number\n }\n filters: SecurityEventFilters\n user?: BaseUser\n version?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nfunction formatTimestamp(ts: number): string {\n const date = new Date(ts)\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n })\n}\n\nfunction severityBadge(severity: string): string {\n const colors: Record<string, string> = {\n info: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n warning: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n critical: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'\n }\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}\">${severity}</span>`\n}\n\nfunction eventTypeBadge(type: string): string {\n const colors: Record<string, string> = {\n login_success: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',\n login_failure: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n registration: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n account_lockout: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n suspicious_activity: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',\n logout: 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400',\n password_reset_request: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n permission_denied: 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'\n }\n const labels: Record<string, string> = {\n login_success: 'Login OK',\n login_failure: 'Login Failed',\n registration: 'Registration',\n account_lockout: 'Lockout',\n suspicious_activity: 'Suspicious',\n logout: 'Logout',\n password_reset_request: 'Password Reset',\n permission_denied: 'Access Denied'\n }\n const color = colors[type] || 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400'\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${color}\">${labels[type] || type}</span>`\n}\n\nfunction buildFilterUrl(filters: SecurityEventFilters, overrides: Record<string, string> = {}): string {\n const params = new URLSearchParams()\n if (filters.eventType && !overrides.type) params.set('type', String(filters.eventType))\n if (filters.severity && !overrides.severity) params.set('severity', String(filters.severity))\n if (filters.email && !overrides.email) params.set('email', filters.email)\n if (filters.ipAddress && !overrides.ip) params.set('ip', filters.ipAddress)\n if (filters.search && !overrides.search) params.set('search', filters.search)\n\n for (const [key, value] of Object.entries(overrides)) {\n if (value) params.set(key, value)\n }\n\n const qs = params.toString()\n return `/admin/plugins/security-audit/events${qs ? '?' + qs : ''}`\n}\n\nexport function renderEventLogPage(data: EventLogPageData): string {\n const { events, pagination, filters, user, version, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Event Log</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Browse and filter all security events. Showing ${pagination.startItem}-${pagination.endItem} of ${pagination.totalItems}.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n Dashboard\n </a>\n </div>\n </div>\n\n <!-- Filters -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm mb-6\">\n <form method=\"GET\" action=\"/admin/plugins/security-audit/events\" class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4\">\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Event Type</label>\n <select name=\"type\" class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <option value=\"\">All Types</option>\n <option value=\"login_success\" ${filters.eventType === 'login_success' ? 'selected' : ''}>Login Success</option>\n <option value=\"login_failure\" ${filters.eventType === 'login_failure' ? 'selected' : ''}>Login Failure</option>\n <option value=\"registration\" ${filters.eventType === 'registration' ? 'selected' : ''}>Registration</option>\n <option value=\"account_lockout\" ${filters.eventType === 'account_lockout' ? 'selected' : ''}>Account Lockout</option>\n <option value=\"suspicious_activity\" ${filters.eventType === 'suspicious_activity' ? 'selected' : ''}>Suspicious Activity</option>\n <option value=\"logout\" ${filters.eventType === 'logout' ? 'selected' : ''}>Logout</option>\n </select>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Severity</label>\n <select name=\"severity\" class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <option value=\"\">All Severities</option>\n <option value=\"info\" ${filters.severity === 'info' ? 'selected' : ''}>Info</option>\n <option value=\"warning\" ${filters.severity === 'warning' ? 'selected' : ''}>Warning</option>\n <option value=\"critical\" ${filters.severity === 'critical' ? 'selected' : ''}>Critical</option>\n </select>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Email</label>\n <input type=\"text\" name=\"email\" value=\"${filters.email || ''}\" placeholder=\"Filter by email\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">IP Address</label>\n <input type=\"text\" name=\"ip\" value=\"${filters.ipAddress || ''}\" placeholder=\"Filter by IP\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400\">\n </div>\n <div class=\"flex items-end gap-2\">\n <button type=\"submit\"\n class=\"flex-1 rounded-lg bg-cyan-600 px-3 py-2 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm\">\n Filter\n </button>\n <a href=\"/admin/plugins/security-audit/events\"\n class=\"rounded-lg bg-zinc-100 dark:bg-zinc-800 px-3 py-2 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors\">\n Clear\n </a>\n </div>\n </form>\n </div>\n\n <!-- Events Table -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n ${events.length === 0\n ? `<div class=\"p-12 text-center\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"/>\n </svg>\n <h3 class=\"mt-2 text-sm font-semibold text-zinc-900 dark:text-white\">No events found</h3>\n <p class=\"mt-1 text-sm text-zinc-500\">No security events match your current filters.</p>\n </div>`\n : `<div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-200 dark:divide-zinc-800\">\n <thead>\n <tr>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Time</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Type</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Severity</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Email</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">IP Address</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Country</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Status</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-100 dark:divide-zinc-800\">\n ${events.map(event => `\n <tr class=\"hover:bg-zinc-50 dark:hover:bg-zinc-800/50 cursor-pointer\" onclick=\"this.querySelector('.event-details').classList.toggle('hidden')\">\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 whitespace-nowrap\">${formatTimestamp(event.createdAt)}</td>\n <td class=\"px-4 py-3\">${eventTypeBadge(event.eventType)}</td>\n <td class=\"px-4 py-3\">${severityBadge(event.severity)}</td>\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 max-w-[200px] truncate\">${event.email || '-'}</td>\n <td class=\"px-4 py-3 text-sm font-mono text-zinc-600 dark:text-zinc-300\">${event.ipAddress || '-'}</td>\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300\">${event.countryCode || '-'}</td>\n <td class=\"px-4 py-3\">\n ${event.blocked\n ? '<span class=\"inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400\">Blocked</span>'\n : '<span class=\"inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400\">Allowed</span>'\n }\n </td>\n </tr>\n <tr class=\"event-details hidden\">\n <td colspan=\"7\" class=\"px-4 py-3 bg-zinc-50 dark:bg-zinc-800/30\">\n <div class=\"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs\">\n <div><span class=\"font-medium text-zinc-500\">Event ID:</span> <span class=\"text-zinc-700 dark:text-zinc-300 font-mono\">${event.id.substring(0, 8)}...</span></div>\n <div><span class=\"font-medium text-zinc-500\">User Agent:</span> <span class=\"text-zinc-700 dark:text-zinc-300 truncate block max-w-[300px]\">${event.userAgent || '-'}</span></div>\n <div><span class=\"font-medium text-zinc-500\">Path:</span> <span class=\"text-zinc-700 dark:text-zinc-300\">${event.requestPath || '-'}</span></div>\n <div><span class=\"font-medium text-zinc-500\">Fingerprint:</span> <span class=\"text-zinc-700 dark:text-zinc-300 font-mono\">${event.fingerprint || '-'}</span></div>\n ${event.details ? `<div class=\"col-span-full\"><span class=\"font-medium text-zinc-500\">Details:</span> <pre class=\"text-zinc-700 dark:text-zinc-300 mt-1 bg-zinc-100 dark:bg-zinc-900 rounded p-2 overflow-x-auto\">${JSON.stringify(event.details, null, 2)}</pre></div>` : ''}\n </div>\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>`\n }\n\n <!-- Pagination -->\n ${pagination.totalPages > 1 ? `\n <div class=\"flex items-center justify-between border-t border-zinc-200 dark:border-zinc-800 px-4 py-3\">\n <div class=\"text-sm text-zinc-500\">\n Page ${pagination.currentPage} of ${pagination.totalPages}\n </div>\n <div class=\"flex gap-1\">\n ${pagination.currentPage > 1 ? `\n <a href=\"${buildFilterUrl(filters, { page: String(pagination.currentPage - 1) })}\"\n class=\"rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\">\n Previous\n </a>\n ` : ''}\n ${pagination.currentPage < pagination.totalPages ? `\n <a href=\"${buildFilterUrl(filters, { page: String(pagination.currentPage + 1) })}\"\n class=\"rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\">\n Next\n </a>\n ` : ''}\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Event Log',\n pageTitle: 'Security Event Log',\n currentPath: '/admin/plugins/security-audit/events',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityAuditSettings } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface SecuritySettingsPageData {\n settings: SecurityAuditSettings\n user?: BaseUser\n version?: string\n message?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nexport function renderSecuritySettingsPage(data: SecuritySettingsPageData): string {\n const { settings, user, version, message, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Audit Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Configure brute-force detection thresholds, event logging, and data retention.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n Dashboard\n </a>\n </div>\n </div>\n\n ${message ? `\n <div class=\"mb-6 rounded-lg bg-emerald-50 dark:bg-emerald-900/20 p-4 ring-1 ring-emerald-200 dark:ring-emerald-800\">\n <p class=\"text-sm text-emerald-800 dark:text-emerald-300\">${message}</p>\n </div>\n ` : ''}\n\n <form method=\"POST\" action=\"/admin/plugins/security-audit/settings\"\n class=\"space-y-6\"\n hx-post=\"/admin/plugins/security-audit/settings\"\n hx-swap=\"none\"\n hx-on::after-request=\"if(event.detail.successful) { window.showNotification && window.showNotification('Settings saved', 'success'); } else { window.showNotification && window.showNotification('Failed to save', 'error'); }\">\n\n <!-- Brute Force Detection -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Brute-Force Detection</h2>\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <label class=\"flex items-center gap-2 mb-4\">\n <input type=\"checkbox\" name=\"bruteForce.enabled\" value=\"true\" ${settings.bruteForce.enabled ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm font-medium text-zinc-700 dark:text-zinc-300\">Enable brute-force detection</span>\n </label>\n </div>\n <div></div><div></div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Failed Attempts per IP</label>\n <input type=\"number\" name=\"bruteForce.maxFailedAttemptsPerIP\" value=\"${settings.bruteForce.maxFailedAttemptsPerIP}\" min=\"1\" max=\"100\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Failed Attempts per Email</label>\n <input type=\"number\" name=\"bruteForce.maxFailedAttemptsPerEmail\" value=\"${settings.bruteForce.maxFailedAttemptsPerEmail}\" min=\"1\" max=\"100\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Window (minutes)</label>\n <input type=\"number\" name=\"bruteForce.windowMinutes\" value=\"${settings.bruteForce.windowMinutes}\" min=\"1\" max=\"1440\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Lockout Duration (minutes)</label>\n <input type=\"number\" name=\"bruteForce.lockoutDurationMinutes\" value=\"${settings.bruteForce.lockoutDurationMinutes}\" min=\"1\" max=\"1440\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Alert Threshold</label>\n <input type=\"number\" name=\"bruteForce.alertThreshold\" value=\"${settings.bruteForce.alertThreshold}\" min=\"1\" max=\"1000\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <p class=\"mt-1 text-xs text-zinc-400\">Events above this count trigger critical severity</p>\n </div>\n </div>\n </div>\n\n <!-- Event Logging -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Event Logging</h2>\n <div class=\"space-y-3\">\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logSuccessfulLogins\" value=\"true\" ${settings.logging.logSuccessfulLogins ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log successful logins</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logLogouts\" value=\"true\" ${settings.logging.logLogouts ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log logouts</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logRegistrations\" value=\"true\" ${settings.logging.logRegistrations ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log registrations</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logPasswordResets\" value=\"true\" ${settings.logging.logPasswordResets ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log password resets</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logPermissionDenied\" value=\"true\" ${settings.logging.logPermissionDenied ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log permission denied events</span>\n </label>\n </div>\n </div>\n\n <!-- Data Retention -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Data Retention</h2>\n <div class=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Days to Keep</label>\n <input type=\"number\" name=\"retention.daysToKeep\" value=\"${settings.retention.daysToKeep}\" min=\"1\" max=\"365\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Events</label>\n <input type=\"number\" name=\"retention.maxEvents\" value=\"${settings.retention.maxEvents}\" min=\"1000\" max=\"1000000\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"flex items-center gap-2 mt-5\">\n <input type=\"checkbox\" name=\"retention.autoPurge\" value=\"true\" ${settings.retention.autoPurge ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Auto-purge old events</span>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex items-center justify-between\">\n <button type=\"button\"\n onclick=\"if(confirm('Purge events older than retention period?')) fetch('/api/security-audit/events/purge', {method:'POST',headers:{'Content-Type':'application/json'}}).then(r=>r.json()).then(d=>window.showNotification && window.showNotification('Purged '+d.deleted+' events','success'))\"\n class=\"rounded-lg bg-red-50 dark:bg-red-900/20 px-4 py-2.5 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 ring-1 ring-red-200 dark:ring-red-800 transition-colors\">\n Purge Old Events\n </button>\n <button type=\"submit\"\n class=\"rounded-lg bg-cyan-600 px-6 py-2.5 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm\">\n Save Settings\n </button>\n </div>\n </form>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Audit Settings',\n pageTitle: 'Security Audit Settings',\n currentPath: '/admin/plugins/security-audit/settings',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { PluginService } from '../../../../services'\nimport { renderSecurityDashboard, SecurityDashboardData } from '../components/dashboard-page'\nimport { renderEventLogPage, EventLogPageData } from '../components/event-log-page'\nimport { renderSecuritySettingsPage, SecuritySettingsPageData } from '../components/settings-page'\nimport type { Bindings, Variables } from '../../../../app'\nimport type { SecurityAuditSettings, SecurityEventType, SecuritySeverity } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst adminRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminRoutes.use('*', requireAuth())\n\n// Check admin role\nadminRoutes.use('*', async (c, next) => {\n const user = c.get('user')\n if (user?.role !== 'admin') {\n return c.text('Access denied', 403)\n }\n return next()\n})\n\nasync function getSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\n// Dashboard\nadminRoutes.get('/', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const [stats, topIPs, hourlyTrend, recentCritical] = await Promise.all([\n service.getStats(),\n service.getTopIPs(10),\n service.getHourlyTrend(24),\n service.getRecentCriticalEvents(20)\n ])\n\n const pageData: SecurityDashboardData = {\n stats,\n topIPs,\n hourlyTrend,\n recentCritical,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderSecurityDashboard(pageData))\n})\n\n// Event log\nadminRoutes.get('/events', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const page = parseInt(c.req.query('page') || '1')\n const limit = 50\n\n const filters = {\n eventType: (c.req.query('type') as SecurityEventType) || undefined,\n severity: (c.req.query('severity') as SecuritySeverity) || undefined,\n email: c.req.query('email') || undefined,\n ipAddress: c.req.query('ip') || undefined,\n search: c.req.query('search') || undefined,\n page,\n limit\n }\n\n const { events, total } = await service.getEvents(filters)\n const totalPages = Math.ceil(total / limit)\n\n const pageData: EventLogPageData = {\n events,\n pagination: {\n currentPage: page,\n totalPages,\n totalItems: total,\n itemsPerPage: limit,\n startItem: total === 0 ? 0 : (page - 1) * limit + 1,\n endItem: Math.min(page * limit, total)\n },\n filters,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderEventLogPage(pageData))\n})\n\n// Settings page\nadminRoutes.get('/settings', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n\n const pageData: SecuritySettingsPageData = {\n settings,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n message: c.req.query('message') || undefined,\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderSecuritySettingsPage(pageData))\n})\n\n// Save settings\nadminRoutes.post('/settings', async (c) => {\n const db = c.env.DB\n const body = await c.req.parseBody()\n\n const settings: SecurityAuditSettings = {\n bruteForce: {\n enabled: body['bruteForce.enabled'] === 'true',\n maxFailedAttemptsPerIP: parseInt(body['bruteForce.maxFailedAttemptsPerIP'] as string) || 10,\n maxFailedAttemptsPerEmail: parseInt(body['bruteForce.maxFailedAttemptsPerEmail'] as string) || 5,\n windowMinutes: parseInt(body['bruteForce.windowMinutes'] as string) || 15,\n lockoutDurationMinutes: parseInt(body['bruteForce.lockoutDurationMinutes'] as string) || 30,\n alertThreshold: parseInt(body['bruteForce.alertThreshold'] as string) || 20\n },\n logging: {\n logSuccessfulLogins: body['logging.logSuccessfulLogins'] === 'true',\n logLogouts: body['logging.logLogouts'] === 'true',\n logRegistrations: body['logging.logRegistrations'] === 'true',\n logPasswordResets: body['logging.logPasswordResets'] === 'true',\n logPermissionDenied: body['logging.logPermissionDenied'] === 'true'\n },\n retention: {\n daysToKeep: parseInt(body['retention.daysToKeep'] as string) || 90,\n maxEvents: parseInt(body['retention.maxEvents'] as string) || 100000,\n autoPurge: body['retention.autoPurge'] === 'true'\n }\n }\n\n const pluginService = new PluginService(db)\n await pluginService.updatePluginSettings('security-audit', settings)\n\n // For HTMX requests, return 200\n if (c.req.header('HX-Request')) {\n return c.json({ success: true })\n }\n\n return c.redirect('/admin/plugins/security-audit/settings?message=Settings saved successfully')\n})\n\nexport { adminRoutes as securityAuditAdminRoutes }\n","import type { KVNamespace } from '@cloudflare/workers-types'\nimport type { SecurityAuditSettings } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst KV_PREFIX = 'security:bf:'\nconst LOCK_PREFIX = 'security:locked:'\n\nexport class BruteForceDetector {\n private settings: SecurityAuditSettings['bruteForce']\n\n constructor(\n private kv: KVNamespace,\n settings?: SecurityAuditSettings['bruteForce']\n ) {\n this.settings = settings || DEFAULT_SETTINGS.bruteForce\n }\n\n async recordFailedAttempt(ip: string, email: string): Promise<{\n ipCount: number\n emailCount: number\n shouldLockIP: boolean\n shouldLockEmail: boolean\n isSuspicious: boolean\n }> {\n if (!this.settings.enabled) {\n return { ipCount: 0, emailCount: 0, shouldLockIP: false, shouldLockEmail: false, isSuspicious: false }\n }\n\n const now = Date.now()\n const windowMs = this.settings.windowMinutes * 60 * 1000\n\n // Increment IP counter\n const ipKey = `${KV_PREFIX}ip:${ip}`\n const ipCount = await this.incrementCounter(ipKey, windowMs)\n\n // Increment email counter\n const emailKey = `${KV_PREFIX}email:${email}`\n const emailCount = await this.incrementCounter(emailKey, windowMs)\n\n // Check for multi-email from single IP (suspicious)\n const ipEmailsKey = `${KV_PREFIX}ip-emails:${ip}`\n await this.addToSet(ipEmailsKey, email, windowMs)\n const emailsFromIP = await this.getSetSize(ipEmailsKey)\n const isSuspicious = emailsFromIP >= 5\n\n const shouldLockIP = ipCount >= this.settings.maxFailedAttemptsPerIP\n const shouldLockEmail = emailCount >= this.settings.maxFailedAttemptsPerEmail\n\n return { ipCount, emailCount, shouldLockIP, shouldLockEmail, isSuspicious }\n }\n\n async isLocked(ip: string, email: string): Promise<{ locked: boolean, reason?: string }> {\n if (!this.settings.enabled) {\n return { locked: false }\n }\n\n const ipLocked = await this.kv.get(`${LOCK_PREFIX}ip:${ip}`)\n if (ipLocked) {\n return { locked: true, reason: 'IP address temporarily locked due to excessive failed login attempts' }\n }\n\n const emailLocked = await this.kv.get(`${LOCK_PREFIX}email:${email}`)\n if (emailLocked) {\n return { locked: true, reason: 'Account temporarily locked due to excessive failed login attempts' }\n }\n\n return { locked: false }\n }\n\n async lockIP(ip: string): Promise<void> {\n const ttl = this.settings.lockoutDurationMinutes * 60\n await this.kv.put(`${LOCK_PREFIX}ip:${ip}`, JSON.stringify({\n lockedAt: Date.now(),\n reason: 'brute_force_ip'\n }), { expirationTtl: ttl })\n }\n\n async lockEmail(email: string): Promise<void> {\n const ttl = this.settings.lockoutDurationMinutes * 60\n await this.kv.put(`${LOCK_PREFIX}email:${email}`, JSON.stringify({\n lockedAt: Date.now(),\n reason: 'brute_force_email'\n }), { expirationTtl: ttl })\n }\n\n async unlockIP(ip: string): Promise<void> {\n await this.kv.delete(`${LOCK_PREFIX}ip:${ip}`)\n }\n\n async unlockEmail(email: string): Promise<void> {\n await this.kv.delete(`${LOCK_PREFIX}email:${email}`)\n }\n\n async getActiveLockouts(): Promise<Array<{ key: string, type: 'ip' | 'email', value: string, lockedAt: number }>> {\n // KV list with prefix to find all active lockouts\n const ipLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}ip:` })\n const emailLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}email:` })\n\n const lockouts: Array<{ key: string, type: 'ip' | 'email', value: string, lockedAt: number }> = []\n\n for (const key of ipLocks.keys) {\n const data = await this.kv.get(key.name)\n if (data) {\n const parsed = JSON.parse(data)\n lockouts.push({\n key: key.name,\n type: 'ip',\n value: key.name.replace(`${LOCK_PREFIX}ip:`, ''),\n lockedAt: parsed.lockedAt\n })\n }\n }\n\n for (const key of emailLocks.keys) {\n const data = await this.kv.get(key.name)\n if (data) {\n const parsed = JSON.parse(data)\n lockouts.push({\n key: key.name,\n type: 'email',\n value: key.name.replace(`${LOCK_PREFIX}email:`, ''),\n lockedAt: parsed.lockedAt\n })\n }\n }\n\n return lockouts\n }\n\n async releaseLockout(key: string): Promise<void> {\n await this.kv.delete(key)\n }\n\n isAboveAlertThreshold(count: number): boolean {\n return count >= this.settings.alertThreshold\n }\n\n private async incrementCounter(key: string, windowMs: number): Promise<number> {\n const existing = await this.kv.get(key)\n const now = Date.now()\n\n let entries: number[] = []\n if (existing) {\n try {\n entries = JSON.parse(existing)\n } catch {\n entries = []\n }\n }\n\n // Remove expired entries\n const cutoff = now - windowMs\n entries = entries.filter(ts => ts > cutoff)\n\n // Add new entry\n entries.push(now)\n\n // Store with TTL equal to window\n const ttlSeconds = Math.ceil(windowMs / 1000)\n await this.kv.put(key, JSON.stringify(entries), { expirationTtl: ttlSeconds })\n\n return entries.length\n }\n\n private async addToSet(key: string, value: string, windowMs: number): Promise<void> {\n const existing = await this.kv.get(key)\n let set: Record<string, number> = {}\n const now = Date.now()\n const cutoff = now - windowMs\n\n if (existing) {\n try {\n set = JSON.parse(existing)\n } catch {\n set = {}\n }\n }\n\n // Remove expired entries\n for (const [k, ts] of Object.entries(set)) {\n if (ts < cutoff) delete set[k]\n }\n\n set[value] = now\n\n const ttlSeconds = Math.ceil(windowMs / 1000)\n await this.kv.put(key, JSON.stringify(set), { expirationTtl: ttlSeconds })\n }\n\n private async getSetSize(key: string): Promise<number> {\n const existing = await this.kv.get(key)\n if (!existing) return 0\n\n try {\n const set = JSON.parse(existing)\n return Object.keys(set).length\n } catch {\n return 0\n }\n }\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { BruteForceDetector } from '../services/brute-force-detector'\nimport { PluginService } from '../../../../services'\nimport type { Bindings, Variables } from '../../../../app'\nimport type { SecurityAuditSettings, SecurityEventFilters, SecurityEventType, SecuritySeverity } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\napiRoutes.use('*', requireAuth())\n\n// Check admin role\napiRoutes.use('*', async (c, next) => {\n const user = c.get('user')\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n return next()\n})\n\nasync function getSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\n// GET /api/security-audit/events\napiRoutes.get('/events', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const filters: SecurityEventFilters = {\n eventType: c.req.query('type') as SecurityEventType | undefined,\n severity: c.req.query('severity') as SecuritySeverity | undefined,\n email: c.req.query('email') || undefined,\n ipAddress: c.req.query('ip') || undefined,\n search: c.req.query('search') || undefined,\n startDate: c.req.query('start') ? parseInt(c.req.query('start')!) : undefined,\n endDate: c.req.query('end') ? parseInt(c.req.query('end')!) : undefined,\n page: c.req.query('page') ? parseInt(c.req.query('page')!) : 1,\n limit: c.req.query('limit') ? Math.min(parseInt(c.req.query('limit')!), 100) : 50,\n sortBy: (c.req.query('sortBy') as any) || 'created_at',\n sortOrder: (c.req.query('sortOrder') as any) || 'desc'\n }\n\n const result = await service.getEvents(filters)\n return c.json(result)\n})\n\n// GET /api/security-audit/events/:id\napiRoutes.get('/events/:id', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const event = await service.getEvent(c.req.param('id'))\n\n if (!event) {\n return c.json({ error: 'Event not found' }, 404)\n }\n\n return c.json(event)\n})\n\n// GET /api/security-audit/stats\napiRoutes.get('/stats', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const stats = await service.getStats()\n return c.json(stats)\n})\n\n// GET /api/security-audit/stats/ips\napiRoutes.get('/stats/ips', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const limit = c.req.query('limit') ? parseInt(c.req.query('limit')!) : 10\n const ips = await service.getTopIPs(limit)\n return c.json(ips)\n})\n\n// GET /api/security-audit/stats/trend\napiRoutes.get('/stats/trend', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const hours = c.req.query('hours') ? parseInt(c.req.query('hours')!) : 24\n const trend = await service.getHourlyTrend(hours)\n return c.json(trend)\n})\n\n// GET /api/security-audit/lockouts\napiRoutes.get('/lockouts', async (c) => {\n const kv = c.env.CACHE_KV\n const db = c.env.DB\n const settings = await getSettings(db)\n const detector = new BruteForceDetector(kv, settings.bruteForce)\n const lockouts = await detector.getActiveLockouts()\n return c.json(lockouts)\n})\n\n// DELETE /api/security-audit/lockouts/:key\napiRoutes.delete('/lockouts/:key', async (c) => {\n const kv = c.env.CACHE_KV\n const key = decodeURIComponent(c.req.param('key'))\n const db = c.env.DB\n const settings = await getSettings(db)\n const detector = new BruteForceDetector(kv, settings.bruteForce)\n await detector.releaseLockout(key)\n return c.json({ success: true })\n})\n\n// POST /api/security-audit/events/purge\napiRoutes.post('/events/purge', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const body = await c.req.json().catch(() => ({})) as { daysToKeep?: number }\n const deleted = await service.purgeOldEvents(body.daysToKeep)\n return c.json({ success: true, deleted })\n})\n\n// GET /api/security-audit/export\napiRoutes.get('/export', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const format = c.req.query('format') || 'json'\n\n const filters: SecurityEventFilters = {\n eventType: c.req.query('type') as SecurityEventType | undefined,\n severity: c.req.query('severity') as SecuritySeverity | undefined,\n startDate: c.req.query('start') ? parseInt(c.req.query('start')!) : undefined,\n endDate: c.req.query('end') ? parseInt(c.req.query('end')!) : undefined,\n limit: 10000,\n page: 1\n }\n\n const { events } = await service.getEvents(filters)\n\n if (format === 'csv') {\n const headers = ['id', 'event_type', 'severity', 'email', 'ip_address', 'country_code', 'blocked', 'created_at']\n const csvRows = [headers.join(',')]\n for (const event of events) {\n csvRows.push([\n event.id,\n event.eventType,\n event.severity,\n event.email || '',\n event.ipAddress || '',\n event.countryCode || '',\n event.blocked ? '1' : '0',\n new Date(event.createdAt).toISOString()\n ].map(v => `\"${String(v).replace(/\"/g, '\"\"')}\"`).join(','))\n }\n\n return new Response(csvRows.join('\\n'), {\n headers: {\n 'Content-Type': 'text/csv',\n 'Content-Disposition': `attachment; filename=\"security-events-${Date.now()}.csv\"`\n }\n })\n }\n\n return c.json(events)\n})\n\nexport { apiRoutes as securityAuditApiRoutes }\n","import type { Context, Next } from 'hono'\nimport type { Bindings, Variables } from '../../../../app'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { BruteForceDetector } from '../services/brute-force-detector'\nimport { PluginService } from '../../../../services'\nimport type { SecurityAuditSettings, SecurityEventType } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nfunction extractRequestInfo(c: Context<{ Bindings: Bindings; Variables: Variables }>) {\n const ip = c.req.header('cf-connecting-ip')\n || c.req.header('x-forwarded-for')?.split(',')[0]?.trim()\n || 'unknown'\n const userAgent = c.req.header('user-agent') || 'unknown'\n const countryCode = c.req.header('cf-ipcountry') || null\n const path = new URL(c.req.url).pathname\n const method = c.req.method\n\n return { ip, userAgent, countryCode, path, method }\n}\n\nfunction generateFingerprint(ip: string, userAgent: string): string {\n // Simple fingerprint from IP + UA - using a basic hash\n const str = `${ip}:${userAgent}`\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash |= 0\n }\n return Math.abs(hash).toString(36)\n}\n\nasync function getPluginSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch {\n // Plugin not installed or DB not ready\n }\n return DEFAULT_SETTINGS\n}\n\nasync function isPluginActive(db: any): Promise<boolean> {\n try {\n const result = await db.prepare(\n \"SELECT status FROM plugins WHERE id = 'security-audit'\"\n ).first() as { status: string } | null\n return result?.status === 'active'\n } catch {\n return false\n }\n}\n\nexport function securityAuditMiddleware() {\n return async (c: Context<{ Bindings: Bindings; Variables: Variables }>, next: Next) => {\n const path = new URL(c.req.url).pathname\n\n // Only intercept auth-related routes\n if (!path.startsWith('/auth/')) {\n return next()\n }\n\n const db = c.env.DB\n\n // Check if plugin is active\n if (!await isPluginActive(db)) {\n return next()\n }\n\n const settings = await getPluginSettings(db)\n const { ip, userAgent, countryCode, method } = extractRequestInfo(c)\n const fingerprint = generateFingerprint(ip, userAgent)\n\n // For login POST, extract email and check lockout before proceeding\n const isLoginPost = (path === '/auth/login' || path === '/auth/login/form') && method === 'POST'\n let preExtractedEmail = ''\n\n if (isLoginPost) {\n try {\n if (path === '/auth/login/form') {\n // Form-based login: clone request to read formData without consuming it\n const clonedReq = c.req.raw.clone()\n const formData = await clonedReq.formData()\n preExtractedEmail = (formData.get('email') as string || '').toLowerCase()\n } else {\n // JSON login: Hono caches parsed JSON so this is safe\n const body = await c.req.json()\n preExtractedEmail = body?.email?.toLowerCase() || ''\n }\n } catch {\n // Can't parse body, continue\n }\n\n if (preExtractedEmail && settings.bruteForce.enabled) {\n const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce)\n const lockStatus = await detector.isLocked(ip, preExtractedEmail)\n\n if (lockStatus.locked) {\n const service = new SecurityAuditService(db, settings)\n // Log the blocked attempt asynchronously\n const logPromise = service.logEvent({\n eventType: 'login_failure',\n severity: 'warning',\n email: preExtractedEmail,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n blocked: true,\n details: { reason: lockStatus.reason }\n })\n\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(logPromise)\n }\n\n return c.json({\n error: lockStatus.reason || 'Too many failed attempts. Please try again later.'\n }, 429)\n }\n }\n }\n\n // Proceed with the request\n await next()\n\n // After response, log the event asynchronously\n const logPromise = logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerprint, path, method, preExtractedEmail)\n\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(logPromise)\n }\n }\n}\n\nasync function logAuthEvent(\n c: Context<{ Bindings: Bindings; Variables: Variables }>,\n db: any,\n settings: SecurityAuditSettings,\n ip: string,\n userAgent: string,\n countryCode: string | null,\n fingerprint: string,\n path: string,\n method: string,\n preExtractedEmail: string = ''\n): Promise<void> {\n try {\n const service = new SecurityAuditService(db, settings)\n const status = c.res.status\n const isLoginPost = (path === '/auth/login' || path === '/auth/login/form') && method === 'POST'\n const isFormLogin = path === '/auth/login/form'\n\n // Login POST\n if (isLoginPost) {\n // Determine if login succeeded or failed.\n // JSON login: 200 = success, 401/400 = failure\n // Form login: always returns 200 — check if response set an auth cookie (HX-Redirect header indicates success)\n let loginSucceeded: boolean\n if (isFormLogin) {\n // Form login redirects to /admin on success via HX-Redirect header or meta refresh\n const hxRedirect = c.res.headers.get('HX-Redirect')\n const setCookieHeader = c.res.headers.get('set-cookie') || ''\n loginSucceeded = !!(hxRedirect?.includes('/admin') || setCookieHeader.includes('auth_token'))\n } else {\n loginSucceeded = status === 200\n }\n\n if (loginSucceeded) {\n if (!settings.logging.logSuccessfulLogins) return\n\n // Try to get user info from response\n let email = preExtractedEmail\n let userId = ''\n if (!isFormLogin) {\n try {\n const cloned = c.res.clone()\n const body = await cloned.json() as any\n email = body?.user?.email || email\n userId = body?.user?.id || ''\n } catch { /* ignore */ }\n }\n\n await service.logEvent({\n eventType: 'login_success',\n severity: 'info',\n userId: userId || undefined,\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n } else {\n // Failed login — use pre-extracted email since body is already consumed\n const email = preExtractedEmail\n\n await service.logEvent({\n eventType: 'login_failure',\n severity: 'warning',\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { statusCode: status }\n })\n\n // Record failed attempt for brute-force detection\n if (email && settings.bruteForce.enabled) {\n const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce)\n const result = await detector.recordFailedAttempt(ip, email)\n\n if (result.shouldLockIP) {\n await detector.lockIP(ip)\n await service.logEvent({\n eventType: 'account_lockout',\n severity: 'critical',\n email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'brute_force_ip', attemptCount: result.ipCount }\n })\n }\n\n if (result.shouldLockEmail) {\n await detector.lockEmail(email)\n await service.logEvent({\n eventType: 'account_lockout',\n severity: 'critical',\n email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'brute_force_email', attemptCount: result.emailCount }\n })\n }\n\n if (result.isSuspicious) {\n await service.logEvent({\n eventType: 'suspicious_activity',\n severity: 'critical',\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'multiple_emails_from_ip', ipCount: result.ipCount }\n })\n }\n }\n }\n }\n\n // Registration POST\n if (path === '/auth/register' && method === 'POST' && settings.logging.logRegistrations) {\n if (status === 201 || status === 200) {\n let email = ''\n let userId = ''\n try {\n const cloned = c.res.clone()\n const body = await cloned.json() as any\n email = body?.user?.email || ''\n userId = body?.user?.id || ''\n } catch { /* ignore */ }\n\n await service.logEvent({\n eventType: 'registration',\n severity: 'info',\n userId: userId || undefined,\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n }\n }\n\n // Logout\n if (path === '/auth/logout' && settings.logging.logLogouts) {\n const user = c.get('user')\n await service.logEvent({\n eventType: 'logout',\n severity: 'info',\n userId: user?.userId,\n email: user?.email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n }\n } catch (error) {\n console.error('[SecurityAudit] Error logging auth event:', error)\n }\n}\n","import { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '../../types'\nimport { securityAuditAdminRoutes } from './routes/admin'\nimport { securityAuditApiRoutes } from './routes/api'\nimport { securityAuditMiddleware } from './middleware/audit-middleware'\n\nexport function createSecurityAuditPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'security-audit',\n version: '1.0.0-beta.1',\n description: 'Security event logging, brute-force detection, and analytics dashboard'\n })\n\n builder.metadata({\n author: { name: 'SonicJS Team' },\n license: 'MIT'\n })\n\n // Admin dashboard and event log routes\n builder.addRoute('/admin/plugins/security-audit', securityAuditAdminRoutes as any, {\n description: 'Security audit dashboard and admin pages',\n requiresAuth: true,\n priority: 50\n })\n\n // API routes\n builder.addRoute('/api/security-audit', securityAuditApiRoutes as any, {\n description: 'Security audit API endpoints',\n requiresAuth: true,\n priority: 50\n })\n\n // Admin menu item — icon is raw SVG to match sidebar rendering\n builder.addMenuItem('Security', '/admin/plugins/security-audit', {\n icon: `<svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"/></svg>`,\n order: 85\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n install: async (context) => {\n console.log('[SecurityAudit] Plugin installed')\n },\n activate: async (context) => {\n console.log('[SecurityAudit] Plugin activated')\n },\n deactivate: async (context) => {\n console.log('[SecurityAudit] Plugin deactivated')\n },\n uninstall: async (context) => {\n console.log('[SecurityAudit] Plugin uninstalled')\n }\n })\n\n return builder.build()\n}\n\nexport const securityAuditPlugin = createSecurityAuditPlugin()\nexport { SecurityAuditService } from './services/security-audit-service'\nexport { BruteForceDetector } from './services/brute-force-detector'\nexport { securityAuditMiddleware } from './middleware/audit-middleware'\nexport default securityAuditPlugin\n","import type { Context, Next } from 'hono'\nimport type { Bindings, Variables } from '../app'\nimport type { Plugin } from '../plugins/types'\n\n// All plugins that define menu items. The single source of truth for menu config\n// is each plugin's addMenuItem() call — this array just lists which plugins to check.\nimport { securityAuditPlugin } from '../plugins/core-plugins/security-audit-plugin'\n\nconst MENU_PLUGINS: Plugin[] = [\n securityAuditPlugin,\n]\n\nconst MARKER = '<!-- DYNAMIC_PLUGIN_MENU -->'\n\nfunction renderMenuItem(item: { label: string; path: string; icon?: string }, currentPath: string): string {\n const isActive = currentPath === item.path || currentPath.startsWith(item.path)\n const fallbackIcon = `<svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/></svg>`\n return `\n <span class=\"relative\">\n ${isActive ? '<span class=\"absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400\"></span>' : ''}\n <a\n href=\"${item.path}\"\n class=\"flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-sm/5 font-medium ${\n isActive\n ? 'text-zinc-950 dark:text-white'\n : 'text-zinc-950 hover:bg-zinc-950/5 dark:text-white dark:hover:bg-white/5'\n }\"\n ${isActive ? 'data-current=\"true\"' : ''}\n >\n <span class=\"shrink-0 ${isActive ? 'fill-zinc-950 dark:fill-white' : 'fill-zinc-500 dark:fill-zinc-400'}\">\n ${item.icon || fallbackIcon}\n </span>\n <span class=\"truncate\">${item.label}</span>\n </a>\n </span>`\n}\n\nexport function pluginMenuMiddleware() {\n return async (c: Context<{ Bindings: Bindings; Variables: Variables }>, next: Next) => {\n const path = new URL(c.req.url).pathname\n if (!path.startsWith('/admin')) {\n return next()\n }\n\n // Collect menu items from active plugins\n let activeMenuItems: Array<{ label: string; path: string; icon?: string }> = []\n try {\n const db = c.env.DB\n const pluginNames = MENU_PLUGINS.map(p => p.name)\n if (pluginNames.length > 0) {\n const placeholders = pluginNames.map(() => '?').join(',')\n const result = await db.prepare(\n `SELECT name FROM plugins WHERE name IN (${placeholders}) AND status = 'active'`\n ).bind(...pluginNames).all()\n\n const activeNames = new Set((result.results || []).map((r: any) => r.name))\n\n for (const plugin of MENU_PLUGINS) {\n if (activeNames.has(plugin.name) && plugin.menuItems) {\n activeMenuItems.push(...plugin.menuItems)\n }\n }\n\n // Sort by order\n activeMenuItems.sort((a, b) => ((a as any).order || 0) - ((b as any).order || 0))\n }\n } catch {\n // DB not ready or plugin table doesn't exist yet\n }\n\n c.set('pluginMenuItems', activeMenuItems.map(m => ({ label: m.label, path: m.path, icon: m.icon || '' })))\n\n await next()\n\n // Inject menu items into HTML response by replacing the marker\n if (activeMenuItems.length > 0 && c.res.headers.get('content-type')?.includes('text/html')) {\n const status = c.res.status\n const headers = new Headers(c.res.headers)\n const html = await c.res.text()\n\n if (html.includes(MARKER)) {\n const renderedItems = activeMenuItems.map(item => renderMenuItem(item, path)).join('')\n const newHtml = html.split(MARKER).join(renderedItems)\n c.res = new Response(newHtml, { status, headers })\n } else {\n // Body was consumed by .text(), must create new Response either way\n c.res = new Response(html, { status, headers })\n }\n }\n }\n}\n","/**\n * Cache Configuration\n *\n * Defines cache configurations for different entity types\n */\n\nexport interface CacheConfig {\n ttl: number // Time-to-live in seconds\n kvEnabled: boolean // Use KV cache tier\n memoryEnabled: boolean // Use in-memory cache tier\n namespace: string // Cache namespace/prefix\n invalidateOn: string[] // Events that invalidate this cache\n version?: string // Cache version for busting\n}\n\nexport interface CacheStats {\n memoryHits: number\n memoryMisses: number\n kvHits: number\n kvMisses: number\n dbHits: number\n totalRequests: number\n hitRate: number\n memorySize: number\n entryCount: number\n}\n\n/**\n * Default cache configurations by entity type\n */\nexport const CACHE_CONFIGS: Record<string, CacheConfig> = {\n // Content (high read, low write)\n content: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'content',\n invalidateOn: ['content.update', 'content.delete', 'content.publish'],\n version: 'v1'\n },\n\n // User data (medium read, medium write)\n user: {\n ttl: 900, // 15 minutes\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'user',\n invalidateOn: ['user.update', 'user.delete', 'auth.login'],\n version: 'v1'\n },\n\n // Configuration (high read, very low write)\n config: {\n ttl: 7200, // 2 hours\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'config',\n invalidateOn: ['config.update', 'plugin.activate', 'plugin.deactivate'],\n version: 'v1'\n },\n\n // Media metadata (high read, low write)\n media: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'media',\n invalidateOn: ['media.upload', 'media.delete', 'media.update'],\n version: 'v1'\n },\n\n // API responses (very high read, low write)\n api: {\n ttl: 300, // 5 minutes\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'api',\n invalidateOn: ['content.update', 'content.publish'],\n version: 'v1'\n },\n\n // Session data (very high read, medium write)\n session: {\n ttl: 1800, // 30 minutes\n kvEnabled: false, // Only in-memory for sessions\n memoryEnabled: true,\n namespace: 'session',\n invalidateOn: ['auth.logout'],\n version: 'v1'\n },\n\n // Plugin data\n plugin: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'plugin',\n invalidateOn: ['plugin.activate', 'plugin.deactivate', 'plugin.update'],\n version: 'v1'\n },\n\n // Collections/schema\n collection: {\n ttl: 7200, // 2 hours\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'collection',\n invalidateOn: ['collection.update', 'collection.delete'],\n version: 'v1'\n }\n}\n\n/**\n * Get cache configuration for a specific namespace\n */\nexport function getCacheConfig(namespace: string): CacheConfig {\n return CACHE_CONFIGS[namespace] || {\n ttl: 3600,\n kvEnabled: true,\n memoryEnabled: true,\n namespace,\n invalidateOn: [],\n version: 'v1'\n }\n}\n\n/**\n * Generate a cache key with consistent format\n * Format: {namespace}:{type}:{identifier}:{version}\n */\nexport function generateCacheKey(\n namespace: string,\n type: string,\n identifier: string,\n version?: string\n): string {\n const v = version || getCacheConfig(namespace).version || 'v1'\n return `${namespace}:${type}:${identifier}:${v}`\n}\n\n/**\n * Parse a cache key back into its components\n */\nexport function parseCacheKey(key: string): {\n namespace: string\n type: string\n identifier: string\n version: string\n} | null {\n const parts = key.split(':')\n if (parts.length !== 4) {\n return null\n }\n\n return {\n namespace: parts[0] || '',\n type: parts[1] || '',\n identifier: parts[2] || '',\n version: parts[3] || ''\n }\n}\n\n/**\n * Generate a hash for complex query parameters\n */\nexport function hashQueryParams(params: Record<string, any>): string {\n // Sort keys for consistent hashing\n const sortedKeys = Object.keys(params).sort()\n const normalized = sortedKeys.map(key => `${key}=${params[key]}`).join('&')\n\n // Simple hash function (for better performance, consider using crypto)\n let hash = 0\n for (let i = 0; i < normalized.length; i++) {\n const char = normalized.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32-bit integer\n }\n\n return Math.abs(hash).toString(36)\n}\n\n/**\n * Create a pattern for cache invalidation\n */\nexport function createCachePattern(\n namespace: string,\n type?: string,\n identifier?: string\n): string {\n let pattern = namespace\n if (type) pattern += `:${type}`\n if (identifier) pattern += `:${identifier}`\n return pattern + ':*'\n}\n","/**\n * Cache Service\n *\n * Three-tiered caching implementation:\n * 1. In-Memory Cache (fastest, region-specific)\n * 2. Cloudflare KV Cache (fast, global)\n * 3. Database (fallback, source of truth)\n */\n\nimport { CacheConfig, CacheStats, generateCacheKey } from './cache-config.js'\n\n/**\n * Cache entry with metadata\n */\ninterface CacheEntry<T> {\n data: T\n timestamp: number\n expiresAt: number\n version: string\n}\n\n/**\n * In-memory cache store\n */\nclass MemoryCache {\n private cache: Map<string, CacheEntry<any>> = new Map()\n private maxSize: number = 50 * 1024 * 1024 // 50MB\n private currentSize: number = 0\n\n /**\n * Get item from memory cache\n */\n get<T>(key: string): T | null {\n const entry = this.cache.get(key)\n\n if (!entry) {\n return null\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n this.delete(key)\n return null\n }\n\n return entry.data as T\n }\n\n /**\n * Set item in memory cache\n */\n set<T>(key: string, value: T, ttl: number, version: string = 'v1'): void {\n const now = Date.now()\n const entry: CacheEntry<T> = {\n data: value,\n timestamp: now,\n expiresAt: now + (ttl * 1000),\n version\n }\n\n // Estimate size (rough approximation)\n const entrySize = JSON.stringify(entry).length * 2 // UTF-16\n\n // Check if we need to evict\n if (this.currentSize + entrySize > this.maxSize) {\n this.evictLRU(entrySize)\n }\n\n // Delete old entry if exists\n if (this.cache.has(key)) {\n this.delete(key)\n }\n\n this.cache.set(key, entry)\n this.currentSize += entrySize\n }\n\n /**\n * Delete item from memory cache\n */\n delete(key: string): boolean {\n const entry = this.cache.get(key)\n if (entry) {\n const entrySize = JSON.stringify(entry).length * 2\n this.currentSize -= entrySize\n return this.cache.delete(key)\n }\n return false\n }\n\n /**\n * Clear all items from memory cache\n */\n clear(): void {\n this.cache.clear()\n this.currentSize = 0\n }\n\n /**\n * Get cache statistics\n */\n getStats(): { size: number; count: number } {\n return {\n size: this.currentSize,\n count: this.cache.size\n }\n }\n\n /**\n * Evict least recently used items to make space\n */\n private evictLRU(neededSpace: number): void {\n // Sort by timestamp (oldest first)\n const entries = Array.from(this.cache.entries()).sort(\n (a, b) => a[1].timestamp - b[1].timestamp\n )\n\n let freedSpace = 0\n for (const [key, entry] of entries) {\n if (freedSpace >= neededSpace) break\n\n const entrySize = JSON.stringify(entry).length * 2\n this.delete(key)\n freedSpace += entrySize\n }\n }\n\n /**\n * Delete items matching a pattern\n */\n invalidatePattern(pattern: string): number {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n )\n\n let count = 0\n for (const key of this.cache.keys()) {\n if (regex.test(key)) {\n this.delete(key)\n count++\n }\n }\n\n return count\n }\n}\n\n/**\n * Cache result with source information\n */\nexport interface CacheResult<T> {\n data: T | null\n source: 'memory' | 'kv' | 'miss'\n hit: boolean\n timestamp?: number\n ttl?: number\n}\n\n/**\n * Main cache service with multi-tier support\n */\nexport class CacheService {\n private memoryCache: MemoryCache\n private config: CacheConfig\n private stats: CacheStats\n private kvNamespace?: KVNamespace\n\n constructor(config: CacheConfig, kvNamespace?: KVNamespace) {\n this.memoryCache = new MemoryCache()\n this.config = config\n this.kvNamespace = kvNamespace\n this.stats = {\n memoryHits: 0,\n memoryMisses: 0,\n kvHits: 0,\n kvMisses: 0,\n dbHits: 0,\n totalRequests: 0,\n hitRate: 0,\n memorySize: 0,\n entryCount: 0\n }\n }\n\n /**\n * Get value from cache (tries memory first, then KV)\n */\n async get<T>(key: string): Promise<T | null> {\n this.stats.totalRequests++\n\n // Try memory cache first (Tier 1)\n if (this.config.memoryEnabled) {\n const memoryValue = this.memoryCache.get<T>(key)\n if (memoryValue !== null) {\n this.stats.memoryHits++\n this.updateHitRate()\n return memoryValue\n }\n this.stats.memoryMisses++\n }\n\n // Try KV cache (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const kvValue = await this.kvNamespace.get(key, 'json')\n if (kvValue !== null) {\n this.stats.kvHits++\n\n // Populate memory cache for faster subsequent access\n if (this.config.memoryEnabled) {\n this.memoryCache.set(key, kvValue as T, this.config.ttl, this.config.version)\n }\n\n this.updateHitRate()\n return kvValue as T\n }\n this.stats.kvMisses++\n } catch (error) {\n console.error('KV cache read error:', error)\n this.stats.kvMisses++\n }\n }\n\n this.updateHitRate()\n return null\n }\n\n /**\n * Get value from cache with source information\n */\n async getWithSource<T>(key: string): Promise<CacheResult<T>> {\n this.stats.totalRequests++\n\n // Try memory cache first (Tier 1)\n if (this.config.memoryEnabled) {\n const memoryValue = this.memoryCache.get<T>(key)\n if (memoryValue !== null) {\n this.stats.memoryHits++\n this.updateHitRate()\n\n const entry = await this.getEntry<T>(key)\n return {\n data: memoryValue,\n source: 'memory',\n hit: true,\n timestamp: entry?.timestamp,\n ttl: entry?.ttl\n }\n }\n this.stats.memoryMisses++\n }\n\n // Try KV cache (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const kvValue = await this.kvNamespace.get(key, 'json')\n if (kvValue !== null) {\n this.stats.kvHits++\n\n // Populate memory cache for faster subsequent access\n if (this.config.memoryEnabled) {\n this.memoryCache.set(key, kvValue as T, this.config.ttl, this.config.version)\n }\n\n this.updateHitRate()\n return {\n data: kvValue as T,\n source: 'kv',\n hit: true\n }\n }\n this.stats.kvMisses++\n } catch (error) {\n console.error('KV cache read error:', error)\n this.stats.kvMisses++\n }\n }\n\n this.updateHitRate()\n return {\n data: null,\n source: 'miss',\n hit: false\n }\n }\n\n /**\n * Set value in cache (stores in both memory and KV)\n */\n async set<T>(\n key: string,\n value: T,\n customConfig?: Partial<CacheConfig>\n ): Promise<void> {\n const config = { ...this.config, ...customConfig }\n\n // Store in memory cache (Tier 1)\n if (config.memoryEnabled) {\n this.memoryCache.set(key, value, config.ttl, config.version)\n }\n\n // Store in KV cache (Tier 2)\n if (config.kvEnabled && this.kvNamespace) {\n try {\n await this.kvNamespace.put(key, JSON.stringify(value), {\n expirationTtl: config.ttl\n })\n } catch (error) {\n console.error('KV cache write error:', error)\n }\n }\n }\n\n /**\n * Delete value from cache (removes from both memory and KV)\n */\n async delete(key: string): Promise<void> {\n // Delete from memory (Tier 1)\n if (this.config.memoryEnabled) {\n this.memoryCache.delete(key)\n }\n\n // Delete from KV (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n await this.kvNamespace.delete(key)\n } catch (error) {\n console.error('KV cache delete error:', error)\n }\n }\n }\n\n /**\n * Clear all cache entries for this namespace\n */\n async clear(): Promise<void> {\n if (this.config.memoryEnabled) {\n this.memoryCache.clear()\n }\n\n // Reset stats\n this.stats = {\n memoryHits: 0,\n memoryMisses: 0,\n kvHits: 0,\n kvMisses: 0,\n dbHits: 0,\n totalRequests: 0,\n hitRate: 0,\n memorySize: 0,\n entryCount: 0\n }\n }\n\n /**\n * Invalidate cache entries matching a pattern\n */\n async invalidate(pattern: string): Promise<number> {\n let count = 0\n\n // Invalidate from memory (Tier 1)\n if (this.config.memoryEnabled) {\n count += this.memoryCache.invalidatePattern(pattern)\n }\n\n // Invalidate from KV (Tier 2)\n // Note: KV doesn't support pattern matching, so we need to list all keys\n // This is expensive and should be used sparingly\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n )\n\n // List all keys with the namespace prefix\n const prefix = this.config.namespace + ':'\n const list = await this.kvNamespace.list({ prefix })\n\n for (const key of list.keys) {\n if (regex.test(key.name)) {\n await this.kvNamespace.delete(key.name)\n count++\n }\n }\n } catch (error) {\n console.error('KV cache invalidation error:', error)\n }\n }\n\n return count\n }\n\n /**\n * Invalidate cache entries matching a pattern (alias for invalidate)\n */\n async invalidatePattern(pattern: string): Promise<number> {\n return this.invalidate(pattern)\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n const memStats = this.memoryCache.getStats()\n\n return {\n ...this.stats,\n memorySize: memStats.size,\n entryCount: memStats.count\n }\n }\n\n /**\n * Update hit rate calculation\n */\n private updateHitRate(): void {\n const totalHits = this.stats.memoryHits + this.stats.kvHits + this.stats.dbHits\n this.stats.hitRate = this.stats.totalRequests > 0\n ? (totalHits / this.stats.totalRequests) * 100\n : 0\n }\n\n /**\n * Generate a cache key using the configured namespace\n */\n generateKey(type: string, identifier: string): string {\n return generateCacheKey(\n this.config.namespace,\n type,\n identifier,\n this.config.version\n )\n }\n\n /**\n * Warm cache with multiple entries\n */\n async warmCache<T>(entries: Array<{ key: string; value: T }>): Promise<void> {\n for (const entry of entries) {\n await this.set(entry.key, entry.value)\n }\n }\n\n /**\n * Check if a key exists in cache\n */\n async has(key: string): Promise<boolean> {\n const value = await this.get(key)\n return value !== null\n }\n\n /**\n * Get multiple values at once\n */\n async getMany<T>(keys: string[]): Promise<Map<string, T>> {\n const results = new Map<string, T>()\n\n for (const key of keys) {\n const value = await this.get<T>(key)\n if (value !== null) {\n results.set(key, value)\n }\n }\n\n return results\n }\n\n /**\n * Set multiple values at once\n */\n async setMany<T>(\n entries: Array<{ key: string; value: T }>,\n customConfig?: Partial<CacheConfig>\n ): Promise<void> {\n for (const entry of entries) {\n await this.set(entry.key, entry.value, customConfig)\n }\n }\n\n /**\n * Delete multiple keys at once\n */\n async deleteMany(keys: string[]): Promise<void> {\n for (const key of keys) {\n await this.delete(key)\n }\n }\n\n /**\n * Get or set pattern - fetch from cache or compute if not found\n */\n async getOrSet<T>(\n key: string,\n fetcher: () => Promise<T>,\n customConfig?: Partial<CacheConfig>\n ): Promise<T> {\n // Try to get from cache\n const cached = await this.get<T>(key)\n if (cached !== null) {\n return cached\n }\n\n // Fetch from source\n const value = await fetcher()\n\n // Store in cache\n await this.set(key, value, customConfig)\n\n return value\n }\n\n /**\n * List all cache keys with metadata\n */\n async listKeys(): Promise<Array<{ key: string; size: number; expiresAt: number; age: number }>> {\n const keys: Array<{ key: string; size: number; expiresAt: number; age: number }> = []\n\n // Get keys from memory cache\n if (this.config.memoryEnabled) {\n const cache = (this.memoryCache as any).cache as Map<string, CacheEntry<any>>\n for (const [key, entry] of cache.entries()) {\n const size = JSON.stringify(entry).length * 2\n const age = Date.now() - entry.timestamp\n keys.push({\n key,\n size,\n expiresAt: entry.expiresAt,\n age\n })\n }\n }\n\n // Sort by age (newest first)\n return keys.sort((a, b) => a.age - b.age)\n }\n\n /**\n * Get cache entry with full metadata\n */\n async getEntry<T>(key: string): Promise<{\n data: T\n timestamp: number\n expiresAt: number\n ttl: number\n size: number\n } | null> {\n if (!this.config.memoryEnabled) {\n return null\n }\n\n const cache = (this.memoryCache as any).cache as Map<string, CacheEntry<any>>\n const entry = cache.get(key)\n\n if (!entry) {\n return null\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n await this.delete(key)\n return null\n }\n\n const size = JSON.stringify(entry).length * 2\n const ttl = Math.max(0, entry.expiresAt - Date.now()) / 1000\n\n return {\n data: entry.data as T,\n timestamp: entry.timestamp,\n expiresAt: entry.expiresAt,\n ttl,\n size\n }\n }\n}\n\n/**\n * Create a cache service instance with configuration\n */\nexport function createCacheService(config: CacheConfig, kvNamespace?: KVNamespace): CacheService {\n return new CacheService(config, kvNamespace)\n}\n\n/**\n * Global cache instances by namespace (singleton pattern)\n */\nconst cacheInstances = new Map<string, CacheService>()\nlet globalKVNamespace: KVNamespace | undefined\n\n/**\n * Set global KV namespace for all cache instances\n */\nexport function setGlobalKVNamespace(kvNamespace: KVNamespace): void {\n globalKVNamespace = kvNamespace\n}\n\n/**\n * Get or create a cache service for a namespace\n */\nexport function getCacheService(config: CacheConfig, kvNamespace?: KVNamespace): CacheService {\n const key = config.namespace\n\n if (!cacheInstances.has(key)) {\n // Use provided KV namespace or global one\n const kv = kvNamespace || globalKVNamespace\n cacheInstances.set(key, new CacheService(config, kv))\n }\n\n return cacheInstances.get(key)!\n}\n\n/**\n * Clear all cache instances\n */\nexport async function clearAllCaches(): Promise<void> {\n for (const cache of cacheInstances.values()) {\n await cache.clear()\n }\n}\n\n/**\n * Get stats from all cache instances\n */\nexport function getAllCacheStats(): Record<string, CacheStats> {\n const stats: Record<string, CacheStats> = {}\n\n for (const [namespace, cache] of cacheInstances.entries()) {\n stats[namespace] = cache.getStats()\n }\n\n return stats\n}\n","/**\n * Event Bus for Cache Invalidation\n *\n * Provides a centralized event system for triggering cache invalidation\n * based on application events.\n */\n\nexport type EventHandler = (data?: any) => Promise<void> | void\n\n// interface EventSubscription {\n// event: string\n// handler: EventHandler\n// }\n\nclass EventBus {\n private subscriptions: Map<string, EventHandler[]> = new Map()\n private eventLog: Array<{ event: string; timestamp: number; data?: any }> = []\n private maxLogSize: number = 100\n\n /**\n * Subscribe to an event\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this.subscriptions.has(event)) {\n this.subscriptions.set(event, [])\n }\n\n this.subscriptions.get(event)!.push(handler)\n\n // Return unsubscribe function\n return () => {\n const handlers = this.subscriptions.get(event)\n if (handlers) {\n const index = handlers.indexOf(handler)\n if (index > -1) {\n handlers.splice(index, 1)\n }\n }\n }\n }\n\n /**\n * Emit an event to all subscribers\n */\n async emit(event: string, data?: any): Promise<void> {\n // Log the event\n this.logEvent(event, data)\n\n const handlers = this.subscriptions.get(event) || []\n\n // Execute all handlers\n await Promise.all(\n handlers.map(async (handler) => {\n try {\n await handler(data)\n } catch (error) {\n console.error(`Error in event handler for ${event}:`, error)\n }\n })\n )\n\n // Also emit to wildcard subscribers\n const wildcardHandlers = this.subscriptions.get('*') || []\n await Promise.all(\n wildcardHandlers.map(async (handler) => {\n try {\n await handler({ event, data })\n } catch (error) {\n console.error(`Error in wildcard event handler for ${event}:`, error)\n }\n })\n )\n }\n\n /**\n * Remove all subscribers for an event\n */\n off(event: string): void {\n this.subscriptions.delete(event)\n }\n\n /**\n * Get all registered events\n */\n getEvents(): string[] {\n return Array.from(this.subscriptions.keys())\n }\n\n /**\n * Get subscriber count for an event\n */\n getSubscriberCount(event: string): number {\n return this.subscriptions.get(event)?.length || 0\n }\n\n /**\n * Log an event for debugging\n */\n private logEvent(event: string, data?: any): void {\n this.eventLog.push({\n event,\n timestamp: Date.now(),\n data\n })\n\n // Keep log size manageable\n if (this.eventLog.length > this.maxLogSize) {\n this.eventLog.shift()\n }\n }\n\n /**\n * Get recent event log\n */\n getEventLog(limit: number = 50): Array<{ event: string; timestamp: number; data?: any }> {\n return this.eventLog.slice(-limit)\n }\n\n /**\n * Clear event log\n */\n clearEventLog(): void {\n this.eventLog = []\n }\n\n /**\n * Get statistics\n */\n getStats(): {\n totalEvents: number\n totalSubscriptions: number\n eventCounts: Record<string, number>\n } {\n const eventCounts: Record<string, number> = {}\n\n for (const log of this.eventLog) {\n eventCounts[log.event] = (eventCounts[log.event] || 0) + 1\n }\n\n return {\n totalEvents: this.eventLog.length,\n totalSubscriptions: this.subscriptions.size,\n eventCounts\n }\n }\n}\n\n// Global event bus instance\nlet globalEventBus: EventBus | null = null\n\n/**\n * Get or create the global event bus\n */\nexport function getEventBus(): EventBus {\n if (!globalEventBus) {\n globalEventBus = new EventBus()\n }\n return globalEventBus\n}\n\n/**\n * Convenience function to emit an event\n */\nexport async function emitEvent(event: string, data?: any): Promise<void> {\n const bus = getEventBus()\n await bus.emit(event, data)\n}\n\n/**\n * Convenience function to subscribe to an event\n */\nexport function onEvent(event: string, handler: EventHandler): () => void {\n const bus = getEventBus()\n return bus.on(event, handler)\n}\n","/**\n * Cache Invalidation Service\n *\n * Automatically invalidates cache entries based on application events\n */\n\nimport { getCacheService } from './cache.js'\nimport { CACHE_CONFIGS } from './cache-config.js'\nimport { getEventBus, onEvent } from './event-bus.js'\n\n/**\n * Setup automatic cache invalidation based on events\n */\nexport function setupCacheInvalidation(): void {\n const _eventBus = getEventBus()\n\n // Content cache invalidation\n setupContentInvalidation()\n\n // User cache invalidation\n setupUserInvalidation()\n\n // Config cache invalidation\n setupConfigInvalidation()\n\n // Media cache invalidation\n setupMediaInvalidation()\n\n // API cache invalidation\n setupAPIInvalidation()\n\n // Collection cache invalidation\n setupCollectionInvalidation()\n\n console.log('Cache invalidation listeners registered')\n}\n\n/**\n * Content cache invalidation\n */\nfunction setupContentInvalidation(): void {\n const config = CACHE_CONFIGS.content\n if (!config) return\n const contentCache = getCacheService(config)\n\n // Invalidate on content updates\n onEvent('content.create', async (_data) => {\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.create')\n })\n\n onEvent('content.update', async (data) => {\n if (data?.id) {\n // Invalidate specific content item\n await contentCache.delete(contentCache.generateKey('item', data.id))\n }\n // Invalidate all content lists\n await contentCache.invalidate('content:list:*')\n console.log('Cache invalidated: content.update', data?.id)\n })\n\n onEvent('content.delete', async (data) => {\n if (data?.id) {\n await contentCache.delete(contentCache.generateKey('item', data.id))\n }\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.delete', data?.id)\n })\n\n onEvent('content.publish', async (_data) => {\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.publish')\n })\n}\n\n/**\n * User cache invalidation\n */\nfunction setupUserInvalidation(): void {\n const config = CACHE_CONFIGS.user\n if (!config) return\n const userCache = getCacheService(config)\n\n onEvent('user.update', async (data) => {\n if (data?.id) {\n await userCache.delete(userCache.generateKey('id', data.id))\n }\n if (data?.email) {\n await userCache.delete(userCache.generateKey('email', data.email))\n }\n console.log('Cache invalidated: user.update', data?.id)\n })\n\n onEvent('user.delete', async (data) => {\n if (data?.id) {\n await userCache.delete(userCache.generateKey('id', data.id))\n }\n if (data?.email) {\n await userCache.delete(userCache.generateKey('email', data.email))\n }\n console.log('Cache invalidated: user.delete', data?.id)\n })\n\n onEvent('auth.login', async (data) => {\n if (data?.userId) {\n await userCache.delete(userCache.generateKey('id', data.userId))\n }\n console.log('Cache invalidated: auth.login', data?.userId)\n })\n\n onEvent('auth.logout', async (data) => {\n // Clear session cache\n const sessionConfig = CACHE_CONFIGS.session\n if (sessionConfig) {\n const sessionCache = getCacheService(sessionConfig)\n if (data?.sessionId) {\n await sessionCache.delete(sessionCache.generateKey('session', data.sessionId))\n }\n }\n console.log('Cache invalidated: auth.logout')\n })\n}\n\n/**\n * Config cache invalidation\n */\nfunction setupConfigInvalidation(): void {\n const configConfig = CACHE_CONFIGS.config\n if (!configConfig) return\n const configCache = getCacheService(configConfig)\n\n onEvent('config.update', async (_data) => {\n await configCache.invalidate('config:*')\n console.log('Cache invalidated: config.update')\n })\n\n onEvent('plugin.activate', async (data) => {\n await configCache.invalidate('config:*')\n const pluginConfig = CACHE_CONFIGS.plugin\n if (pluginConfig) {\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n }\n console.log('Cache invalidated: plugin.activate', data?.pluginId)\n })\n\n onEvent('plugin.deactivate', async (data) => {\n await configCache.invalidate('config:*')\n const pluginConfig = CACHE_CONFIGS.plugin\n if (pluginConfig) {\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n }\n console.log('Cache invalidated: plugin.deactivate', data?.pluginId)\n })\n\n onEvent('plugin.update', async (data) => {\n const pluginConfig = CACHE_CONFIGS.plugin\n if (!pluginConfig) return\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n console.log('Cache invalidated: plugin.update', data?.pluginId)\n })\n}\n\n/**\n * Media cache invalidation\n */\nfunction setupMediaInvalidation(): void {\n const config = CACHE_CONFIGS.media\n if (!config) return\n const mediaCache = getCacheService(config)\n\n onEvent('media.upload', async (_data) => {\n await mediaCache.invalidate('media:*')\n console.log('Cache invalidated: media.upload')\n })\n\n onEvent('media.delete', async (data) => {\n if (data?.id) {\n await mediaCache.delete(mediaCache.generateKey('item', data.id))\n }\n await mediaCache.invalidate('media:list:*')\n console.log('Cache invalidated: media.delete', data?.id)\n })\n\n onEvent('media.update', async (data) => {\n if (data?.id) {\n await mediaCache.delete(mediaCache.generateKey('item', data.id))\n }\n await mediaCache.invalidate('media:list:*')\n console.log('Cache invalidated: media.update', data?.id)\n })\n}\n\n/**\n * API cache invalidation (depends on content changes)\n */\nfunction setupAPIInvalidation(): void {\n const config = CACHE_CONFIGS.api\n if (!config) return\n const apiCache = getCacheService(config)\n\n onEvent('content.update', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.update)')\n })\n\n onEvent('content.publish', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.publish)')\n })\n\n onEvent('content.create', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.create)')\n })\n\n onEvent('content.delete', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.delete)')\n })\n\n onEvent('collection.update', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (collection.update)')\n })\n}\n\n/**\n * Collection cache invalidation\n */\nfunction setupCollectionInvalidation(): void {\n const config = CACHE_CONFIGS.collection\n if (!config) return\n const collectionCache = getCacheService(config)\n\n onEvent('collection.create', async (_data) => {\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.create')\n })\n\n onEvent('collection.update', async (data) => {\n if (data?.id) {\n await collectionCache.delete(collectionCache.generateKey('item', data.id))\n }\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.update', data?.id)\n })\n\n onEvent('collection.delete', async (data) => {\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.delete', data?.id)\n })\n}\n\n/**\n * Get invalidation statistics\n */\nexport function getCacheInvalidationStats() {\n const eventBus = getEventBus()\n return eventBus.getStats()\n}\n\n/**\n * Get recent invalidation events\n */\nexport function getRecentInvalidations(limit: number = 50) {\n const eventBus = getEventBus()\n return eventBus.getEventLog(limit)\n}\n","/**\n * Cache Warming Utilities\n *\n * Utilities for preloading and warming cache entries\n */\n\nimport { getCacheService } from './cache.js'\nimport { CACHE_CONFIGS } from './cache-config.js'\n\n/**\n * Warm cache with common queries\n */\nexport async function warmCommonCaches(db: D1Database): Promise<{\n warmed: number\n errors: number\n details: Array<{ namespace: string; count: number }>\n}> {\n let totalWarmed = 0\n let totalErrors = 0\n const details: Array<{ namespace: string; count: number }> = []\n\n try {\n // Warm collection cache\n const collectionCount = await warmCollections(db)\n totalWarmed += collectionCount\n details.push({ namespace: 'collection', count: collectionCount })\n\n // Warm content cache (most recent items)\n const contentCount = await warmRecentContent(db)\n totalWarmed += contentCount\n details.push({ namespace: 'content', count: contentCount })\n\n // Warm media cache (most recent items)\n const mediaCount = await warmRecentMedia(db)\n totalWarmed += mediaCount\n details.push({ namespace: 'media', count: mediaCount })\n\n } catch (error) {\n console.error('Error warming caches:', error)\n totalErrors++\n }\n\n return {\n warmed: totalWarmed,\n errors: totalErrors,\n details\n }\n}\n\n/**\n * Warm collections cache\n */\nasync function warmCollections(db: D1Database): Promise<number> {\n const config = CACHE_CONFIGS.collection\n if (!config) return 0\n const collectionCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare('SELECT * FROM collections WHERE is_active = 1')\n const { results } = await stmt.all()\n\n for (const collection of results as any[]) {\n const key = collectionCache.generateKey('item', collection.id)\n await collectionCache.set(key, collection)\n count++\n }\n\n // Also cache the full list\n const listKey = collectionCache.generateKey('list', 'all')\n await collectionCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming collections cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm recent content cache\n */\nasync function warmRecentContent(db: D1Database, limit: number = 50): Promise<number> {\n const config = CACHE_CONFIGS.content\n if (!config) return 0\n const contentCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare(`SELECT * FROM content ORDER BY created_at DESC LIMIT ${limit}`)\n const { results } = await stmt.all()\n\n for (const content of results as any[]) {\n const key = contentCache.generateKey('item', content.id)\n await contentCache.set(key, content)\n count++\n }\n\n // Cache the list\n const listKey = contentCache.generateKey('list', 'recent')\n await contentCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming content cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm recent media cache\n */\nasync function warmRecentMedia(db: D1Database, limit: number = 50): Promise<number> {\n const config = CACHE_CONFIGS.media\n if (!config) return 0\n const mediaCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare(`SELECT * FROM media WHERE deleted_at IS NULL ORDER BY uploaded_at DESC LIMIT ${limit}`)\n const { results } = await stmt.all()\n\n for (const media of results as any[]) {\n const key = mediaCache.generateKey('item', media.id)\n await mediaCache.set(key, media)\n count++\n }\n\n // Cache the list\n const listKey = mediaCache.generateKey('list', 'recent')\n await mediaCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming media cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm specific namespace with custom data\n */\nexport async function warmNamespace(\n namespace: string,\n entries: Array<{ key: string; value: any }>\n): Promise<number> {\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n throw new Error(`Unknown namespace: ${namespace}`)\n }\n\n const cache = getCacheService(config)\n await cache.setMany(entries)\n\n return entries.length\n}\n\n/**\n * Preload cache on application startup\n */\nexport async function preloadCache(db: D1Database): Promise<void> {\n console.log('🔥 Preloading cache...')\n\n const result = await warmCommonCaches(db)\n\n console.log(`✅ Cache preloaded: ${result.warmed} entries across ${result.details.length} namespaces`)\n result.details.forEach(detail => {\n console.log(` - ${detail.namespace}: ${detail.count} entries`)\n })\n\n if (result.errors > 0) {\n console.warn(`⚠️ ${result.errors} errors during cache preloading`)\n }\n}\n\n/**\n * Schedule periodic cache warming\n */\nexport function schedulePeriodicWarming(\n db: D1Database,\n intervalMs: number = 300000 // 5 minutes default\n): NodeJS.Timeout {\n console.log(`⏰ Scheduling periodic cache warming every ${intervalMs / 1000}s`)\n\n return setInterval(async () => {\n try {\n console.log('🔄 Running periodic cache warming...')\n await warmCommonCaches(db)\n } catch (error) {\n console.error('Error during periodic cache warming:', error)\n }\n }, intervalMs)\n}\n","/**\n * Admin Cache Dashboard Template\n *\n * Moved from @sonicjs-cms/templates to avoid circular dependency\n * during build (templates imports from core, core can't import from templates)\n */\n\nimport { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface CacheStats {\n memoryHits: number\n memoryMisses: number\n kvHits: number\n kvMisses: number\n dbHits: number\n totalRequests: number\n hitRate: number\n memorySize: number\n entryCount: number\n}\n\nexport interface CacheDashboardData {\n stats: Record<string, CacheStats>\n totals: {\n hits: number\n misses: number\n requests: number\n hitRate: string\n memorySize: number\n entryCount: number\n }\n namespaces: string[]\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderCacheDashboard(data: CacheDashboardData): string {\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-2xl font-semibold text-zinc-950 dark:text-white\">Cache System</h1>\n <p class=\"mt-1 text-sm text-zinc-600 dark:text-zinc-400\">\n Monitor and manage cache performance across all namespaces\n </p>\n </div>\n <div class=\"flex gap-3\">\n <button\n onclick=\"refreshStats()\"\n class=\"inline-flex items-center gap-2 rounded-lg bg-white dark:bg-zinc-900 px-4 py-2 text-sm font-medium text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n <button\n onclick=\"clearAllCaches()\"\n class=\"inline-flex items-center gap-2 rounded-lg bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n Clear All\n </button>\n </div>\n </div>\n\n <!-- Overall Stats Cards -->\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n ${renderStatCard('Total Requests', data.totals.requests.toLocaleString(), 'lime', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 7h8m0 0v8m0-8l-8 8-4-4-6 6\"/>\n </svg>\n `)}\n\n ${renderStatCard('Hit Rate', data.totals.hitRate + '%', 'blue', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n `, parseFloat(data.totals.hitRate) > 70 ? 'lime' : parseFloat(data.totals.hitRate) > 40 ? 'amber' : 'red')}\n\n ${renderStatCard('Memory Usage', formatBytes(data.totals.memorySize), 'purple', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z\"/>\n </svg>\n `)}\n\n ${renderStatCard('Cached Entries', data.totals.entryCount.toLocaleString(), 'sky', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01\"/>\n </svg>\n `)}\n </div>\n\n <!-- Namespace Statistics -->\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-4 border-b border-zinc-950/5 dark:border-white/10\">\n <h2 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Cache Namespaces</h2>\n </div>\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-950/5 dark:divide-white/10\">\n <thead class=\"bg-zinc-50 dark:bg-zinc-800/50\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Namespace\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Requests\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Hit Rate\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Memory Hits\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n KV Hits\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Entries\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Size\n </th>\n <th class=\"px-6 py-3 text-right text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-950/5 dark:divide-white/10\">\n ${data.namespaces.map(namespace => {\n const stat = data.stats[namespace]\n if (!stat) return ''\n return renderNamespaceRow(namespace, stat)\n }).join('')}\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Performance Chart Placeholder -->\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-4 border-b border-zinc-950/5 dark:border-white/10\">\n <h2 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Performance Overview</h2>\n </div>\n <div class=\"p-6\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n ${renderPerformanceMetric('Memory Cache', data.totals.hits, data.totals.misses)}\n ${renderHealthStatus(parseFloat(data.totals.hitRate))}\n </div>\n </div>\n </div>\n </div>\n\n <script>\n async function refreshStats() {\n window.location.reload()\n }\n\n async function clearAllCaches() {\n showConfirmDialog('clear-all-cache-confirm')\n }\n\n async function performClearAllCaches() {\n try {\n const response = await fetch('/admin/cache/clear', {\n method: 'POST'\n })\n\n const result = await response.json()\n if (result.success) {\n alert('All caches cleared successfully')\n window.location.reload()\n } else {\n alert('Error clearing caches: ' + result.error)\n }\n } catch (error) {\n alert('Error clearing caches: ' + error.message)\n }\n }\n\n let namespaceToDelete = null\n\n async function clearNamespaceCache(namespace) {\n namespaceToDelete = namespace\n showConfirmDialog('clear-namespace-cache-confirm')\n }\n\n async function performClearNamespaceCache() {\n if (!namespaceToDelete) return\n\n try {\n const response = await fetch(\\`/admin/cache/clear/\\${namespaceToDelete}\\`, {\n method: 'POST'\n })\n\n const result = await response.json()\n if (result.success) {\n alert('Cache cleared successfully')\n window.location.reload()\n } else {\n alert('Error clearing cache: ' + result.error)\n }\n } catch (error) {\n alert('Error clearing cache: ' + error.message)\n } finally {\n namespaceToDelete = null\n }\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'clear-all-cache-confirm',\n title: 'Clear All Cache',\n message: 'Are you sure you want to clear all cache entries? This cannot be undone.',\n confirmText: 'Clear All',\n cancelText: 'Cancel',\n iconColor: 'yellow',\n confirmClass: 'bg-yellow-500 hover:bg-yellow-400',\n onConfirm: 'performClearAllCaches()'\n })}\n\n ${renderConfirmationDialog({\n id: 'clear-namespace-cache-confirm',\n title: 'Clear Namespace Cache',\n message: 'Clear cache for this namespace?',\n confirmText: 'Clear',\n cancelText: 'Cancel',\n iconColor: 'yellow',\n confirmClass: 'bg-yellow-500 hover:bg-yellow-400',\n onConfirm: 'performClearNamespaceCache()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Cache System',\n pageTitle: 'Cache System',\n currentPath: '/admin/cache',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction renderStatCard(label: string, value: string, color: string, icon: string, colorOverride?: string): string {\n const finalColor = colorOverride || color\n const colorClasses = {\n lime: 'bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20',\n blue: 'bg-blue-50 dark:bg-blue-500/10 text-blue-600 dark:text-blue-400 ring-blue-600/20 dark:ring-blue-500/20',\n purple: 'bg-purple-50 dark:bg-purple-500/10 text-purple-600 dark:text-purple-400 ring-purple-600/20 dark:ring-purple-500/20',\n sky: 'bg-sky-50 dark:bg-sky-500/10 text-sky-600 dark:text-sky-400 ring-sky-600/20 dark:ring-sky-500/20',\n amber: 'bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20',\n red: 'bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20'\n }\n\n return `\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"p-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3\">\n <div class=\"rounded-lg p-2 ring-1 ring-inset ${colorClasses[finalColor as keyof typeof colorClasses]}\">\n ${icon}\n </div>\n <div>\n <p class=\"text-sm text-zinc-600 dark:text-zinc-400\">${label}</p>\n <p class=\"mt-1 text-2xl font-semibold text-zinc-950 dark:text-white\">${value}</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n `\n}\n\nfunction renderNamespaceRow(namespace: string, stat: CacheStats): string {\n const hitRate = stat.hitRate.toFixed(1)\n const hitRateColor = stat.hitRate > 70 ? 'text-lime-600 dark:text-lime-400' :\n stat.hitRate > 40 ? 'text-amber-600 dark:text-amber-400' :\n 'text-red-600 dark:text-red-400'\n\n return `\n <tr class=\"hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700\">\n ${namespace}\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100\">\n ${stat.totalRequests.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"text-sm font-medium ${hitRateColor}\">\n ${hitRate}%\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.memoryHits.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.kvHits.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.entryCount.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${formatBytes(stat.memorySize)}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-right text-sm\">\n <button\n onclick=\"clearNamespaceCache('${namespace}')\"\n class=\"text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300\"\n >\n Clear\n </button>\n </td>\n </tr>\n `\n}\n\nfunction renderPerformanceMetric(label: string, hits: number, misses: number): string {\n const total = hits + misses\n const hitPercentage = total > 0 ? (hits / total) * 100 : 0\n\n return `\n <div>\n <h3 class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3\">${label}</h3>\n <div class=\"space-y-2\">\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Hits</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${hits.toLocaleString()}</span>\n </div>\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Misses</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${misses.toLocaleString()}</span>\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between text-sm mb-1\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Hit Rate</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${hitPercentage.toFixed(1)}%</span>\n </div>\n <div class=\"h-2 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden\">\n <div class=\"h-full bg-lime-500 dark:bg-lime-400\" style=\"width: ${hitPercentage}%\"></div>\n </div>\n </div>\n </div>\n </div>\n `\n}\n\nfunction renderHealthStatus(hitRate: number): string {\n const status = hitRate > 70 ? 'healthy' : hitRate > 40 ? 'warning' : 'critical'\n const statusConfig = {\n healthy: {\n label: 'Healthy',\n color: 'lime',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>`\n },\n warning: {\n label: 'Needs Attention',\n color: 'amber',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"/>\n </svg>`\n },\n critical: {\n label: 'Critical',\n color: 'red',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>`\n }\n }\n\n const config = statusConfig[status]\n const colorClasses = {\n lime: 'bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20',\n amber: 'bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20',\n red: 'bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20'\n }\n\n return `\n <div>\n <h3 class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3\">System Health</h3>\n <div class=\"flex items-center gap-3 p-4 rounded-lg ring-1 ring-inset ${colorClasses[config.color as keyof typeof colorClasses]}\">\n ${config.icon}\n <div>\n <p class=\"text-sm font-medium\">${config.label}</p>\n <p class=\"text-xs mt-0.5 opacity-80\">\n ${status === 'healthy' ? 'Cache is performing well' :\n status === 'warning' ? 'Consider increasing cache TTL or capacity' :\n 'Cache hit rate is too low'}\n </p>\n </div>\n </div>\n </div>\n `\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`\n}\n","/**\n * Cache Plugin Routes\n *\n * Admin routes for cache management\n */\n\nimport { Hono } from 'hono'\nimport type { Context } from 'hono'\nimport { getAllCacheStats, clearAllCaches, getCacheService } from './services/cache.js'\nimport { CACHE_CONFIGS, parseCacheKey } from './services/cache-config.js'\nimport { getRecentInvalidations, getCacheInvalidationStats } from './services/cache-invalidation.js'\nimport { warmCommonCaches, warmNamespace } from './services/cache-warming.js'\nimport { renderCacheDashboard, CacheDashboardData } from '../../templates/pages/admin-cache.template'\n\nconst app = new Hono()\n\n/**\n * GET /admin/cache\n * Cache statistics dashboard\n */\napp.get('/', async (c: Context) => {\n const stats = getAllCacheStats()\n const user = c.get('user')\n\n // Calculate totals\n let totalHits = 0\n let totalMisses = 0\n let totalSize = 0\n let totalEntries = 0\n\n Object.values(stats).forEach(stat => {\n totalHits += stat.memoryHits + stat.kvHits\n totalMisses += stat.memoryMisses + stat.kvMisses\n totalSize += stat.memorySize\n totalEntries += stat.entryCount\n })\n\n const totalRequests = totalHits + totalMisses\n const overallHitRate = totalRequests > 0 ? (totalHits / totalRequests) * 100 : 0\n\n const dashboardData: CacheDashboardData = {\n stats,\n totals: {\n hits: totalHits,\n misses: totalMisses,\n requests: totalRequests,\n hitRate: overallHitRate.toFixed(2),\n memorySize: totalSize,\n entryCount: totalEntries\n },\n namespaces: Object.keys(stats),\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion')\n }\n\n return c.html(renderCacheDashboard(dashboardData))\n})\n\n/**\n * GET /admin/cache/stats\n * Detailed statistics for all namespaces\n */\napp.get('/stats', async (c: Context) => {\n const stats = getAllCacheStats()\n\n return c.json({\n success: true,\n data: stats,\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/stats/:namespace\n * Statistics for a specific namespace\n */\napp.get('/stats/:namespace', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const config = CACHE_CONFIGS[namespace]\n\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n const stats = cache.getStats()\n\n return c.json({\n success: true,\n data: {\n namespace,\n config,\n stats\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/clear\n * Clear all cache entries\n */\napp.post('/clear', async (c: Context) => {\n await clearAllCaches()\n\n return c.json({\n success: true,\n message: 'All cache entries cleared',\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/clear/:namespace\n * Clear cache for a specific namespace\n */\napp.post('/clear/:namespace', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const config = CACHE_CONFIGS[namespace]\n\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n await cache.clear()\n\n return c.json({\n success: true,\n message: `Cache cleared for namespace: ${namespace}`,\n namespace,\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/invalidate\n * Invalidate cache entries matching a pattern\n */\napp.post('/invalidate', async (c: Context) => {\n const body = await c.req.json()\n const { pattern, namespace } = body\n\n if (!pattern) {\n return c.json({\n success: false,\n error: 'Pattern is required'\n }, 400)\n }\n\n let totalInvalidated = 0\n\n if (namespace) {\n // Invalidate from specific namespace\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n totalInvalidated = await cache.invalidate(pattern)\n } else {\n // Invalidate from all namespaces\n for (const config of Object.values(CACHE_CONFIGS)) {\n const cache = getCacheService(config)\n totalInvalidated += await cache.invalidate(pattern)\n }\n }\n\n return c.json({\n success: true,\n invalidated: totalInvalidated,\n pattern,\n namespace: namespace || 'all',\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/health\n * Cache system health check\n */\napp.get('/health', async (c: Context) => {\n const stats = getAllCacheStats()\n\n // Calculate health metrics\n const namespaces = Object.entries(stats)\n const healthChecks = namespaces.map(([name, stat]) => {\n const hitRate = stat.hitRate\n const memoryUsage = stat.memorySize / (50 * 1024 * 1024) // Assume 50MB max\n\n return {\n namespace: name,\n status: hitRate > 70 ? 'healthy' : hitRate > 40 ? 'warning' : 'unhealthy',\n hitRate,\n memoryUsage: (memoryUsage * 100).toFixed(2) + '%',\n entryCount: stat.entryCount\n }\n })\n\n const overallStatus = healthChecks.every(h => h.status === 'healthy')\n ? 'healthy'\n : healthChecks.some(h => h.status === 'unhealthy')\n ? 'unhealthy'\n : 'warning'\n\n return c.json({\n success: true,\n data: {\n status: overallStatus,\n namespaces: healthChecks,\n timestamp: new Date().toISOString()\n }\n })\n})\n\n/**\n * GET /admin/cache/browser\n * Browse all cache entries across namespaces\n */\napp.get('/browser', async (c: Context) => {\n const namespace = c.req.query('namespace') || 'all'\n const search = c.req.query('search') || ''\n const sortBy = c.req.query('sort') || 'age' // age, size, key\n const limit = parseInt(c.req.query('limit') || '100')\n\n const entries: Array<{\n namespace: string\n key: string\n size: number\n age: number\n ttl: number\n expiresAt: number\n parsed: any\n }> = []\n\n const namespaces = namespace === 'all'\n ? Object.keys(CACHE_CONFIGS)\n : [namespace]\n\n for (const ns of namespaces) {\n const config = CACHE_CONFIGS[ns]\n if (!config) continue\n\n const cache = getCacheService(config)\n const keys = await cache.listKeys()\n\n for (const keyInfo of keys) {\n // Apply search filter\n if (search && !keyInfo.key.toLowerCase().includes(search.toLowerCase())) {\n continue\n }\n\n const parsed = parseCacheKey(keyInfo.key)\n const ttl = Math.max(0, keyInfo.expiresAt - Date.now()) / 1000\n\n entries.push({\n namespace: ns,\n key: keyInfo.key,\n size: keyInfo.size,\n age: keyInfo.age,\n ttl,\n expiresAt: keyInfo.expiresAt,\n parsed\n })\n }\n }\n\n // Sort entries\n if (sortBy === 'size') {\n entries.sort((a, b) => b.size - a.size)\n } else if (sortBy === 'age') {\n entries.sort((a, b) => a.age - b.age)\n } else if (sortBy === 'key') {\n entries.sort((a, b) => a.key.localeCompare(b.key))\n }\n\n // Limit results\n const limitedEntries = entries.slice(0, limit)\n\n return c.json({\n success: true,\n data: {\n entries: limitedEntries,\n total: entries.length,\n showing: limitedEntries.length,\n namespace,\n search,\n sortBy\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/browser/:namespace/:key\n * Get detailed information about a specific cache entry\n */\napp.get('/browser/:namespace/:key', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const key = decodeURIComponent(c.req.param('key')!)\n\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n const entry = await cache.getEntry(key)\n\n if (!entry) {\n return c.json({\n success: false,\n error: 'Cache entry not found or expired'\n }, 404)\n }\n\n const parsed = parseCacheKey(key)\n\n return c.json({\n success: true,\n data: {\n key,\n namespace,\n parsed,\n ...entry,\n createdAt: new Date(entry.timestamp).toISOString(),\n expiresAt: new Date(entry.expiresAt).toISOString()\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics\n * Advanced cache analytics\n */\napp.get('/analytics', async (c: Context) => {\n const stats = getAllCacheStats()\n const invalidationStats = getCacheInvalidationStats()\n const recentInvalidations = getRecentInvalidations(20)\n\n // Calculate analytics\n let totalHits = 0\n let totalMisses = 0\n let totalSize = 0\n let totalEntries = 0\n\n const namespacesAnalytics = []\n\n for (const [namespace, stat] of Object.entries(stats)) {\n totalHits += stat.memoryHits + stat.kvHits\n totalMisses += stat.memoryMisses + stat.kvMisses\n totalSize += stat.memorySize\n totalEntries += stat.entryCount\n\n const totalRequests = stat.memoryHits + stat.kvHits + stat.memoryMisses + stat.kvMisses\n const hitRate = totalRequests > 0 ? ((stat.memoryHits + stat.kvHits) / totalRequests) * 100 : 0\n const avgEntrySize = stat.entryCount > 0 ? stat.memorySize / stat.entryCount : 0\n\n namespacesAnalytics.push({\n namespace,\n hitRate: hitRate.toFixed(2),\n totalRequests,\n memoryHitRate: totalRequests > 0 ? ((stat.memoryHits / totalRequests) * 100).toFixed(2) : '0',\n kvHitRate: totalRequests > 0 ? ((stat.kvHits / totalRequests) * 100).toFixed(2) : '0',\n avgEntrySize: Math.round(avgEntrySize),\n totalSize: stat.memorySize,\n entryCount: stat.entryCount,\n efficiency: totalRequests > 0 ? ((stat.memoryHits + stat.kvHits) / (stat.memoryHits + stat.kvHits + stat.dbHits + 1)).toFixed(2) : '0'\n })\n }\n\n // Sort by hit rate\n namespacesAnalytics.sort((a, b) => parseFloat(b.hitRate) - parseFloat(a.hitRate))\n\n const totalRequests = totalHits + totalMisses\n const overallHitRate = totalRequests > 0 ? (totalHits / totalRequests) * 100 : 0\n\n // Calculate cost savings (assume 50ms per DB query vs 2ms for cache)\n const dbQueriesAvoided = totalHits\n const timeSaved = dbQueriesAvoided * 48 // 48ms saved per cache hit\n const estimatedCostSavings = (dbQueriesAvoided / 1000000) * 0.50 // $0.50 per million queries\n\n return c.json({\n success: true,\n data: {\n overview: {\n totalHits,\n totalMisses,\n totalRequests,\n overallHitRate: overallHitRate.toFixed(2),\n totalSize,\n totalEntries,\n avgEntrySize: totalEntries > 0 ? Math.round(totalSize / totalEntries) : 0\n },\n performance: {\n dbQueriesAvoided,\n timeSavedMs: timeSaved,\n timeSavedMinutes: (timeSaved / 1000 / 60).toFixed(2),\n estimatedCostSavings: estimatedCostSavings.toFixed(4)\n },\n namespaces: namespacesAnalytics,\n invalidation: {\n ...invalidationStats,\n recent: recentInvalidations\n }\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics/trends\n * Cache trends over time (simplified - would need historical data storage)\n */\napp.get('/analytics/trends', async (c: Context) => {\n const stats = getAllCacheStats()\n\n // For now, return current snapshot as a data point\n // In production, this would query historical data\n const dataPoint = {\n timestamp: Date.now(),\n stats: Object.entries(stats).map(([namespace, stat]) => ({\n namespace,\n hitRate: stat.hitRate,\n entryCount: stat.entryCount,\n memorySize: stat.memorySize,\n totalRequests: stat.totalRequests\n }))\n }\n\n return c.json({\n success: true,\n data: {\n trends: [dataPoint],\n note: 'Historical trends require persistent storage. This returns current snapshot only.'\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics/top-keys\n * Most accessed cache keys (would need hit tracking)\n */\napp.get('/analytics/top-keys', async (c: Context) => {\n const _namespace = c.req.query('namespace') || 'all'\n const _limit = parseInt(c.req.query('limit') || '10')\n\n // This is a placeholder - would need per-key hit tracking\n return c.json({\n success: true,\n data: {\n topKeys: [],\n note: 'Top keys tracking requires per-key hit counting. Feature not yet implemented.'\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/warm\n * Warm cache with common queries\n */\napp.post('/warm', async (c: Context) => {\n try {\n const db = c.env.DB as D1Database\n const result = await warmCommonCaches(db)\n\n return c.json({\n success: true,\n message: 'Cache warming completed',\n ...result,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Cache warming error:', error)\n return c.json({\n success: false,\n error: 'Cache warming failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\n/**\n * POST /admin/cache/warm/:namespace\n * Warm specific namespace cache\n */\napp.post('/warm/:namespace', async (c: Context) => {\n try {\n const namespace = c.req.param('namespace')!\n const body = await c.req.json()\n const { entries } = body\n\n if (!entries || !Array.isArray(entries)) {\n return c.json({\n success: false,\n error: 'Entries array is required'\n }, 400)\n }\n\n const count = await warmNamespace(namespace, entries)\n\n return c.json({\n success: true,\n message: `Warmed ${count} entries in namespace: ${namespace}`,\n namespace,\n count,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Namespace warming error:', error)\n return c.json({\n success: false,\n error: 'Namespace warming failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\nexport default app\n","/**\n * Cache Plugin\n *\n * Three-tiered caching system for SonicJS\n * - Tier 1: In-Memory (fastest, region-specific)\n * - Tier 2: Cloudflare KV (fast, global)\n * - Tier 3: Database (source of truth)\n */\n\nimport type { Context } from 'hono'\nimport type { PluginContext } from '@sonicjs-cms/core'\nimport { getCacheService, clearAllCaches, getAllCacheStats } from './services/cache.js'\nimport { CACHE_CONFIGS } from './services/cache-config.js'\nimport { setupCacheInvalidation } from './services/cache-invalidation.js'\nimport cacheRoutes from './routes.js'\n\nexport class CachePlugin {\n private _context: PluginContext | null = null\n\n /**\n * Get plugin routes\n */\n getRoutes() {\n return cacheRoutes\n }\n\n /**\n * Activate the cache plugin\n */\n async activate(context: PluginContext): Promise<void> {\n this._context = context\n\n const settings = context.config || {}\n\n console.log('✅ Cache plugin activated', {\n memoryEnabled: settings.memoryEnabled ?? true,\n kvEnabled: settings.kvEnabled ?? false,\n defaultTTL: settings.defaultTTL ?? 3600\n })\n\n // Initialize default cache services\n for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {\n getCacheService({\n ...config,\n memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,\n kvEnabled: settings.kvEnabled ?? config.kvEnabled,\n ttl: settings.defaultTTL ?? config.ttl\n })\n }\n\n // Setup event-based cache invalidation\n setupCacheInvalidation()\n }\n\n /**\n * Deactivate the cache plugin\n */\n async deactivate(): Promise<void> {\n console.log('❌ Cache plugin deactivated - clearing all caches')\n await clearAllCaches()\n this._context = null\n }\n\n /**\n * Configure the cache plugin\n */\n async configure(settings: Record<string, any>): Promise<void> {\n console.log('⚙️ Cache plugin configured', settings)\n\n // Reconfigure all cache instances with new settings\n for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {\n getCacheService({\n ...config,\n memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,\n kvEnabled: settings.kvEnabled ?? config.kvEnabled,\n ttl: settings.defaultTTL ?? config.ttl\n })\n }\n }\n\n /**\n * Get cache statistics\n */\n async getStats(c: Context): Promise<Response> {\n const stats = getAllCacheStats()\n\n return c.json({\n success: true,\n data: stats,\n timestamp: new Date().toISOString()\n })\n }\n\n /**\n * Clear all cache entries\n */\n async clearCache(c: Context): Promise<Response> {\n await clearAllCaches()\n\n return c.json({\n success: true,\n message: 'All cache entries cleared',\n timestamp: new Date().toISOString()\n })\n }\n\n /**\n * Invalidate cache entries matching pattern\n */\n async invalidatePattern(c: Context): Promise<Response> {\n const body = await c.req.json()\n const { pattern, namespace: _namespace } = body\n\n if (!pattern) {\n return c.json({\n success: false,\n error: 'Pattern is required'\n }, 400)\n }\n\n let totalInvalidated = 0\n\n if (_namespace) {\n // Invalidate from specific namespace\n const cache = getCacheService(CACHE_CONFIGS[_namespace] || {\n ttl: 3600,\n kvEnabled: false,\n memoryEnabled: true,\n namespace: _namespace,\n invalidateOn: [],\n version: 'v1'\n })\n totalInvalidated = await cache.invalidate(pattern)\n } else {\n // Invalidate from all namespaces\n for (const config of Object.values(CACHE_CONFIGS)) {\n const cache = getCacheService(config)\n totalInvalidated += await cache.invalidate(pattern)\n }\n }\n\n return c.json({\n success: true,\n invalidated: totalInvalidated,\n pattern,\n namespace: _namespace || 'all',\n timestamp: new Date().toISOString()\n })\n }\n}\n\n// Export cache services for use by other plugins/routes when cache plugin is active\nexport {\n getCacheService,\n clearAllCaches,\n getAllCacheStats,\n setGlobalKVNamespace\n} from './services/cache'\nexport { CACHE_CONFIGS, getCacheConfig, generateCacheKey } from './services/cache-config'\nexport type { CacheConfig, CacheStats } from './services/cache-config'\nexport { emitEvent, onEvent, getEventBus } from './services/event-bus'\nexport { getCacheInvalidationStats, getRecentInvalidations } from './services/cache-invalidation'\nexport { warmCommonCaches, warmNamespace, preloadCache } from './services/cache-warming'\n\n// Create and export plugin instance\nconst plugin = new CachePlugin()\nexport default plugin\n","/**\n * SonicJS Favicon SVG\n *\n * Embedded SVG favicon for the admin interface and auth pages.\n * This ensures the favicon is always available without external dependencies.\n */\n\nexport const faviconSvg = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n version=\"1.1\"\n id=\"Layer_1\"\n x=\"0px\"\n y=\"0px\"\n viewBox=\"380 1300 257.89001 278.8855\"\n xml:space=\"preserve\"\n width=\"257.89001\"\n height=\"278.8855\"\n xmlns=\"http://www.w3.org/2000/svg\">\n<g\n id=\"g10\"\n transform=\"translate(-383.935,-60.555509)\">\n\t<g\n id=\"g9\">\n\t\t<path\n fill=\"#f1f2f2\"\n d=\"m 974.78,1398.211 c -5.016,6.574 -10.034,13.146 -15.048,19.721 -1.828,2.398 -3.657,4.796 -5.487,7.194 1.994,1.719 3.958,3.51 5.873,5.424 18.724,18.731 28.089,41.216 28.089,67.459 0,26.251 -9.366,48.658 -28.089,67.237 -18.731,18.579 -41.215,27.868 -67.459,27.868 -9.848,0 -19.156,-1.308 -27.923,-3.923 l -4.185,3.354 c -8.587,6.885 -17.154,13.796 -25.725,20.702 17.52,8.967 36.86,13.487 58.054,13.487 35.533,0 65.91,-12.608 91.124,-37.821 25.214,-25.215 37.821,-55.584 37.821,-91.125 0,-35.534 -12.607,-65.911 -37.821,-91.126 -3,-2.999 -6.078,-5.808 -9.224,-8.451 z\"\n id=\"path2\" />\n\t\t<path\n fill=\"#34d399\"\n d=\"m 854.024,1585.195 20.001,-16.028 c 16.616,-13.507 33.04,-27.265 50.086,-40.251 1.13,-0.861 2.9,-1.686 2.003,-3.516 -0.843,-1.716 -2.481,-2.302 -4.484,-2.123 -8.514,0.765 -17.016,-0.538 -25.537,-0.353 -1.124,0.024 -2.768,0.221 -3.163,-1.25 -0.371,-1.369 1.088,-2.063 1.919,-2.894 6.26,-6.242 12.574,-12.43 18.816,-18.691 9.303,-9.327 18.565,-18.714 27.851,-28.066 1.848,-1.859 3.701,-3.713 5.549,-5.572 2.655,-2.661 5.309,-5.315 7.958,-7.982 0.574,-0.579 1.259,-1.141 1.246,-1.94 -0.004,-0.257 -0.078,-0.538 -0.254,-0.853 -0.556,-0.981 -1.441,-1.1 -2.469,-0.957 -0.658,0.096 -1.315,0.185 -1.973,0.275 -3.844,0.538 -7.689,1.076 -11.533,1.608 -3.641,0.505 -7.281,1.02 -10.922,1.529 -4.162,0.582 -8.324,1.158 -12.486,1.748 -1.142,0.161 -2.409,1.662 -3.354,0.508 -0.419,-0.508 -0.431,-1.028 -0.251,-1.531 0.269,-0.741 0.957,-1.441 1.387,-2.021 3.414,-4.58 6.882,-9.124 10.356,-13.662 1.74,-2.272 3.48,-4.544 5.214,-6.822 4.682,-6.141 9.369,-12.281 14.051,-18.422 0.09,-0.119 0.181,-0.237 0.271,-0.355 6.848,-8.98 13.7,-17.958 20.553,-26.936 0.488,-0.64 0.977,-1.28 1.465,-1.92 2.159,-2.828 4.315,-5.658 6.476,-8.486 4.197,-5.501 8.454,-10.954 12.67,-16.442 0.263,-0.347 0.538,-0.718 0.717,-1.106 0.269,-0.586 0.299,-1.196 -0.335,-1.776 -0.825,-0.753 -1.8,-0.15 -2.595,0.419 -0.67,0.472 -1.333,0.957 -1.955,1.489 -2.206,1.889 -4.401,3.797 -6.595,5.698 -3.958,3.438 -7.922,6.876 -11.976,10.194 -2.443,2.003 -4.865,4.028 -7.301,6.038 -18.689,-10.581 -39.53,-15.906 -62.549,-15.906 -35.54,0 -65.911,12.607 -91.125,37.82 -25.214,25.215 -37.821,55.592 -37.821,91.126 0,35.54 12.607,65.91 37.821,91.125 4.146,4.146 8.445,7.916 12.87,11.381 -9.015,11.14 -18.036,22.277 -27.034,33.429 -1.208,1.489 -3.755,3.151 -2.745,4.891 0.078,0.144 0.173,0.281 0.305,0.425 1.321,1.429 3.492,-1.303 4.933,-2.457 6.673,-5.333 13.333,-10.685 19.982,-16.042 3.707,-2.984 7.417,-5.965 11.124,-8.952 1.474,-1.188 2.951,-2.373 4.425,-3.561 6.41,-5.164 12.816,-10.333 19.238,-15.481 z m -56.472,-87.186 c 0,-26.243 9.29,-48.728 27.868,-67.459 18.579,-18.723 40.987,-28.089 67.238,-28.089 12.273,0 23.712,2.075 34.34,6.171 -3.37,2.905 -6.734,5.816 -10.069,8.762 -6.075,5.351 -12.365,10.469 -18.667,15.564 -4.179,3.378 -8.371,6.744 -12.514,10.164 -7.54,6.23 -15.037,12.52 -22.529,18.804 -7.091,5.955 -14.182,11.904 -21.19,17.949 -1.136,0.974 -3.055,1.907 -2.135,3.94 0.831,1.836 2.774,1.417 4.341,1.578 l 12.145,-0.599 14.151,-0.698 c 1.031,-0.102 2.192,-0.257 2.89,0.632 0.034,0.044 0.073,0.078 0.106,0.127 1.017,1.561 -0.67,2.105 -1.387,2.942 -6.308,7.318 -12.616,14.637 -18.978,21.907 -8.161,9.339 -16.353,18.649 -24.544,27.958 -2.146,2.433 -4.275,4.879 -6.422,7.312 -1.034,1.172 -2.129,2.272 -1.238,3.922 0.933,1.728 2.685,1.752 4.323,1.602 4.134,-0.367 8.263,-0.489 12.396,-0.492 0.242,0 0.485,-0.01 0.728,0 2.711,0.01 5.422,0.068 8.134,0.145 2.582,0.074 5.166,0.165 7.752,0.249 0.275,1.62 -0.879,2.356 -1.62,3.259 -1.333,1.626 -2.667,3.247 -4,4.867 -4.315,5.252 -8.62,10.514 -12.928,15.772 -3.562,-2.725 -7.007,-5.733 -10.324,-9.051 -18.577,-18.576 -27.867,-40.983 -27.867,-67.234 z\"\n id=\"path9\" />\n\t</g>\n</g>\n</svg>`;\n","/**\n * Main Application Factory\n *\n * Creates a configured SonicJS application with all core functionality\n */\n\nimport { Hono } from 'hono'\nimport type { Context } from 'hono'\nimport type { D1Database, KVNamespace, R2Bucket } from '@cloudflare/workers-types'\nimport {\n apiRoutes,\n apiMediaRoutes,\n apiSystemRoutes,\n adminApiRoutes,\n authRoutes,\n testCleanupRoutes,\n adminContentRoutes,\n adminUsersRoutes,\n adminMediaRoutes,\n adminPluginRoutes,\n adminLogsRoutes,\n adminDashboardRoutes,\n adminCollectionsRoutes,\n adminSettingsRoutes,\n adminFormsRoutes,\n publicFormsRoutes,\n adminApiReferenceRoutes\n} from './routes'\nimport { getCoreVersion } from './utils/version'\nimport { bootstrapMiddleware } from './middleware/bootstrap'\nimport { metricsMiddleware } from './middleware/metrics'\nimport { csrfProtection } from './middleware/csrf'\nimport { securityHeadersMiddleware } from './middleware/security-headers'\nimport { createDatabaseToolsAdminRoutes } from './plugins/core-plugins/database-tools-plugin/admin-routes'\nimport { createSeedDataAdminRoutes } from './plugins/core-plugins/seed-data-plugin/admin-routes'\nimport { emailPlugin } from './plugins/core-plugins/email-plugin'\nimport { otpLoginPlugin } from './plugins/core-plugins/otp-login-plugin'\nimport { oauthProvidersPlugin } from './plugins/core-plugins/oauth-providers'\nimport { userProfilesPlugin } from './plugins/core-plugins/user-profiles'\nimport { aiSearchPlugin } from './plugins/core-plugins/ai-search-plugin'\nimport { createMagicLinkAuthPlugin } from './plugins/available/magic-link-auth'\nimport { securityAuditPlugin } from './plugins/core-plugins/security-audit-plugin'\nimport { securityAuditMiddleware } from './plugins/core-plugins/security-audit-plugin'\nimport { pluginMenuMiddleware } from './middleware/plugin-menu'\nimport cachePlugin from './plugins/cache'\nimport { faviconSvg } from './assets/favicon'\nimport { setAppInstance } from './services/route-metadata'\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\nexport interface Bindings {\n DB: D1Database\n CACHE_KV: KVNamespace\n MEDIA_BUCKET: R2Bucket\n ASSETS: Fetcher\n EMAIL_QUEUE?: Queue\n SENDGRID_API_KEY?: string\n DEFAULT_FROM_EMAIL?: string\n IMAGES_ACCOUNT_ID?: string\n IMAGES_API_TOKEN?: string\n ENVIRONMENT?: string\n CORS_ORIGINS?: string\n JWT_SECRET?: string\n BUCKET_NAME?: string\n GOOGLE_MAPS_API_KEY?: string\n}\n\nexport interface Variables {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n requestId?: string\n startTime?: number\n appVersion?: string\n csrfToken?: string\n pluginMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nexport interface SonicJSConfig {\n // Collections configuration\n collections?: {\n directory?: string\n autoSync?: boolean\n }\n\n // Plugins configuration\n plugins?: {\n directory?: string\n autoLoad?: boolean\n disableAll?: boolean // Disable all plugins including core plugins\n }\n\n // Custom routes\n routes?: Array<{\n path: string\n handler: Hono\n }>\n\n // Custom middleware\n middleware?: {\n beforeAuth?: Array<(c: Context, next: () => Promise<void>) => Promise<void>>\n afterAuth?: Array<(c: Context, next: () => Promise<void>) => Promise<void>>\n }\n\n // App metadata\n version?: string\n name?: string\n}\n\nexport type SonicJSApp = Hono<{ Bindings: Bindings; Variables: Variables }>\n\n// ============================================================================\n// Application Factory\n// ============================================================================\n\n/**\n * Create a SonicJS application with core functionality\n *\n * @param config - Application configuration\n * @returns Configured Hono application\n *\n * @example\n * ```typescript\n * import { createSonicJSApp } from '@sonicjs-cms/core'\n *\n * const app = createSonicJSApp({\n * collections: {\n * directory: './src/collections',\n * autoSync: true\n * },\n * plugins: {\n * directory: './src/plugins',\n * autoLoad: true\n * }\n * })\n *\n * export default app\n * ```\n */\nexport function createSonicJSApp(config: SonicJSConfig = {}): SonicJSApp {\n const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n // Set app metadata\n const appVersion = config.version || getCoreVersion()\n const appName = config.name || 'SonicJS AI'\n\n // App version middleware\n app.use('*', async (c, next) => {\n c.set('appVersion', appVersion)\n await next()\n })\n\n // Metrics middleware - track all requests for real-time analytics\n app.use('*', metricsMiddleware())\n\n // Bootstrap middleware - runs migrations, syncs collections, and initializes plugins\n app.use('*', bootstrapMiddleware(config))\n\n // Custom middleware - before auth\n if (config.middleware?.beforeAuth) {\n for (const middleware of config.middleware.beforeAuth) {\n app.use('*', middleware)\n }\n }\n\n // Logging middleware\n app.use('*', async (_c, next) => {\n // Logging logic here\n await next()\n })\n\n // Security middleware\n app.use('*', securityHeadersMiddleware())\n\n // CSRF protection middleware\n app.use('*', csrfProtection())\n\n // Custom middleware - after auth\n if (config.middleware?.afterAuth) {\n for (const middleware of config.middleware.afterAuth) {\n app.use('*', middleware)\n }\n }\n\n // Plugin dynamic menu items for admin sidebar\n app.use('/admin/*', pluginMenuMiddleware())\n\n // Core routes\n // Routes are being imported incrementally from routes/*\n // Each route is tested and migrated one-by-one\n app.route('/api', apiRoutes)\n app.route('/api/media', apiMediaRoutes)\n app.route('/api/system', apiSystemRoutes)\n app.route('/admin/api', adminApiRoutes)\n app.route('/admin/dashboard', adminDashboardRoutes)\n app.route('/admin/collections', adminCollectionsRoutes)\n app.route('/admin/forms', adminFormsRoutes)\n app.route('/admin/settings', adminSettingsRoutes)\n app.route('/forms', publicFormsRoutes)\n app.route('/api/forms', publicFormsRoutes) // API endpoint for form submissions\n app.route('/admin/api-reference', adminApiReferenceRoutes)\n app.route('/admin/database-tools', createDatabaseToolsAdminRoutes())\n app.route('/admin/seed-data', createSeedDataAdminRoutes())\n app.route('/admin/content', adminContentRoutes)\n app.route('/admin/media', adminMediaRoutes)\n // Security audit middleware - logs auth events (login, register, logout)\n app.use('/auth/*', securityAuditMiddleware())\n\n // Plugin routes - Security Audit (MUST be registered BEFORE admin/plugins to avoid route conflict)\n if (securityAuditPlugin.routes && securityAuditPlugin.routes.length > 0) {\n for (const route of securityAuditPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - AI Search (MUST be registered BEFORE admin/plugins to avoid route conflict)\n // Register AI Search routes first so they take precedence over the generic /:id handler\n if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {\n for (const route of aiSearchPlugin.routes) {\n app.route(route.path, route.handler)\n }\n }\n\n // Plugin routes - Cache (dashboard and management API)\n // Fixes GitHub Issue #461: Cache routes were not registered\n app.route('/admin/cache', cachePlugin.getRoutes())\n\n // Plugin routes - OAuth Providers (MUST be registered BEFORE admin/plugins to avoid route conflict)\n if (oauthProvidersPlugin.routes && oauthProvidersPlugin.routes.length > 0) {\n for (const route of oauthProvidersPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - User Profiles\n if (userProfilesPlugin.routes && userProfilesPlugin.routes.length > 0) {\n for (const route of userProfilesPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - OTP Login (MUST be registered BEFORE admin/plugins to avoid route conflict)\n // Register OTP Login routes first so they take precedence over the generic /:id handler\n if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {\n for (const route of otpLoginPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n app.route('/admin/plugins', adminPluginRoutes)\n app.route('/admin/logs', adminLogsRoutes)\n app.route('/admin', adminUsersRoutes)\n app.route('/auth', authRoutes)\n\n // Test cleanup routes (only for development/test environments)\n app.route('/', testCleanupRoutes)\n\n // Plugin routes - Email\n if (emailPlugin.routes && emailPlugin.routes.length > 0) {\n for (const route of emailPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - Magic Link Auth (passwordless authentication via email links)\n const magicLinkPlugin = createMagicLinkAuthPlugin()\n if (magicLinkPlugin.routes && magicLinkPlugin.routes.length > 0) {\n for (const route of magicLinkPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Serve favicon\n app.get('/favicon.svg', (c) => {\n return new Response(faviconSvg, {\n headers: {\n 'Content-Type': 'image/svg+xml',\n 'Cache-Control': 'public, max-age=31536000'\n }\n })\n })\n\n // Serve files from R2 storage (public file access)\n app.get('/files/*', async (c) => {\n try {\n // Extract the path from the URL pathname (everything after /files/)\n const url = new URL(c.req.url)\n const pathname = url.pathname\n\n // Remove the /files/ prefix to get the R2 object key\n const objectKey = pathname.replace(/^\\/files\\//, '')\n\n if (!objectKey) {\n return c.notFound()\n }\n\n // Get file from R2\n const object = await c.env.MEDIA_BUCKET.get(objectKey)\n\n if (!object) {\n return c.notFound()\n }\n\n // Set appropriate headers\n const headers = new Headers()\n object.httpMetadata?.contentType && headers.set('Content-Type', object.httpMetadata.contentType)\n object.httpMetadata?.contentDisposition && headers.set('Content-Disposition', object.httpMetadata.contentDisposition)\n headers.set('Cache-Control', 'public, max-age=31536000') // 1 year cache\n headers.set('Access-Control-Allow-Origin', '*') // Allow CORS for media files\n headers.set('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS')\n headers.set('Access-Control-Allow-Headers', 'Content-Type')\n\n return new Response(object.body as any, {\n headers\n })\n } catch (error) {\n console.error('Error serving file:', error)\n return c.notFound()\n }\n })\n\n // Custom routes - User-defined routes\n if (config.routes) {\n for (const route of config.routes) {\n app.route(route.path, route.handler)\n }\n }\n\n // Root redirect to login\n app.get('/', (c) => {\n return c.redirect('/auth/login')\n })\n\n // Health check\n app.get('/health', (c) => {\n return c.json({\n name: appName,\n version: appVersion,\n status: 'running',\n timestamp: new Date().toISOString()\n })\n })\n\n // Store app instance for route introspection (API reference auto-discovery)\n setAppInstance(app)\n\n // 404 handler\n app.notFound((c) => {\n return c.json({ error: 'Not Found', status: 404 }, 404)\n })\n\n // Error handler\n app.onError((err, c) => {\n console.error(err)\n return c.json({ error: 'Internal Server Error', status: 500 }, 500)\n })\n\n return app\n}\n\n/**\n * Setup core middleware (backward compatibility)\n *\n * @param _app - Hono application\n * @deprecated Use createSonicJSApp() instead\n */\nexport function setupCoreMiddleware(_app: SonicJSApp): void {\n console.warn('setupCoreMiddleware is deprecated. Use createSonicJSApp() instead.')\n // Backward compatibility implementation\n}\n\n/**\n * Setup core routes (backward compatibility)\n *\n * @param _app - Hono application\n * @deprecated Use createSonicJSApp() instead\n */\nexport function setupCoreRoutes(_app: SonicJSApp): void {\n console.warn('setupCoreRoutes is deprecated. Use createSonicJSApp() instead.')\n // Backward compatibility implementation\n}\n","import { drizzle } from 'drizzle-orm/d1';\nimport * as schema from './schema';\n\nexport function createDb(d1: D1Database) {\n return drizzle(d1, { schema });\n}\n\nexport * from './schema';","/**\n * @sonicjs/core - Main Entry Point\n *\n * Core framework for SonicJS headless CMS\n * Built for Cloudflare's edge platform with TypeScript\n *\n * Phase 2 Migration Status:\n * - Week 1: Types, Utils, Database (COMPLETED ✓)\n * - Week 2: Services, Middleware, Plugins (COMPLETED ✓)\n * - Week 3: Routes, Templates (COMPLETED ✓)\n * - Week 4: Integration & Testing (COMPLETED ✓)\n *\n * Test Coverage:\n * - Utilities: 48 tests (sanitize, query-filter, metrics)\n * - Middleware: 51 tests (auth, logging, security, performance)\n * - Total: 99 tests passing\n */\n\n// ============================================================================\n// Main Application API (Phase 2 Week 1)\n// ============================================================================\n\nexport { createSonicJSApp, setupCoreMiddleware, setupCoreRoutes } from './app'\nexport type { SonicJSConfig, SonicJSApp, Bindings, Variables } from './app'\n\n// ============================================================================\n// Placeholders - To be populated in Phase 2\n// ============================================================================\n\n// Services - Week 2 (COMPLETED)\nexport {\n // Collection Management\n loadCollectionConfigs,\n loadCollectionConfig,\n getAvailableCollectionNames,\n validateCollectionConfig,\n registerCollections,\n syncCollections,\n syncCollection,\n isCollectionManaged,\n getManagedCollections,\n cleanupRemovedCollections,\n fullCollectionSync,\n // Form-Collection Sync\n syncAllFormCollections,\n syncFormCollection,\n createContentFromSubmission,\n deriveCollectionSchemaFromFormio,\n deriveSubmissionTitle,\n mapFormStatusToContentStatus,\n backfillFormSubmissions,\n // Database Migrations\n MigrationService,\n // Logging\n Logger,\n getLogger,\n initLogger,\n // Plugin Services - Class implementations\n PluginService as PluginServiceClass,\n PluginBootstrapService,\n} from './services'\n\nexport type { Migration, MigrationStatus, LogLevel, LogCategory, LogEntry, LogFilter, CorePlugin } from './services'\n\n// Middleware - Week 2 (COMPLETED)\nexport {\n // Authentication\n AuthManager,\n requireAuth,\n requireRole,\n optionalAuth,\n // Logging\n loggingMiddleware,\n detailedLoggingMiddleware,\n securityLoggingMiddleware,\n performanceLoggingMiddleware,\n // Performance\n cacheHeaders,\n compressionMiddleware,\n securityHeaders,\n // Permissions\n PermissionManager,\n requirePermission,\n requireAnyPermission,\n logActivity,\n // Plugin middleware\n requireActivePlugin,\n requireActivePlugins,\n getActivePlugins,\n isPluginActive,\n // Bootstrap\n bootstrapMiddleware,\n} from './middleware'\n\nexport type { Permission, UserPermissions } from './middleware'\n\n// Plugins - Week 2 (COMPLETED)\nexport {\n // Hook System - Class implementations\n HookSystemImpl,\n ScopedHookSystem as ScopedHookSystemClass,\n HookUtils,\n // Plugin Registry\n PluginRegistryImpl,\n // Plugin Manager - Class implementation\n PluginManager as PluginManagerClass,\n // Plugin Validator - Class implementation\n PluginValidator as PluginValidatorClass,\n} from './plugins'\n\n// Routes - Week 3 (COMPLETED)\nexport {\n ROUTES_INFO,\n apiRoutes,\n apiContentCrudRoutes,\n apiMediaRoutes,\n apiSystemRoutes,\n adminApiRoutes,\n authRoutes,\n adminContentRoutes,\n adminUsersRoutes,\n adminMediaRoutes,\n adminLogsRoutes,\n adminPluginRoutes,\n adminDesignRoutes,\n adminCheckboxRoutes,\n adminTestimonialsRoutes,\n adminCodeExamplesRoutes,\n adminDashboardRoutes,\n adminCollectionsRoutes,\n adminSettingsRoutes,\n} from './routes'\n\n// Templates - Week 3 (COMPLETED)\nexport {\n // Form templates\n renderForm,\n renderFormField,\n // Table templates\n renderTable,\n // Pagination templates\n renderPagination,\n // Alert templates\n renderAlert,\n // Confirmation dialog templates\n renderConfirmationDialog,\n getConfirmationDialogScript,\n // Filter bar templates\n renderFilterBar,\n} from './templates'\n\nexport type {\n FormField,\n FormData,\n TableColumn,\n TableData,\n PaginationData,\n AlertData,\n ConfirmationDialogOptions,\n FilterBarData,\n Filter,\n FilterOption,\n} from './templates'\n\n// Types - Week 1 (COMPLETED)\nexport type {\n // Collection types\n FieldType,\n FieldConfig,\n CollectionSchema,\n CollectionConfig,\n CollectionConfigModule,\n CollectionSyncResult,\n // Plugin types\n Plugin,\n PluginContext,\n PluginConfig,\n PluginRoutes,\n PluginMiddleware,\n PluginModel,\n PluginService,\n PluginAdminPage,\n PluginComponent,\n PluginMenuItem,\n PluginHook,\n HookHandler,\n HookContext,\n HookSystem,\n ScopedHookSystem,\n PluginRegistry,\n PluginManager,\n PluginStatus,\n AuthService,\n ContentService,\n MediaService,\n PluginLogger,\n PluginBuilderOptions,\n PluginValidator,\n PluginValidationResult,\n HookName,\n // Plugin manifest\n PluginManifest,\n} from './types'\n\nexport { HOOKS } from './types'\n\n// Utils - Week 1 (COMPLETED)\nexport {\n // Sanitization\n escapeHtml,\n sanitizeInput,\n sanitizeObject,\n // Template rendering\n TemplateRenderer,\n templateRenderer,\n renderTemplate,\n // Query filtering\n QueryFilterBuilder,\n buildQuery,\n // Metrics\n metricsTracker,\n // Version\n SONICJS_VERSION,\n getCoreVersion,\n} from './utils'\n\nexport type {\n FilterOperator,\n FilterCondition,\n FilterGroup,\n QueryFilter,\n QueryResult,\n} from './utils'\n\n// Database - Week 1 (COMPLETED)\nexport {\n createDb,\n // Schema exports\n users,\n collections,\n content,\n contentVersions,\n media,\n apiTokens,\n workflowHistory,\n plugins,\n pluginHooks,\n pluginRoutes,\n pluginAssets,\n pluginActivityLog,\n systemLogs,\n logConfig,\n // Zod validation schemas\n insertUserSchema,\n selectUserSchema,\n insertCollectionSchema,\n selectCollectionSchema,\n insertContentSchema,\n selectContentSchema,\n insertMediaSchema,\n selectMediaSchema,\n insertWorkflowHistorySchema,\n selectWorkflowHistorySchema,\n insertPluginSchema,\n selectPluginSchema,\n insertPluginHookSchema,\n selectPluginHookSchema,\n insertPluginRouteSchema,\n selectPluginRouteSchema,\n insertPluginAssetSchema,\n selectPluginAssetSchema,\n insertPluginActivityLogSchema,\n selectPluginActivityLogSchema,\n insertSystemLogSchema,\n selectSystemLogSchema,\n insertLogConfigSchema,\n selectLogConfigSchema,\n} from './db'\n\nexport type {\n User,\n NewUser,\n Collection,\n NewCollection,\n Content,\n NewContent,\n Media,\n NewMedia,\n WorkflowHistory,\n NewWorkflowHistory,\n Plugin as DbPlugin,\n NewPlugin,\n PluginHook as DbPluginHook,\n NewPluginHook,\n PluginRoute,\n NewPluginRoute,\n PluginAsset,\n NewPluginAsset,\n PluginActivityLog,\n NewPluginActivityLog,\n SystemLog,\n NewSystemLog,\n LogConfig,\n NewLogConfig,\n} from './db'\n\n// Plugin SDK (Beta)\nexport { PluginBuilder, PluginHelpers } from './plugins/sdk'\n\n// OAuth Providers Plugin\nexport { oauthProvidersPlugin, createOAuthProvidersPlugin } from './plugins/core-plugins/oauth-providers'\nexport { OAuthService, BUILT_IN_PROVIDERS } from './plugins/core-plugins/oauth-providers/oauth-service'\n\n// User Profiles Plugin\nexport { userProfilesPlugin, createUserProfilesPlugin, defineUserProfile, getUserProfileConfig } from './plugins/core-plugins/user-profiles'\nexport type { ProfileFieldDefinition, UserProfileConfig } from './plugins/core-plugins/user-profiles'\n\n// ============================================================================\n// Version\n// ============================================================================\n\n// Import version from package.json\nimport packageJson from '../package.json'\nexport const VERSION = packageJson.version\n\n// ============================================================================\n// Phase 2 Migration Notes\n// ============================================================================\n\n/**\n * This is a work-in-progress package being extracted from the main SonicJS codebase.\n *\n * Current Phase: 2 (Core Module Migration)\n * Current Week: 1 (Types, Utils, Database)\n *\n * Expected completion: 4 weeks from 2025-01-17\n *\n * DO NOT USE IN PRODUCTION - Alpha release for development only\n */\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugins/core-plugins/database-tools-plugin/services/database-service.ts","../src/templates/pages/admin-database-table.template.ts","../src/plugins/core-plugins/database-tools-plugin/admin-routes.ts","../src/plugins/core-plugins/seed-data-plugin/services/seed-data-service.ts","../src/plugins/core-plugins/seed-data-plugin/admin-routes.ts","../src/plugins/core-plugins/email-plugin/index.ts","../src/plugins/core-plugins/otp-login-plugin/otp-service.ts","../src/plugins/core-plugins/otp-login-plugin/email-templates.ts","../src/plugins/core-plugins/otp-login-plugin/index.ts","../src/plugins/core-plugins/oauth-providers/oauth-service.ts","../src/plugins/core-plugins/oauth-providers/index.ts","../src/plugins/core-plugins/ai-search-plugin/services/embedding.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/chunking.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/custom-rag.service.ts","../src/plugins/core-plugins/ai-search-plugin/services/ai-search.ts","../src/plugins/core-plugins/ai-search-plugin/services/indexer.ts","../src/plugins/core-plugins/ai-search-plugin/components/settings-page.ts","../src/plugins/core-plugins/ai-search-plugin/routes/admin.ts","../src/plugins/core-plugins/ai-search-plugin/routes/api.ts","../src/plugins/core-plugins/ai-search-plugin/manifest.json","../src/plugins/core-plugins/ai-search-plugin/index.ts","../src/plugins/available/magic-link-auth/index.ts","../src/plugins/core-plugins/security-audit-plugin/types.ts","../src/plugins/core-plugins/security-audit-plugin/services/security-audit-service.ts","../src/plugins/core-plugins/security-audit-plugin/components/dashboard-page.ts","../src/plugins/core-plugins/security-audit-plugin/components/event-log-page.ts","../src/plugins/core-plugins/security-audit-plugin/components/settings-page.ts","../src/plugins/core-plugins/security-audit-plugin/routes/admin.ts","../src/plugins/core-plugins/security-audit-plugin/services/brute-force-detector.ts","../src/plugins/core-plugins/security-audit-plugin/routes/api.ts","../src/plugins/core-plugins/security-audit-plugin/middleware/audit-middleware.ts","../src/plugins/core-plugins/security-audit-plugin/index.ts","../src/plugins/core-plugins/stripe-plugin/services/subscription-service.ts","../src/plugins/core-plugins/stripe-plugin/components/subscriptions-page.ts","../src/plugins/core-plugins/stripe-plugin/types.ts","../src/plugins/core-plugins/stripe-plugin/routes/admin.ts","../src/plugins/core-plugins/stripe-plugin/services/stripe-api.ts","../src/plugins/core-plugins/stripe-plugin/routes/api.ts","../src/plugins/core-plugins/stripe-plugin/index.ts","../src/middleware/plugin-menu.ts","../src/plugins/cache/services/cache-config.ts","../src/plugins/cache/services/cache.ts","../src/plugins/cache/services/event-bus.ts","../src/plugins/cache/services/cache-invalidation.ts","../src/plugins/cache/services/cache-warming.ts","../src/templates/pages/admin-cache.template.ts","../src/plugins/cache/routes.ts","../src/plugins/cache/index.ts","../src/assets/favicon.ts","../src/app.ts","../src/db/index.ts","../src/index.ts"],"names":["init_admin_layout_catalyst_template","escapeHtml","renderAdminLayoutCatalyst","router","Hono","requireAuth","PluginBuilder","plugin","z","SettingsService","emailPlugin","AuthManager","setCookie","getCookie","jwt","content","collections","statusBadge","renderAdminLayout","api_default","DEFAULT_SETTINGS","formatTimestamp","severityBadge","eventTypeBadge","adminRoutes","PluginService","apiRoutes","getSettings","isPluginActive","logPromise","renderPagination","media","renderConfirmationDialog","getConfirmationDialogScript","totalRequests","app","getCoreVersion","metricsMiddleware","bootstrapMiddleware","securityHeadersMiddleware","csrfProtection","api_media_default","api_system_default","admin_api_default","adminCollectionsRoutes","adminFormsRoutes","adminSettingsRoutes","public_forms_default","admin_content_default","adminMediaRoutes","userProfilesPlugin","adminPluginRoutes","adminLogsRoutes","userRoutes","auth_default","test_cleanup_default","setAppInstance","d1","drizzle","schema_exports","package_default"],"mappings":"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","file":"index.cjs","sourcesContent":["import { D1Database } from '@cloudflare/workers-types'\n\nexport interface TruncateResult {\n success: boolean\n message: string\n tablesCleared: string[]\n adminUserPreserved: boolean\n errors?: string[]\n}\n\nexport interface DatabaseStats {\n tables: Array<{\n name: string\n rowCount: number\n }>\n totalRows: number\n}\n\nexport interface TableData {\n tableName: string\n columns: string[]\n rows: any[]\n totalRows: number\n}\n\nexport class DatabaseToolsService {\n constructor(private db: D1Database) {}\n\n /**\n * Get database statistics\n */\n async getDatabaseStats(): Promise<DatabaseStats> {\n const tables = await this.getTables()\n const stats: DatabaseStats = {\n tables: [],\n totalRows: 0\n }\n\n for (const tableName of tables) {\n try {\n const result = await this.db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).first()\n const rowCount = (result?.count as number) || 0\n \n stats.tables.push({\n name: tableName,\n rowCount\n })\n stats.totalRows += rowCount\n } catch (error) {\n // Skip tables that can't be counted (might be views or system tables)\n console.warn(`Could not count rows in table ${tableName}:`, error)\n }\n }\n\n return stats\n }\n\n /**\n * Get all tables in the database\n */\n private async getTables(): Promise<string[]> {\n const result = await this.db.prepare(`\n SELECT name FROM sqlite_master \n WHERE type='table' \n AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `).all()\n\n return result.results?.map((row: any) => row.name) || []\n }\n\n /**\n * Truncate all data except admin user\n */\n async truncateAllData(adminEmail: string): Promise<TruncateResult> {\n const errors: string[] = []\n const tablesCleared: string[] = []\n let adminUserPreserved = false\n\n try {\n // First, preserve the admin user data\n const adminUser = await this.db.prepare(\n 'SELECT * FROM users WHERE email = ? AND role = ?'\n ).bind(adminEmail, 'admin').first()\n\n if (!adminUser) {\n return {\n success: false,\n message: 'Admin user not found. Operation cancelled for safety.',\n tablesCleared: [],\n adminUserPreserved: false,\n errors: ['Admin user not found']\n }\n }\n\n // Define tables to truncate (excluding system tables)\n const tablesToTruncate = [\n 'content',\n 'content_versions', \n 'content_workflow_status',\n 'collections',\n 'media',\n 'sessions',\n 'notifications',\n 'api_tokens',\n 'workflow_history',\n 'scheduled_content',\n 'faqs',\n 'faq_categories',\n 'plugins',\n 'plugin_settings',\n 'email_templates',\n 'email_themes'\n ]\n\n // Check which tables exist\n const existingTables = await this.getTables()\n const tablesToClear = tablesToTruncate.filter(table => \n existingTables.includes(table)\n )\n\n // Clear all data except users table\n for (const tableName of tablesToClear) {\n try {\n await this.db.prepare(`DELETE FROM ${tableName}`).run()\n tablesCleared.push(tableName)\n } catch (error) {\n errors.push(`Failed to clear table ${tableName}: ${error}`)\n console.error(`Error clearing table ${tableName}:`, error)\n }\n }\n\n // Clear users table but preserve admin\n try {\n await this.db.prepare('DELETE FROM users WHERE email != ? OR role != ?')\n .bind(adminEmail, 'admin').run()\n \n // Verify admin user still exists\n const verifyAdmin = await this.db.prepare(\n 'SELECT id FROM users WHERE email = ? AND role = ?'\n ).bind(adminEmail, 'admin').first()\n\n adminUserPreserved = !!verifyAdmin\n tablesCleared.push('users (non-admin)')\n } catch (error) {\n errors.push(`Failed to clear non-admin users: ${error}`)\n console.error('Error clearing non-admin users:', error)\n }\n\n // Reset auto-increment counters if supported\n try {\n await this.db.prepare('DELETE FROM sqlite_sequence').run()\n } catch (error) {\n // sqlite_sequence might not exist, ignore\n }\n\n const message = errors.length > 0 \n ? `Truncation completed with ${errors.length} errors. ${tablesCleared.length} tables cleared.`\n : `Successfully truncated database. ${tablesCleared.length} tables cleared.`\n\n return {\n success: errors.length === 0,\n message,\n tablesCleared,\n adminUserPreserved,\n errors: errors.length > 0 ? errors : undefined\n }\n\n } catch (error) {\n return {\n success: false,\n message: `Database truncation failed: ${error}`,\n tablesCleared,\n adminUserPreserved,\n errors: [String(error)]\n }\n }\n }\n\n /**\n * Create a backup of current data (simplified version)\n */\n async createBackup(): Promise<{ success: boolean; message: string; backupId?: string }> {\n try {\n const backupId = `backup_${Date.now()}`\n const stats = await this.getDatabaseStats()\n \n // In a real implementation, this would export data to a file or cloud storage\n // For now, we'll just log the stats and return success\n console.log(`Backup ${backupId} created with ${stats.totalRows} total rows`)\n \n return {\n success: true,\n message: `Backup created successfully (${stats.totalRows} rows)`,\n backupId\n }\n } catch (error) {\n return {\n success: false,\n message: `Backup failed: ${error}`\n }\n }\n }\n\n /**\n * Get table data with optional pagination and sorting\n */\n async getTableData(\n tableName: string,\n limit: number = 100,\n offset: number = 0,\n sortColumn?: string,\n sortDirection: 'asc' | 'desc' = 'asc'\n ): Promise<TableData> {\n try {\n // Validate table name to prevent SQL injection\n const tables = await this.getTables()\n if (!tables.includes(tableName)) {\n throw new Error(`Table ${tableName} not found`)\n }\n\n // Get column names\n const pragmaResult = await this.db.prepare(`PRAGMA table_info(${tableName})`).all()\n const columns = pragmaResult.results?.map((col: any) => col.name) || []\n\n // Validate sort column if provided\n if (sortColumn && !columns.includes(sortColumn)) {\n sortColumn = undefined\n }\n\n // Get total row count\n const countResult = await this.db.prepare(`SELECT COUNT(*) as count FROM ${tableName}`).first()\n const totalRows = (countResult?.count as number) || 0\n\n // Build query with optional sorting\n let query = `SELECT * FROM ${tableName}`\n if (sortColumn) {\n query += ` ORDER BY ${sortColumn} ${sortDirection.toUpperCase()}`\n }\n query += ` LIMIT ${limit} OFFSET ${offset}`\n\n // Get paginated data\n const dataResult = await this.db.prepare(query).all()\n\n return {\n tableName,\n columns,\n rows: dataResult.results || [],\n totalRows\n }\n } catch (error) {\n throw new Error(`Failed to fetch table data: ${error}`)\n }\n }\n\n /**\n * Validate database integrity\n */\n async validateDatabase(): Promise<{ valid: boolean; issues: string[] }> {\n const issues: string[] = []\n\n try {\n // Check critical tables exist\n const requiredTables = ['users', 'content', 'collections']\n const existingTables = await this.getTables()\n\n for (const table of requiredTables) {\n if (!existingTables.includes(table)) {\n issues.push(`Critical table missing: ${table}`)\n }\n }\n\n // Check admin user exists\n const adminCount = await this.db.prepare(\n 'SELECT COUNT(*) as count FROM users WHERE role = ?'\n ).bind('admin').first()\n\n if ((adminCount?.count as number) === 0) {\n issues.push('No admin users found')\n }\n\n // Run SQLite integrity check\n try {\n const integrityResult = await this.db.prepare('PRAGMA integrity_check').first()\n if (integrityResult && (integrityResult as any).integrity_check !== 'ok') {\n issues.push(`Database integrity check failed: ${(integrityResult as any).integrity_check}`)\n }\n } catch (error) {\n issues.push(`Could not run integrity check: ${error}`)\n }\n\n } catch (error) {\n issues.push(`Validation error: ${error}`)\n }\n\n return {\n valid: issues.length === 0,\n issues\n }\n }\n}","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\n\nexport interface DatabaseTablePageData {\n user?: {\n name: string\n email: string\n role: string\n }\n tableName: string\n columns: string[]\n rows: any[]\n totalRows: number\n currentPage: number\n pageSize: number\n sortColumn?: string\n sortDirection?: 'asc' | 'desc'\n}\n\nexport function renderDatabaseTablePage(data: DatabaseTablePageData): string {\n const totalPages = Math.ceil(data.totalRows / data.pageSize)\n const startRow = (data.currentPage - 1) * data.pageSize + 1\n const endRow = Math.min(data.currentPage * data.pageSize, data.totalRows)\n\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <div class=\"flex items-center space-x-3\">\n <a\n href=\"/admin/settings/database-tools\"\n class=\"inline-flex items-center text-sm/6 text-zinc-500 dark:text-zinc-400 hover:text-zinc-700 dark:hover:text-zinc-300\"\n >\n <svg class=\"w-5 h-5 mr-1\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 19l-7-7 7-7\"/>\n </svg>\n Back to Database Tools\n </a>\n </div>\n <h1 class=\"mt-2 text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Table: ${data.tableName}</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Showing ${startRow.toLocaleString()} - ${endRow.toLocaleString()} of ${data.totalRows.toLocaleString()} rows\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 flex items-center space-x-3\">\n <div class=\"flex items-center space-x-2\">\n <label for=\"pageSize\" class=\"text-sm font-medium text-zinc-700 dark:text-zinc-300\">\n Rows per page:\n </label>\n <select\n id=\"pageSize\"\n onchange=\"changePageSize(this.value)\"\n class=\"rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm cursor-pointer\"\n >\n <option value=\"10\" ${data.pageSize === 10 ? 'selected' : ''}>10</option>\n <option value=\"20\" ${data.pageSize === 20 ? 'selected' : ''}>20</option>\n <option value=\"50\" ${data.pageSize === 50 ? 'selected' : ''}>50</option>\n <option value=\"100\" ${data.pageSize === 100 ? 'selected' : ''}>100</option>\n <option value=\"200\" ${data.pageSize === 200 ? 'selected' : ''}>200</option>\n </select>\n </div>\n <button\n onclick=\"refreshTableData()\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\"\n >\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n </div>\n </div>\n\n <!-- Table Card -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 overflow-hidden\">\n <!-- Table -->\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-950/10 dark:divide-white/10\">\n <thead class=\"bg-zinc-50 dark:bg-white/5\">\n <tr>\n ${data.columns.map(col => `\n <th\n scope=\"col\"\n class=\"px-4 py-3.5 text-left text-xs font-semibold text-zinc-950 dark:text-white uppercase tracking-wider cursor-pointer hover:bg-zinc-100 dark:hover:bg-white/10 transition-colors\"\n onclick=\"sortTable('${col}')\"\n >\n <div class=\"flex items-center space-x-1\">\n <span>${col}</span>\n ${data.sortColumn === col ? `\n <svg class=\"w-4 h-4 ${data.sortDirection === 'asc' ? '' : 'rotate-180'}\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 15l7-7 7 7\"/>\n </svg>\n ` : `\n <svg class=\"w-4 h-4 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\"/>\n </svg>\n `}\n </div>\n </th>\n `).join('')}\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-950/5 dark:divide-white/5\">\n ${data.rows.length > 0\n ? data.rows.map((row, idx) => `\n <tr class=\"${idx % 2 === 0 ? 'bg-white dark:bg-zinc-900' : 'bg-zinc-50 dark:bg-zinc-900/50'}\">\n ${data.columns.map(col => `\n <td class=\"px-4 py-3 text-sm text-zinc-700 dark:text-zinc-300 whitespace-nowrap max-w-xs overflow-hidden text-ellipsis\" title=\"${escapeHtml(String(row[col] ?? ''))}\">\n ${formatCellValue(row[col])}\n </td>\n `).join('')}\n </tr>\n `).join('')\n : `\n <tr>\n <td colspan=\"${data.columns.length}\" class=\"px-4 py-12 text-center text-sm text-zinc-500 dark:text-zinc-400\">\n <svg class=\"w-12 h-12 mx-auto mb-4 text-zinc-400 dark:text-zinc-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4\"/>\n </svg>\n <p>No data in this table</p>\n </td>\n </tr>\n `\n }\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n ${totalPages > 1 ? `\n <div class=\"flex items-center justify-between border-t border-zinc-950/10 dark:border-white/10 bg-zinc-50 dark:bg-zinc-900/50 px-4 py-3 sm:px-6\">\n <div class=\"flex flex-1 justify-between sm:hidden\">\n <button\n onclick=\"goToPage(${data.currentPage - 1})\"\n ${data.currentPage === 1 ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-lg px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-100 dark:hover:bg-zinc-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Previous\n </button>\n <button\n onclick=\"goToPage(${data.currentPage + 1})\"\n ${data.currentPage === totalPages ? 'disabled' : ''}\n class=\"relative ml-3 inline-flex items-center rounded-lg px-4 py-2 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-100 dark:hover:bg-zinc-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n </button>\n </div>\n <div class=\"hidden sm:flex sm:flex-1 sm:items-center sm:justify-between\">\n <div>\n <p class=\"text-sm text-zinc-700 dark:text-zinc-300\">\n Page <span class=\"font-medium\">${data.currentPage}</span> of <span class=\"font-medium\">${totalPages}</span>\n </p>\n </div>\n <div>\n <nav class=\"isolate inline-flex -space-x-px rounded-lg shadow-sm\" aria-label=\"Pagination\">\n <button\n onclick=\"goToPage(${data.currentPage - 1})\"\n ${data.currentPage === 1 ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-l-lg px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 focus:z-20 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <span class=\"sr-only\">Previous</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n ${generatePageNumbers(data.currentPage, totalPages)}\n\n <button\n onclick=\"goToPage(${data.currentPage + 1})\"\n ${data.currentPage === totalPages ? 'disabled' : ''}\n class=\"relative inline-flex items-center rounded-r-lg px-2 py-2 text-zinc-400 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800 focus:z-20 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <span class=\"sr-only\">Next</span>\n <svg class=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fill-rule=\"evenodd\" d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n </nav>\n </div>\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n\n <script>\n const currentTableName = '${data.tableName}';\n let currentPage = ${data.currentPage};\n let currentPageSize = ${data.pageSize};\n let currentSort = '${data.sortColumn || ''}';\n let currentSortDir = '${data.sortDirection || 'asc'}';\n\n function goToPage(page) {\n if (page < 1 || page > ${totalPages}) return;\n const params = new URLSearchParams();\n params.set('page', page);\n params.set('pageSize', currentPageSize);\n if (currentSort) {\n params.set('sort', currentSort);\n params.set('dir', currentSortDir);\n }\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function sortTable(column) {\n let newDir = 'asc';\n if (currentSort === column && currentSortDir === 'asc') {\n newDir = 'desc';\n }\n\n const params = new URLSearchParams();\n params.set('page', '1');\n params.set('pageSize', currentPageSize);\n params.set('sort', column);\n params.set('dir', newDir);\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function changePageSize(newSize) {\n const params = new URLSearchParams();\n params.set('page', '1');\n params.set('pageSize', newSize);\n if (currentSort) {\n params.set('sort', currentSort);\n params.set('dir', currentSortDir);\n }\n window.location.href = \\`/admin/database-tools/tables/\\${currentTableName}?\\${params}\\`;\n }\n\n function refreshTableData() {\n window.location.reload();\n }\n\n function formatCellValue(value) {\n if (value === null || value === undefined) {\n return '<span class=\"text-zinc-400 dark:text-zinc-500 italic\">null</span>';\n }\n if (typeof value === 'boolean') {\n return \\`<span class=\"px-2 py-0.5 rounded text-xs font-medium \\${value ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400'}\">\\${value}</span>\\`;\n }\n if (typeof value === 'object') {\n return '<span class=\"text-xs font-mono text-zinc-600 dark:text-zinc-400\">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? '...' : '') + '</span>';\n }\n const str = String(value);\n if (str.length > 100) {\n return escapeHtml(str.substring(0, 100)) + '...';\n }\n return escapeHtml(str);\n }\n\n function escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return String(text).replace(/[&<>\"']/g, m => map[m]);\n }\n </script>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: `Table: ${data.tableName}`,\n pageTitle: `Database: ${data.tableName}`,\n currentPath: `/admin/database-tools/tables/${data.tableName}`,\n user: data.user,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction generatePageNumbers(currentPage: number, totalPages: number): string {\n const pages: number[] = []\n const maxVisible = 7\n\n if (totalPages <= maxVisible) {\n for (let i = 1; i <= totalPages; i++) {\n pages.push(i)\n }\n } else {\n if (currentPage <= 4) {\n for (let i = 1; i <= 5; i++) pages.push(i)\n pages.push(-1) // ellipsis\n pages.push(totalPages)\n } else if (currentPage >= totalPages - 3) {\n pages.push(1)\n pages.push(-1) // ellipsis\n for (let i = totalPages - 4; i <= totalPages; i++) pages.push(i)\n } else {\n pages.push(1)\n pages.push(-1) // ellipsis\n for (let i = currentPage - 1; i <= currentPage + 1; i++) pages.push(i)\n pages.push(-1) // ellipsis\n pages.push(totalPages)\n }\n }\n\n return pages.map(page => {\n if (page === -1) {\n return `\n <span class=\"relative inline-flex items-center px-4 py-2 text-sm font-semibold text-zinc-700 dark:text-zinc-300 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700\">\n ...\n </span>\n `\n }\n\n const isActive = page === currentPage\n return `\n <button\n onclick=\"goToPage(${page})\"\n class=\"relative inline-flex items-center px-4 py-2 text-sm font-semibold ${\n isActive\n ? 'z-10 bg-indigo-600 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'\n : 'text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800'\n }\"\n >\n ${page}\n </button>\n `\n }).join('')\n}\n\nfunction escapeHtml(text: string): string {\n const map: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }\n return String(text).replace(/[&<>\"']/g, m => map[m] || m)\n}\n\nfunction formatCellValue(value: any): string {\n if (value === null || value === undefined) {\n return '<span class=\"text-zinc-400 dark:text-zinc-500 italic\">null</span>'\n }\n if (typeof value === 'boolean') {\n return `<span class=\"px-2 py-0.5 rounded text-xs font-medium ${value ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-zinc-100 text-zinc-800 dark:bg-zinc-800 dark:text-zinc-400'}\">${value}</span>`\n }\n if (typeof value === 'object') {\n return '<span class=\"text-xs font-mono text-zinc-600 dark:text-zinc-400\">' + JSON.stringify(value).substring(0, 50) + (JSON.stringify(value).length > 50 ? '...' : '') + '</span>'\n }\n const str = String(value)\n if (str.length > 100) {\n return escapeHtml(str.substring(0, 100)) + '...'\n }\n return escapeHtml(str)\n}\n","import { Hono } from 'hono'\nimport { DatabaseToolsService } from './services/database-service'\nimport { renderDatabaseTablePage, DatabaseTablePageData } from '../../../templates/pages/admin-database-table.template'\nimport { requireAuth } from '../../../middleware'\n\ntype Bindings = {\n DB: D1Database\n}\n\ntype Variables = {\n user?: {\n userId: string\n email: string\n role: string\n }\n}\n\nexport function createDatabaseToolsAdminRoutes() {\n const router = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n // Apply authentication middleware\n router.use('*', requireAuth())\n\n // Get database statistics\n router.get('/api/stats', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const stats = await service.getDatabaseStats()\n\n return c.json({\n success: true,\n data: stats\n })\n } catch (error) {\n console.error('Error fetching database stats:', error)\n return c.json({ \n success: false, \n error: 'Failed to fetch database statistics' \n }, 500)\n }\n })\n\n // Truncate all data except admin user\n router.post('/api/truncate', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const body = await c.req.json()\n const { confirmText } = body\n\n // Require confirmation text for safety\n if (confirmText !== 'TRUNCATE ALL DATA') {\n return c.json({\n success: false,\n error: 'Invalid confirmation text. Operation cancelled.'\n }, 400)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const result = await service.truncateAllData(user.email)\n\n return c.json({\n success: result.success,\n message: result.message,\n data: {\n tablesCleared: result.tablesCleared,\n adminUserPreserved: result.adminUserPreserved,\n errors: result.errors\n }\n })\n } catch (error) {\n console.error('Error truncating database:', error)\n return c.json({ \n success: false, \n error: 'Failed to truncate database' \n }, 500)\n }\n })\n\n // Create backup\n router.post('/api/backup', async (c) => {\n try {\n const user = c.get('user')\n \n if (!user || user.role !== 'admin') {\n return c.json({ \n success: false, \n error: 'Unauthorized. Admin access required.' \n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const result = await service.createBackup()\n\n return c.json({\n success: result.success,\n message: result.message,\n data: {\n backupId: result.backupId\n }\n })\n } catch (error) {\n console.error('Error creating backup:', error)\n return c.json({ \n success: false, \n error: 'Failed to create backup' \n }, 500)\n }\n })\n\n // Validate database\n router.get('/api/validate', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const validation = await service.validateDatabase()\n\n return c.json({\n success: true,\n data: validation\n })\n } catch (error) {\n console.error('Error validating database:', error)\n return c.json({\n success: false,\n error: 'Failed to validate database'\n }, 500)\n }\n })\n\n // Get table data (API endpoint)\n router.get('/api/tables/:tableName', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.json({\n success: false,\n error: 'Unauthorized. Admin access required.'\n }, 403)\n }\n\n const tableName = c.req.param('tableName')\n const limit = parseInt(c.req.query('limit') || '100')\n const offset = parseInt(c.req.query('offset') || '0')\n const sortColumn = c.req.query('sort')\n const sortDirection = (c.req.query('dir') || 'asc') as 'asc' | 'desc'\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const tableData = await service.getTableData(tableName, limit, offset, sortColumn, sortDirection)\n\n return c.json({\n success: true,\n data: tableData\n })\n } catch (error) {\n console.error('Error fetching table data:', error)\n return c.json({\n success: false,\n error: `Failed to fetch table data: ${error}`\n }, 500)\n }\n })\n\n // View table data page\n router.get('/tables/:tableName', async (c) => {\n try {\n const user = c.get('user')\n\n if (!user || user.role !== 'admin') {\n return c.redirect('/admin/login')\n }\n\n const tableName = c.req.param('tableName')\n const page = parseInt(c.req.query('page') || '1')\n const pageSize = parseInt(c.req.query('pageSize') || '20')\n const sortColumn = c.req.query('sort')\n const sortDirection = (c.req.query('dir') || 'asc') as 'asc' | 'desc'\n\n const offset = (page - 1) * pageSize\n\n const db = c.env.DB\n const service = new DatabaseToolsService(db)\n const tableData = await service.getTableData(tableName, pageSize, offset, sortColumn, sortDirection)\n\n const pageData: DatabaseTablePageData = {\n user: {\n name: user.email.split('@')[0] || 'Unknown',\n email: user.email,\n role: user.role\n },\n tableName: tableData.tableName,\n columns: tableData.columns,\n rows: tableData.rows,\n totalRows: tableData.totalRows,\n currentPage: page,\n pageSize: pageSize,\n sortColumn: sortColumn,\n sortDirection: sortDirection\n }\n\n return c.html(renderDatabaseTablePage(pageData))\n } catch (error) {\n console.error('Error rendering table page:', error)\n return c.text(`Error: ${error}`, 500)\n }\n })\n\n return router\n}","import type { D1Database } from '@cloudflare/workers-types'\n\nexport class SeedDataService {\n constructor(private db: D1Database) {}\n\n // First names for generating realistic users\n private firstNames = [\n 'Emma', 'Liam', 'Olivia', 'Noah', 'Ava', 'Ethan', 'Sophia', 'Mason',\n 'Isabella', 'William', 'Mia', 'James', 'Charlotte', 'Benjamin', 'Amelia',\n 'Lucas', 'Harper', 'Henry', 'Evelyn', 'Alexander'\n ]\n\n // Last names for generating realistic users\n private lastNames = [\n 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',\n 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson',\n 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin'\n ]\n\n // Content titles for blog posts\n private blogTitles = [\n 'Getting Started with Modern Web Development',\n 'The Future of JavaScript Frameworks',\n 'Building Scalable Applications with Microservices',\n 'Understanding TypeScript: A Complete Guide',\n 'Best Practices for API Design',\n 'Introduction to Cloud Computing',\n 'Mastering Git and Version Control',\n 'The Art of Code Review',\n 'Performance Optimization Techniques',\n 'Security Best Practices for Web Apps',\n 'Exploring Serverless Architecture',\n 'Database Design Fundamentals',\n 'Testing Strategies for Modern Apps',\n 'CI/CD Pipeline Implementation',\n 'Mobile-First Development Approach'\n ]\n\n // Content titles for pages\n private pageTitles = [\n 'About Us', 'Contact', 'Privacy Policy', 'Terms of Service',\n 'FAQ', 'Our Team', 'Careers', 'Press Kit',\n 'Support', 'Documentation', 'Pricing', 'Features'\n ]\n\n // Content titles for products\n private productTitles = [\n 'Premium Wireless Headphones',\n 'Smart Watch Pro',\n 'Laptop Stand Adjustable',\n 'Mechanical Keyboard RGB',\n 'HD Webcam 4K',\n 'USB-C Hub 7-in-1',\n 'Portable SSD 1TB',\n 'Wireless Mouse Ergonomic',\n 'Monitor 27\" 4K',\n 'Desk Lamp LED',\n 'Phone Case Premium',\n 'Tablet Stand Aluminum',\n 'Cable Management Kit',\n 'Power Bank 20000mAh',\n 'Bluetooth Speaker Portable'\n ]\n\n // Content for generating blog posts\n private blogContent = [\n 'This comprehensive guide covers everything you need to know about modern development practices and tools.',\n 'Learn the fundamentals and advanced concepts that will help you build better applications.',\n 'Discover the latest trends and best practices used by industry professionals.',\n 'A deep dive into the technologies and methodologies shaping the future of software development.',\n 'Practical tips and real-world examples to improve your development workflow.',\n 'Explore cutting-edge techniques and proven strategies for building robust applications.',\n 'Master the essential skills needed to excel in modern software development.',\n 'An in-depth look at the tools and frameworks that power today\\'s web applications.',\n 'Step-by-step instructions and expert insights for developers of all levels.',\n 'Understanding the core principles that drive successful software projects.'\n ]\n\n // Generate a random ID\n private generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n }\n\n // Generate a slug from a title\n private generateSlug(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '')\n }\n\n // Generate random date within the last year\n private randomDate(): Date {\n const now = new Date()\n const yearAgo = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate())\n const randomTime = yearAgo.getTime() + Math.random() * (now.getTime() - yearAgo.getTime())\n return new Date(randomTime)\n }\n\n // Create 20 example users\n async createUsers(): Promise<number> {\n const roles = ['admin', 'editor', 'author', 'viewer']\n // const hashedPassword = await bcrypt.hash('password123', 10)\n const hashedPassword = 'password123' // TODO: Use actual bcrypt hash\n\n let count = 0\n for (let i = 0; i < 20; i++) {\n const firstName = this.firstNames[Math.floor(Math.random() * this.firstNames.length)] || 'John'\n const lastName = this.lastNames[Math.floor(Math.random() * this.lastNames.length)] || 'Doe'\n const username = `${firstName.toLowerCase()}${lastName.toLowerCase()}${i}`\n const email = `${username}@example.com`\n const createdAt = this.randomDate()\n const createdAtTimestamp = Math.floor(createdAt.getTime() / 1000)\n\n const stmt = this.db.prepare(`\n INSERT INTO users (id, email, username, first_name, last_name, password_hash, role, is_active, last_login_at, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await stmt.bind(\n this.generateId(),\n email,\n username,\n firstName,\n lastName,\n hashedPassword,\n roles[Math.floor(Math.random() * roles.length)],\n Math.random() > 0.1 ? 1 : 0, // 90% active\n Math.random() > 0.3 ? createdAtTimestamp : null,\n createdAtTimestamp,\n createdAtTimestamp\n ).run()\n\n count++\n }\n\n return count\n }\n\n // Create 200 content items across different types\n async createContent(): Promise<number> {\n // Get all users and collections\n const usersStmt = this.db.prepare('SELECT * FROM users')\n const { results: allUsers } = await usersStmt.all()\n\n const collectionsStmt = this.db.prepare('SELECT * FROM collections')\n const { results: allCollections } = await collectionsStmt.all()\n\n if (!allUsers || allUsers.length === 0) {\n throw new Error('No users found. Please create users first.')\n }\n\n if (!allCollections || allCollections.length === 0) {\n throw new Error('No collections found. Please create collections first.')\n }\n\n const statuses = ['draft', 'published', 'archived']\n\n // Create 200 content items\n let count = 0\n for (let i = 0; i < 200; i++) {\n const collection: any = allCollections[Math.floor(Math.random() * allCollections.length)]\n const author: any = allUsers[Math.floor(Math.random() * allUsers.length)]\n const status = statuses[Math.floor(Math.random() * statuses.length)]\n\n let title: string\n let contentData: any\n\n // Generate content based on collection type\n if (collection.name === 'blog_posts' || collection.name.includes('blog')) {\n title = this.blogTitles[Math.floor(Math.random() * this.blogTitles.length)] || 'Untitled Blog Post'\n contentData = {\n body: this.blogContent[Math.floor(Math.random() * this.blogContent.length)] || 'Blog content here',\n excerpt: 'A brief introduction to this article that provides an overview of the main topics covered.',\n tags: this.generateTags(),\n featured: Math.random() > 0.7\n }\n } else if (collection.name === 'pages' || collection.name.includes('page')) {\n title = this.pageTitles[Math.floor(Math.random() * this.pageTitles.length)] || 'Untitled Page'\n contentData = {\n body: 'This is a standard page with important information about our services and policies.',\n template: 'default',\n showInMenu: Math.random() > 0.5\n }\n } else if (collection.name === 'products' || collection.name.includes('product')) {\n title = this.productTitles[Math.floor(Math.random() * this.productTitles.length)] || 'Untitled Product'\n contentData = {\n description: 'High-quality product with excellent features and great value for money.',\n price: (Math.random() * 500 + 10).toFixed(2),\n sku: `SKU-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n inStock: Math.random() > 0.2,\n rating: (Math.random() * 2 + 3).toFixed(1) // 3.0 - 5.0\n }\n } else {\n // Generic content\n title = `${collection.display_name || collection.name} Item ${i + 1}`\n contentData = {\n description: 'This is a sample content item with generic data.',\n value: Math.floor(Math.random() * 1000)\n }\n }\n\n const slug = `${this.generateSlug(title)}-${i}`\n const createdAt = this.randomDate()\n const createdAtTimestamp = Math.floor(createdAt.getTime() / 1000)\n const publishedAtTimestamp = status === 'published' ? createdAtTimestamp : null\n\n const stmt = this.db.prepare(`\n INSERT INTO content (id, collection_id, slug, title, data, status, published_at, author_id, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n await stmt.bind(\n this.generateId(),\n collection.id,\n slug,\n `${title} ${i}`,\n JSON.stringify(contentData),\n status,\n publishedAtTimestamp,\n author.id,\n createdAtTimestamp,\n createdAtTimestamp\n ).run()\n\n count++\n }\n\n return count\n }\n\n // Generate random tags for blog posts\n private generateTags(): string[] {\n const allTags = [\n 'tutorial', 'guide', 'javascript', 'typescript', 'web-dev',\n 'backend', 'frontend', 'best-practices', 'security', 'performance',\n 'testing', 'deployment', 'cloud', 'database', 'api'\n ]\n\n const numTags = Math.floor(Math.random() * 4) + 1 // 1-4 tags\n const shuffled = allTags.sort(() => 0.5 - Math.random())\n return shuffled.slice(0, numTags)\n }\n\n // Seed all data\n async seedAll(): Promise<{ users: number; content: number }> {\n const userCount = await this.createUsers()\n const contentCount = await this.createContent()\n\n return {\n users: userCount,\n content: contentCount\n }\n }\n\n // Clear all seed data (optional cleanup method)\n async clearSeedData(): Promise<void> {\n // Delete content first (due to foreign key constraints)\n const deleteContentStmt = this.db.prepare('DELETE FROM content')\n await deleteContentStmt.run()\n\n // Delete users (but keep admin users)\n const deleteUsersStmt = this.db.prepare(\n \"DELETE FROM users WHERE role != 'admin'\"\n )\n await deleteUsersStmt.run()\n }\n}\n","import { Hono } from 'hono'\nimport { SeedDataService } from './services/seed-data-service'\n\ntype Bindings = {\n DB: D1Database\n}\n\nexport function createSeedDataAdminRoutes() {\n const routes = new Hono<{ Bindings: Bindings }>()\n\n // Get seed data status/info\n routes.get('/', async (c) => {\n const html = `\n <!DOCTYPE html>\n <html>\n <head>\n <title>Seed Data - SonicJS Admin</title>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #f5f5f5;\n padding: 2rem;\n }\n .container {\n max-width: 800px;\n margin: 0 auto;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n padding: 2rem;\n }\n h1 {\n color: #333;\n margin-bottom: 1rem;\n font-size: 2rem;\n }\n .description {\n color: #666;\n margin-bottom: 2rem;\n line-height: 1.6;\n }\n .card {\n background: #f9f9f9;\n border-radius: 6px;\n padding: 1.5rem;\n margin-bottom: 1.5rem;\n }\n .card h2 {\n color: #333;\n font-size: 1.25rem;\n margin-bottom: 0.75rem;\n }\n .card p {\n color: #666;\n line-height: 1.6;\n margin-bottom: 1rem;\n }\n .card ul {\n color: #666;\n margin-left: 1.5rem;\n margin-bottom: 1rem;\n }\n .card li {\n margin-bottom: 0.5rem;\n }\n button {\n background: #3b82f6;\n color: white;\n border: none;\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n font-size: 1rem;\n cursor: pointer;\n transition: background 0.2s;\n }\n button:hover {\n background: #2563eb;\n }\n button:disabled {\n background: #94a3b8;\n cursor: not-allowed;\n }\n .danger {\n background: #ef4444;\n }\n .danger:hover {\n background: #dc2626;\n }\n .warning {\n background: #f59e0b;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n }\n .success {\n background: #10b981;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n display: none;\n }\n .error {\n background: #ef4444;\n color: #fff;\n padding: 1rem;\n border-radius: 6px;\n margin-bottom: 1.5rem;\n display: none;\n }\n .loading {\n display: none;\n margin-left: 1rem;\n }\n .back-link {\n display: inline-block;\n margin-bottom: 1rem;\n color: #3b82f6;\n text-decoration: none;\n font-size: 0.9rem;\n }\n .back-link:hover {\n text-decoration: underline;\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <a href=\"/admin/plugins/seed-data\" class=\"back-link\">← Back to Plugin Settings</a>\n <h1>🌱 Seed Data Generator</h1>\n <p class=\"description\">\n Generate realistic example data for testing and development. This will create 20 users and 200 content items with realistic data.\n </p>\n\n <div class=\"warning\">\n <strong>⚠️ Warning:</strong> This will create new data in your database. Make sure you're not running this in production!\n </div>\n\n <div class=\"success\" id=\"successMessage\"></div>\n <div class=\"error\" id=\"errorMessage\"></div>\n\n <div class=\"card\">\n <h2>What will be created?</h2>\n <ul>\n <li><strong>20 Users:</strong> With realistic names, emails, and various roles (admin, editor, author, viewer)</li>\n <li><strong>200 Content Items:</strong> Including blog posts, pages, and products with realistic titles and data</li>\n <li><strong>All passwords:</strong> Set to \"password123\" for testing</li>\n <li><strong>Random dates:</strong> Created within the last year</li>\n <li><strong>Various statuses:</strong> Draft, published, and archived content</li>\n </ul>\n </div>\n\n <div class=\"card\">\n <h2>Generate Seed Data</h2>\n <p>Click the button below to generate example data. This may take a few moments.</p>\n <button id=\"seedButton\" onclick=\"generateSeedData()\">\n Generate Data\n <span class=\"loading\" id=\"loading\">...</span>\n </button>\n </div>\n\n <div class=\"card\">\n <h2>Clear Seed Data</h2>\n <p>Remove all users and content from the database (except admin users).</p>\n <button class=\"danger\" id=\"clearButton\" onclick=\"clearSeedData()\">\n Clear All Data\n <span class=\"loading\" id=\"clearLoading\">...</span>\n </button>\n </div>\n </div>\n\n <script>\n async function generateSeedData() {\n const button = document.getElementById('seedButton');\n const loading = document.getElementById('loading');\n const success = document.getElementById('successMessage');\n const error = document.getElementById('errorMessage');\n\n button.disabled = true;\n loading.style.display = 'inline';\n success.style.display = 'none';\n error.style.display = 'none';\n\n try {\n const response = await fetch('/admin/seed-data/generate', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n const data = await response.json();\n\n if (response.ok) {\n success.textContent = \\`✅ Successfully created \\${data.users} users and \\${data.content} content items!\\`;\n success.style.display = 'block';\n } else {\n throw new Error(data.error || 'Failed to generate seed data');\n }\n } catch (err) {\n error.textContent = \\`❌ Error: \\${err.message}\\`;\n error.style.display = 'block';\n } finally {\n button.disabled = false;\n loading.style.display = 'none';\n }\n }\n\n async function clearSeedData() {\n if (!confirm('Are you sure you want to clear all data? This cannot be undone!')) {\n return;\n }\n\n const button = document.getElementById('clearButton');\n const loading = document.getElementById('clearLoading');\n const success = document.getElementById('successMessage');\n const error = document.getElementById('errorMessage');\n\n button.disabled = true;\n loading.style.display = 'inline';\n success.style.display = 'none';\n error.style.display = 'none';\n\n try {\n const response = await fetch('/admin/seed-data/clear', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n\n const data = await response.json();\n\n if (response.ok) {\n success.textContent = '✅ Successfully cleared all seed data!';\n success.style.display = 'block';\n } else {\n throw new Error(data.error || 'Failed to clear seed data');\n }\n } catch (err) {\n error.textContent = \\`❌ Error: \\${err.message}\\`;\n error.style.display = 'block';\n } finally {\n button.disabled = false;\n loading.style.display = 'none';\n }\n }\n </script>\n </body>\n </html>\n `\n return c.html(html)\n })\n\n // Generate seed data\n routes.post('/generate', async (c) => {\n try {\n const db = c.env.DB\n const seedService = new SeedDataService(db)\n\n const result = await seedService.seedAll()\n\n return c.json({\n success: true,\n users: result.users,\n content: result.content\n })\n } catch (error: any) {\n return c.json({\n success: false,\n error: error.message\n }, 500)\n }\n })\n\n // Clear seed data\n routes.post('/clear', async (c) => {\n try {\n const db = c.env.DB\n const seedService = new SeedDataService(db)\n\n await seedService.clearSeedData()\n\n return c.json({\n success: true\n })\n } catch (error: any) {\n return c.json({\n success: false,\n error: error.message\n }, 500)\n }\n })\n\n return routes\n}\n","/**\n * Email Plugin\n *\n * Send transactional emails using Resend\n * Handles registration, verification, password reset, and one-time codes\n */\n\nimport { Hono } from 'hono'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\n\nexport function createEmailPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'email',\n version: '1.0.0-beta.1',\n description: 'Send transactional emails using Resend'\n })\n\n // Add plugin metadata\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // Create the Email Settings route (POST only - GET is handled by generic plugin settings page)\n const emailRoutes = new Hono()\n\n // Note: Admin UI is now handled by the generic plugin settings page\n // with custom component at admin-plugin-settings.template.ts\n\n // POST endpoint for saving settings\n emailRoutes.post('/settings', async (c: any) => {\n try {\n const body = await c.req.json()\n const db = c.env.DB\n\n // Update plugin settings in database\n await db.prepare(`\n UPDATE plugins\n SET settings = ?,\n updated_at = unixepoch()\n WHERE id = 'email'\n `).bind(JSON.stringify(body)).run()\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error saving email settings:', error)\n return c.json({ success: false, error: 'Failed to save settings' }, 500)\n }\n })\n\n // POST endpoint for test email\n emailRoutes.post('/test', async (c: any) => {\n try {\n const db = c.env.DB\n const body = await c.req.json()\n\n // Load settings from database\n const plugin = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'email'\n `).first() as { settings: string | null } | null\n\n if (!plugin?.settings) {\n return c.json({\n success: false,\n error: 'Email settings not configured. Please save your settings first.'\n }, 400)\n }\n\n const settings = JSON.parse(plugin.settings)\n\n // Validate required settings\n if (!settings.apiKey || !settings.fromEmail || !settings.fromName) {\n return c.json({\n success: false,\n error: 'Missing required settings. Please configure API Key, From Email, and From Name.'\n }, 400)\n }\n\n // Use provided email or fallback to fromEmail\n const toEmail = body.toEmail || settings.fromEmail\n\n // Validate email format\n if (!toEmail.match(/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/)) {\n return c.json({\n success: false,\n error: 'Invalid email address format'\n }, 400)\n }\n\n // Send test email via Resend API\n const response = await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${settings.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n from: `${settings.fromName} <${settings.fromEmail}>`,\n to: [toEmail],\n subject: 'Test Email from SonicJS',\n html: `\n <div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n <h1 style=\"color: #667eea;\">Test Email Successful! 🎉</h1>\n <p>This is a test email from your SonicJS Email plugin.</p>\n <p><strong>Configuration:</strong></p>\n <ul>\n <li>From: ${settings.fromName} <${settings.fromEmail}></li>\n <li>Reply-To: ${settings.replyTo || 'Not set'}</li>\n <li>Sent at: ${new Date().toISOString()}</li>\n </ul>\n <p>Your email settings are working correctly!</p>\n </div>\n `,\n reply_to: settings.replyTo || settings.fromEmail\n })\n })\n\n const data = await response.json() as any\n\n if (!response.ok) {\n console.error('Resend API error:', data)\n return c.json({\n success: false,\n error: data.message || 'Failed to send test email. Check your API key and domain verification.'\n }, response.status)\n }\n\n return c.json({\n success: true,\n message: `Test email sent successfully to ${toEmail}`,\n emailId: data.id\n })\n\n } catch (error: any) {\n console.error('Test email error:', error)\n return c.json({\n success: false,\n error: error.message || 'An error occurred while sending test email'\n }, 500)\n }\n })\n\n // Register the route\n builder.addRoute('/admin/plugins/email', emailRoutes, {\n description: 'Email plugin settings',\n requiresAuth: true,\n priority: 80\n })\n\n // Add menu item (points to generic plugin settings page)\n builder.addMenuItem('Email', '/admin/plugins/email', {\n icon: 'envelope',\n order: 80,\n permissions: ['email:manage']\n })\n\n // Add lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ Email plugin activated')\n },\n\n deactivate: async () => {\n console.info('❌ Email plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\n// Export the plugin instance\nexport const emailPlugin = createEmailPlugin()\n","/**\n * OTP Service\n * Handles OTP code generation, verification, and management\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\nexport interface OTPSettings {\n codeLength: number\n codeExpiryMinutes: number\n maxAttempts: number\n rateLimitPerHour: number\n allowNewUserRegistration: boolean\n logoUrl?: string\n}\n\nexport interface OTPCode {\n id: string\n user_email: string\n code: string\n expires_at: number\n used: number\n used_at: number | null\n ip_address: string | null\n user_agent: string | null\n attempts: number\n created_at: number\n}\n\nexport class OTPService {\n constructor(private db: D1Database) {}\n\n /**\n * Generate a secure random OTP code\n */\n generateCode(length: number = 6): string {\n const digits = '0123456789'\n let code = ''\n\n for (let i = 0; i < length; i++) {\n const randomValues = new Uint8Array(1)\n crypto.getRandomValues(randomValues)\n const randomValue = randomValues[0] ?? 0\n code += digits[randomValue % digits.length]\n }\n\n return code\n }\n\n /**\n * Create and store a new OTP code\n */\n async createOTPCode(\n email: string,\n settings: OTPSettings,\n ipAddress?: string,\n userAgent?: string\n ): Promise<OTPCode> {\n const code = this.generateCode(settings.codeLength)\n const id = crypto.randomUUID()\n const now = Date.now()\n const expiresAt = now + (settings.codeExpiryMinutes * 60 * 1000)\n\n const otpCode: OTPCode = {\n id,\n user_email: email.toLowerCase(),\n code,\n expires_at: expiresAt,\n used: 0,\n used_at: null,\n ip_address: ipAddress || null,\n user_agent: userAgent || null,\n attempts: 0,\n created_at: now\n }\n\n await this.db.prepare(`\n INSERT INTO otp_codes (\n id, user_email, code, expires_at, used, used_at,\n ip_address, user_agent, attempts, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n otpCode.id,\n otpCode.user_email,\n otpCode.code,\n otpCode.expires_at,\n otpCode.used,\n otpCode.used_at,\n otpCode.ip_address,\n otpCode.user_agent,\n otpCode.attempts,\n otpCode.created_at\n ).run()\n\n return otpCode\n }\n\n /**\n * Verify an OTP code\n */\n async verifyCode(\n email: string,\n code: string,\n settings: OTPSettings\n ): Promise<{ valid: boolean; attemptsRemaining?: number; error?: string }> {\n const normalizedEmail = email.toLowerCase()\n const now = Date.now()\n\n // Find the most recent unused code for this email\n const otpCode = await this.db.prepare(`\n SELECT * FROM otp_codes\n WHERE user_email = ? AND code = ? AND used = 0\n ORDER BY created_at DESC\n LIMIT 1\n `).bind(normalizedEmail, code).first() as OTPCode | null\n\n if (!otpCode) {\n return { valid: false, error: 'Invalid or expired code' }\n }\n\n // Check if expired\n if (now > otpCode.expires_at) {\n return { valid: false, error: 'Code has expired' }\n }\n\n // Check attempts\n if (otpCode.attempts >= settings.maxAttempts) {\n return { valid: false, error: 'Maximum attempts exceeded' }\n }\n\n // Code is valid - mark as used\n await this.db.prepare(`\n UPDATE otp_codes\n SET used = 1, used_at = ?, attempts = attempts + 1\n WHERE id = ?\n `).bind(now, otpCode.id).run()\n\n return { valid: true }\n }\n\n /**\n * Increment failed attempt count\n */\n async incrementAttempts(email: string, code: string): Promise<number> {\n const normalizedEmail = email.toLowerCase()\n\n const result = await this.db.prepare(`\n UPDATE otp_codes\n SET attempts = attempts + 1\n WHERE user_email = ? AND code = ? AND used = 0\n RETURNING attempts\n `).bind(normalizedEmail, code).first() as { attempts: number } | null\n\n return result?.attempts || 0\n }\n\n /**\n * Check rate limiting\n */\n async checkRateLimit(email: string, settings: OTPSettings): Promise<boolean> {\n const normalizedEmail = email.toLowerCase()\n const oneHourAgo = Date.now() - (60 * 60 * 1000)\n\n const result = await this.db.prepare(`\n SELECT COUNT(*) as count\n FROM otp_codes\n WHERE user_email = ? AND created_at > ?\n `).bind(normalizedEmail, oneHourAgo).first() as { count: number } | null\n\n const count = result?.count || 0\n return count < settings.rateLimitPerHour\n }\n\n /**\n * Get recent OTP requests for activity log\n */\n async getRecentRequests(limit: number = 50): Promise<OTPCode[]> {\n const result = await this.db.prepare(`\n SELECT * FROM otp_codes\n ORDER BY created_at DESC\n LIMIT ?\n `).bind(limit).all()\n\n const rows = (result.results || []) as Record<string, unknown>[]\n return rows.map(row => this.mapRowToOTP(row))\n }\n\n /**\n * Clean up expired codes (for maintenance)\n */\n async cleanupExpiredCodes(): Promise<number> {\n const now = Date.now()\n\n const result = await this.db.prepare(`\n DELETE FROM otp_codes\n WHERE expires_at < ? OR (used = 1 AND used_at < ?)\n `).bind(now, now - (30 * 24 * 60 * 60 * 1000)).run() // Keep used codes for 30 days\n\n return result.meta.changes || 0\n }\n\n private mapRowToOTP(row: Record<string, unknown>): OTPCode {\n return {\n id: String(row.id),\n user_email: String(row.user_email),\n code: String(row.code),\n expires_at: Number(row.expires_at ?? Date.now()),\n used: Number(row.used ?? 0),\n used_at: row.used_at === null || row.used_at === undefined ? null : Number(row.used_at),\n ip_address: typeof row.ip_address === 'string' ? row.ip_address : null,\n user_agent: typeof row.user_agent === 'string' ? row.user_agent : null,\n attempts: Number(row.attempts ?? 0),\n created_at: Number(row.created_at ?? Date.now())\n }\n }\n\n /**\n * Get OTP statistics\n */\n async getStats(days: number = 7): Promise<{\n total: number\n successful: number\n failed: number\n expired: number\n }> {\n const since = Date.now() - (days * 24 * 60 * 60 * 1000)\n\n const stats = await this.db.prepare(`\n SELECT\n COUNT(*) as total,\n SUM(CASE WHEN used = 1 THEN 1 ELSE 0 END) as successful,\n SUM(CASE WHEN attempts >= 3 AND used = 0 THEN 1 ELSE 0 END) as failed,\n SUM(CASE WHEN expires_at < ? AND used = 0 THEN 1 ELSE 0 END) as expired\n FROM otp_codes\n WHERE created_at > ?\n `).bind(Date.now(), since).first() as any\n\n return {\n total: stats?.total || 0,\n successful: stats?.successful || 0,\n failed: stats?.failed || 0,\n expired: stats?.expired || 0\n }\n }\n}\n","/**\n * OTP Email Templates\n * HTML and plain text templates for OTP codes\n */\n\nexport interface OTPEmailData {\n code: string\n expiryMinutes: number\n codeLength: number\n maxAttempts: number\n email: string\n ipAddress?: string\n timestamp: string\n appName: string\n logoUrl?: string\n}\n\nexport function renderOTPEmailHTML(data: OTPEmailData): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Your Login Code</title>\n</head>\n<body style=\"font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f5f5f5;\">\n\n <div style=\"background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);\">\n\n ${data.logoUrl ? `\n <div style=\"text-align: center; padding: 30px 20px 20px;\">\n <img src=\"${data.logoUrl}\" alt=\"Logo\" style=\"max-width: 150px; height: auto;\">\n </div>\n ` : ''}\n\n <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 30px; text-align: center;\">\n <h1 style=\"margin: 0 0 10px 0; font-size: 32px; font-weight: 600;\">Your Login Code</h1>\n <p style=\"margin: 0; opacity: 0.95; font-size: 16px;\">Enter this code to sign in to ${data.appName}</p>\n </div>\n\n <div style=\"padding: 40px 30px;\">\n <div style=\"background: #f8f9fa; border: 2px dashed #667eea; border-radius: 12px; padding: 30px; text-align: center; margin: 0 0 30px 0;\">\n <div style=\"font-size: 56px; font-weight: bold; letter-spacing: 12px; color: #667eea; font-family: 'Courier New', Courier, monospace; line-height: 1;\">\n ${data.code}\n </div>\n </div>\n\n <div style=\"background: #fff3cd; border-left: 4px solid #ffc107; padding: 16px 20px; margin: 0 0 30px 0; border-radius: 6px;\">\n <p style=\"margin: 0; font-size: 14px; color: #856404;\">\n <strong>⚠️ This code expires in ${data.expiryMinutes} minutes</strong>\n </p>\n </div>\n\n <div style=\"margin: 0 0 30px 0;\">\n <h3 style=\"color: #333; margin: 0 0 15px 0; font-size: 18px;\">Quick Tips:</h3>\n <ul style=\"color: #666; font-size: 14px; line-height: 1.8; margin: 0; padding-left: 20px;\">\n <li>Enter the code exactly as shown (${data.codeLength} digits)</li>\n <li>The code can only be used once</li>\n <li>You have ${data.maxAttempts} attempts to enter the correct code</li>\n <li>Request a new code if this one expires</li>\n </ul>\n </div>\n\n <div style=\"background: #e8f4ff; border-radius: 8px; padding: 20px; margin: 0 0 30px 0;\">\n <p style=\"margin: 0 0 10px 0; font-size: 14px; color: #0066cc; font-weight: 600;\">\n 🔒 Security Notice\n </p>\n <p style=\"margin: 0; font-size: 13px; color: #004080; line-height: 1.6;\">\n Never share this code with anyone. ${data.appName} will never ask you for this code via phone, email, or social media.\n </p>\n </div>\n </div>\n\n <div style=\"border-top: 1px solid #eee; padding: 30px; background: #f8f9fa;\">\n <p style=\"margin: 0 0 15px 0; font-size: 14px; color: #666; text-align: center;\">\n <strong>Didn't request this code?</strong><br>\n Someone may have entered your email by mistake. You can safely ignore this email.\n </p>\n\n <div style=\"text-align: center; color: #999; font-size: 12px; line-height: 1.6;\">\n <p style=\"margin: 5px 0;\">This email was sent to ${data.email}</p>\n ${data.ipAddress ? `<p style=\"margin: 5px 0;\">IP Address: ${data.ipAddress}</p>` : ''}\n <p style=\"margin: 5px 0;\">Time: ${data.timestamp}</p>\n </div>\n </div>\n\n </div>\n\n <div style=\"text-align: center; padding: 20px; color: #999; font-size: 12px;\">\n <p style=\"margin: 0;\">© ${new Date().getFullYear()} ${data.appName}. All rights reserved.</p>\n </div>\n\n</body>\n</html>`\n}\n\nexport function renderOTPEmailText(data: OTPEmailData): string {\n return `Your Login Code for ${data.appName}\n\nYour one-time verification code is:\n\n${data.code}\n\nThis code expires in ${data.expiryMinutes} minutes.\n\nQuick Tips:\n• Enter the code exactly as shown (${data.codeLength} digits)\n• The code can only be used once\n• You have ${data.maxAttempts} attempts to enter the correct code\n• Request a new code if this one expires\n\nSecurity Notice:\nNever share this code with anyone. ${data.appName} will never ask you for this code via phone, email, or social media.\n\nDidn't request this code?\nSomeone may have entered your email by mistake. You can safely ignore this email.\n\n---\nThis email was sent to ${data.email}\n${data.ipAddress ? `IP Address: ${data.ipAddress}` : ''}\nTime: ${data.timestamp}\n\n© ${new Date().getFullYear()} ${data.appName}. All rights reserved.`\n}\n\nexport function renderOTPEmail(data: OTPEmailData): { html: string; text: string } {\n return {\n html: renderOTPEmailHTML(data),\n text: renderOTPEmailText(data)\n }\n}\n","/**\n * OTP Login Plugin\n *\n * Passwordless authentication via email one-time codes\n * Users receive a secure 6-digit code to sign in without passwords\n */\n\nimport { Hono } from 'hono'\nimport { setCookie } from 'hono/cookie'\nimport { z } from 'zod'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\nimport { OTPService, type OTPSettings } from './otp-service'\nimport { renderOTPEmail } from './email-templates'\nimport { AuthManager } from '../../../middleware'\nimport { SettingsService } from '../../../services/settings'\n\n// Validation schemas\nconst otpRequestSchema = z.object({\n email: z.string().email('Valid email is required')\n})\n\nconst otpVerifySchema = z.object({\n email: z.string().email('Valid email is required'),\n code: z.string().min(4).max(8)\n})\n\n// Default settings (site name comes from general settings)\nconst DEFAULT_SETTINGS: OTPSettings = {\n codeLength: 6,\n codeExpiryMinutes: 10,\n maxAttempts: 3,\n rateLimitPerHour: 5,\n allowNewUserRegistration: false\n}\n\nexport function createOTPLoginPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'otp-login',\n version: '1.0.0-beta.1',\n description: 'Passwordless authentication via email one-time codes'\n })\n\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // ==================== API Routes ====================\n\n const otpAPI = new Hono()\n\n // POST /auth/otp/request - Request OTP code\n otpAPI.post('/request', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB\n const otpService = new OTPService(db)\n\n // Load plugin settings from database\n let settings: OTPSettings = { ...DEFAULT_SETTINGS }\n const pluginRow = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'otp-login'\n `).first() as { settings: string | null } | null\n if (pluginRow?.settings) {\n try {\n const savedSettings = JSON.parse(pluginRow.settings)\n settings = { ...DEFAULT_SETTINGS, ...savedSettings }\n } catch (e) {\n console.warn('Failed to parse OTP plugin settings, using defaults')\n }\n }\n\n // Get site name from general settings\n const settingsService = new SettingsService(db)\n const generalSettings = await settingsService.getGeneralSettings()\n const siteName = generalSettings.siteName\n\n // Check rate limiting\n const canRequest = await otpService.checkRateLimit(normalizedEmail, settings)\n if (!canRequest) {\n return c.json({\n error: 'Too many requests. Please try again in an hour.'\n }, 429)\n }\n\n // Check if user exists\n const user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n if (!user && !settings.allowNewUserRegistration) {\n // Don't reveal if user exists or not (security)\n return c.json({\n message: 'If an account exists for this email, you will receive a verification code shortly.',\n expiresIn: settings.codeExpiryMinutes * 60\n })\n }\n\n if (user && !user.is_active) {\n return c.json({\n error: 'This account has been deactivated.'\n }, 403)\n }\n\n // Get IP and user agent\n const ipAddress = c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown'\n const userAgent = c.req.header('user-agent') || 'unknown'\n\n // Create OTP code\n const otpCode = await otpService.createOTPCode(\n normalizedEmail,\n settings,\n ipAddress,\n userAgent\n )\n\n // Send email via Email plugin\n try {\n const isDevMode = c.env.ENVIRONMENT === 'development'\n\n if (isDevMode) {\n console.log(`[DEV] OTP Code for ${normalizedEmail}: ${otpCode.code}`)\n }\n\n // Prepare email content\n const emailContent = renderOTPEmail({\n code: otpCode.code,\n expiryMinutes: settings.codeExpiryMinutes,\n codeLength: settings.codeLength,\n maxAttempts: settings.maxAttempts,\n email: normalizedEmail,\n ipAddress,\n timestamp: new Date().toISOString(),\n appName: siteName,\n logoUrl: settings.logoUrl || ''\n })\n\n // Load email plugin settings from database\n // Note: We don't check status='active' because the email plugin's\n // settings UI works regardless of status, so we follow the same pattern\n const emailPlugin = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'email'\n `).first() as { settings: string | null } | null\n\n if (emailPlugin?.settings) {\n const emailSettings = JSON.parse(emailPlugin.settings)\n\n if (emailSettings.apiKey && emailSettings.fromEmail && emailSettings.fromName) {\n // Send email via Resend API\n const emailResponse = await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${emailSettings.apiKey}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n from: `${emailSettings.fromName} <${emailSettings.fromEmail}>`,\n to: [normalizedEmail],\n subject: `Your login code for ${siteName}`,\n html: emailContent.html,\n text: emailContent.text,\n reply_to: emailSettings.replyTo || emailSettings.fromEmail\n })\n })\n\n if (!emailResponse.ok) {\n const errorData = await emailResponse.json() as { message?: string }\n console.error('Failed to send OTP email via Resend:', errorData)\n // Don't expose error to user for security - just log it\n }\n } else {\n console.warn('Email plugin is not fully configured (missing apiKey, fromEmail, or fromName)')\n }\n } else {\n console.warn('Email plugin is not active or has no settings configured')\n }\n\n const response: any = {\n message: 'If an account exists for this email, you will receive a verification code shortly.',\n expiresIn: settings.codeExpiryMinutes * 60\n }\n\n // In development, include the code\n if (isDevMode) {\n response.dev_code = otpCode.code\n }\n\n return c.json(response)\n } catch (emailError) {\n console.error('Error sending OTP email:', emailError)\n return c.json({\n error: 'Failed to send verification code. Please try again.'\n }, 500)\n }\n } catch (error) {\n console.error('OTP request error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // POST /auth/otp/verify - Verify OTP code\n otpAPI.post('/verify', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpVerifySchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email, code } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB\n const otpService = new OTPService(db)\n\n // Load plugin settings from database\n let settings = { ...DEFAULT_SETTINGS }\n const pluginRow = await db.prepare(`\n SELECT settings FROM plugins WHERE id = 'otp-login'\n `).first() as { settings: string | null } | null\n if (pluginRow?.settings) {\n try {\n const savedSettings = JSON.parse(pluginRow.settings)\n settings = { ...DEFAULT_SETTINGS, ...savedSettings }\n } catch (e) {\n console.warn('Failed to parse OTP plugin settings, using defaults')\n }\n }\n\n // Verify the code\n const verification = await otpService.verifyCode(normalizedEmail, code, settings)\n\n if (!verification.valid) {\n // Increment attempts on failure\n await otpService.incrementAttempts(normalizedEmail, code)\n\n return c.json({\n error: verification.error || 'Invalid code',\n attemptsRemaining: verification.attemptsRemaining\n }, 401)\n }\n\n // Code is valid - get user\n let user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n if (!user && settings.allowNewUserRegistration) {\n // Auto-create new user on first OTP verification\n const userId = crypto.randomUUID()\n const now = Date.now()\n const username = normalizedEmail.split('@')[0] + '_' + userId.slice(0, 6)\n\n await db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, is_active, email_verified, created_at, updated_at\n ) VALUES (?, ?, ?, '', '', NULL, 'viewer', 1, 1, ?, ?)\n `).bind(userId, normalizedEmail, username, now, now).run()\n\n user = { id: userId, email: normalizedEmail, role: 'viewer', is_active: 1 }\n }\n\n if (!user) {\n return c.json({\n error: 'User not found'\n }, 404)\n }\n\n if (!user.is_active) {\n return c.json({\n error: 'Account is deactivated'\n }, 403)\n }\n\n // Generate JWT token\n const token = await AuthManager.generateToken(user.id, user.email, user.role, (c.env as any).JWT_SECRET)\n\n // Set HTTP-only cookie\n setCookie(c, 'auth_token', token, {\n httpOnly: true,\n secure: true,\n sameSite: 'Strict',\n maxAge: 60 * 60 * 24 // 24 hours\n })\n\n return c.json({\n success: true,\n user: {\n id: user.id,\n email: user.email,\n role: user.role\n },\n token,\n message: 'Authentication successful'\n })\n } catch (error) {\n console.error('OTP verify error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // POST /auth/otp/resend - Resend OTP code\n otpAPI.post('/resend', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = otpRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n // Reuse the request endpoint logic\n return otpAPI.fetch(\n new Request(c.req.url.replace('/resend', '/request'), {\n method: 'POST',\n headers: c.req.raw.headers,\n body: JSON.stringify({ email: validation.data.email })\n }),\n c.env\n )\n } catch (error) {\n console.error('OTP resend error:', error)\n return c.json({\n error: 'An error occurred. Please try again.'\n }, 500)\n }\n })\n\n // Register API routes\n builder.addRoute('/auth/otp', otpAPI, {\n description: 'OTP authentication endpoints',\n requiresAuth: false,\n priority: 100\n })\n\n // Note: Admin UI is now handled by the generic plugin settings page\n // with custom component at admin-plugin-settings.template.ts\n\n // Add menu item (points to generic plugin settings page)\n builder.addMenuItem('OTP Login', '/admin/plugins/otp-login', {\n icon: 'key',\n order: 85,\n permissions: ['otp:manage']\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ OTP Login plugin activated')\n },\n deactivate: async () => {\n console.info('❌ OTP Login plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\nexport const otpLoginPlugin = createOTPLoginPlugin()\n","/**\n * OAuth Service\n * Handles OAuth2 authorization code flow, token exchange, and user info fetching.\n * Provider-agnostic — each provider is a simple config object.\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\n// ─── Provider Configuration ─────────────────────────────────────────────────\n\nexport interface OAuthProviderConfig {\n id: string\n name: string\n authorizeUrl: string\n tokenUrl: string\n userInfoUrl: string\n scopes: string[]\n /** Map provider profile JSON to a normalized user profile */\n mapProfile: (profile: Record<string, any>) => OAuthUserProfile\n}\n\nexport interface OAuthUserProfile {\n providerAccountId: string\n email: string\n name: string\n avatar?: string\n}\n\nexport interface OAuthPluginSettings {\n providers: Record<string, {\n clientId: string\n clientSecret: string\n enabled: boolean\n }>\n}\n\n// ─── Built-in Providers ─────────────────────────────────────────────────────\n\nexport const GITHUB_PROVIDER: OAuthProviderConfig = {\n id: 'github',\n name: 'GitHub',\n authorizeUrl: 'https://github.com/login/oauth/authorize',\n tokenUrl: 'https://github.com/login/oauth/access_token',\n userInfoUrl: 'https://api.github.com/user',\n scopes: ['read:user', 'user:email'],\n mapProfile: (profile) => ({\n providerAccountId: String(profile.id),\n email: profile.email || '',\n name: profile.name || profile.login || '',\n avatar: profile.avatar_url || undefined\n })\n}\n\nexport const GOOGLE_PROVIDER: OAuthProviderConfig = {\n id: 'google',\n name: 'Google',\n authorizeUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n userInfoUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',\n scopes: ['openid', 'email', 'profile'],\n mapProfile: (profile) => ({\n providerAccountId: String(profile.id),\n email: profile.email || '',\n name: profile.name || '',\n avatar: profile.picture || undefined\n })\n}\n\nexport const BUILT_IN_PROVIDERS: Record<string, OAuthProviderConfig> = {\n github: GITHUB_PROVIDER,\n google: GOOGLE_PROVIDER\n}\n\n// ─── OAuth Account DB Record ────────────────────────────────────────────────\n\nexport interface OAuthAccount {\n id: string\n user_id: string\n provider: string\n provider_account_id: string\n access_token: string | null\n refresh_token: string | null\n token_expires_at: number | null\n profile_data: string | null\n created_at: number\n updated_at: number\n}\n\n// ─── OAuth Service ──────────────────────────────────────────────────────────\n\nexport class OAuthService {\n constructor(private db: D1Database) {}\n\n /**\n * Build the authorization redirect URL for a provider.\n */\n buildAuthorizeUrl(\n provider: OAuthProviderConfig,\n clientId: string,\n redirectUri: string,\n state: string\n ): string {\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n scope: provider.scopes.join(' '),\n state\n })\n\n // Google requires access_type for refresh tokens\n if (provider.id === 'google') {\n params.set('access_type', 'offline')\n params.set('prompt', 'consent')\n }\n\n return `${provider.authorizeUrl}?${params.toString()}`\n }\n\n /**\n * Exchange authorization code for tokens using native fetch.\n */\n async exchangeCode(\n provider: OAuthProviderConfig,\n clientId: string,\n clientSecret: string,\n code: string,\n redirectUri: string\n ): Promise<{ access_token: string; refresh_token?: string; expires_in?: number }> {\n const body: Record<string, string> = {\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri,\n grant_type: 'authorization_code'\n }\n\n const response = await fetch(provider.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Accept': 'application/json'\n },\n body: new URLSearchParams(body).toString()\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Token exchange failed (${response.status}): ${errorText}`)\n }\n\n const data = await response.json() as Record<string, any>\n\n if (data.error) {\n throw new Error(`Token exchange error: ${data.error_description || data.error}`)\n }\n\n return {\n access_token: data.access_token,\n refresh_token: data.refresh_token,\n expires_in: data.expires_in ? Number(data.expires_in) : undefined\n }\n }\n\n /**\n * Fetch user profile from the provider's userinfo endpoint.\n */\n async fetchUserProfile(\n provider: OAuthProviderConfig,\n accessToken: string\n ): Promise<OAuthUserProfile> {\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${accessToken}`,\n 'Accept': 'application/json'\n }\n\n // GitHub uses a different auth header format\n if (provider.id === 'github') {\n headers['Authorization'] = `token ${accessToken}`\n }\n\n const response = await fetch(provider.userInfoUrl, { headers })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch user profile (${response.status})`)\n }\n\n const profile = await response.json() as Record<string, any>\n\n // For GitHub, email may not be in the profile — fetch from /user/emails\n if (provider.id === 'github' && !profile.email) {\n const emailResponse = await fetch('https://api.github.com/user/emails', {\n headers: {\n 'Authorization': `token ${accessToken}`,\n 'Accept': 'application/json'\n }\n })\n\n if (emailResponse.ok) {\n const emails = await emailResponse.json() as Array<{ email: string; primary: boolean; verified: boolean }>\n const primaryEmail = emails.find(e => e.primary && e.verified)\n if (primaryEmail) {\n profile.email = primaryEmail.email\n }\n }\n }\n\n return provider.mapProfile(profile)\n }\n\n // ─── Database Operations ────────────────────────────────────────────────\n\n /**\n * Find an existing OAuth account link.\n */\n async findOAuthAccount(\n provider: string,\n providerAccountId: string\n ): Promise<OAuthAccount | null> {\n return await this.db.prepare(`\n SELECT * FROM oauth_accounts\n WHERE provider = ? AND provider_account_id = ?\n `).bind(provider, providerAccountId).first() as OAuthAccount | null\n }\n\n /**\n * Find all OAuth accounts for a user.\n */\n async findUserOAuthAccounts(userId: string): Promise<OAuthAccount[]> {\n const result = await this.db.prepare(`\n SELECT * FROM oauth_accounts WHERE user_id = ?\n `).bind(userId).all()\n return (result.results || []) as unknown as OAuthAccount[]\n }\n\n /**\n * Create a new OAuth account link.\n */\n async createOAuthAccount(params: {\n userId: string\n provider: string\n providerAccountId: string\n accessToken: string\n refreshToken?: string\n tokenExpiresAt?: number\n profileData?: string\n }): Promise<OAuthAccount> {\n const id = crypto.randomUUID()\n const now = Date.now()\n\n await this.db.prepare(`\n INSERT INTO oauth_accounts (\n id, user_id, provider, provider_account_id,\n access_token, refresh_token, token_expires_at,\n profile_data, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n id,\n params.userId,\n params.provider,\n params.providerAccountId,\n params.accessToken,\n params.refreshToken || null,\n params.tokenExpiresAt || null,\n params.profileData || null,\n now,\n now\n ).run()\n\n return {\n id,\n user_id: params.userId,\n provider: params.provider,\n provider_account_id: params.providerAccountId,\n access_token: params.accessToken,\n refresh_token: params.refreshToken || null,\n token_expires_at: params.tokenExpiresAt || null,\n profile_data: params.profileData || null,\n created_at: now,\n updated_at: now\n }\n }\n\n /**\n * Update tokens for an existing OAuth account.\n */\n async updateOAuthTokens(\n id: string,\n accessToken: string,\n refreshToken?: string,\n tokenExpiresAt?: number\n ): Promise<void> {\n await this.db.prepare(`\n UPDATE oauth_accounts\n SET access_token = ?, refresh_token = ?, token_expires_at = ?, updated_at = ?\n WHERE id = ?\n `).bind(accessToken, refreshToken || null, tokenExpiresAt || null, Date.now(), id).run()\n }\n\n /**\n * Unlink an OAuth account from a user (only if they have another auth method).\n */\n async unlinkOAuthAccount(userId: string, provider: string): Promise<boolean> {\n // Check user has a password or another OAuth link before unlinking\n const user = await this.db.prepare(`\n SELECT password_hash FROM users WHERE id = ?\n `).bind(userId).first() as { password_hash: string | null } | null\n\n const otherLinks = await this.db.prepare(`\n SELECT COUNT(*) as count FROM oauth_accounts\n WHERE user_id = ? AND provider != ?\n `).bind(userId, provider).first() as { count: number } | null\n\n const hasPassword = !!user?.password_hash\n const hasOtherLinks = (otherLinks?.count || 0) > 0\n\n if (!hasPassword && !hasOtherLinks) {\n return false // Cannot unlink the only auth method\n }\n\n await this.db.prepare(`\n DELETE FROM oauth_accounts WHERE user_id = ? AND provider = ?\n `).bind(userId, provider).run()\n\n return true\n }\n\n /**\n * Find a user by email.\n */\n async findUserByEmail(email: string): Promise<{\n id: string\n email: string\n role: string\n is_active: number\n first_name: string\n last_name: string\n } | null> {\n return await this.db.prepare(`\n SELECT id, email, role, is_active, first_name, last_name\n FROM users WHERE email = ?\n `).bind(email.toLowerCase()).first() as any\n }\n\n /**\n * Create a new user from an OAuth profile.\n */\n async createUserFromOAuth(profile: OAuthUserProfile): Promise<string> {\n const id = crypto.randomUUID()\n const now = Date.now()\n const email = profile.email.toLowerCase()\n const nameParts = (profile.name || email.split('@')[0] || 'User').split(' ')\n const firstName = nameParts[0] || 'User'\n const lastName = nameParts.slice(1).join(' ') || ''\n const username = email.split('@')[0] || id.substring(0, 8)\n\n // Check for username collision and append random suffix if needed\n const existing = await this.db.prepare(\n 'SELECT id FROM users WHERE username = ?'\n ).bind(username).first()\n\n const finalUsername = existing\n ? `${username}-${id.substring(0, 6)}`\n : username\n\n await this.db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, avatar, is_active, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, NULL, 'viewer', ?, 1, ?, ?)\n `).bind(\n id, email, finalUsername, firstName, lastName,\n profile.avatar || null, now, now\n ).run()\n\n return id\n }\n\n /**\n * Generate a cryptographically random state parameter for CSRF protection.\n */\n generateState(): string {\n const bytes = new Uint8Array(32)\n crypto.getRandomValues(bytes)\n return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')\n }\n}\n","/**\n * OAuth Providers Plugin\n *\n * OAuth2/OIDC social login support for SonicJS.\n * Phase 1: Core OAuth2 authorization code flow with GitHub and Google providers.\n *\n * Routes:\n * GET /auth/oauth/:provider → Redirect to provider authorization\n * GET /auth/oauth/:provider/callback → Handle OAuth callback\n * POST /auth/oauth/link → Link OAuth provider to logged-in account\n * POST /auth/oauth/unlink → Unlink OAuth provider from account\n * GET /auth/oauth/accounts → List linked OAuth accounts for current user\n */\n\nimport { Hono } from 'hono'\nimport { setCookie, getCookie } from 'hono/cookie'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '../../types'\nimport {\n OAuthService,\n BUILT_IN_PROVIDERS,\n type OAuthPluginSettings,\n type OAuthProviderConfig\n} from './oauth-service'\nimport { AuthManager } from '../../../middleware'\n\nconst STATE_COOKIE_NAME = 'oauth_state'\nconst STATE_COOKIE_MAX_AGE = 600 // 10 minutes\n\nexport function createOAuthProvidersPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'oauth-providers',\n version: '1.0.0-beta.1',\n description: 'OAuth2/OIDC social login with GitHub, Google, and more'\n })\n\n builder.metadata({\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n license: 'MIT',\n compatibility: '^2.0.0'\n })\n\n // ==================== Helper Functions ====================\n\n function getCallbackUrl(c: any, provider: string): string {\n const proto = c.req.header('x-forwarded-proto') || 'https'\n const host = c.req.header('host') || 'localhost'\n return `${proto}://${host}/auth/oauth/${provider}/callback`\n }\n\n async function loadSettings(db: any): Promise<OAuthPluginSettings | null> {\n const row = await db.prepare(\n `SELECT settings FROM plugins WHERE id = 'oauth-providers'`\n ).first() as { settings: string | null } | null\n\n if (!row?.settings) return null\n\n try {\n return JSON.parse(row.settings) as OAuthPluginSettings\n } catch {\n return null\n }\n }\n\n function getProviderCredentials(\n settings: OAuthPluginSettings | null,\n providerId: string\n ): { clientId: string; clientSecret: string } | null {\n if (!settings?.providers?.[providerId]) return null\n const p = settings.providers[providerId]\n if (!p.enabled || !p.clientId || !p.clientSecret) return null\n return { clientId: p.clientId, clientSecret: p.clientSecret }\n }\n\n // ==================== API Routes ====================\n\n const oauthAPI = new Hono()\n\n // GET /auth/oauth/:provider — Redirect to provider authorization\n oauthAPI.get('/:provider', async (c: any) => {\n try {\n const providerId = c.req.param('provider')\n const providerConfig = BUILT_IN_PROVIDERS[providerId]\n\n if (!providerConfig) {\n return c.json({ error: `Unknown OAuth provider: ${providerId}` }, 400)\n }\n\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, providerId)\n\n if (!creds) {\n return c.json({\n error: `OAuth provider \"${providerId}\" is not configured or not enabled`\n }, 400)\n }\n\n const oauthService = new OAuthService(db)\n const state = oauthService.generateState()\n const redirectUri = getCallbackUrl(c, providerId)\n\n // Store state in a cookie for CSRF validation on callback\n setCookie(c, STATE_COOKIE_NAME, state, {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax', // Lax required for OAuth redirect flow\n maxAge: STATE_COOKIE_MAX_AGE,\n path: '/auth/oauth'\n })\n\n const authorizeUrl = oauthService.buildAuthorizeUrl(\n providerConfig,\n creds.clientId,\n redirectUri,\n state\n )\n\n return c.redirect(authorizeUrl)\n } catch (error) {\n console.error('OAuth authorize error:', error)\n return c.json({ error: 'Failed to initiate OAuth flow' }, 500)\n }\n })\n\n // GET /auth/oauth/:provider/callback — Handle OAuth callback\n oauthAPI.get('/:provider/callback', async (c: any) => {\n try {\n const providerId = c.req.param('provider')\n const providerConfig = BUILT_IN_PROVIDERS[providerId]\n\n if (!providerConfig) {\n return c.redirect('/auth/login?error=Unknown OAuth provider')\n }\n\n // Validate state (CSRF protection)\n const stateParam = c.req.query('state')\n const stateCookie = getCookie(c, STATE_COOKIE_NAME)\n\n if (!stateParam || !stateCookie || stateParam !== stateCookie) {\n return c.redirect('/auth/login?error=Invalid OAuth state. Please try again.')\n }\n\n // Clear the state cookie\n setCookie(c, STATE_COOKIE_NAME, '', {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax',\n maxAge: 0,\n path: '/auth/oauth'\n })\n\n // Check for error from provider\n const errorParam = c.req.query('error')\n if (errorParam) {\n const errorDesc = c.req.query('error_description') || errorParam\n return c.redirect(`/auth/login?error=${encodeURIComponent(errorDesc)}`)\n }\n\n const code = c.req.query('code')\n if (!code) {\n return c.redirect('/auth/login?error=No authorization code received')\n }\n\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, providerId)\n\n if (!creds) {\n return c.redirect('/auth/login?error=OAuth provider not configured')\n }\n\n const oauthService = new OAuthService(db)\n const redirectUri = getCallbackUrl(c, providerId)\n\n // Exchange code for tokens\n const tokens = await oauthService.exchangeCode(\n providerConfig,\n creds.clientId,\n creds.clientSecret,\n code,\n redirectUri\n )\n\n // Fetch user profile from provider\n const profile = await oauthService.fetchUserProfile(providerConfig, tokens.access_token)\n\n if (!profile.email) {\n return c.redirect('/auth/login?error=Could not retrieve email from OAuth provider. Please ensure your email is public or grant email permission.')\n }\n\n const tokenExpiresAt = tokens.expires_in\n ? Date.now() + (tokens.expires_in * 1000)\n : null\n\n // Check if this OAuth account is already linked to a user\n const existingOAuth = await oauthService.findOAuthAccount(providerId, profile.providerAccountId)\n\n if (existingOAuth) {\n // Existing OAuth link — update tokens and log in\n await oauthService.updateOAuthTokens(\n existingOAuth.id,\n tokens.access_token,\n tokens.refresh_token,\n tokenExpiresAt ?? undefined\n )\n\n // Fetch user to generate JWT\n const user = await db.prepare(\n 'SELECT id, email, role, is_active FROM users WHERE id = ?'\n ).bind(existingOAuth.user_id).first() as any\n\n if (!user || !user.is_active) {\n return c.redirect('/auth/login?error=Account is deactivated')\n }\n\n const jwt = await AuthManager.generateToken(\n user.id, user.email, user.role,\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n }\n\n // No existing OAuth link — check if user exists by email\n const existingUser = await oauthService.findUserByEmail(profile.email)\n\n if (existingUser) {\n if (!existingUser.is_active) {\n return c.redirect('/auth/login?error=Account is deactivated')\n }\n\n // Link OAuth to existing account\n await oauthService.createOAuthAccount({\n userId: existingUser.id,\n provider: providerId,\n providerAccountId: profile.providerAccountId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n tokenExpiresAt: tokenExpiresAt ?? undefined,\n profileData: JSON.stringify(profile)\n })\n\n const jwt = await AuthManager.generateToken(\n existingUser.id, existingUser.email, existingUser.role,\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n }\n\n // Brand new user — create account from OAuth profile\n const newUserId = await oauthService.createUserFromOAuth(profile)\n\n await oauthService.createOAuthAccount({\n userId: newUserId,\n provider: providerId,\n providerAccountId: profile.providerAccountId,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n tokenExpiresAt: tokenExpiresAt ?? undefined,\n profileData: JSON.stringify(profile)\n })\n\n const jwt = await AuthManager.generateToken(\n newUserId, profile.email.toLowerCase(), 'viewer',\n (c.env as any).JWT_SECRET\n )\n\n AuthManager.setAuthCookie(c, jwt, { sameSite: 'Lax' })\n return c.redirect('/admin')\n\n } catch (error) {\n console.error('OAuth callback error:', error)\n const message = error instanceof Error ? error.message : 'OAuth authentication failed'\n return c.redirect(`/auth/login?error=${encodeURIComponent(message)}`)\n }\n })\n\n // POST /auth/oauth/link — Link an OAuth provider to the current logged-in user\n oauthAPI.post('/link', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const body = await c.req.json()\n const { provider } = body\n\n if (!provider || !BUILT_IN_PROVIDERS[provider]) {\n return c.json({ error: 'Invalid provider' }, 400)\n }\n\n // Redirect the user to the OAuth flow — the callback will auto-link\n // since the user already exists by email\n const db = c.env.DB\n const settings = await loadSettings(db)\n const creds = getProviderCredentials(settings, provider)\n\n if (!creds) {\n return c.json({ error: `OAuth provider \"${provider}\" is not configured` }, 400)\n }\n\n const oauthService = new OAuthService(db)\n const state = oauthService.generateState()\n const redirectUri = getCallbackUrl(c, provider)\n\n setCookie(c, STATE_COOKIE_NAME, state, {\n httpOnly: true,\n secure: true,\n sameSite: 'Lax',\n maxAge: STATE_COOKIE_MAX_AGE,\n path: '/auth/oauth'\n })\n\n const authorizeUrl = oauthService.buildAuthorizeUrl(\n BUILT_IN_PROVIDERS[provider]!,\n creds.clientId,\n redirectUri,\n state\n )\n\n return c.json({ redirectUrl: authorizeUrl })\n } catch (error) {\n console.error('OAuth link error:', error)\n return c.json({ error: 'Failed to initiate account linking' }, 500)\n }\n })\n\n // POST /auth/oauth/unlink — Unlink an OAuth provider from the current user\n oauthAPI.post('/unlink', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const body = await c.req.json()\n const { provider } = body\n\n if (!provider) {\n return c.json({ error: 'Provider is required' }, 400)\n }\n\n const db = c.env.DB\n const oauthService = new OAuthService(db)\n const success = await oauthService.unlinkOAuthAccount(user.userId, provider)\n\n if (!success) {\n return c.json({\n error: 'Cannot unlink the only authentication method. Set a password first.'\n }, 400)\n }\n\n return c.json({ success: true, message: `${provider} account unlinked` })\n } catch (error) {\n console.error('OAuth unlink error:', error)\n return c.json({ error: 'Failed to unlink account' }, 500)\n }\n })\n\n // GET /auth/oauth/accounts — List linked OAuth accounts for current user\n oauthAPI.get('/accounts', async (c: any) => {\n try {\n const user = c.get('user')\n if (!user) {\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const db = c.env.DB\n const oauthService = new OAuthService(db)\n const accounts = await oauthService.findUserOAuthAccounts(user.userId)\n\n return c.json({\n accounts: accounts.map(a => ({\n provider: a.provider,\n providerAccountId: a.provider_account_id,\n linkedAt: a.created_at\n }))\n })\n } catch (error) {\n console.error('OAuth accounts error:', error)\n return c.json({ error: 'Failed to fetch linked accounts' }, 500)\n }\n })\n\n // Register routes\n builder.addRoute('/auth/oauth', oauthAPI, {\n description: 'OAuth2 social login endpoints',\n requiresAuth: false,\n priority: 100\n })\n\n // Add menu item for admin settings\n builder.addMenuItem('OAuth Providers', '/admin/plugins/oauth-providers', {\n icon: 'shield',\n order: 86,\n permissions: ['oauth:manage']\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n activate: async () => {\n console.info('✅ OAuth Providers plugin activated')\n },\n deactivate: async () => {\n console.info('❌ OAuth Providers plugin deactivated')\n }\n })\n\n return builder.build() as Plugin\n}\n\nexport const oauthProvidersPlugin = createOAuthProvidersPlugin()\n","/**\n * Embedding Service\n * Generates embeddings using Cloudflare Workers AI\n */\n\nexport class EmbeddingService {\n constructor(private ai: any) {}\n\n /**\n * Generate embedding for a single text\n */\n async generateEmbedding(text: string): Promise<number[]> {\n try {\n // Use Cloudflare Workers AI embedding model\n // @cf/baai/bge-base-en-v1.5 produces 768-dimensional vectors\n const response = await this.ai.run('@cf/baai/bge-base-en-v1.5', {\n text: this.preprocessText(text)\n })\n\n // Extract embedding vector\n if (response.data && response.data.length > 0) {\n return response.data[0]\n }\n\n throw new Error('No embedding data returned')\n } catch (error) {\n console.error('[EmbeddingService] Error generating embedding:', error)\n throw error\n }\n }\n\n /**\n * Generate embeddings for multiple texts (batch processing)\n */\n async generateBatch(texts: string[]): Promise<number[][]> {\n try {\n // Process in smaller batches to avoid rate limits\n const batchSize = 10\n const batches: string[][] = []\n \n for (let i = 0; i < texts.length; i += batchSize) {\n batches.push(texts.slice(i, i + batchSize))\n }\n\n const allEmbeddings: number[][] = []\n\n for (const batch of batches) {\n const batchEmbeddings = await Promise.all(\n batch.map(text => this.generateEmbedding(text))\n )\n allEmbeddings.push(...batchEmbeddings)\n }\n\n return allEmbeddings\n } catch (error) {\n console.error('[EmbeddingService] Error generating batch embeddings:', error)\n throw error\n }\n }\n\n /**\n * Preprocess text before generating embedding\n * - Trim whitespace\n * - Limit length to avoid token limits\n * - Remove special characters that might cause issues\n */\n private preprocessText(text: string): string {\n if (!text) return ''\n\n // Trim and normalize whitespace\n let processed = text.trim().replace(/\\s+/g, ' ')\n\n // Limit to ~8000 characters (rough token limit)\n if (processed.length > 8000) {\n processed = processed.substring(0, 8000)\n }\n\n return processed\n }\n\n /**\n * Calculate cosine similarity between two embeddings\n */\n cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error('Embeddings must have same dimensions')\n }\n\n let dotProduct = 0\n let normA = 0\n let normB = 0\n\n for (let i = 0; i < a.length; i++) {\n const aVal = a[i] ?? 0\n const bVal = b[i] ?? 0\n dotProduct += aVal * bVal\n normA += aVal * aVal\n normB += bVal * bVal\n }\n\n return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB))\n }\n}\n","/**\n * Chunking Service\n * Splits content into optimal chunks for embedding and search\n */\n\nexport interface ContentChunk {\n id: string\n content_id: string\n collection_id: string\n title: string\n text: string\n chunk_index: number\n metadata: Record<string, any>\n}\n\nexport class ChunkingService {\n // Default chunk size (in approximate tokens)\n private readonly CHUNK_SIZE = 500\n private readonly CHUNK_OVERLAP = 50\n\n /**\n * Chunk a single content item\n */\n chunkContent(\n contentId: string,\n collectionId: string,\n title: string,\n data: any,\n metadata: Record<string, any> = {}\n ): ContentChunk[] {\n // Extract all text from content\n const text = this.extractText(data)\n \n if (!text || text.trim().length === 0) {\n console.warn(`[ChunkingService] No text found for content ${contentId}`)\n return []\n }\n\n // Split into chunks\n const textChunks = this.splitIntoChunks(text)\n\n // Create chunk objects\n return textChunks.map((chunkText, index) => ({\n id: `${contentId}_chunk_${index}`,\n content_id: contentId,\n collection_id: collectionId,\n title: title,\n text: chunkText,\n chunk_index: index,\n metadata: {\n ...metadata,\n total_chunks: textChunks.length\n }\n }))\n }\n\n /**\n * Chunk multiple content items\n */\n chunkContentBatch(items: Array<{\n id: string\n collection_id: string\n title: string\n data: any\n metadata?: Record<string, any>\n }>): ContentChunk[] {\n const allChunks: ContentChunk[] = []\n\n for (const item of items) {\n const chunks = this.chunkContent(\n item.id,\n item.collection_id,\n item.title,\n item.data,\n item.metadata\n )\n allChunks.push(...chunks)\n }\n\n return allChunks\n }\n\n /**\n * Extract all text from content data\n */\n private extractText(data: any): string {\n const parts: string[] = []\n\n // Common text fields\n if (data.title) parts.push(String(data.title))\n if (data.name) parts.push(String(data.name))\n if (data.description) parts.push(String(data.description))\n if (data.content) parts.push(String(data.content))\n if (data.body) parts.push(String(data.body))\n if (data.text) parts.push(String(data.text))\n if (data.summary) parts.push(String(data.summary))\n\n // Recursively extract from nested objects\n const extractRecursive = (obj: any): void => {\n if (typeof obj === 'string') {\n // Skip very short strings and URLs\n if (obj.length > 10 && !obj.startsWith('http')) {\n parts.push(obj)\n }\n } else if (Array.isArray(obj)) {\n obj.forEach(extractRecursive)\n } else if (obj && typeof obj === 'object') {\n // Skip certain keys\n const skipKeys = ['id', 'slug', 'url', 'image', 'thumbnail', 'metadata']\n \n Object.entries(obj).forEach(([key, value]) => {\n if (!skipKeys.includes(key.toLowerCase())) {\n extractRecursive(value)\n }\n })\n }\n }\n\n extractRecursive(data)\n\n return parts.join('\\n\\n').trim()\n }\n\n /**\n * Split text into overlapping chunks\n */\n private splitIntoChunks(text: string): string[] {\n // Split by words\n const words = text.split(/\\s+/)\n \n if (words.length <= this.CHUNK_SIZE) {\n return [text]\n }\n\n const chunks: string[] = []\n let startIndex = 0\n\n while (startIndex < words.length) {\n // Get chunk with overlap\n const endIndex = Math.min(startIndex + this.CHUNK_SIZE, words.length)\n const chunk = words.slice(startIndex, endIndex).join(' ')\n chunks.push(chunk)\n\n // Move forward by chunk size minus overlap\n startIndex += this.CHUNK_SIZE - this.CHUNK_OVERLAP\n\n // Ensure we don't create a tiny last chunk\n if (startIndex >= words.length - this.CHUNK_OVERLAP) {\n break\n }\n }\n\n return chunks\n }\n\n /**\n * Get optimal chunk size based on content type\n */\n getOptimalChunkSize(contentType: string): number {\n switch (contentType) {\n case 'blog_posts':\n case 'articles':\n return 600 // Larger chunks for long-form content\n case 'products':\n case 'pages':\n return 400 // Medium chunks for structured content\n case 'messages':\n case 'comments':\n return 200 // Small chunks for short content\n default:\n return this.CHUNK_SIZE\n }\n }\n}\n","/**\n * Custom RAG Service\n * Implements full RAG pipeline using Cloudflare Vectorize\n * \n * Fulfills GitHub Issue #362: Advanced search with Cloudflare Search\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\nimport { EmbeddingService } from './embedding.service'\nimport { ChunkingService, type ContentChunk } from './chunking.service'\nimport type { SearchQuery, SearchResponse, SearchResult, AISearchSettings } from '../types'\n\nexport class CustomRAGService {\n private embeddingService: EmbeddingService\n private chunkingService: ChunkingService\n\n constructor(\n private db: D1Database,\n private ai: any,\n private vectorize: any\n ) {\n this.embeddingService = new EmbeddingService(ai)\n this.chunkingService = new ChunkingService()\n }\n\n /**\n * Index all content from a collection\n */\n async indexCollection(collectionId: string): Promise<{\n total_items: number\n total_chunks: number\n indexed_chunks: number\n errors: number\n }> {\n console.log(`[CustomRAG] Starting indexing for collection: ${collectionId}`)\n \n try {\n // Get all published content from collection\n const { results: contentItems } = await this.db\n .prepare(`\n SELECT c.id, c.title, c.data, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.collection_id = ? AND c.status = 'published'\n `)\n .bind(collectionId)\n .all<{\n id: string\n title: string\n data: string\n collection_id: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n const totalItems = contentItems?.length || 0\n \n if (totalItems === 0) {\n console.log(`[CustomRAG] No content found in collection ${collectionId}`)\n return { total_items: 0, total_chunks: 0, indexed_chunks: 0, errors: 0 }\n }\n\n // Chunk all content\n const items = (contentItems || []).map(item => ({\n id: item.id,\n collection_id: item.collection_id,\n title: item.title || 'Untitled',\n data: typeof item.data === 'string' ? JSON.parse(item.data) : item.data,\n metadata: {\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at,\n author_id: item.author_id,\n collection_name: item.collection_name,\n collection_display_name: item.collection_display_name\n }\n }))\n\n const chunks = this.chunkingService.chunkContentBatch(items)\n const totalChunks = chunks.length\n\n console.log(`[CustomRAG] Generated ${totalChunks} chunks from ${totalItems} items`)\n\n // Generate embeddings in batches\n const embeddings = await this.embeddingService.generateBatch(\n chunks.map(c => `${c.title}\\n\\n${c.text}`)\n )\n\n console.log(`[CustomRAG] Generated ${embeddings.length} embeddings`)\n\n // Store in Vectorize\n let indexedChunks = 0\n let errors = 0\n const batchSize = 100\n\n for (let i = 0; i < chunks.length; i += batchSize) {\n const chunkBatch = chunks.slice(i, i + batchSize)\n const embeddingBatch = embeddings.slice(i, i + batchSize)\n\n try {\n await this.vectorize.upsert(\n chunkBatch.map((chunk, idx) => ({\n id: chunk.id,\n values: embeddingBatch[idx],\n metadata: {\n content_id: chunk.content_id,\n collection_id: chunk.collection_id,\n title: chunk.title,\n text: chunk.text.substring(0, 500), // Store snippet for display\n chunk_index: chunk.chunk_index,\n ...chunk.metadata\n }\n }))\n )\n\n indexedChunks += chunkBatch.length\n console.log(`[CustomRAG] Indexed batch ${i / batchSize + 1}: ${chunkBatch.length} chunks`)\n } catch (error) {\n console.error(`[CustomRAG] Error indexing batch ${i / batchSize + 1}:`, error)\n errors += chunkBatch.length\n }\n }\n\n console.log(`[CustomRAG] Indexing complete: ${indexedChunks}/${totalChunks} chunks indexed`)\n\n return {\n total_items: totalItems,\n total_chunks: totalChunks,\n indexed_chunks: indexedChunks,\n errors\n }\n } catch (error) {\n console.error(`[CustomRAG] Error indexing collection ${collectionId}:`, error)\n throw error\n }\n }\n\n /**\n * Search using RAG (semantic search with Vectorize)\n */\n async search(query: SearchQuery, settings: AISearchSettings): Promise<SearchResponse> {\n const startTime = Date.now()\n\n try {\n console.log(`[CustomRAG] Searching for: \"${query.query}\"`)\n\n // Generate query embedding\n const queryEmbedding = await this.embeddingService.generateEmbedding(query.query)\n\n // Build Vectorize query filters\n const filter: any = {}\n \n if (query.filters?.collections && query.filters.collections.length > 0) {\n filter.collection_id = { $in: query.filters.collections }\n } else if (settings.selected_collections.length > 0) {\n filter.collection_id = { $in: settings.selected_collections }\n }\n\n if (query.filters?.status && query.filters.status.length > 0) {\n filter.status = { $in: query.filters.status }\n }\n\n // Vectorize filters have issues, so we query without filter and manually filter results\n const vectorResults = await this.vectorize.query(queryEmbedding, {\n topK: 50, // Max allowed with returnMetadata: true\n returnMetadata: true\n })\n\n // Manually filter results by collection_id if filter exists\n let filteredMatches = vectorResults.matches || []\n if (filter.collection_id?.$in && Array.isArray(filter.collection_id.$in)) {\n const allowedCollections = filter.collection_id.$in\n filteredMatches = filteredMatches.filter((match: any) => \n allowedCollections.includes(match.metadata?.collection_id)\n )\n }\n\n // Apply status filter if exists\n if (filter.status?.$in && Array.isArray(filter.status.$in)) {\n const allowedStatuses = filter.status.$in\n filteredMatches = filteredMatches.filter((match: any) => \n allowedStatuses.includes(match.metadata?.status)\n )\n }\n\n // Limit to requested topK\n const topK = query.limit || settings.results_limit || 20\n filteredMatches = filteredMatches.slice(0, topK)\n\n // Replace matches with filtered results\n vectorResults.matches = filteredMatches\n\n if (!vectorResults.matches || vectorResults.matches.length === 0) {\n return {\n results: [],\n total: 0,\n query_time_ms: Date.now() - startTime,\n mode: 'ai'\n }\n }\n\n // Get unique content IDs\n const contentIds = [...new Set(\n vectorResults.matches.map((m: any) => m.metadata.content_id)\n )]\n\n // Fetch full content from D1\n const placeholders = contentIds.map(() => '?').join(',')\n const { results: contentItems } = await this.db\n .prepare(`\n SELECT c.id, c.title, c.slug, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.display_name as collection_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id IN (${placeholders})\n `)\n .bind(...contentIds)\n .all<{\n id: string\n title: string\n slug: string\n collection_id: string\n collection_name: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n }>()\n\n // Map results with relevance scores\n const searchResults: SearchResult[] = (contentItems || []).map(item => {\n // Find best matching chunk for this content\n const matchingChunks = vectorResults.matches.filter(\n (m: any) => m.metadata.content_id === item.id\n )\n \n const bestMatch = matchingChunks.reduce((best: any, current: any) => \n current.score > (best?.score || 0) ? current : best\n , null)\n\n return {\n id: item.id,\n title: item.title || 'Untitled',\n slug: item.slug || '',\n collection_id: item.collection_id,\n collection_name: item.collection_name,\n snippet: bestMatch?.metadata?.text || '',\n relevance_score: bestMatch?.score || 0,\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at\n }\n })\n\n // Sort by relevance score\n searchResults.sort((a, b) => (b.relevance_score || 0) - (a.relevance_score || 0))\n\n const queryTime = Date.now() - startTime\n console.log(`[CustomRAG] Search completed in ${queryTime}ms, ${searchResults.length} results`)\n\n return {\n results: searchResults,\n total: searchResults.length,\n query_time_ms: queryTime,\n mode: 'ai'\n }\n } catch (error) {\n console.error('[CustomRAG] Search error:', error)\n throw error\n }\n }\n\n /**\n * Update index for a single content item\n */\n async updateContentIndex(contentId: string): Promise<void> {\n try {\n // Get content item\n const content = await this.db\n .prepare(`\n SELECT c.id, c.title, c.data, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id = ?\n `)\n .bind(contentId)\n .first<{\n id: string\n title: string\n data: string\n collection_id: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n if (!content) {\n console.warn(`[CustomRAG] Content ${contentId} not found`)\n return\n }\n\n // If content is not published, remove from index\n if (content.status !== 'published') {\n await this.removeContentFromIndex(contentId)\n return\n }\n\n // Chunk content\n const chunks = this.chunkingService.chunkContent(\n content.id,\n content.collection_id,\n content.title || 'Untitled',\n typeof content.data === 'string' ? JSON.parse(content.data) : content.data,\n {\n status: content.status,\n created_at: content.created_at,\n updated_at: content.updated_at,\n author_id: content.author_id,\n collection_name: content.collection_name,\n collection_display_name: content.collection_display_name\n }\n )\n\n // Generate embeddings\n const embeddings = await this.embeddingService.generateBatch(\n chunks.map(c => `${c.title}\\n\\n${c.text}`)\n )\n\n // Update in Vectorize\n await this.vectorize.upsert(\n chunks.map((chunk, idx) => ({\n id: chunk.id,\n values: embeddings[idx],\n metadata: {\n content_id: chunk.content_id,\n collection_id: chunk.collection_id,\n title: chunk.title,\n text: chunk.text.substring(0, 500),\n chunk_index: chunk.chunk_index,\n ...chunk.metadata\n }\n }))\n )\n\n console.log(`[CustomRAG] Updated index for content ${contentId}: ${chunks.length} chunks`)\n } catch (error) {\n console.error(`[CustomRAG] Error updating index for ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Remove content from index\n */\n async removeContentFromIndex(contentId: string): Promise<void> {\n try {\n // Note: Vectorize doesn't have a bulk delete by metadata filter\n // We need to delete each chunk individually\n // In practice, we would track chunk IDs or use a different approach\n \n console.log(`[CustomRAG] Removing content ${contentId} from index`)\n \n // For now, we'll let stale chunks age out\n // A better approach would be to maintain a mapping in D1\n // TODO: Implement proper chunk tracking\n \n } catch (error) {\n console.error(`[CustomRAG] Error removing content ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Get search suggestions based on query\n */\n async getSuggestions(partialQuery: string, limit: number = 5): Promise<string[]> {\n try {\n // Generate embedding for partial query\n const queryEmbedding = await this.embeddingService.generateEmbedding(partialQuery)\n\n // Search for similar content titles\n const results = await this.vectorize.query(queryEmbedding, {\n topK: limit * 2, // Get more to filter\n returnMetadata: true\n })\n\n // Extract unique titles\n const suggestions = [...new Set(\n results.matches?.map((m: any) => m.metadata.title).filter(Boolean) || []\n )].slice(0, limit)\n\n return suggestions as string[]\n } catch (error) {\n console.error('[CustomRAG] Error getting suggestions:', error)\n return []\n }\n }\n\n /**\n * Check if Vectorize is available and configured\n */\n isAvailable(): boolean {\n return !!this.vectorize && !!this.ai\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type {\n AISearchSettings,\n SearchQuery,\n SearchResponse,\n SearchResult,\n CollectionInfo,\n NewCollectionNotification,\n} from '../types'\nimport { CustomRAGService } from './custom-rag.service'\n\n/**\n * AI Search Service\n * Handles search operations, settings management, and collection detection\n * Now uses Custom RAG with Vectorize for semantic search\n */\nexport class AISearchService {\n private customRAG?: CustomRAGService\n\n constructor(\n private db: D1Database,\n private ai?: any, // Workers AI for embeddings\n private vectorize?: any // Vectorize for vector search\n ) {\n // Initialize Custom RAG if bindings are available\n if (this.ai && this.vectorize) {\n this.customRAG = new CustomRAGService(db, ai, vectorize)\n console.log('[AISearchService] Custom RAG initialized')\n } else {\n console.log('[AISearchService] Custom RAG not available, using keyword search only')\n }\n }\n\n /**\n * Get plugin settings\n */\n async getSettings(): Promise<AISearchSettings | null> {\n try {\n const plugin = await this.db\n .prepare(`SELECT settings FROM plugins WHERE id = ? LIMIT 1`)\n .bind('ai-search')\n .first<{ settings: string | null }>()\n\n if (!plugin || !plugin.settings) {\n return this.getDefaultSettings()\n }\n\n return JSON.parse(plugin.settings) as AISearchSettings\n } catch (error) {\n console.error('Error fetching AI Search settings:', error)\n return this.getDefaultSettings()\n }\n }\n\n /**\n * Get default settings\n */\n getDefaultSettings(): AISearchSettings {\n return {\n enabled: true,\n ai_mode_enabled: true,\n selected_collections: [],\n dismissed_collections: [],\n autocomplete_enabled: true,\n cache_duration: 1,\n results_limit: 20,\n index_media: false,\n }\n }\n\n /**\n * Update plugin settings\n */\n async updateSettings(settings: Partial<AISearchSettings>): Promise<AISearchSettings> {\n const existing = await this.getSettings()\n const updated: AISearchSettings = {\n ...existing!,\n ...settings,\n }\n\n try {\n // Update plugin settings in plugins table\n await this.db\n .prepare(`\n UPDATE plugins\n SET settings = ?,\n updated_at = unixepoch()\n WHERE id = 'ai-search'\n `)\n .bind(JSON.stringify(updated))\n .run()\n\n return updated\n } catch (error) {\n console.error('Error updating AI Search settings:', error)\n throw error\n }\n }\n\n /**\n * Detect new collections that aren't indexed or dismissed\n */\n async detectNewCollections(): Promise<NewCollectionNotification[]> {\n try {\n // Get all collections (exclude test collections)\n // Note: D1 doesn't support parameterized LIKE, so we filter in JavaScript\n const collectionsStmt = this.db.prepare(\n 'SELECT id, name, display_name, description FROM collections WHERE is_active = 1'\n )\n const { results: allCollections } = await collectionsStmt.all<{\n id: number\n name: string\n display_name: string\n description?: string\n }>()\n \n // Filter out test collections (starts with test_, ends with _test, or is test_collection)\n const collections = (allCollections || []).filter(\n (col) => {\n if (!col.name) return false\n const name = col.name.toLowerCase()\n return !name.startsWith('test_') && \n !name.endsWith('_test') && \n name !== 'test_collection' &&\n !name.includes('_test_') &&\n name !== 'large_payload_test' &&\n name !== 'concurrent_test'\n }\n )\n\n // Get settings\n const settings = await this.getSettings()\n const selected = settings?.selected_collections || []\n const dismissed = settings?.dismissed_collections || []\n\n // Get item counts for each collection\n const notifications: NewCollectionNotification[] = []\n\n for (const collection of collections || []) {\n const collectionId = String(collection.id)\n\n // Skip if already selected or dismissed\n if (selected.includes(collectionId) || dismissed.includes(collectionId)) {\n continue\n }\n\n // Get item count\n const countStmt = this.db.prepare(\n 'SELECT COUNT(*) as count FROM content WHERE collection_id = ?'\n )\n const countResult = await countStmt.bind(collectionId).first<{ count: number }>()\n const itemCount = countResult?.count || 0\n\n notifications.push({\n collection: {\n id: collectionId,\n name: collection.name,\n display_name: collection.display_name,\n description: collection.description,\n item_count: itemCount,\n is_indexed: false,\n is_dismissed: false,\n is_new: true,\n },\n message: `New collection \"${collection.display_name}\" with ${itemCount} items available for indexing`,\n })\n }\n\n return notifications\n } catch (error) {\n console.error('Error detecting new collections:', error)\n return []\n }\n }\n\n /**\n * Get all collections with indexing status\n */\n async getAllCollections(): Promise<CollectionInfo[]> {\n try {\n // Get all collections (same query as content page)\n const collectionsStmt = this.db.prepare(\n 'SELECT id, name, display_name, description FROM collections WHERE is_active = 1 ORDER BY display_name'\n )\n const { results: allCollections } = await collectionsStmt.all<{\n id: string\n name: string\n display_name: string\n description?: string\n }>()\n \n console.log('[AISearchService.getAllCollections] Raw collections from DB:', allCollections?.length || 0)\n const firstCollection = allCollections?.[0]\n if (firstCollection) {\n console.log('[AISearchService.getAllCollections] Sample collection:', {\n id: firstCollection.id,\n name: firstCollection.name,\n display_name: firstCollection.display_name\n })\n }\n \n // No filtering needed - test collections are now properly cleaned up by E2E tests\n const collections = (allCollections || []).filter(\n (col) => col.id && col.name\n )\n \n console.log('[AISearchService.getAllCollections] After filtering test collections:', collections.length)\n console.log('[AISearchService.getAllCollections] Remaining collections:', collections.map(c => c.name).join(', '))\n\n // Get settings\n const settings = await this.getSettings()\n const selected = settings?.selected_collections || []\n const dismissed = settings?.dismissed_collections || []\n \n console.log('[AISearchService.getAllCollections] Settings:', {\n selected_count: selected.length,\n dismissed_count: dismissed.length,\n selected: selected\n })\n\n // Get item counts and indexing status\n const collectionInfos: CollectionInfo[] = []\n\n for (const collection of collections) {\n if (!collection.id || !collection.name) continue\n const collectionId = String(collection.id)\n \n if (!collectionId) {\n console.warn('[AISearchService] Skipping invalid collection:', collection)\n continue\n }\n\n // Get item count\n const countStmt = this.db.prepare(\n 'SELECT COUNT(*) as count FROM content WHERE collection_id = ?'\n )\n const countResult = await countStmt.bind(collectionId).first<{ count: number }>()\n const itemCount = countResult?.count || 0\n\n collectionInfos.push({\n id: collectionId,\n name: collection.name,\n display_name: collection.display_name || collection.name,\n description: collection.description,\n item_count: itemCount,\n is_indexed: selected.includes(collectionId),\n is_dismissed: dismissed.includes(collectionId),\n is_new: !selected.includes(collectionId) && !dismissed.includes(collectionId),\n })\n }\n \n console.log('[AISearchService.getAllCollections] Returning collectionInfos:', collectionInfos.length)\n const firstInfo = collectionInfos[0]\n if (collectionInfos.length > 0 && firstInfo) {\n console.log('[AISearchService.getAllCollections] First collectionInfo:', {\n id: firstInfo.id,\n name: firstInfo.name,\n display_name: firstInfo.display_name,\n item_count: firstInfo.item_count\n })\n }\n return collectionInfos\n } catch (error) {\n console.error('[AISearchService] Error fetching collections:', error)\n return []\n }\n }\n\n /**\n * Execute search query\n */\n async search(query: SearchQuery): Promise<SearchResponse> {\n const startTime = Date.now()\n const settings = await this.getSettings()\n\n if (!settings?.enabled) {\n return {\n results: [],\n total: 0,\n query_time_ms: 0,\n mode: query.mode,\n }\n }\n\n // Use AI Search if enabled and mode is 'ai'\n if (query.mode === 'ai' && settings.ai_mode_enabled && this.customRAG?.isAvailable()) {\n return this.searchAI(query, settings)\n }\n\n // Fallback to keyword search\n return this.searchKeyword(query, settings)\n }\n\n /**\n * AI-powered semantic search using Custom RAG\n */\n private async searchAI(query: SearchQuery, settings: AISearchSettings): Promise<SearchResponse> {\n const startTime = Date.now()\n \n try {\n if (!this.customRAG) {\n console.warn('[AISearchService] CustomRAG not available, falling back to keyword search')\n return this.searchKeyword(query, settings)\n }\n\n // Use Custom RAG for semantic search - pass the full query object and settings\n const result = await this.customRAG.search(query, settings)\n\n return result\n } catch (error) {\n console.error('[AISearchService] AI search error, falling back to keyword:', error)\n // Fallback to keyword search\n return this.searchKeyword(query, settings)\n }\n }\n\n /**\n * Traditional keyword search\n */\n private async searchKeyword(\n query: SearchQuery,\n settings: AISearchSettings\n ): Promise<SearchResponse> {\n const startTime = Date.now()\n\n try {\n const conditions: string[] = []\n const params: any[] = []\n\n // Search query\n if (query.query) {\n conditions.push('(c.title LIKE ? OR c.slug LIKE ? OR c.data LIKE ?)')\n const searchTerm = `%${query.query}%`\n params.push(searchTerm, searchTerm, searchTerm)\n }\n\n // Collection filter\n if (query.filters?.collections && query.filters.collections.length > 0) {\n const placeholders = query.filters.collections.map(() => '?').join(',')\n conditions.push(`c.collection_id IN (${placeholders})`)\n params.push(...query.filters.collections)\n } else if (settings.selected_collections.length > 0) {\n // Only search indexed collections\n const placeholders = settings.selected_collections.map(() => '?').join(',')\n conditions.push(`c.collection_id IN (${placeholders})`)\n params.push(...settings.selected_collections)\n }\n\n // Status filter\n if (query.filters?.status && query.filters.status.length > 0) {\n const placeholders = query.filters.status.map(() => '?').join(',')\n conditions.push(`c.status IN (${placeholders})`)\n params.push(...query.filters.status)\n } else {\n // Exclude deleted by default\n conditions.push(\"c.status != 'deleted'\")\n }\n\n // Date range filter\n if (query.filters?.dateRange) {\n const field = query.filters.dateRange.field || 'created_at'\n if (query.filters.dateRange.start) {\n conditions.push(`c.${field} >= ?`)\n params.push(query.filters.dateRange.start.getTime())\n }\n if (query.filters.dateRange.end) {\n conditions.push(`c.${field} <= ?`)\n params.push(query.filters.dateRange.end.getTime())\n }\n }\n\n // Author filter\n if (query.filters?.author) {\n conditions.push('c.author_id = ?')\n params.push(query.filters.author)\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n\n // Get total count\n const countStmt = this.db.prepare(`\n SELECT COUNT(*) as count \n FROM content c\n ${whereClause}\n `)\n const countResult = await countStmt.bind(...params).first<{ count: number }>()\n const total = countResult?.count || 0\n\n // Get results\n const limit = query.limit || settings.results_limit\n const offset = query.offset || 0\n\n const resultsStmt = this.db.prepare(`\n SELECT \n c.id, c.title, c.slug, c.collection_id, c.status,\n c.created_at, c.updated_at, c.author_id, c.data,\n col.name as collection_name, col.display_name as collection_display_name,\n u.email as author_email\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n LEFT JOIN users u ON c.author_id = u.id\n ${whereClause}\n ORDER BY c.updated_at DESC\n LIMIT ? OFFSET ?\n `)\n\n const { results } = await resultsStmt.bind(...params, limit, offset).all<{\n id: string\n title: string\n slug: string\n collection_id: number\n collection_name: string\n collection_display_name: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n author_email?: string\n data: string\n }>()\n\n const searchResults: SearchResult[] = (results || []).map((row) => ({\n id: String(row.id),\n title: row.title || 'Untitled',\n slug: row.slug || '',\n collection_id: String(row.collection_id),\n collection_name: row.collection_display_name || row.collection_name,\n snippet: this.extractSnippet(row.data, query.query),\n status: row.status,\n created_at: Number(row.created_at),\n updated_at: Number(row.updated_at),\n author_name: row.author_email,\n }))\n\n const queryTime = Date.now() - startTime\n\n // Log search history\n await this.logSearch(query.query, query.mode, searchResults.length)\n\n return {\n results: searchResults,\n total,\n query_time_ms: queryTime,\n mode: query.mode,\n }\n } catch (error) {\n console.error('Keyword search error:', error)\n return {\n results: [],\n total: 0,\n query_time_ms: Date.now() - startTime,\n mode: query.mode,\n }\n }\n }\n\n /**\n * Extract snippet from content data\n */\n private extractSnippet(data: string, query: string): string {\n try {\n const parsed = typeof data === 'string' ? JSON.parse(data) : data\n const text = JSON.stringify(parsed).toLowerCase()\n const queryLower = query.toLowerCase()\n\n const index = text.indexOf(queryLower)\n if (index === -1) {\n // Return first 200 chars\n return JSON.stringify(parsed).substring(0, 200) + '...'\n }\n\n // Extract context around match\n const start = Math.max(0, index - 50)\n const end = Math.min(text.length, index + query.length + 50)\n return text.substring(start, end) + '...'\n } catch {\n return data.substring(0, 200) + '...'\n }\n }\n\n /**\n * Get search suggestions (autocomplete)\n */\n async getSearchSuggestions(partial: string): Promise<string[]> {\n try {\n const settings = await this.getSettings()\n if (!settings?.autocomplete_enabled) {\n return []\n }\n\n // If Custom RAG is available, use AI-powered suggestions\n if (this.customRAG?.isAvailable()) {\n try {\n const aiSuggestions = await this.customRAG.getSuggestions(partial, 5)\n if (aiSuggestions.length > 0) {\n return aiSuggestions\n }\n } catch (error) {\n console.error('[AISearchService] Error getting AI suggestions:', error)\n // Fall through to history-based suggestions\n }\n }\n\n // Fallback to history-based suggestions\n const stmt = this.db.prepare(`\n SELECT DISTINCT query \n FROM ai_search_history \n WHERE query LIKE ? \n ORDER BY created_at DESC \n LIMIT 10\n `)\n const { results } = await stmt.bind(`%${partial}%`).all<{ query: string }>()\n\n return (results || []).map((r) => r.query)\n } catch (error) {\n console.error('Error getting suggestions:', error)\n return []\n }\n }\n\n /**\n * Log search query to history\n */\n private async logSearch(query: string, mode: 'ai' | 'keyword', resultsCount: number): Promise<void> {\n try {\n const stmt = this.db.prepare(`\n INSERT INTO ai_search_history (query, mode, results_count, created_at)\n VALUES (?, ?, ?, ?)\n `)\n await stmt.bind(query, mode, resultsCount, Date.now()).run()\n } catch (error) {\n console.error('Error logging search:', error)\n }\n }\n\n /**\n * Get search analytics\n */\n async getSearchAnalytics(): Promise<{\n total_queries: number\n ai_queries: number\n keyword_queries: number\n popular_queries: Array<{ query: string; count: number }>\n average_query_time: number\n }> {\n try {\n // Total queries (last 30 days)\n const totalStmt = this.db.prepare(`\n SELECT COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n `)\n const thirtyDaysAgo = Date.now() - 30 * 24 * 60 * 60 * 1000\n const totalResult = await totalStmt.bind(thirtyDaysAgo).first<{ count: number }>()\n\n // AI vs Keyword breakdown\n const modeStmt = this.db.prepare(`\n SELECT mode, COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n GROUP BY mode\n `)\n const { results: modeResults } = await modeStmt.bind(thirtyDaysAgo).all<{\n mode: string\n count: number\n }>()\n\n const aiCount = modeResults?.find((r) => r.mode === 'ai')?.count || 0\n const keywordCount = modeResults?.find((r) => r.mode === 'keyword')?.count || 0\n\n // Popular queries\n const popularStmt = this.db.prepare(`\n SELECT query, COUNT(*) as count \n FROM ai_search_history \n WHERE created_at >= ?\n GROUP BY query \n ORDER BY count DESC \n LIMIT 10\n `)\n const { results: popularResults } = await popularStmt.bind(thirtyDaysAgo).all<{\n query: string\n count: number\n }>()\n\n return {\n total_queries: totalResult?.count || 0,\n ai_queries: aiCount,\n keyword_queries: keywordCount,\n popular_queries: (popularResults || []).map((r) => ({\n query: r.query,\n count: r.count,\n })),\n average_query_time: 0, // TODO: Track query times\n }\n } catch (error) {\n console.error('Error getting analytics:', error)\n return {\n total_queries: 0,\n ai_queries: 0,\n keyword_queries: 0,\n popular_queries: [],\n average_query_time: 0,\n }\n }\n }\n\n /**\n * Verify Custom RAG is available\n */\n verifyBinding(): boolean {\n return this.customRAG?.isAvailable() ?? false\n }\n\n /**\n * Get Custom RAG service instance (for indexer)\n */\n getCustomRAG(): CustomRAGService | undefined {\n return this.customRAG\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type { AISearchSettings, IndexStatus } from '../types'\nimport { CustomRAGService } from './custom-rag.service'\n\n/**\n * Index Manager Service\n * Handles indexing of content items using Custom RAG with Vectorize\n */\nexport class IndexManager {\n private customRAG?: CustomRAGService\n\n constructor(\n private db: D1Database,\n private ai?: any, // Workers AI for embeddings\n private vectorize?: any // Vectorize for vector search\n ) {\n // Initialize Custom RAG if bindings are available\n if (this.ai && this.vectorize) {\n this.customRAG = new CustomRAGService(db, ai, vectorize)\n console.log('[IndexManager] Custom RAG initialized')\n }\n }\n\n /**\n * Index all content items within a collection using Custom RAG\n */\n async indexCollection(collectionId: string): Promise<IndexStatus> {\n try {\n // Get collection info\n const collectionStmt = this.db.prepare(\n 'SELECT id, name, display_name FROM collections WHERE id = ?'\n )\n const collection = await collectionStmt.bind(collectionId).first<{\n id: string\n name: string\n display_name: string\n }>()\n\n if (!collection) {\n throw new Error(`Collection ${collectionId} not found`)\n }\n\n // Update status to indexing\n await this.updateIndexStatus(collectionId, {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: 0,\n indexed_items: 0,\n status: 'indexing',\n })\n\n // Use Custom RAG for indexing if available\n if (this.customRAG?.isAvailable()) {\n console.log(`[IndexManager] Using Custom RAG to index collection ${collectionId}`)\n \n const result = await this.customRAG.indexCollection(collectionId)\n\n const finalStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: result.total_items,\n indexed_items: result.indexed_chunks,\n last_sync_at: Date.now(),\n status: result.errors > 0 ? 'error' : 'completed',\n error_message: result.errors > 0 ? `${result.errors} errors during indexing` : undefined\n }\n\n await this.updateIndexStatus(collectionId, finalStatus)\n return finalStatus\n }\n\n // Fallback: No indexing without Custom RAG\n console.warn(`[IndexManager] Custom RAG not available, skipping indexing for ${collectionId}`)\n \n const fallbackStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: collection.display_name,\n total_items: 0,\n indexed_items: 0,\n last_sync_at: Date.now(),\n status: 'completed',\n error_message: 'Custom RAG not available - using keyword search only'\n }\n\n await this.updateIndexStatus(collectionId, fallbackStatus)\n return fallbackStatus\n } catch (error) {\n console.error(`[IndexManager] Error indexing collection ${collectionId}:`, error)\n const errorStatus: IndexStatus = {\n collection_id: collectionId,\n collection_name: 'Unknown',\n total_items: 0,\n indexed_items: 0,\n status: 'error',\n error_message: error instanceof Error ? error.message : String(error),\n }\n await this.updateIndexStatus(collectionId, errorStatus)\n return errorStatus\n }\n }\n\n /**\n * Index a single content item\n */\n private async indexContentItem(\n item: {\n id: string\n title: string\n slug: string\n data: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n },\n collectionId: string\n ): Promise<void> {\n try {\n // Parse content data\n let parsedData: any = {}\n try {\n parsedData = typeof item.data === 'string' ? JSON.parse(item.data) : item.data\n } catch {\n parsedData = {}\n }\n\n // Prepare document for AI Search\n const document = {\n id: `content_${item.id}`,\n title: item.title || 'Untitled',\n slug: item.slug || '',\n content: this.extractSearchableText(parsedData),\n metadata: {\n collection_id: collectionId,\n collection_name: item.collection_name,\n collection_display_name: item.collection_display_name,\n status: item.status,\n created_at: item.created_at,\n updated_at: item.updated_at,\n author_id: item.author_id,\n },\n }\n\n // TODO: Call Cloudflare AI Search API to index document\n // await this.aiSearch.index(document)\n\n // For now, just log (actual implementation will use AI Search API)\n console.log(`Indexed content item: ${item.id}`)\n } catch (error) {\n console.error(`Error indexing content item ${item.id}:`, error)\n throw error\n }\n }\n\n /**\n * Extract searchable text from content data\n */\n private extractSearchableText(data: any): string {\n const parts: string[] = []\n\n // Add title if present\n if (data.title) parts.push(String(data.title))\n if (data.name) parts.push(String(data.name))\n\n // Add description/content fields\n if (data.description) parts.push(String(data.description))\n if (data.content) parts.push(String(data.content))\n if (data.body) parts.push(String(data.body))\n if (data.text) parts.push(String(data.text))\n\n // Add all string values from data\n const extractStrings = (obj: any): void => {\n if (typeof obj === 'string') {\n parts.push(obj)\n } else if (Array.isArray(obj)) {\n obj.forEach(extractStrings)\n } else if (obj && typeof obj === 'object') {\n Object.values(obj).forEach(extractStrings)\n }\n }\n\n extractStrings(data)\n\n return parts.join(' ')\n }\n\n /**\n * Update a single content item in the index\n */\n async updateIndex(collectionId: number, contentId: string): Promise<void> {\n try {\n // Get content item\n const stmt = this.db.prepare(`\n SELECT \n c.id, c.title, c.slug, c.data, c.status,\n c.created_at, c.updated_at, c.author_id,\n col.name as collection_name, col.display_name as collection_display_name\n FROM content c\n JOIN collections col ON c.collection_id = col.id\n WHERE c.id = ? AND c.collection_id = ?\n `)\n const item = await stmt.bind(contentId, collectionId).first<{\n id: string\n title: string\n slug: string\n data: string\n status: string\n created_at: number\n updated_at: number\n author_id?: string\n collection_name: string\n collection_display_name: string\n }>()\n\n if (!item) {\n throw new Error(`Content item ${contentId} not found`)\n }\n\n // Re-index the item\n await this.indexContentItem(item, String(collectionId))\n\n // Update last sync time for collection\n const status = await this.getIndexStatus(String(collectionId))\n if (status) {\n await this.updateIndexStatus(String(collectionId), {\n ...status,\n last_sync_at: Date.now(),\n })\n }\n } catch (error) {\n console.error(`Error updating index for content ${contentId}:`, error)\n throw error\n }\n }\n\n /**\n * Remove a content item from the index using Custom RAG\n */\n async removeFromIndex(collectionId: string, contentId: string): Promise<void> {\n try {\n if (this.customRAG?.isAvailable()) {\n console.log(`[IndexManager] Removing content ${contentId} from index`)\n await this.customRAG.removeContentFromIndex(contentId)\n } else {\n console.warn(`[IndexManager] Custom RAG not available, skipping removal for ${contentId}`)\n }\n } catch (error) {\n console.error(`[IndexManager] Error removing content ${contentId} from index:`, error)\n throw error\n }\n }\n\n /**\n * Get indexing status for a collection\n */\n async getIndexStatus(collectionId: string): Promise<IndexStatus | null> {\n try {\n const stmt = this.db.prepare(\n 'SELECT * FROM ai_search_index_meta WHERE collection_id = ?'\n )\n const result = await stmt.bind(collectionId).first<{\n id: number\n collection_id: string\n collection_name: string\n total_items: number\n indexed_items: number\n last_sync_at?: number\n status: string\n error_message?: string\n }>()\n\n if (!result) {\n return null\n }\n\n return {\n collection_id: String(result.collection_id),\n collection_name: result.collection_name,\n total_items: result.total_items,\n indexed_items: result.indexed_items,\n last_sync_at: result.last_sync_at,\n status: result.status as IndexStatus['status'],\n error_message: result.error_message,\n }\n } catch (error) {\n console.error(`Error getting index status for collection ${collectionId}:`, error)\n return null\n }\n }\n\n /**\n * Get indexing status for all collections\n */\n async getAllIndexStatus(): Promise<Record<string, IndexStatus>> {\n try {\n const stmt = this.db.prepare('SELECT * FROM ai_search_index_meta')\n const { results } = await stmt.all<{\n id: number\n collection_id: number\n collection_name: string\n total_items: number\n indexed_items: number\n last_sync_at?: number\n status: string\n error_message?: string\n }>()\n\n const statusMap: Record<string, IndexStatus> = {}\n\n for (const row of results || []) {\n const collectionId = String(row.collection_id)\n statusMap[collectionId] = {\n collection_id: collectionId,\n collection_name: row.collection_name,\n total_items: row.total_items,\n indexed_items: row.indexed_items,\n last_sync_at: row.last_sync_at,\n status: row.status as IndexStatus['status'],\n error_message: row.error_message,\n }\n }\n\n return statusMap\n } catch (error) {\n console.error('Error getting all index status:', error)\n return {}\n }\n }\n\n /**\n * Update index status in database\n */\n private async updateIndexStatus(collectionId: string, status: IndexStatus): Promise<void> {\n try {\n // Check if record exists\n const checkStmt = this.db.prepare(\n 'SELECT id FROM ai_search_index_meta WHERE collection_id = ?'\n )\n const existing = await checkStmt.bind(collectionId).first<{ id: number }>()\n\n if (existing) {\n // Update existing\n const stmt = this.db.prepare(`\n UPDATE ai_search_index_meta \n SET collection_name = ?,\n total_items = ?,\n indexed_items = ?,\n last_sync_at = ?,\n status = ?,\n error_message = ?\n WHERE collection_id = ?\n `)\n await stmt\n .bind(\n status.collection_name,\n status.total_items,\n status.indexed_items,\n status.last_sync_at || null,\n status.status,\n status.error_message || null,\n String(collectionId)\n )\n .run()\n } else {\n // Insert new\n const stmt = this.db.prepare(`\n INSERT INTO ai_search_index_meta (\n collection_id, collection_name, total_items, indexed_items,\n last_sync_at, status, error_message\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n `)\n await stmt\n .bind(\n String(status.collection_id),\n status.collection_name,\n status.total_items,\n status.indexed_items,\n status.last_sync_at || null,\n status.status,\n status.error_message || null\n )\n .run()\n }\n } catch (error) {\n console.error(`Error updating index status for collection ${collectionId}:`, error)\n throw error\n }\n }\n\n /**\n * Sync all selected collections\n */\n async syncAll(selectedCollections: string[]): Promise<void> {\n for (const collectionId of selectedCollections) {\n try {\n await this.indexCollection(collectionId)\n } catch (error) {\n console.error(`Error syncing collection ${collectionId}:`, error)\n }\n }\n }\n}\n","import { renderAdminLayout } from '../../../../templates/layouts/admin-layout-v2.template'\nimport type {\n AISearchSettings,\n CollectionInfo,\n IndexStatus,\n NewCollectionNotification,\n} from '../types'\n\ninterface SettingsPageData {\n settings: AISearchSettings | null\n collections: CollectionInfo[]\n newCollections: NewCollectionNotification[]\n indexStatus: Record<number, IndexStatus>\n analytics: {\n total_queries: number\n ai_queries: number\n keyword_queries: number\n popular_queries: Array<{ query: string; count: number }>\n average_query_time: number\n }\n user?: {\n name: string\n email: string\n role: string\n }\n}\n\nexport function renderSettingsPage(data: SettingsPageData): string {\n const settings = data.settings || {\n enabled: false,\n ai_mode_enabled: true,\n selected_collections: [],\n dismissed_collections: [],\n autocomplete_enabled: true,\n cache_duration: 1,\n results_limit: 20,\n index_media: false,\n }\n\n // Ensure arrays exist\n const selectedCollections = Array.isArray(settings.selected_collections) ? settings.selected_collections : []\n const dismissedCollections = Array.isArray(settings.dismissed_collections) ? settings.dismissed_collections : []\n\n const enabled = settings.enabled === true\n const aiModeEnabled = settings.ai_mode_enabled !== false\n const autocompleteEnabled = settings.autocomplete_enabled !== false\n const indexMedia = settings.index_media === true\n\n const selectedCollectionIds = new Set(selectedCollections.map(id => String(id)))\n const dismissedCollectionIds = new Set(dismissedCollections.map(id => String(id)))\n\n // Ensure collections array exists\n const collections = Array.isArray(data.collections) ? data.collections : []\n\n // Debug: Log collections in template\n console.log('[SettingsPage Template] Collections received:', collections.length)\n if (collections.length > 0) {\n console.log('[SettingsPage Template] First collection:', collections[0])\n }\n\n const content = `\n <div class=\"w-full px-4 sm:px-6 lg:px-8 py-6\">\n <!-- Header with Back Button -->\n <div class=\"flex flex-col sm:flex-row sm:items-center sm:justify-between mb-6\">\n <div>\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">🔍 AI Search Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Configure advanced search with Cloudflare AI Search. Select collections to index and manage search preferences.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 sm:flex-none\">\n <a href=\"/admin/plugins\" class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-700 transition-colors shadow-sm\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 19l-7-7m0 0l7-7m-7 7h18\"/>\n </svg>\n Back to Plugins\n </a>\n </div>\n </div>\n\n\n <!-- Main Settings Card -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6 mb-6\">\n <form id=\"settingsForm\" class=\"space-y-6\">\n <!-- Enable Search Section -->\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">🔍 Search Settings</h2>\n <div class=\"space-y-3\">\n <div class=\"flex items-center gap-3 p-4 border border-indigo-200 bg-indigo-50 dark:bg-indigo-900/20 rounded-lg\">\n <input type=\"checkbox\" id=\"enabled\" name=\"enabled\" ${enabled ? 'checked' : ''} class=\"w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div class=\"flex-1\">\n <label for=\"enabled\" class=\"text-base font-semibold text-zinc-900 dark:text-white select-none cursor-pointer block\">Enable AI Search</label>\n <p class=\"text-xs text-zinc-600 dark:text-zinc-400 mt-0.5\">Turn on advanced search capabilities across your content</p>\n </div>\n </div>\n\n <div class=\"flex items-center gap-3 p-4 border border-blue-200 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\n <input type=\"checkbox\" id=\"ai_mode_enabled\" name=\"ai_mode_enabled\" ${aiModeEnabled ? 'checked' : ''} class=\"w-5 h-5 rounded border-gray-300 text-blue-600 focus:ring-blue-500 cursor-pointer\">\n <div class=\"flex-1\">\n <label for=\"ai_mode_enabled\" class=\"text-base font-semibold text-zinc-900 dark:text-white select-none cursor-pointer block\">🤖 AI/Semantic Search</label>\n <p class=\"text-xs text-zinc-600 dark:text-zinc-400 mt-0.5\">\n Enable natural language queries (requires Cloudflare Workers AI binding)\n <a href=\"https://developers.cloudflare.com/workers-ai/\" target=\"_blank\" class=\"text-blue-600 dark:text-blue-400 hover:underline ml-1\">→ Setup Guide</a>\n </p>\n <p class=\"text-xs text-amber-600 dark:text-amber-400 mt-1\">\n ⚠️ If AI binding unavailable, will fallback to keyword search\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <hr class=\"border-zinc-200 dark:border-zinc-800\">\n\n <!-- Collections Section -->\n <div>\n <div class=\"flex items-start justify-between mb-4\">\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white\">📚 Collections to Index</h2>\n <p class=\"text-sm text-zinc-600 dark:text-zinc-400 mt-1\">\n Select which content collections should be indexed and searchable. Only checked collections will be included in search results.\n </p>\n </div>\n </div>\n <div class=\"space-y-3 max-h-96 overflow-y-auto border-2 border-zinc-300 dark:border-zinc-700 rounded-lg p-4 bg-white dark:bg-zinc-800\" id=\"collections-list\">\n ${collections.length === 0\n ? '<p class=\"text-sm text-zinc-500 dark:text-zinc-400 p-4\">No collections available. Create collections first.</p>'\n : collections.map((collection) => {\n const collectionId = String(collection.id)\n const isChecked = selectedCollectionIds.has(collectionId)\n const isDismissed = dismissedCollectionIds.has(collectionId)\n const indexStatusMap: Record<string, any> = data.indexStatus || {}\n const status = indexStatusMap[collectionId]\n // Only show NEW badge if collection is new, not dismissed, and has never been indexed\n const isNew = collection.is_new === true && !isDismissed && !status\n // Only show status badge if collection is CHECKED and has status\n const statusBadge = (status && isChecked)\n ? `<span class=\"ml-2 px-2 py-1 text-xs rounded-full ${status.status === 'completed'\n ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'\n : status.status === 'indexing'\n ? 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300'\n : status.status === 'error'\n ? 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'\n : 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300'\n }\">${status.status}</span>`\n : ''\n\n return `<div class=\"flex items-start gap-3 p-3 rounded-lg border border-zinc-200 dark:border-zinc-700 ${isNew ? 'bg-blue-50 dark:bg-blue-900/10 border-blue-200 dark:border-blue-800' : 'hover:bg-zinc-50 dark:hover:bg-zinc-800'}\">\n <input\n type=\"checkbox\"\n id=\"collection_${collectionId}\"\n name=\"selected_collections\"\n value=\"${collectionId}\"\n ${isChecked ? 'checked' : ''}\n class=\"mt-1 w-5 h-5 text-indigo-600 bg-white border-gray-300 rounded focus:ring-indigo-500 focus:ring-2 cursor-pointer\"\n style=\"cursor: pointer; flex-shrink: 0;\"\n />\n <div class=\"flex-1 min-w-0\">\n <label for=\"collection_${collectionId}\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer flex items-center\">\n ${collection.display_name || collection.name || 'Unnamed Collection'}\n ${isNew ? '<span class=\"ml-2 px-2 py-0.5 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300\">NEW</span>' : ''}\n ${statusBadge}\n </label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n ${collection.description || collection.name || 'No description'} • ${collection.item_count || 0} items\n ${status ? ` • ${status.indexed_items}/${status.total_items} indexed` : ''}\n </p>\n ${status && status.status === 'indexing'\n ? `<div class=\"mt-2 w-full bg-gray-200 rounded-full h-2 dark:bg-gray-700\">\n <div class=\"bg-blue-600 h-2 rounded-full\" style=\"width: ${(status.indexed_items / status.total_items) * 100}%\"></div>\n </div>`\n : ''}\n </div>\n ${isChecked ? `\n <button\n type=\"button\"\n onclick=\"reindexCollection('${collectionId}')\"\n class=\"px-3 py-1.5 text-xs font-medium text-white bg-indigo-600 hover:bg-indigo-700 rounded-md transition-colors flex items-center gap-1.5 whitespace-nowrap\"\n ${status && status.status === 'indexing' ? 'disabled' : ''}\n >\n <svg class=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n Re-index\n </button>\n ` : ''}\n </div>`\n }).join('')}\n </div>\n </div>\n\n <hr class=\"border-zinc-200 dark:border-zinc-800\">\n\n <!-- Advanced Options -->\n <div>\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">⚙️ Advanced Options</h2>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"flex items-start gap-3 p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg\">\n <input type=\"checkbox\" id=\"autocomplete_enabled\" name=\"autocomplete_enabled\" ${autocompleteEnabled ? 'checked' : ''} class=\"mt-0.5 w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div>\n <label for=\"autocomplete_enabled\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer block\">Autocomplete Suggestions</label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">Show search suggestions as users type</p>\n </div>\n </div>\n\n <div class=\"flex items-start gap-3 p-3 border border-zinc-200 dark:border-zinc-700 rounded-lg\">\n <input type=\"checkbox\" id=\"index_media\" name=\"index_media\" ${indexMedia ? 'checked' : ''} class=\"mt-0.5 w-5 h-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 cursor-pointer\">\n <div>\n <label for=\"index_media\" class=\"text-sm font-medium text-zinc-950 dark:text-white select-none cursor-pointer block\">Index Media Metadata</label>\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">Include media files in search results</p>\n </div>\n </div>\n\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Cache Duration (hours)</label>\n <input type=\"number\" id=\"cache_duration\" name=\"cache_duration\" value=\"${settings.cache_duration || 1}\" min=\"0\" max=\"24\" class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-indigo-500\">\n </div>\n <div>\n <label class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">Results Per Page</label>\n <input type=\"number\" id=\"results_limit\" name=\"results_limit\" value=\"${settings.results_limit || 20}\" min=\"10\" max=\"100\" class=\"w-full rounded-lg bg-white dark:bg-white/5 px-3 py-2 text-sm text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 focus:ring-2 focus:ring-indigo-500\">\n </div>\n </div>\n </div>\n\n <!-- Save Button -->\n <div class=\"flex items-center justify-between pt-4 border-t border-zinc-200 dark:border-zinc-800\">\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400\">\n 💡 Collections marked as <span class=\"px-1.5 py-0.5 text-xs font-medium rounded-full bg-blue-500 text-white\">NEW</span> haven't been indexed yet\n </p>\n <button type=\"submit\" class=\"inline-flex items-center justify-center rounded-lg bg-indigo-600 text-white px-6 py-2.5 text-sm font-semibold hover:bg-indigo-500 shadow-sm transition-colors\">\n 💾 Save Settings\n </button>\n </div>\n </form>\n </div>\n\n\n <!-- Search Analytics -->\n <div class=\"rounded-xl bg-white dark:bg-zinc-900 shadow-sm ring-1 ring-zinc-950/5 dark:ring-white/10 p-6\">\n <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">📊 Search Analytics</h2>\n <div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 mb-6\">\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">Total Queries</div>\n <div class=\"text-2xl font-bold text-zinc-950 dark:text-white mt-1\">${data.analytics.total_queries}</div>\n </div>\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">AI Queries</div>\n <div class=\"text-2xl font-bold text-blue-600 dark:text-blue-400 mt-1\">${data.analytics.ai_queries}</div>\n </div>\n <div class=\"p-4 rounded-lg bg-zinc-50 dark:bg-zinc-800\">\n <div class=\"text-sm text-zinc-500 dark:text-zinc-400\">Keyword Queries</div>\n <div class=\"text-2xl font-bold text-indigo-600 dark:text-indigo-400 mt-1\">${data.analytics.keyword_queries}</div>\n </div>\n </div>\n ${data.analytics.popular_queries.length > 0\n ? `\n <div>\n <h3 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-2\">Popular Searches</h3>\n <div class=\"space-y-1\">\n ${data.analytics.popular_queries.map(\n (item) => `\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-700 dark:text-zinc-300\">\"${item.query}\"</span>\n <span class=\"text-zinc-500 dark:text-zinc-400\">${item.count} times</span>\n </div>\n `\n ).join('')}\n </div>\n </div>\n `\n : '<p class=\"text-sm text-zinc-500 dark:text-zinc-400\">No search history yet.</p>'}\n </div>\n\n <!-- Success Message -->\n <div id=\"msg\" class=\"hidden fixed bottom-4 right-4 p-4 rounded-lg bg-green-50 text-green-900 border border-green-200 dark:bg-green-900/20 dark:text-green-100 dark:border-green-800 shadow-lg z-50\">\n <div class=\"flex items-center gap-2\">\n <span class=\"text-xl\">✅</span>\n <span class=\"font-semibold\">Settings Saved Successfully!</span>\n </div>\n </div>\n </div>\n <script>\n // Form submission with error handling\n document.getElementById('settingsForm').addEventListener('submit', async (e) => {\n e.preventDefault();\n console.log('[AI Search Client] Form submitted');\n \n try {\n const btn = e.submitter;\n btn.innerText = 'Saving...'; \n btn.disabled = true;\n \n const formData = new FormData(e.target);\n const selectedCollections = Array.from(formData.getAll('selected_collections')).map(String);\n \n const data = {\n enabled: document.getElementById('enabled').checked,\n ai_mode_enabled: document.getElementById('ai_mode_enabled').checked,\n selected_collections: selectedCollections,\n autocomplete_enabled: document.getElementById('autocomplete_enabled').checked,\n cache_duration: Number(formData.get('cache_duration')),\n results_limit: Number(formData.get('results_limit')),\n index_media: document.getElementById('index_media').checked,\n };\n \n console.log('[AI Search Client] Sending data:', data);\n console.log('[AI Search Client] Selected collections:', selectedCollections);\n \n const res = await fetch('/admin/plugins/ai-search', { \n method: 'POST', \n headers: {'Content-Type': 'application/json'}, \n body: JSON.stringify(data) \n });\n \n console.log('[AI Search Client] Response status:', res.status);\n \n if (res.ok) {\n const result = await res.json();\n console.log('[AI Search Client] Save successful:', result);\n document.getElementById('msg').classList.remove('hidden'); \n setTimeout(() => {\n document.getElementById('msg').classList.add('hidden');\n location.reload();\n }, 2000); \n } else {\n const error = await res.text();\n console.error('[AI Search Client] Save failed:', error);\n alert('Failed to save settings: ' + error);\n }\n \n btn.innerText = 'Save Settings'; \n btn.disabled = false;\n } catch (error) {\n console.error('[AI Search Client] Error:', error);\n alert('Error saving settings: ' + error.message);\n }\n });\n\n // Add collection to index\n async function addCollectionToIndex(collectionId) {\n const form = document.getElementById('settingsForm');\n const checkbox = document.getElementById('collection_' + collectionId);\n if (checkbox) {\n checkbox.checked = true;\n form.dispatchEvent(new Event('submit'));\n }\n }\n\n // Dismiss collection\n async function dismissCollection(collectionId) {\n const res = await fetch('/admin/plugins/ai-search', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify({\n dismissed_collections: [collectionId]\n })\n });\n if (res.ok) {\n location.reload();\n }\n }\n\n // Re-index collection\n async function reindexCollection(collectionId) {\n const res = await fetch('/admin/plugins/ai-search/api/reindex', {\n method: 'POST',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify({ collection_id: collectionId })\n });\n if (res.ok) {\n alert('Re-indexing started. Page will refresh in a moment.');\n setTimeout(() => location.reload(), 2000);\n } else {\n alert('Failed to start re-indexing. Please try again.');\n }\n }\n\n // Poll for index status updates\n setInterval(async () => {\n const res = await fetch('/admin/plugins/ai-search/api/status');\n if (res.ok) {\n const { data } = await res.json();\n // Update status indicators if needed\n // For now, just reload every 30 seconds if indexing is in progress\n const hasIndexing = Object.values(data).some((s) => s.status === 'indexing');\n if (hasIndexing) {\n location.reload();\n }\n }\n }, 30000);\n </script>\n `\n\n return renderAdminLayout({\n title: 'AI Search Settings',\n pageTitle: 'AI Search Settings',\n currentPath: '/admin/plugins/ai-search/settings',\n user: data.user,\n content: content\n })\n}\n","import { Hono } from 'hono'\nimport type { Bindings } from '../../../../app'\nimport { requireAuth } from '../../../../middleware'\nimport { AISearchService } from '../services/ai-search'\nimport { IndexManager } from '../services/indexer'\nimport { renderSettingsPage } from '../components/settings-page'\nimport type { AISearchSettings, SearchQuery } from '../types'\n\ntype Variables = {\n user: {\n id: number\n email: string\n role: string\n }\n}\n\nconst adminRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// Apply authentication middleware\nadminRoutes.use('*', requireAuth())\n\n/**\n * GET /admin/plugins/ai-search\n * Render settings page\n */\nadminRoutes.get('/', async (c) => {\n try {\n const user = c.get('user')\n const db = c.env.DB\n const ai = (c.env as any).AI // Workers AI for embeddings\n const vectorize = (c.env as any).VECTORIZE_INDEX // Vectorize for vector search\n\n const service = new AISearchService(db, ai, vectorize)\n const indexer = new IndexManager(db, ai, vectorize)\n\n // Get settings\n const settings = await service.getSettings()\n console.log('[AI Search Settings Route] Settings loaded:', !!settings)\n\n // Get all collections with status\n const collections = await service.getAllCollections()\n console.log('[AI Search Settings Route] Collections returned:', collections.length)\n \n // If no collections, try direct query\n if (collections.length === 0) {\n const directQuery = await db.prepare('SELECT id, name, display_name FROM collections WHERE is_active = 1').all()\n console.log('[AI Search Settings Route] Direct DB query found:', directQuery.results?.length || 0, 'collections')\n if (directQuery.results && directQuery.results.length > 0) {\n console.log('[AI Search Settings Route] Sample from DB:', directQuery.results[0])\n }\n } else if (collections.length > 0 && collections[0]) {\n console.log('[AI Search Settings Route] First collection:', {\n id: collections[0].id,\n name: collections[0].name,\n display_name: collections[0].display_name\n })\n }\n\n // Get new collections notifications\n const newCollections = await service.detectNewCollections()\n console.log('AI Search: New collections:', newCollections.length)\n\n // Get index status for all collections\n const indexStatus = await indexer.getAllIndexStatus()\n console.log('AI Search: Index status:', Object.keys(indexStatus).length)\n\n // Get analytics\n const analytics = await service.getSearchAnalytics()\n\n return c.html(\n renderSettingsPage({\n settings,\n collections: collections || [],\n newCollections: newCollections || [],\n indexStatus: indexStatus || {},\n analytics,\n user: {\n name: user.email,\n email: user.email,\n role: user.role,\n },\n })\n )\n } catch (error) {\n console.error('Error rendering AI Search settings:', error)\n return c.html(`<p>Error loading settings: ${error instanceof Error ? error.message : String(error)}</p>`, 500)\n }\n})\n\n/**\n * POST /admin/plugins/ai-search\n * Update settings\n */\nadminRoutes.post('/', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n const indexer = new IndexManager(db, ai, vectorize)\n\n const body = await c.req.json()\n console.log('[AI Search POST] Received body:', JSON.stringify(body, null, 2))\n\n // Get current settings\n const currentSettings = await service.getSettings()\n console.log('[AI Search POST] Current settings selected_collections:', currentSettings?.selected_collections)\n\n // Update settings\n const updatedSettings: Partial<AISearchSettings> = {\n enabled: body.enabled !== undefined ? Boolean(body.enabled) : currentSettings?.enabled,\n ai_mode_enabled: body.ai_mode_enabled !== undefined ? Boolean(body.ai_mode_enabled) : currentSettings?.ai_mode_enabled,\n selected_collections: Array.isArray(body.selected_collections) ? body.selected_collections.map(String) : (currentSettings?.selected_collections || []),\n dismissed_collections: Array.isArray(body.dismissed_collections) ? body.dismissed_collections.map(String) : (currentSettings?.dismissed_collections || []),\n autocomplete_enabled: body.autocomplete_enabled !== undefined ? Boolean(body.autocomplete_enabled) : currentSettings?.autocomplete_enabled,\n cache_duration: body.cache_duration ? Number(body.cache_duration) : currentSettings?.cache_duration,\n results_limit: body.results_limit ? Number(body.results_limit) : currentSettings?.results_limit,\n index_media: body.index_media !== undefined ? Boolean(body.index_media) : currentSettings?.index_media,\n }\n\n console.log('[AI Search POST] Updated settings selected_collections:', updatedSettings.selected_collections)\n\n // If collections changed, trigger indexing\n const collectionsChanged =\n JSON.stringify(updatedSettings.selected_collections) !==\n JSON.stringify(currentSettings?.selected_collections || [])\n\n const saved = await service.updateSettings(updatedSettings)\n console.log('[AI Search POST] Settings saved, selected_collections:', saved.selected_collections)\n\n // Start indexing if collections were added\n if (collectionsChanged && updatedSettings.selected_collections) {\n console.log('[AI Search POST] Collections changed, starting background indexing')\n // Start indexing in background (non-blocking) - must use waitUntil to ensure it completes\n c.executionCtx.waitUntil(\n indexer\n .syncAll(updatedSettings.selected_collections)\n .then(() => console.log('[AI Search POST] Background indexing completed'))\n .catch((error) => console.error('[AI Search POST] Background indexing error:', error))\n )\n }\n\n return c.json({ success: true, settings: saved })\n } catch (error) {\n console.error('Error updating AI Search settings:', error)\n return c.json({ error: 'Failed to update settings' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/settings\n * Get settings API endpoint\n */\nadminRoutes.get('/api/settings', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const settings = await service.getSettings()\n return c.json({ success: true, data: settings })\n } catch (error) {\n console.error('Error fetching settings:', error)\n return c.json({ error: 'Failed to fetch settings' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/new-collections\n * Get new collections that aren't indexed or dismissed\n */\nadminRoutes.get('/api/new-collections', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const notifications = await service.detectNewCollections()\n return c.json({ success: true, data: notifications })\n } catch (error) {\n console.error('Error detecting new collections:', error)\n return c.json({ error: 'Failed to detect new collections' }, 500)\n }\n})\n\n/**\n * GET /admin/api/ai-search/status\n * Get indexing status\n */\nadminRoutes.get('/api/status', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const indexer = new IndexManager(db, ai, vectorize)\n\n const status = await indexer.getAllIndexStatus()\n return c.json({ success: true, data: status })\n } catch (error) {\n console.error('Error fetching index status:', error)\n return c.json({ error: 'Failed to fetch status' }, 500)\n }\n})\n\n/**\n * POST /admin/api/ai-search/reindex\n * Trigger re-indexing for a collection\n */\nadminRoutes.post('/api/reindex', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const indexer = new IndexManager(db, ai, vectorize)\n\n const body = await c.req.json()\n const collectionIdRaw: unknown = body.collection_id\n const collectionId = collectionIdRaw ? String(collectionIdRaw) : ''\n\n if (!collectionId || collectionId === 'undefined' || collectionId === 'null') {\n return c.json({ error: 'collection_id is required' }, 400)\n }\n\n // Start indexing in background - must use waitUntil to ensure it completes\n c.executionCtx.waitUntil(\n indexer\n .indexCollection(collectionId)\n .then(() => console.log(`[AI Search Reindex] Completed for collection ${collectionId}`))\n .catch((error) => console.error(`[AI Search Reindex] Error for collection ${collectionId}:`, error))\n )\n\n return c.json({ success: true, message: 'Re-indexing started' })\n } catch (error) {\n console.error('Error starting re-index:', error)\n return c.json({ error: 'Failed to start re-indexing' }, 500)\n }\n})\n\nexport default adminRoutes\n","import { Hono } from 'hono'\nimport type { Bindings } from '../../../../app'\nimport { AISearchService } from '../services/ai-search'\nimport type { SearchQuery } from '../types'\n\ntype Variables = {\n user?: {\n id: number\n email: string\n role: string\n }\n}\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n/**\n * POST /api/search\n * Execute search query\n */\napiRoutes.post('/', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const body = await c.req.json()\n\n const query: SearchQuery = {\n query: body.query || '',\n mode: body.mode || 'keyword',\n filters: body.filters || {},\n limit: body.limit ? Number(body.limit) : undefined,\n offset: body.offset ? Number(body.offset) : undefined,\n }\n\n // Convert date strings to Date objects if present\n if (query.filters?.dateRange) {\n if (typeof query.filters.dateRange.start === 'string') {\n query.filters.dateRange.start = new Date(query.filters.dateRange.start)\n }\n if (typeof query.filters.dateRange.end === 'string') {\n query.filters.dateRange.end = new Date(query.filters.dateRange.end)\n }\n }\n\n const results = await service.search(query)\n\n return c.json({\n success: true,\n data: results,\n })\n } catch (error) {\n console.error('Search error:', error)\n return c.json(\n {\n success: false,\n error: 'Search failed',\n message: error instanceof Error ? error.message : String(error),\n },\n 500\n )\n }\n})\n\n/**\n * GET /api/search/suggest\n * Get search suggestions (autocomplete)\n */\napiRoutes.get('/suggest', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const query = c.req.query('q') || ''\n\n if (!query || query.length < 2) {\n return c.json({ success: true, data: [] })\n }\n\n const suggestions = await service.getSearchSuggestions(query)\n\n return c.json({\n success: true,\n data: suggestions,\n })\n } catch (error) {\n console.error('Suggestions error:', error)\n return c.json(\n {\n success: false,\n error: 'Failed to get suggestions',\n },\n 500\n )\n }\n})\n\n/**\n * GET /admin/api/search/analytics\n * Get search analytics\n */\napiRoutes.get('/analytics', async (c) => {\n try {\n const db = c.env.DB\n const ai = (c.env as any).AI\n const vectorize = (c.env as any).VECTORIZE_INDEX\n const service = new AISearchService(db, ai, vectorize)\n\n const analytics = await service.getSearchAnalytics()\n\n return c.json({\n success: true,\n data: analytics,\n })\n } catch (error) {\n console.error('Analytics error:', error)\n return c.json(\n {\n success: false,\n error: 'Failed to get analytics',\n },\n 500\n )\n }\n})\n\nexport default apiRoutes\n","{\n \"id\": \"ai-search\",\n \"name\": \"AI Search\",\n \"description\": \"Advanced search with Cloudflare AI Search. Full-text search, semantic search, and advanced filtering across all content collections.\",\n \"version\": \"1.0.0\",\n \"author\": \"SonicJS\",\n \"category\": \"content\",\n \"icon\": \"magnifying-glass\",\n \"homepage\": \"https://developers.cloudflare.com/ai-search/\",\n \"repository\": \"https://github.com/sonicjs/sonicjs\",\n \"license\": \"MIT\",\n \"permissions\": [\"settings:write\", \"admin:access\", \"content:read\"],\n \"dependencies\": [],\n \"configSchema\": {\n \"enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable AI Search\",\n \"description\": \"Enable or disable AI Search functionality\",\n \"default\": true\n },\n \"ai_mode_enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable AI/Semantic Search\",\n \"description\": \"Enable AI-powered semantic search (requires Cloudflare Workers AI binding)\",\n \"default\": false\n },\n \"ai_provider\": {\n \"type\": \"string\",\n \"label\": \"AI Provider\",\n \"description\": \"Which AI service to use for semantic search\",\n \"default\": \"cloudflare\",\n \"enum\": [\"cloudflare\", \"keyword-only\"]\n },\n \"autocomplete_enabled\": {\n \"type\": \"boolean\",\n \"label\": \"Enable Autocomplete\",\n \"description\": \"Show search suggestions as user types\",\n \"default\": true\n },\n \"cache_duration\": {\n \"type\": \"number\",\n \"label\": \"Cache Duration (hours)\",\n \"description\": \"How long to cache search results\",\n \"default\": 1,\n \"min\": 0,\n \"max\": 24\n },\n \"results_limit\": {\n \"type\": \"number\",\n \"label\": \"Results Per Page\",\n \"description\": \"Maximum number of results to show per page\",\n \"default\": 20,\n \"min\": 10,\n \"max\": 100\n },\n \"index_media\": {\n \"type\": \"boolean\",\n \"label\": \"Index Media Metadata\",\n \"description\": \"Include R2 media files in search index\",\n \"default\": false\n }\n },\n \"adminMenu\": {\n \"label\": \"AI Search\",\n \"icon\": \"magnifying-glass\",\n \"href\": \"/admin/plugins/ai-search\",\n \"parentId\": \"plugins\",\n \"order\": 50\n }\n}\n","import { PluginBuilder } from '../../sdk/plugin-builder'\nimport { AISearchService } from './services/ai-search'\nimport { IndexManager } from './services/indexer'\nimport adminRoutes from './routes/admin'\nimport apiRoutes from './routes/api'\nimport manifest from './manifest.json'\n\n/**\n * AI Search Plugin\n * \n * Provides advanced search capabilities using Cloudflare AI Search.\n * Features:\n * - Semantic/AI-powered search with natural language queries\n * - Traditional keyword search\n * - Full-text search across all content collections\n * - Advanced filtering (collections, dates, status, tags)\n * - Autocomplete suggestions\n * - Search analytics\n * - Dynamic collection discovery and indexing\n * \n * @example\n * ```typescript\n * import { AISearchService } from '@sonicjs-cms/core/plugins'\n * \n * const service = new AISearchService(db, aiSearch)\n * const results = await service.search({\n * query: 'blog posts about security',\n * mode: 'ai',\n * filters: { collections: [1, 2] }\n * })\n * ```\n */\n\nexport const aiSearchPlugin = new PluginBuilder({\n name: manifest.name,\n version: manifest.version,\n description: manifest.description,\n author: { name: manifest.author },\n})\n .metadata({\n description: manifest.description,\n author: { name: manifest.author },\n })\n .addService('aiSearch', AISearchService)\n .addService('indexManager', IndexManager)\n .addRoute('/admin/plugins/ai-search', adminRoutes as any)\n .addRoute('/api/search', apiRoutes as any)\n .build()\n\n// Export services and types for easy import\nexport { AISearchService } from './services/ai-search'\nexport { IndexManager } from './services/indexer'\nexport type {\n AISearchSettings,\n SearchQuery,\n SearchResponse,\n SearchResult,\n CollectionInfo,\n IndexStatus,\n} from './types'\n","/**\n * Magic Link Authentication Plugin\n *\n * Provides passwordless authentication via email magic links\n * Users receive a secure one-time link to sign in without passwords\n */\n\nimport { Hono } from 'hono'\nimport { z } from 'zod'\nimport type { Plugin, PluginContext } from '../../types'\nimport type { D1Database } from '@cloudflare/workers-types'\nimport { AuthManager } from '../../../middleware/auth'\n\nconst magicLinkRequestSchema = z.object({\n email: z.string().email('Valid email is required')\n})\n\nexport function createMagicLinkAuthPlugin(): Plugin {\n const magicLinkRoutes = new Hono()\n\n // Request a magic link\n magicLinkRoutes.post('/request', async (c: any) => {\n try {\n const body = await c.req.json()\n const validation = magicLinkRequestSchema.safeParse(body)\n\n if (!validation.success) {\n return c.json({\n error: 'Validation failed',\n details: validation.error.issues\n }, 400)\n }\n\n const { email } = validation.data\n const normalizedEmail = email.toLowerCase()\n const db = c.env.DB as D1Database\n\n // Check rate limiting\n const oneHourAgo = Date.now() - (60 * 60 * 1000)\n const recentLinks = await db.prepare(`\n SELECT COUNT(*) as count\n FROM magic_links\n WHERE user_email = ? AND created_at > ?\n `).bind(normalizedEmail, oneHourAgo).first() as any\n\n const rateLimitPerHour = 5 // TODO: Get from plugin settings\n if (recentLinks && recentLinks.count >= rateLimitPerHour) {\n return c.json({\n error: 'Too many requests. Please try again later.'\n }, 429)\n }\n\n // Check if user exists\n const user = await db.prepare(`\n SELECT id, email, role, is_active\n FROM users\n WHERE email = ?\n `).bind(normalizedEmail).first() as any\n\n const allowNewUsers = false // TODO: Get from plugin settings\n\n if (!user && !allowNewUsers) {\n // Don't reveal if user exists or not for security\n return c.json({\n message: 'If an account exists for this email, you will receive a magic link shortly.'\n })\n }\n\n if (user && !user.is_active) {\n return c.json({\n error: 'This account has been deactivated.'\n }, 403)\n }\n\n // Generate secure token\n const token = crypto.randomUUID() + '-' + crypto.randomUUID()\n const tokenId = crypto.randomUUID()\n const linkExpiryMinutes = 15 // TODO: Get from plugin settings\n const expiresAt = Date.now() + (linkExpiryMinutes * 60 * 1000)\n\n // Store magic link\n await db.prepare(`\n INSERT INTO magic_links (\n id, user_email, token, expires_at, used, created_at, ip_address, user_agent\n ) VALUES (?, ?, ?, ?, 0, ?, ?, ?)\n `).bind(\n tokenId,\n normalizedEmail,\n token,\n expiresAt,\n Date.now(),\n c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown',\n c.req.header('user-agent') || 'unknown'\n ).run()\n\n // Generate magic link URL\n const baseUrl = new URL(c.req.url).origin\n const magicLink = `${baseUrl}/auth/magic-link/verify?token=${token}`\n\n // Send email via email plugin\n try {\n const emailPlugin = c.env.plugins?.get('email')\n if (emailPlugin && emailPlugin.sendEmail) {\n await emailPlugin.sendEmail({\n to: normalizedEmail,\n subject: 'Your Magic Link to Sign In',\n html: renderMagicLinkEmail(magicLink, linkExpiryMinutes)\n })\n } else {\n console.error('Email plugin not available')\n // In production, this should fail. For now, log the link for testing\n console.log(`Magic link for ${normalizedEmail}: ${magicLink}`)\n }\n } catch (error) {\n console.error('Failed to send magic link email:', error)\n return c.json({\n error: 'Failed to send email. Please try again later.'\n }, 500)\n }\n\n return c.json({\n message: 'If an account exists for this email, you will receive a magic link shortly.',\n // For development only - remove in production\n ...(c.env.ENVIRONMENT === 'development' && { dev_link: magicLink })\n })\n } catch (error) {\n console.error('Magic link request error:', error)\n return c.json({ error: 'Failed to process request' }, 500)\n }\n })\n\n // Verify magic link and sign in\n magicLinkRoutes.get('/verify', async (c: any) => {\n try {\n const token = c.req.query('token')\n\n if (!token) {\n return c.redirect('/auth/login?error=Invalid magic link')\n }\n\n const db = c.env.DB as D1Database\n\n // Find magic link\n const magicLink = await db.prepare(`\n SELECT * FROM magic_links\n WHERE token = ? AND used = 0\n `).bind(token).first() as any\n\n if (!magicLink) {\n return c.redirect('/auth/login?error=Invalid or expired magic link')\n }\n\n // Check expiration\n if (magicLink.expires_at < Date.now()) {\n return c.redirect('/auth/login?error=This magic link has expired')\n }\n\n // Get or create user\n let user = await db.prepare(`\n SELECT * FROM users WHERE email = ? AND is_active = 1\n `).bind(magicLink.user_email).first() as any\n\n const allowNewUsers = false // TODO: Get from plugin settings\n\n if (!user && allowNewUsers) {\n // Create new user\n const userId = crypto.randomUUID()\n const username = magicLink.user_email.split('@')[0]\n const now = Date.now()\n\n await db.prepare(`\n INSERT INTO users (\n id, email, username, first_name, last_name,\n password_hash, role, is_active, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, NULL, 'viewer', 1, ?, ?)\n `).bind(\n userId,\n magicLink.user_email,\n username,\n username,\n '',\n now,\n now\n ).run()\n\n user = {\n id: userId,\n email: magicLink.user_email,\n username,\n role: 'viewer'\n }\n } else if (!user) {\n return c.redirect('/auth/login?error=No account found for this email')\n }\n\n // Mark magic link as used\n await db.prepare(`\n UPDATE magic_links\n SET used = 1, used_at = ?\n WHERE id = ?\n `).bind(Date.now(), magicLink.id).run()\n\n // Generate JWT token\n const jwtToken = await AuthManager.generateToken(\n user.id,\n user.email,\n user.role,\n (c.env as any).JWT_SECRET\n )\n\n // Set auth cookie\n AuthManager.setAuthCookie(c, jwtToken)\n\n // Update last login\n await db.prepare(`\n UPDATE users SET last_login_at = ? WHERE id = ?\n `).bind(Date.now(), user.id).run()\n\n // Redirect to admin dashboard\n return c.redirect('/admin/dashboard?message=Successfully signed in')\n } catch (error) {\n console.error('Magic link verification error:', error)\n return c.redirect('/auth/login?error=Authentication failed')\n }\n })\n\n return {\n name: 'magic-link-auth',\n version: '1.0.0',\n description: 'Passwordless authentication via email magic links',\n author: {\n name: 'SonicJS Team',\n email: 'team@sonicjs.com'\n },\n dependencies: ['email'],\n\n routes: [{\n path: '/auth/magic-link',\n handler: magicLinkRoutes,\n description: 'Magic link authentication endpoints',\n requiresAuth: false\n }],\n\n async install(context: PluginContext) {\n console.log('Installing magic-link-auth plugin...')\n // Migration is handled by plugin system\n },\n\n async activate(context: PluginContext) {\n console.log('Magic link authentication activated')\n console.log('Users can now sign in via /auth/magic-link/request')\n },\n\n async deactivate(context: PluginContext) {\n console.log('Magic link authentication deactivated')\n },\n\n async uninstall(context: PluginContext) {\n console.log('Uninstalling magic-link-auth plugin...')\n // Optionally clean up magic_links table\n // await context.db.prepare('DROP TABLE IF EXISTS magic_links').run()\n }\n }\n}\n\n/**\n * Render magic link email template\n */\nfunction renderMagicLinkEmail(magicLink: string, expiryMinutes: number): string {\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Your Magic Link</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n max-width: 600px;\n margin: 0 auto;\n padding: 20px;\n }\n .container {\n background: #ffffff;\n border-radius: 8px;\n padding: 40px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n .header {\n text-align: center;\n margin-bottom: 30px;\n }\n .header h1 {\n color: #0ea5e9;\n margin: 0;\n font-size: 24px;\n }\n .content {\n margin-bottom: 30px;\n }\n .button {\n display: inline-block;\n padding: 14px 32px;\n background: linear-gradient(135deg, #0ea5e9 0%, #06b6d4 100%);\n color: #ffffff !important;\n text-decoration: none;\n border-radius: 6px;\n font-weight: 600;\n text-align: center;\n margin: 20px 0;\n }\n .button:hover {\n opacity: 0.9;\n }\n .expiry {\n color: #ef4444;\n font-size: 14px;\n margin-top: 20px;\n }\n .footer {\n margin-top: 40px;\n padding-top: 20px;\n border-top: 1px solid #e5e7eb;\n font-size: 12px;\n color: #6b7280;\n text-align: center;\n }\n .security-note {\n background: #fef3c7;\n border-left: 4px solid #f59e0b;\n padding: 12px 16px;\n margin-top: 20px;\n border-radius: 4px;\n font-size: 14px;\n }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>🔗 Your Magic Link</h1>\n </div>\n\n <div class=\"content\">\n <p>Hello!</p>\n <p>You requested a magic link to sign in to your account. Click the button below to continue:</p>\n\n <div style=\"text-align: center;\">\n <a href=\"${magicLink}\" class=\"button\">Sign In</a>\n </div>\n\n <p class=\"expiry\">⏰ This link expires in ${expiryMinutes} minutes</p>\n\n <div class=\"security-note\">\n <strong>Security Notice:</strong> If you didn't request this link, you can safely ignore this email.\n Someone may have entered your email address by mistake.\n </div>\n </div>\n\n <div class=\"footer\">\n <p>This is an automated email from SonicJS.</p>\n <p>For security, this link can only be used once.</p>\n </div>\n </div>\n </body>\n </html>\n `\n}\n\nexport default createMagicLinkAuthPlugin()\n","export type SecurityEventType =\n | 'login_success'\n | 'login_failure'\n | 'registration'\n | 'password_reset_request'\n | 'password_reset_complete'\n | 'account_lockout'\n | 'suspicious_activity'\n | 'logout'\n | 'permission_denied'\n\nexport type SecuritySeverity = 'info' | 'warning' | 'critical'\n\nexport interface SecurityEvent {\n id: string\n eventType: SecurityEventType\n severity: SecuritySeverity\n userId?: string | null\n email?: string | null\n ipAddress?: string | null\n userAgent?: string | null\n countryCode?: string | null\n requestPath?: string | null\n requestMethod?: string | null\n details?: Record<string, any> | null\n fingerprint?: string | null\n blocked: boolean\n createdAt: number\n}\n\nexport interface SecurityEventInsert {\n eventType: SecurityEventType\n severity?: SecuritySeverity\n userId?: string\n email?: string\n ipAddress?: string\n userAgent?: string\n countryCode?: string\n requestPath?: string\n requestMethod?: string\n details?: Record<string, any>\n fingerprint?: string\n blocked?: boolean\n}\n\nexport interface SecurityEventFilters {\n eventType?: SecurityEventType | SecurityEventType[]\n severity?: SecuritySeverity | SecuritySeverity[]\n email?: string\n ipAddress?: string\n search?: string\n startDate?: number\n endDate?: number\n blocked?: boolean\n page?: number\n limit?: number\n sortBy?: 'created_at' | 'event_type' | 'severity'\n sortOrder?: 'asc' | 'desc'\n}\n\nexport interface SecurityStats {\n totalEvents: number\n failedLogins24h: number\n failedLoginsTrend: number // percentage change vs prior 24h\n activeLockouts: number\n flaggedIPs: number\n eventsByType: Record<string, number>\n eventsBySeverity: Record<string, number>\n}\n\nexport interface TopIP {\n ipAddress: string\n countryCode: string | null\n failedAttempts: number\n lastSeen: number\n locked: boolean\n}\n\nexport interface HourlyBucket {\n hour: string\n count: number\n}\n\nexport interface SecurityAuditSettings {\n retention: {\n daysToKeep: number\n maxEvents: number\n autoPurge: boolean\n }\n bruteForce: {\n enabled: boolean\n maxFailedAttemptsPerIP: number\n maxFailedAttemptsPerEmail: number\n windowMinutes: number\n lockoutDurationMinutes: number\n alertThreshold: number\n }\n logging: {\n logSuccessfulLogins: boolean\n logLogouts: boolean\n logRegistrations: boolean\n logPasswordResets: boolean\n logPermissionDenied: boolean\n }\n}\n\nexport const DEFAULT_SETTINGS: SecurityAuditSettings = {\n retention: {\n daysToKeep: 90,\n maxEvents: 100000,\n autoPurge: true\n },\n bruteForce: {\n enabled: true,\n maxFailedAttemptsPerIP: 10,\n maxFailedAttemptsPerEmail: 5,\n windowMinutes: 15,\n lockoutDurationMinutes: 30,\n alertThreshold: 20\n },\n logging: {\n logSuccessfulLogins: true,\n logLogouts: true,\n logRegistrations: true,\n logPasswordResets: true,\n logPermissionDenied: true\n }\n}\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type {\n SecurityEvent,\n SecurityEventInsert,\n SecurityEventFilters,\n SecurityStats,\n TopIP,\n HourlyBucket,\n SecurityAuditSettings\n} from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nexport class SecurityAuditService {\n constructor(\n private db: D1Database,\n private settings: SecurityAuditSettings = DEFAULT_SETTINGS\n ) {}\n\n async logEvent(event: SecurityEventInsert): Promise<string> {\n const id = crypto.randomUUID()\n const now = Date.now()\n\n await this.db.prepare(`\n INSERT INTO security_events (id, event_type, severity, user_id, email, ip_address, user_agent, country_code, request_path, request_method, details, fingerprint, blocked, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).bind(\n id,\n event.eventType,\n event.severity || 'info',\n event.userId || null,\n event.email || null,\n event.ipAddress || null,\n event.userAgent || null,\n event.countryCode || null,\n event.requestPath || null,\n event.requestMethod || null,\n event.details ? JSON.stringify(event.details) : null,\n event.fingerprint || null,\n event.blocked ? 1 : 0,\n now\n ).run()\n\n return id\n }\n\n async getEvents(filters: SecurityEventFilters = {}): Promise<{ events: SecurityEvent[], total: number }> {\n const conditions: string[] = []\n const params: any[] = []\n\n if (filters.eventType) {\n if (Array.isArray(filters.eventType)) {\n conditions.push(`event_type IN (${filters.eventType.map(() => '?').join(',')})`)\n params.push(...filters.eventType)\n } else {\n conditions.push('event_type = ?')\n params.push(filters.eventType)\n }\n }\n\n if (filters.severity) {\n if (Array.isArray(filters.severity)) {\n conditions.push(`severity IN (${filters.severity.map(() => '?').join(',')})`)\n params.push(...filters.severity)\n } else {\n conditions.push('severity = ?')\n params.push(filters.severity)\n }\n }\n\n if (filters.email) {\n conditions.push('email LIKE ?')\n params.push(`%${filters.email}%`)\n }\n\n if (filters.ipAddress) {\n conditions.push('ip_address LIKE ?')\n params.push(`%${filters.ipAddress}%`)\n }\n\n if (filters.search) {\n conditions.push('(email LIKE ? OR ip_address LIKE ? OR details LIKE ?)')\n params.push(`%${filters.search}%`, `%${filters.search}%`, `%${filters.search}%`)\n }\n\n if (filters.startDate) {\n conditions.push('created_at >= ?')\n params.push(filters.startDate)\n }\n\n if (filters.endDate) {\n conditions.push('created_at <= ?')\n params.push(filters.endDate)\n }\n\n if (filters.blocked !== undefined) {\n conditions.push('blocked = ?')\n params.push(filters.blocked ? 1 : 0)\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''\n const sortBy = filters.sortBy || 'created_at'\n const sortOrder = filters.sortOrder || 'desc'\n const page = filters.page || 1\n const limit = filters.limit || 50\n const offset = (page - 1) * limit\n\n // Get total count\n const countResult = await this.db.prepare(\n `SELECT COUNT(*) as count FROM security_events ${where}`\n ).bind(...params).first<{ count: number }>()\n const total = countResult?.count || 0\n\n // Get page of results\n const results = await this.db.prepare(\n `SELECT * FROM security_events ${where} ORDER BY ${sortBy} ${sortOrder} LIMIT ? OFFSET ?`\n ).bind(...params, limit, offset).all()\n\n const events: SecurityEvent[] = (results.results || []).map((row: any) => ({\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }))\n\n return { events, total }\n }\n\n async getEvent(id: string): Promise<SecurityEvent | null> {\n const row = await this.db.prepare(\n 'SELECT * FROM security_events WHERE id = ?'\n ).bind(id).first<any>()\n\n if (!row) return null\n\n return {\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }\n }\n\n async getStats(): Promise<SecurityStats> {\n const now = Date.now()\n const h24 = now - 24 * 60 * 60 * 1000\n const h48 = now - 48 * 60 * 60 * 1000\n\n // Total events\n const totalResult = await this.db.prepare(\n 'SELECT COUNT(*) as count FROM security_events'\n ).first<{ count: number }>()\n\n // Failed logins last 24h\n const failed24hResult = await this.db.prepare(\n \"SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ?\"\n ).bind(h24).first<{ count: number }>()\n\n // Failed logins prior 24h (for trend)\n const failedPrior24hResult = await this.db.prepare(\n \"SELECT COUNT(*) as count FROM security_events WHERE event_type = 'login_failure' AND created_at >= ? AND created_at < ?\"\n ).bind(h48, h24).first<{ count: number }>()\n\n const failed24h = failed24hResult?.count || 0\n const failedPrior24h = failedPrior24hResult?.count || 0\n const trend = failedPrior24h > 0\n ? Math.round(((failed24h - failedPrior24h) / failedPrior24h) * 100)\n : (failed24h > 0 ? 100 : 0)\n\n // Active lockouts (events in last lockout window)\n const lockoutWindow = now - (this.settings.bruteForce.lockoutDurationMinutes * 60 * 1000)\n const lockoutsResult = await this.db.prepare(\n \"SELECT COUNT(DISTINCT ip_address) as count FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?\"\n ).bind(lockoutWindow).first<{ count: number }>()\n\n // Flagged IPs (IPs with more than threshold failed attempts in window)\n const windowStart = now - (this.settings.bruteForce.windowMinutes * 60 * 1000)\n const flaggedResult = await this.db.prepare(\n `SELECT COUNT(*) as count FROM (\n SELECT ip_address FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY ip_address HAVING COUNT(*) >= ?\n )`\n ).bind(windowStart, this.settings.bruteForce.maxFailedAttemptsPerIP).first<{ count: number }>()\n\n // Events by type\n const typeResults = await this.db.prepare(\n 'SELECT event_type, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY event_type'\n ).bind(h24).all()\n\n const eventsByType: Record<string, number> = {}\n for (const row of (typeResults.results || []) as any[]) {\n eventsByType[row.event_type] = row.count\n }\n\n // Events by severity\n const severityResults = await this.db.prepare(\n 'SELECT severity, COUNT(*) as count FROM security_events WHERE created_at >= ? GROUP BY severity'\n ).bind(h24).all()\n\n const eventsBySeverity: Record<string, number> = {}\n for (const row of (severityResults.results || []) as any[]) {\n eventsBySeverity[row.severity] = row.count\n }\n\n return {\n totalEvents: totalResult?.count || 0,\n failedLogins24h: failed24h,\n failedLoginsTrend: trend,\n activeLockouts: lockoutsResult?.count || 0,\n flaggedIPs: flaggedResult?.count || 0,\n eventsByType,\n eventsBySeverity\n }\n }\n\n async getTopIPs(limit: number = 10): Promise<TopIP[]> {\n const now = Date.now()\n const h24 = now - 24 * 60 * 60 * 1000\n\n const results = await this.db.prepare(`\n SELECT\n ip_address,\n country_code,\n COUNT(*) as failed_attempts,\n MAX(created_at) as last_seen\n FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY ip_address\n ORDER BY failed_attempts DESC\n LIMIT ?\n `).bind(h24, limit).all()\n\n // Check which IPs are locked\n const lockoutWindow = now - (this.settings.bruteForce.lockoutDurationMinutes * 60 * 1000)\n const lockoutResults = await this.db.prepare(\n \"SELECT DISTINCT ip_address FROM security_events WHERE event_type = 'account_lockout' AND created_at >= ?\"\n ).bind(lockoutWindow).all()\n\n const lockedIPs = new Set((lockoutResults.results || []).map((r: any) => r.ip_address))\n\n return (results.results || []).map((row: any) => ({\n ipAddress: row.ip_address,\n countryCode: row.country_code,\n failedAttempts: row.failed_attempts,\n lastSeen: row.last_seen,\n locked: lockedIPs.has(row.ip_address)\n }))\n }\n\n async getHourlyTrend(hours: number = 24): Promise<HourlyBucket[]> {\n const now = Date.now()\n const start = now - hours * 60 * 60 * 1000\n\n // Build hourly buckets\n const buckets: HourlyBucket[] = []\n for (let i = 0; i < hours; i++) {\n const bucketStart = start + i * 60 * 60 * 1000\n const date = new Date(bucketStart)\n buckets.push({\n hour: `${date.getUTCHours().toString().padStart(2, '0')}:00`,\n count: 0\n })\n }\n\n const results = await this.db.prepare(`\n SELECT\n CAST((created_at - ?) / 3600000 AS INTEGER) as bucket,\n COUNT(*) as count\n FROM security_events\n WHERE event_type = 'login_failure' AND created_at >= ?\n GROUP BY bucket\n ORDER BY bucket\n `).bind(start, start).all()\n\n for (const row of (results.results || []) as any[]) {\n const idx = row.bucket\n if (idx >= 0 && idx < buckets.length) {\n buckets[idx]!.count = row.count\n }\n }\n\n return buckets\n }\n\n async purgeOldEvents(daysToKeep?: number): Promise<number> {\n const days = daysToKeep || this.settings.retention.daysToKeep\n const cutoff = Date.now() - days * 24 * 60 * 60 * 1000\n\n const result = await this.db.prepare(\n 'DELETE FROM security_events WHERE created_at < ?'\n ).bind(cutoff).run()\n\n return (result.meta as any)?.changes || 0\n }\n\n async getRecentCriticalEvents(limit: number = 20): Promise<SecurityEvent[]> {\n const results = await this.db.prepare(\n \"SELECT * FROM security_events WHERE severity = 'critical' ORDER BY created_at DESC LIMIT ?\"\n ).bind(limit).all()\n\n return (results.results || []).map((row: any) => ({\n id: row.id,\n eventType: row.event_type,\n severity: row.severity,\n userId: row.user_id,\n email: row.email,\n ipAddress: row.ip_address,\n userAgent: row.user_agent,\n countryCode: row.country_code,\n requestPath: row.request_path,\n requestMethod: row.request_method,\n details: row.details ? JSON.parse(row.details) : null,\n fingerprint: row.fingerprint,\n blocked: !!row.blocked,\n createdAt: row.created_at\n }))\n }\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityStats, TopIP, HourlyBucket, SecurityEvent } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface SecurityDashboardData {\n stats: SecurityStats\n topIPs: TopIP[]\n hourlyTrend: HourlyBucket[]\n recentCritical: SecurityEvent[]\n user?: BaseUser\n version?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nfunction formatTimestamp(ts: number): string {\n const date = new Date(ts)\n const now = Date.now()\n const diff = now - ts\n\n if (diff < 60000) return 'just now'\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`\n return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n}\n\nfunction severityBadge(severity: string): string {\n const colors: Record<string, string> = {\n info: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n warning: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n critical: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'\n }\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}\">${severity}</span>`\n}\n\nfunction eventTypeBadge(type: string): string {\n const labels: Record<string, string> = {\n login_success: 'Login OK',\n login_failure: 'Login Failed',\n registration: 'Registration',\n account_lockout: 'Lockout',\n suspicious_activity: 'Suspicious',\n logout: 'Logout',\n password_reset_request: 'Password Reset',\n permission_denied: 'Access Denied'\n }\n return labels[type] || type\n}\n\nfunction trendArrow(trend: number): string {\n if (trend > 0) return `<span class=\"text-red-500\">+${trend}%</span>`\n if (trend < 0) return `<span class=\"text-emerald-500\">${trend}%</span>`\n return `<span class=\"text-zinc-400\">0%</span>`\n}\n\nfunction renderBarChart(data: HourlyBucket[]): string {\n if (data.length === 0) return '<p class=\"text-zinc-500 text-sm\">No data available</p>'\n\n const max = Math.max(...data.map(d => d.count), 1)\n\n const bars = data.map(d => {\n const height = Math.max((d.count / max) * 100, 2)\n const color = d.count === 0\n ? 'bg-zinc-200 dark:bg-zinc-700'\n : d.count >= max * 0.75\n ? 'bg-red-500'\n : d.count >= max * 0.5\n ? 'bg-amber-500'\n : 'bg-cyan-500'\n return `\n <div class=\"flex flex-col items-center flex-1 min-w-0 group relative\">\n <div class=\"w-full flex flex-col items-center justify-end\" style=\"height: 120px\">\n <div class=\"absolute bottom-8 hidden group-hover:block bg-zinc-900 text-white text-xs rounded px-2 py-1 whitespace-nowrap z-10\">\n ${d.hour}: ${d.count} failed\n </div>\n <div class=\"${color} w-full max-w-[12px] rounded-t transition-all\" style=\"height: ${height}%\"></div>\n </div>\n <span class=\"text-[9px] text-zinc-400 mt-1 ${data.length > 12 ? 'hidden sm:block' : ''}\">${d.hour}</span>\n </div>\n `\n }).join('')\n\n return `<div class=\"flex items-end gap-px\">${bars}</div>`\n}\n\nexport function renderSecurityDashboard(data: SecurityDashboardData): string {\n const { stats, topIPs, hourlyTrend, recentCritical, user, version, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Dashboard</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Monitor login attempts, brute-force detection, and security events.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit/events\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n View Event Log\n </a>\n <a href=\"/api/security-audit/export?format=csv\"\n class=\"inline-flex items-center justify-center rounded-lg bg-zinc-950 dark:bg-white px-3.5 py-2.5 text-sm font-semibold text-white dark:text-zinc-950 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors shadow-sm\">\n Export CSV\n </a>\n </div>\n </div>\n\n <!-- Summary Cards -->\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-6\">\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Total Events</p>\n <p class=\"mt-2 text-3xl font-bold text-zinc-950 dark:text-white\">${stats.totalEvents.toLocaleString()}</p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Failed Logins (24h)</p>\n <p class=\"mt-2 text-3xl font-bold text-zinc-950 dark:text-white\">\n ${stats.failedLogins24h}\n <span class=\"ml-2 text-sm font-normal\">${trendArrow(stats.failedLoginsTrend)}</span>\n </p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Active Lockouts</p>\n <p class=\"mt-2 text-3xl font-bold ${stats.activeLockouts > 0 ? 'text-red-600 dark:text-red-400' : 'text-zinc-950 dark:text-white'}\">${stats.activeLockouts}</p>\n </div>\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <p class=\"text-sm font-medium text-zinc-500 dark:text-zinc-400\">Flagged IPs</p>\n <p class=\"mt-2 text-3xl font-bold ${stats.flaggedIPs > 0 ? 'text-amber-600 dark:text-amber-400' : 'text-zinc-950 dark:text-white'}\">${stats.flaggedIPs}</p>\n </div>\n </div>\n\n <!-- Charts Row -->\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6\">\n <!-- Failed Login Trend -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-4\">Failed Login Attempts (24h)</h2>\n ${renderBarChart(hourlyTrend)}\n </div>\n\n <!-- Events by Type -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white mb-4\">Events by Type (24h)</h2>\n <div class=\"space-y-3\">\n ${Object.entries(stats.eventsByType).length === 0\n ? '<p class=\"text-zinc-500 text-sm\">No events in the last 24 hours</p>'\n : Object.entries(stats.eventsByType)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => {\n const total = Object.values(stats.eventsByType).reduce((s, v) => s + v, 0)\n const pct = total > 0 ? Math.round((count / total) * 100) : 0\n return `\n <div>\n <div class=\"flex justify-between text-sm mb-1\">\n <span class=\"text-zinc-600 dark:text-zinc-300\">${eventTypeBadge(type)}</span>\n <span class=\"text-zinc-500 dark:text-zinc-400\">${count}</span>\n </div>\n <div class=\"w-full bg-zinc-100 dark:bg-zinc-800 rounded-full h-1.5\">\n <div class=\"h-1.5 rounded-full ${type === 'login_failure' ? 'bg-red-500' : type === 'login_success' ? 'bg-emerald-500' : 'bg-cyan-500'}\" style=\"width: ${pct}%\"></div>\n </div>\n </div>\n `\n }).join('')\n }\n </div>\n </div>\n </div>\n\n <!-- Top IPs and Recent Critical -->\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6\">\n <!-- Top IPs -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n <div class=\"p-5 border-b border-zinc-100 dark:border-zinc-800\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white\">Top IPs by Failed Logins (24h)</h2>\n </div>\n ${topIPs.length === 0\n ? '<div class=\"p-5\"><p class=\"text-zinc-500 text-sm\">No failed login attempts</p></div>'\n : `<table class=\"min-w-full\">\n <thead>\n <tr class=\"border-b border-zinc-100 dark:border-zinc-800\">\n <th class=\"px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase\">IP Address</th>\n <th class=\"px-5 py-3 text-left text-xs font-medium text-zinc-500 uppercase\">Country</th>\n <th class=\"px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase\">Attempts</th>\n <th class=\"px-5 py-3 text-right text-xs font-medium text-zinc-500 uppercase\">Status</th>\n </tr>\n </thead>\n <tbody>\n ${topIPs.map(ip => `\n <tr class=\"border-b border-zinc-50 dark:border-zinc-800/50 hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <td class=\"px-5 py-3 text-sm font-mono text-zinc-900 dark:text-zinc-100\">${ip.ipAddress}</td>\n <td class=\"px-5 py-3 text-sm text-zinc-600 dark:text-zinc-400\">${ip.countryCode || '-'}</td>\n <td class=\"px-5 py-3 text-sm text-right font-semibold ${ip.failedAttempts >= 10 ? 'text-red-600 dark:text-red-400' : 'text-zinc-900 dark:text-zinc-100'}\">${ip.failedAttempts}</td>\n <td class=\"px-5 py-3 text-sm text-right\">\n ${ip.locked\n ? '<span class=\"inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400\">Locked</span>'\n : '<span class=\"inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400\">Active</span>'\n }\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>`\n }\n </div>\n\n <!-- Recent Critical Events -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n <div class=\"p-5 border-b border-zinc-100 dark:border-zinc-800\">\n <h2 class=\"text-sm font-semibold text-zinc-950 dark:text-white\">Recent Critical Events</h2>\n </div>\n ${recentCritical.length === 0\n ? '<div class=\"p-5\"><p class=\"text-zinc-500 text-sm\">No critical events</p></div>'\n : `<div class=\"divide-y divide-zinc-100 dark:divide-zinc-800\">\n ${recentCritical.slice(0, 10).map(event => `\n <div class=\"px-5 py-3 hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-2\">\n ${severityBadge(event.severity)}\n <span class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100\">${eventTypeBadge(event.eventType)}</span>\n </div>\n <span class=\"text-xs text-zinc-400\">${formatTimestamp(event.createdAt)}</span>\n </div>\n <div class=\"mt-1 text-xs text-zinc-500 dark:text-zinc-400\">\n ${event.ipAddress ? `IP: ${event.ipAddress}` : ''}\n ${event.email ? ` | ${event.email}` : ''}\n </div>\n </div>\n `).join('')}\n </div>`\n }\n </div>\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Dashboard',\n pageTitle: 'Security Dashboard',\n currentPath: '/admin/plugins/security-audit',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityEvent, SecurityEventFilters } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface EventLogPageData {\n events: SecurityEvent[]\n pagination: {\n currentPage: number\n totalPages: number\n totalItems: number\n itemsPerPage: number\n startItem: number\n endItem: number\n }\n filters: SecurityEventFilters\n user?: BaseUser\n version?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nfunction formatTimestamp(ts: number): string {\n const date = new Date(ts)\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n })\n}\n\nfunction severityBadge(severity: string): string {\n const colors: Record<string, string> = {\n info: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n warning: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n critical: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'\n }\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${colors[severity] || colors.info}\">${severity}</span>`\n}\n\nfunction eventTypeBadge(type: string): string {\n const colors: Record<string, string> = {\n login_success: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',\n login_failure: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n registration: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',\n account_lockout: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400',\n suspicious_activity: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',\n logout: 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400',\n password_reset_request: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',\n permission_denied: 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'\n }\n const labels: Record<string, string> = {\n login_success: 'Login OK',\n login_failure: 'Login Failed',\n registration: 'Registration',\n account_lockout: 'Lockout',\n suspicious_activity: 'Suspicious',\n logout: 'Logout',\n password_reset_request: 'Password Reset',\n permission_denied: 'Access Denied'\n }\n const color = colors[type] || 'bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-400'\n return `<span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ${color}\">${labels[type] || type}</span>`\n}\n\nfunction buildFilterUrl(filters: SecurityEventFilters, overrides: Record<string, string> = {}): string {\n const params = new URLSearchParams()\n if (filters.eventType && !overrides.type) params.set('type', String(filters.eventType))\n if (filters.severity && !overrides.severity) params.set('severity', String(filters.severity))\n if (filters.email && !overrides.email) params.set('email', filters.email)\n if (filters.ipAddress && !overrides.ip) params.set('ip', filters.ipAddress)\n if (filters.search && !overrides.search) params.set('search', filters.search)\n\n for (const [key, value] of Object.entries(overrides)) {\n if (value) params.set(key, value)\n }\n\n const qs = params.toString()\n return `/admin/plugins/security-audit/events${qs ? '?' + qs : ''}`\n}\n\nexport function renderEventLogPage(data: EventLogPageData): string {\n const { events, pagination, filters, user, version, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Event Log</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Browse and filter all security events. Showing ${pagination.startItem}-${pagination.endItem} of ${pagination.totalItems}.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n Dashboard\n </a>\n </div>\n </div>\n\n <!-- Filters -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-5 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm mb-6\">\n <form method=\"GET\" action=\"/admin/plugins/security-audit/events\" class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4\">\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Event Type</label>\n <select name=\"type\" class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <option value=\"\">All Types</option>\n <option value=\"login_success\" ${filters.eventType === 'login_success' ? 'selected' : ''}>Login Success</option>\n <option value=\"login_failure\" ${filters.eventType === 'login_failure' ? 'selected' : ''}>Login Failure</option>\n <option value=\"registration\" ${filters.eventType === 'registration' ? 'selected' : ''}>Registration</option>\n <option value=\"account_lockout\" ${filters.eventType === 'account_lockout' ? 'selected' : ''}>Account Lockout</option>\n <option value=\"suspicious_activity\" ${filters.eventType === 'suspicious_activity' ? 'selected' : ''}>Suspicious Activity</option>\n <option value=\"logout\" ${filters.eventType === 'logout' ? 'selected' : ''}>Logout</option>\n </select>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Severity</label>\n <select name=\"severity\" class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <option value=\"\">All Severities</option>\n <option value=\"info\" ${filters.severity === 'info' ? 'selected' : ''}>Info</option>\n <option value=\"warning\" ${filters.severity === 'warning' ? 'selected' : ''}>Warning</option>\n <option value=\"critical\" ${filters.severity === 'critical' ? 'selected' : ''}>Critical</option>\n </select>\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Email</label>\n <input type=\"text\" name=\"email\" value=\"${filters.email || ''}\" placeholder=\"Filter by email\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">IP Address</label>\n <input type=\"text\" name=\"ip\" value=\"${filters.ipAddress || ''}\" placeholder=\"Filter by IP\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500 placeholder:text-zinc-400\">\n </div>\n <div class=\"flex items-end gap-2\">\n <button type=\"submit\"\n class=\"flex-1 rounded-lg bg-cyan-600 px-3 py-2 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm\">\n Filter\n </button>\n <a href=\"/admin/plugins/security-audit/events\"\n class=\"rounded-lg bg-zinc-100 dark:bg-zinc-800 px-3 py-2 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors\">\n Clear\n </a>\n </div>\n </form>\n </div>\n\n <!-- Events Table -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm overflow-hidden\">\n ${events.length === 0\n ? `<div class=\"p-12 text-center\">\n <svg class=\"mx-auto h-12 w-12 text-zinc-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"/>\n </svg>\n <h3 class=\"mt-2 text-sm font-semibold text-zinc-900 dark:text-white\">No events found</h3>\n <p class=\"mt-1 text-sm text-zinc-500\">No security events match your current filters.</p>\n </div>`\n : `<div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-200 dark:divide-zinc-800\">\n <thead>\n <tr>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Time</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Type</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Severity</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Email</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">IP Address</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Country</th>\n <th class=\"px-4 py-3 text-left text-xs font-medium text-zinc-500 uppercase tracking-wider\">Status</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-100 dark:divide-zinc-800\">\n ${events.map(event => `\n <tr class=\"hover:bg-zinc-50 dark:hover:bg-zinc-800/50 cursor-pointer\" onclick=\"this.querySelector('.event-details').classList.toggle('hidden')\">\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 whitespace-nowrap\">${formatTimestamp(event.createdAt)}</td>\n <td class=\"px-4 py-3\">${eventTypeBadge(event.eventType)}</td>\n <td class=\"px-4 py-3\">${severityBadge(event.severity)}</td>\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300 max-w-[200px] truncate\">${event.email || '-'}</td>\n <td class=\"px-4 py-3 text-sm font-mono text-zinc-600 dark:text-zinc-300\">${event.ipAddress || '-'}</td>\n <td class=\"px-4 py-3 text-sm text-zinc-600 dark:text-zinc-300\">${event.countryCode || '-'}</td>\n <td class=\"px-4 py-3\">\n ${event.blocked\n ? '<span class=\"inline-flex items-center rounded-md bg-red-100 dark:bg-red-900/30 px-2 py-1 text-xs font-medium text-red-700 dark:text-red-400\">Blocked</span>'\n : '<span class=\"inline-flex items-center rounded-md bg-emerald-100 dark:bg-emerald-900/30 px-2 py-1 text-xs font-medium text-emerald-700 dark:text-emerald-400\">Allowed</span>'\n }\n </td>\n </tr>\n <tr class=\"event-details hidden\">\n <td colspan=\"7\" class=\"px-4 py-3 bg-zinc-50 dark:bg-zinc-800/30\">\n <div class=\"grid grid-cols-2 md:grid-cols-4 gap-4 text-xs\">\n <div><span class=\"font-medium text-zinc-500\">Event ID:</span> <span class=\"text-zinc-700 dark:text-zinc-300 font-mono\">${event.id.substring(0, 8)}...</span></div>\n <div><span class=\"font-medium text-zinc-500\">User Agent:</span> <span class=\"text-zinc-700 dark:text-zinc-300 truncate block max-w-[300px]\">${event.userAgent || '-'}</span></div>\n <div><span class=\"font-medium text-zinc-500\">Path:</span> <span class=\"text-zinc-700 dark:text-zinc-300\">${event.requestPath || '-'}</span></div>\n <div><span class=\"font-medium text-zinc-500\">Fingerprint:</span> <span class=\"text-zinc-700 dark:text-zinc-300 font-mono\">${event.fingerprint || '-'}</span></div>\n ${event.details ? `<div class=\"col-span-full\"><span class=\"font-medium text-zinc-500\">Details:</span> <pre class=\"text-zinc-700 dark:text-zinc-300 mt-1 bg-zinc-100 dark:bg-zinc-900 rounded p-2 overflow-x-auto\">${JSON.stringify(event.details, null, 2)}</pre></div>` : ''}\n </div>\n </td>\n </tr>\n `).join('')}\n </tbody>\n </table>\n </div>`\n }\n\n <!-- Pagination -->\n ${pagination.totalPages > 1 ? `\n <div class=\"flex items-center justify-between border-t border-zinc-200 dark:border-zinc-800 px-4 py-3\">\n <div class=\"text-sm text-zinc-500\">\n Page ${pagination.currentPage} of ${pagination.totalPages}\n </div>\n <div class=\"flex gap-1\">\n ${pagination.currentPage > 1 ? `\n <a href=\"${buildFilterUrl(filters, { page: String(pagination.currentPage - 1) })}\"\n class=\"rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\">\n Previous\n </a>\n ` : ''}\n ${pagination.currentPage < pagination.totalPages ? `\n <a href=\"${buildFilterUrl(filters, { page: String(pagination.currentPage + 1) })}\"\n class=\"rounded-lg px-3 py-1.5 text-sm font-medium text-zinc-600 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors\">\n Next\n </a>\n ` : ''}\n </div>\n </div>\n ` : ''}\n </div>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Event Log',\n pageTitle: 'Security Event Log',\n currentPath: '/admin/plugins/security-audit/events',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../../../../templates/layouts/admin-layout-catalyst.template'\nimport type { SecurityAuditSettings } from '../types'\n\ninterface BaseUser {\n name: string\n email: string\n role: string\n}\n\nexport interface SecuritySettingsPageData {\n settings: SecurityAuditSettings\n user?: BaseUser\n version?: string\n message?: string\n dynamicMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nexport function renderSecuritySettingsPage(data: SecuritySettingsPageData): string {\n const { settings, user, version, message, dynamicMenuItems } = data\n\n const content = `\n <div>\n <div class=\"sm:flex sm:items-center sm:justify-between mb-6\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8\">Security Audit Settings</h1>\n <p class=\"mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400\">\n Configure brute-force detection thresholds, event logging, and data retention.\n </p>\n </div>\n <div class=\"mt-4 sm:mt-0 sm:ml-16 flex gap-x-2\">\n <a href=\"/admin/plugins/security-audit\"\n class=\"inline-flex items-center justify-center rounded-lg bg-white dark:bg-zinc-800 px-3.5 py-2.5 text-sm font-semibold text-zinc-950 dark:text-white hover:bg-zinc-50 dark:hover:bg-zinc-700 ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 transition-colors shadow-sm\">\n Dashboard\n </a>\n </div>\n </div>\n\n ${message ? `\n <div class=\"mb-6 rounded-lg bg-emerald-50 dark:bg-emerald-900/20 p-4 ring-1 ring-emerald-200 dark:ring-emerald-800\">\n <p class=\"text-sm text-emerald-800 dark:text-emerald-300\">${message}</p>\n </div>\n ` : ''}\n\n <form method=\"POST\" action=\"/admin/plugins/security-audit/settings\"\n class=\"space-y-6\"\n hx-post=\"/admin/plugins/security-audit/settings\"\n hx-swap=\"none\"\n hx-on::after-request=\"if(event.detail.successful) { window.showNotification && window.showNotification('Settings saved', 'success'); } else { window.showNotification && window.showNotification('Failed to save', 'error'); }\">\n\n <!-- Brute Force Detection -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Brute-Force Detection</h2>\n <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <label class=\"flex items-center gap-2 mb-4\">\n <input type=\"checkbox\" name=\"bruteForce.enabled\" value=\"true\" ${settings.bruteForce.enabled ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm font-medium text-zinc-700 dark:text-zinc-300\">Enable brute-force detection</span>\n </label>\n </div>\n <div></div><div></div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Failed Attempts per IP</label>\n <input type=\"number\" name=\"bruteForce.maxFailedAttemptsPerIP\" value=\"${settings.bruteForce.maxFailedAttemptsPerIP}\" min=\"1\" max=\"100\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Failed Attempts per Email</label>\n <input type=\"number\" name=\"bruteForce.maxFailedAttemptsPerEmail\" value=\"${settings.bruteForce.maxFailedAttemptsPerEmail}\" min=\"1\" max=\"100\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Window (minutes)</label>\n <input type=\"number\" name=\"bruteForce.windowMinutes\" value=\"${settings.bruteForce.windowMinutes}\" min=\"1\" max=\"1440\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Lockout Duration (minutes)</label>\n <input type=\"number\" name=\"bruteForce.lockoutDurationMinutes\" value=\"${settings.bruteForce.lockoutDurationMinutes}\" min=\"1\" max=\"1440\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Alert Threshold</label>\n <input type=\"number\" name=\"bruteForce.alertThreshold\" value=\"${settings.bruteForce.alertThreshold}\" min=\"1\" max=\"1000\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n <p class=\"mt-1 text-xs text-zinc-400\">Events above this count trigger critical severity</p>\n </div>\n </div>\n </div>\n\n <!-- Event Logging -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Event Logging</h2>\n <div class=\"space-y-3\">\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logSuccessfulLogins\" value=\"true\" ${settings.logging.logSuccessfulLogins ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log successful logins</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logLogouts\" value=\"true\" ${settings.logging.logLogouts ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log logouts</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logRegistrations\" value=\"true\" ${settings.logging.logRegistrations ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log registrations</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logPasswordResets\" value=\"true\" ${settings.logging.logPasswordResets ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log password resets</span>\n </label>\n <label class=\"flex items-center gap-2\">\n <input type=\"checkbox\" name=\"logging.logPermissionDenied\" value=\"true\" ${settings.logging.logPermissionDenied ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Log permission denied events</span>\n </label>\n </div>\n </div>\n\n <!-- Data Retention -->\n <div class=\"rounded-xl bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl p-6 ring-1 ring-zinc-950/5 dark:ring-white/10 shadow-sm\">\n <h2 class=\"text-base font-semibold text-zinc-950 dark:text-white mb-4\">Data Retention</h2>\n <div class=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Days to Keep</label>\n <input type=\"number\" name=\"retention.daysToKeep\" value=\"${settings.retention.daysToKeep}\" min=\"1\" max=\"365\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"block text-xs font-medium text-zinc-500 dark:text-zinc-400 mb-1\">Max Events</label>\n <input type=\"number\" name=\"retention.maxEvents\" value=\"${settings.retention.maxEvents}\" min=\"1000\" max=\"1000000\"\n class=\"w-full rounded-lg border-0 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-white ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 focus:ring-2 focus:ring-cyan-500\">\n </div>\n <div>\n <label class=\"flex items-center gap-2 mt-5\">\n <input type=\"checkbox\" name=\"retention.autoPurge\" value=\"true\" ${settings.retention.autoPurge ? 'checked' : ''}\n class=\"rounded border-zinc-300 text-cyan-600 focus:ring-cyan-500\">\n <span class=\"text-sm text-zinc-700 dark:text-zinc-300\">Auto-purge old events</span>\n </label>\n </div>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex items-center justify-between\">\n <button type=\"button\"\n onclick=\"if(confirm('Purge events older than retention period?')) fetch('/api/security-audit/events/purge', {method:'POST',headers:{'Content-Type':'application/json'}}).then(r=>r.json()).then(d=>window.showNotification && window.showNotification('Purged '+d.deleted+' events','success'))\"\n class=\"rounded-lg bg-red-50 dark:bg-red-900/20 px-4 py-2.5 text-sm font-medium text-red-700 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900/40 ring-1 ring-red-200 dark:ring-red-800 transition-colors\">\n Purge Old Events\n </button>\n <button type=\"submit\"\n class=\"rounded-lg bg-cyan-600 px-6 py-2.5 text-sm font-semibold text-white hover:bg-cyan-500 transition-colors shadow-sm\">\n Save Settings\n </button>\n </div>\n </form>\n </div>\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Security Audit Settings',\n pageTitle: 'Security Audit Settings',\n currentPath: '/admin/plugins/security-audit/settings',\n user,\n content,\n version,\n dynamicMenuItems\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { PluginService } from '../../../../services'\nimport { renderSecurityDashboard, SecurityDashboardData } from '../components/dashboard-page'\nimport { renderEventLogPage, EventLogPageData } from '../components/event-log-page'\nimport { renderSecuritySettingsPage, SecuritySettingsPageData } from '../components/settings-page'\nimport type { Bindings, Variables } from '../../../../app'\nimport type { SecurityAuditSettings, SecurityEventType, SecuritySeverity } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst adminRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminRoutes.use('*', requireAuth())\n\n// Check admin role\nadminRoutes.use('*', async (c, next) => {\n const user = c.get('user')\n if (user?.role !== 'admin') {\n return c.text('Access denied', 403)\n }\n return next()\n})\n\nasync function getSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\n// Dashboard\nadminRoutes.get('/', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const [stats, topIPs, hourlyTrend, recentCritical] = await Promise.all([\n service.getStats(),\n service.getTopIPs(10),\n service.getHourlyTrend(24),\n service.getRecentCriticalEvents(20)\n ])\n\n const pageData: SecurityDashboardData = {\n stats,\n topIPs,\n hourlyTrend,\n recentCritical,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderSecurityDashboard(pageData))\n})\n\n// Event log\nadminRoutes.get('/events', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const page = parseInt(c.req.query('page') || '1')\n const limit = 50\n\n const filters = {\n eventType: (c.req.query('type') as SecurityEventType) || undefined,\n severity: (c.req.query('severity') as SecuritySeverity) || undefined,\n email: c.req.query('email') || undefined,\n ipAddress: c.req.query('ip') || undefined,\n search: c.req.query('search') || undefined,\n page,\n limit\n }\n\n const { events, total } = await service.getEvents(filters)\n const totalPages = Math.ceil(total / limit)\n\n const pageData: EventLogPageData = {\n events,\n pagination: {\n currentPage: page,\n totalPages,\n totalItems: total,\n itemsPerPage: limit,\n startItem: total === 0 ? 0 : (page - 1) * limit + 1,\n endItem: Math.min(page * limit, total)\n },\n filters,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderEventLogPage(pageData))\n})\n\n// Settings page\nadminRoutes.get('/settings', async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n const settings = await getSettings(db)\n\n const pageData: SecuritySettingsPageData = {\n settings,\n user: user ? { name: user.email, email: user.email, role: user.role } : undefined,\n version: c.get('appVersion'),\n message: c.req.query('message') || undefined,\n dynamicMenuItems: c.get('pluginMenuItems')\n }\n\n return c.html(renderSecuritySettingsPage(pageData))\n})\n\n// Save settings\nadminRoutes.post('/settings', async (c) => {\n const db = c.env.DB\n const body = await c.req.parseBody()\n\n const settings: SecurityAuditSettings = {\n bruteForce: {\n enabled: body['bruteForce.enabled'] === 'true',\n maxFailedAttemptsPerIP: parseInt(body['bruteForce.maxFailedAttemptsPerIP'] as string) || 10,\n maxFailedAttemptsPerEmail: parseInt(body['bruteForce.maxFailedAttemptsPerEmail'] as string) || 5,\n windowMinutes: parseInt(body['bruteForce.windowMinutes'] as string) || 15,\n lockoutDurationMinutes: parseInt(body['bruteForce.lockoutDurationMinutes'] as string) || 30,\n alertThreshold: parseInt(body['bruteForce.alertThreshold'] as string) || 20\n },\n logging: {\n logSuccessfulLogins: body['logging.logSuccessfulLogins'] === 'true',\n logLogouts: body['logging.logLogouts'] === 'true',\n logRegistrations: body['logging.logRegistrations'] === 'true',\n logPasswordResets: body['logging.logPasswordResets'] === 'true',\n logPermissionDenied: body['logging.logPermissionDenied'] === 'true'\n },\n retention: {\n daysToKeep: parseInt(body['retention.daysToKeep'] as string) || 90,\n maxEvents: parseInt(body['retention.maxEvents'] as string) || 100000,\n autoPurge: body['retention.autoPurge'] === 'true'\n }\n }\n\n const pluginService = new PluginService(db)\n await pluginService.updatePluginSettings('security-audit', settings)\n\n // For HTMX requests, return 200\n if (c.req.header('HX-Request')) {\n return c.json({ success: true })\n }\n\n return c.redirect('/admin/plugins/security-audit/settings?message=Settings saved successfully')\n})\n\nexport { adminRoutes as securityAuditAdminRoutes }\n","import type { KVNamespace } from '@cloudflare/workers-types'\nimport type { SecurityAuditSettings } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst KV_PREFIX = 'security:bf:'\nconst LOCK_PREFIX = 'security:locked:'\n\nexport class BruteForceDetector {\n private settings: SecurityAuditSettings['bruteForce']\n\n constructor(\n private kv: KVNamespace,\n settings?: SecurityAuditSettings['bruteForce']\n ) {\n this.settings = settings || DEFAULT_SETTINGS.bruteForce\n }\n\n async recordFailedAttempt(ip: string, email: string): Promise<{\n ipCount: number\n emailCount: number\n shouldLockIP: boolean\n shouldLockEmail: boolean\n isSuspicious: boolean\n }> {\n if (!this.settings.enabled) {\n return { ipCount: 0, emailCount: 0, shouldLockIP: false, shouldLockEmail: false, isSuspicious: false }\n }\n\n const now = Date.now()\n const windowMs = this.settings.windowMinutes * 60 * 1000\n\n // Increment IP counter\n const ipKey = `${KV_PREFIX}ip:${ip}`\n const ipCount = await this.incrementCounter(ipKey, windowMs)\n\n // Increment email counter\n const emailKey = `${KV_PREFIX}email:${email}`\n const emailCount = await this.incrementCounter(emailKey, windowMs)\n\n // Check for multi-email from single IP (suspicious)\n const ipEmailsKey = `${KV_PREFIX}ip-emails:${ip}`\n await this.addToSet(ipEmailsKey, email, windowMs)\n const emailsFromIP = await this.getSetSize(ipEmailsKey)\n const isSuspicious = emailsFromIP >= 5\n\n const shouldLockIP = ipCount >= this.settings.maxFailedAttemptsPerIP\n const shouldLockEmail = emailCount >= this.settings.maxFailedAttemptsPerEmail\n\n return { ipCount, emailCount, shouldLockIP, shouldLockEmail, isSuspicious }\n }\n\n async isLocked(ip: string, email: string): Promise<{ locked: boolean, reason?: string }> {\n if (!this.settings.enabled) {\n return { locked: false }\n }\n\n const ipLocked = await this.kv.get(`${LOCK_PREFIX}ip:${ip}`)\n if (ipLocked) {\n return { locked: true, reason: 'IP address temporarily locked due to excessive failed login attempts' }\n }\n\n const emailLocked = await this.kv.get(`${LOCK_PREFIX}email:${email}`)\n if (emailLocked) {\n return { locked: true, reason: 'Account temporarily locked due to excessive failed login attempts' }\n }\n\n return { locked: false }\n }\n\n async lockIP(ip: string): Promise<void> {\n const ttl = this.settings.lockoutDurationMinutes * 60\n await this.kv.put(`${LOCK_PREFIX}ip:${ip}`, JSON.stringify({\n lockedAt: Date.now(),\n reason: 'brute_force_ip'\n }), { expirationTtl: ttl })\n }\n\n async lockEmail(email: string): Promise<void> {\n const ttl = this.settings.lockoutDurationMinutes * 60\n await this.kv.put(`${LOCK_PREFIX}email:${email}`, JSON.stringify({\n lockedAt: Date.now(),\n reason: 'brute_force_email'\n }), { expirationTtl: ttl })\n }\n\n async unlockIP(ip: string): Promise<void> {\n await this.kv.delete(`${LOCK_PREFIX}ip:${ip}`)\n }\n\n async unlockEmail(email: string): Promise<void> {\n await this.kv.delete(`${LOCK_PREFIX}email:${email}`)\n }\n\n async getActiveLockouts(): Promise<Array<{ key: string, type: 'ip' | 'email', value: string, lockedAt: number }>> {\n // KV list with prefix to find all active lockouts\n const ipLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}ip:` })\n const emailLocks = await this.kv.list({ prefix: `${LOCK_PREFIX}email:` })\n\n const lockouts: Array<{ key: string, type: 'ip' | 'email', value: string, lockedAt: number }> = []\n\n for (const key of ipLocks.keys) {\n const data = await this.kv.get(key.name)\n if (data) {\n const parsed = JSON.parse(data)\n lockouts.push({\n key: key.name,\n type: 'ip',\n value: key.name.replace(`${LOCK_PREFIX}ip:`, ''),\n lockedAt: parsed.lockedAt\n })\n }\n }\n\n for (const key of emailLocks.keys) {\n const data = await this.kv.get(key.name)\n if (data) {\n const parsed = JSON.parse(data)\n lockouts.push({\n key: key.name,\n type: 'email',\n value: key.name.replace(`${LOCK_PREFIX}email:`, ''),\n lockedAt: parsed.lockedAt\n })\n }\n }\n\n return lockouts\n }\n\n async releaseLockout(key: string): Promise<void> {\n await this.kv.delete(key)\n }\n\n isAboveAlertThreshold(count: number): boolean {\n return count >= this.settings.alertThreshold\n }\n\n private async incrementCounter(key: string, windowMs: number): Promise<number> {\n const existing = await this.kv.get(key)\n const now = Date.now()\n\n let entries: number[] = []\n if (existing) {\n try {\n entries = JSON.parse(existing)\n } catch {\n entries = []\n }\n }\n\n // Remove expired entries\n const cutoff = now - windowMs\n entries = entries.filter(ts => ts > cutoff)\n\n // Add new entry\n entries.push(now)\n\n // Store with TTL equal to window\n const ttlSeconds = Math.ceil(windowMs / 1000)\n await this.kv.put(key, JSON.stringify(entries), { expirationTtl: ttlSeconds })\n\n return entries.length\n }\n\n private async addToSet(key: string, value: string, windowMs: number): Promise<void> {\n const existing = await this.kv.get(key)\n let set: Record<string, number> = {}\n const now = Date.now()\n const cutoff = now - windowMs\n\n if (existing) {\n try {\n set = JSON.parse(existing)\n } catch {\n set = {}\n }\n }\n\n // Remove expired entries\n for (const [k, ts] of Object.entries(set)) {\n if (ts < cutoff) delete set[k]\n }\n\n set[value] = now\n\n const ttlSeconds = Math.ceil(windowMs / 1000)\n await this.kv.put(key, JSON.stringify(set), { expirationTtl: ttlSeconds })\n }\n\n private async getSetSize(key: string): Promise<number> {\n const existing = await this.kv.get(key)\n if (!existing) return 0\n\n try {\n const set = JSON.parse(existing)\n return Object.keys(set).length\n } catch {\n return 0\n }\n }\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { BruteForceDetector } from '../services/brute-force-detector'\nimport { PluginService } from '../../../../services'\nimport type { Bindings, Variables } from '../../../../app'\nimport type { SecurityAuditSettings, SecurityEventFilters, SecurityEventType, SecuritySeverity } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\napiRoutes.use('*', requireAuth())\n\n// Check admin role\napiRoutes.use('*', async (c, next) => {\n const user = c.get('user')\n if (user?.role !== 'admin') {\n return c.json({ error: 'Access denied' }, 403)\n }\n return next()\n})\n\nasync function getSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\n// GET /api/security-audit/events\napiRoutes.get('/events', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n\n const filters: SecurityEventFilters = {\n eventType: c.req.query('type') as SecurityEventType | undefined,\n severity: c.req.query('severity') as SecuritySeverity | undefined,\n email: c.req.query('email') || undefined,\n ipAddress: c.req.query('ip') || undefined,\n search: c.req.query('search') || undefined,\n startDate: c.req.query('start') ? parseInt(c.req.query('start')!) : undefined,\n endDate: c.req.query('end') ? parseInt(c.req.query('end')!) : undefined,\n page: c.req.query('page') ? parseInt(c.req.query('page')!) : 1,\n limit: c.req.query('limit') ? Math.min(parseInt(c.req.query('limit')!), 100) : 50,\n sortBy: (c.req.query('sortBy') as any) || 'created_at',\n sortOrder: (c.req.query('sortOrder') as any) || 'desc'\n }\n\n const result = await service.getEvents(filters)\n return c.json(result)\n})\n\n// GET /api/security-audit/events/:id\napiRoutes.get('/events/:id', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const event = await service.getEvent(c.req.param('id'))\n\n if (!event) {\n return c.json({ error: 'Event not found' }, 404)\n }\n\n return c.json(event)\n})\n\n// GET /api/security-audit/stats\napiRoutes.get('/stats', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const stats = await service.getStats()\n return c.json(stats)\n})\n\n// GET /api/security-audit/stats/ips\napiRoutes.get('/stats/ips', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const limit = c.req.query('limit') ? parseInt(c.req.query('limit')!) : 10\n const ips = await service.getTopIPs(limit)\n return c.json(ips)\n})\n\n// GET /api/security-audit/stats/trend\napiRoutes.get('/stats/trend', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const hours = c.req.query('hours') ? parseInt(c.req.query('hours')!) : 24\n const trend = await service.getHourlyTrend(hours)\n return c.json(trend)\n})\n\n// GET /api/security-audit/lockouts\napiRoutes.get('/lockouts', async (c) => {\n const kv = c.env.CACHE_KV\n const db = c.env.DB\n const settings = await getSettings(db)\n const detector = new BruteForceDetector(kv, settings.bruteForce)\n const lockouts = await detector.getActiveLockouts()\n return c.json(lockouts)\n})\n\n// DELETE /api/security-audit/lockouts/:key\napiRoutes.delete('/lockouts/:key', async (c) => {\n const kv = c.env.CACHE_KV\n const key = decodeURIComponent(c.req.param('key'))\n const db = c.env.DB\n const settings = await getSettings(db)\n const detector = new BruteForceDetector(kv, settings.bruteForce)\n await detector.releaseLockout(key)\n return c.json({ success: true })\n})\n\n// POST /api/security-audit/events/purge\napiRoutes.post('/events/purge', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const body = await c.req.json().catch(() => ({})) as { daysToKeep?: number }\n const deleted = await service.purgeOldEvents(body.daysToKeep)\n return c.json({ success: true, deleted })\n})\n\n// GET /api/security-audit/export\napiRoutes.get('/export', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n const service = new SecurityAuditService(db, settings)\n const format = c.req.query('format') || 'json'\n\n const filters: SecurityEventFilters = {\n eventType: c.req.query('type') as SecurityEventType | undefined,\n severity: c.req.query('severity') as SecuritySeverity | undefined,\n startDate: c.req.query('start') ? parseInt(c.req.query('start')!) : undefined,\n endDate: c.req.query('end') ? parseInt(c.req.query('end')!) : undefined,\n limit: 10000,\n page: 1\n }\n\n const { events } = await service.getEvents(filters)\n\n if (format === 'csv') {\n const headers = ['id', 'event_type', 'severity', 'email', 'ip_address', 'country_code', 'blocked', 'created_at']\n const csvRows = [headers.join(',')]\n for (const event of events) {\n csvRows.push([\n event.id,\n event.eventType,\n event.severity,\n event.email || '',\n event.ipAddress || '',\n event.countryCode || '',\n event.blocked ? '1' : '0',\n new Date(event.createdAt).toISOString()\n ].map(v => `\"${String(v).replace(/\"/g, '\"\"')}\"`).join(','))\n }\n\n return new Response(csvRows.join('\\n'), {\n headers: {\n 'Content-Type': 'text/csv',\n 'Content-Disposition': `attachment; filename=\"security-events-${Date.now()}.csv\"`\n }\n })\n }\n\n return c.json(events)\n})\n\nexport { apiRoutes as securityAuditApiRoutes }\n","import type { Context, Next } from 'hono'\nimport type { Bindings, Variables } from '../../../../app'\nimport { SecurityAuditService } from '../services/security-audit-service'\nimport { BruteForceDetector } from '../services/brute-force-detector'\nimport { PluginService } from '../../../../services'\nimport type { SecurityAuditSettings, SecurityEventType } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nfunction extractRequestInfo(c: Context<{ Bindings: Bindings; Variables: Variables }>) {\n const ip = c.req.header('cf-connecting-ip')\n || c.req.header('x-forwarded-for')?.split(',')[0]?.trim()\n || 'unknown'\n const userAgent = c.req.header('user-agent') || 'unknown'\n const countryCode = c.req.header('cf-ipcountry') || null\n const path = new URL(c.req.url).pathname\n const method = c.req.method\n\n return { ip, userAgent, countryCode, path, method }\n}\n\nfunction generateFingerprint(ip: string, userAgent: string): string {\n // Simple fingerprint from IP + UA - using a basic hash\n const str = `${ip}:${userAgent}`\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash |= 0\n }\n return Math.abs(hash).toString(36)\n}\n\nasync function getPluginSettings(db: any): Promise<SecurityAuditSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('security-audit')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch {\n // Plugin not installed or DB not ready\n }\n return DEFAULT_SETTINGS\n}\n\nasync function isPluginActive(db: any): Promise<boolean> {\n try {\n const result = await db.prepare(\n \"SELECT status FROM plugins WHERE id = 'security-audit'\"\n ).first() as { status: string } | null\n return result?.status === 'active'\n } catch {\n return false\n }\n}\n\nexport function securityAuditMiddleware() {\n return async (c: Context<{ Bindings: Bindings; Variables: Variables }>, next: Next) => {\n const path = new URL(c.req.url).pathname\n\n // Only intercept auth-related routes\n if (!path.startsWith('/auth/')) {\n return next()\n }\n\n const db = c.env.DB\n\n // Check if plugin is active\n if (!await isPluginActive(db)) {\n return next()\n }\n\n const settings = await getPluginSettings(db)\n const { ip, userAgent, countryCode, method } = extractRequestInfo(c)\n const fingerprint = generateFingerprint(ip, userAgent)\n\n // For login POST, extract email and check lockout before proceeding\n const isLoginPost = (path === '/auth/login' || path === '/auth/login/form') && method === 'POST'\n let preExtractedEmail = ''\n\n if (isLoginPost) {\n try {\n if (path === '/auth/login/form') {\n // Form-based login: clone request to read formData without consuming it\n const clonedReq = c.req.raw.clone()\n const formData = await clonedReq.formData()\n preExtractedEmail = (formData.get('email') as string || '').toLowerCase()\n } else {\n // JSON login: Hono caches parsed JSON so this is safe\n const body = await c.req.json()\n preExtractedEmail = body?.email?.toLowerCase() || ''\n }\n } catch {\n // Can't parse body, continue\n }\n\n if (preExtractedEmail && settings.bruteForce.enabled) {\n const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce)\n const lockStatus = await detector.isLocked(ip, preExtractedEmail)\n\n if (lockStatus.locked) {\n const service = new SecurityAuditService(db, settings)\n // Log the blocked attempt asynchronously\n const logPromise = service.logEvent({\n eventType: 'login_failure',\n severity: 'warning',\n email: preExtractedEmail,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n blocked: true,\n details: { reason: lockStatus.reason }\n })\n\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(logPromise)\n }\n\n return c.json({\n error: lockStatus.reason || 'Too many failed attempts. Please try again later.'\n }, 429)\n }\n }\n }\n\n // Proceed with the request\n await next()\n\n // After response, log the event asynchronously\n const logPromise = logAuthEvent(c, db, settings, ip, userAgent, countryCode, fingerprint, path, method, preExtractedEmail)\n\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(logPromise)\n }\n }\n}\n\nasync function logAuthEvent(\n c: Context<{ Bindings: Bindings; Variables: Variables }>,\n db: any,\n settings: SecurityAuditSettings,\n ip: string,\n userAgent: string,\n countryCode: string | null,\n fingerprint: string,\n path: string,\n method: string,\n preExtractedEmail: string = ''\n): Promise<void> {\n try {\n const service = new SecurityAuditService(db, settings)\n const status = c.res.status\n const isLoginPost = (path === '/auth/login' || path === '/auth/login/form') && method === 'POST'\n const isFormLogin = path === '/auth/login/form'\n\n // Login POST\n if (isLoginPost) {\n // Determine if login succeeded or failed.\n // JSON login: 200 = success, 401/400 = failure\n // Form login: always returns 200 — check if response set an auth cookie (HX-Redirect header indicates success)\n let loginSucceeded: boolean\n if (isFormLogin) {\n // Form login redirects to /admin on success via HX-Redirect header or meta refresh\n const hxRedirect = c.res.headers.get('HX-Redirect')\n const setCookieHeader = c.res.headers.get('set-cookie') || ''\n loginSucceeded = !!(hxRedirect?.includes('/admin') || setCookieHeader.includes('auth_token'))\n } else {\n loginSucceeded = status === 200\n }\n\n if (loginSucceeded) {\n if (!settings.logging.logSuccessfulLogins) return\n\n // Try to get user info from response\n let email = preExtractedEmail\n let userId = ''\n if (!isFormLogin) {\n try {\n const cloned = c.res.clone()\n const body = await cloned.json() as any\n email = body?.user?.email || email\n userId = body?.user?.id || ''\n } catch { /* ignore */ }\n }\n\n await service.logEvent({\n eventType: 'login_success',\n severity: 'info',\n userId: userId || undefined,\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n } else {\n // Failed login — use pre-extracted email since body is already consumed\n const email = preExtractedEmail\n\n await service.logEvent({\n eventType: 'login_failure',\n severity: 'warning',\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { statusCode: status }\n })\n\n // Record failed attempt for brute-force detection\n if (email && settings.bruteForce.enabled) {\n const detector = new BruteForceDetector(c.env.CACHE_KV, settings.bruteForce)\n const result = await detector.recordFailedAttempt(ip, email)\n\n if (result.shouldLockIP) {\n await detector.lockIP(ip)\n await service.logEvent({\n eventType: 'account_lockout',\n severity: 'critical',\n email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'brute_force_ip', attemptCount: result.ipCount }\n })\n }\n\n if (result.shouldLockEmail) {\n await detector.lockEmail(email)\n await service.logEvent({\n eventType: 'account_lockout',\n severity: 'critical',\n email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'brute_force_email', attemptCount: result.emailCount }\n })\n }\n\n if (result.isSuspicious) {\n await service.logEvent({\n eventType: 'suspicious_activity',\n severity: 'critical',\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint,\n details: { reason: 'multiple_emails_from_ip', ipCount: result.ipCount }\n })\n }\n }\n }\n }\n\n // Registration POST\n if (path === '/auth/register' && method === 'POST' && settings.logging.logRegistrations) {\n if (status === 201 || status === 200) {\n let email = ''\n let userId = ''\n try {\n const cloned = c.res.clone()\n const body = await cloned.json() as any\n email = body?.user?.email || ''\n userId = body?.user?.id || ''\n } catch { /* ignore */ }\n\n await service.logEvent({\n eventType: 'registration',\n severity: 'info',\n userId: userId || undefined,\n email: email || undefined,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n }\n }\n\n // Logout\n if (path === '/auth/logout' && settings.logging.logLogouts) {\n const user = c.get('user')\n await service.logEvent({\n eventType: 'logout',\n severity: 'info',\n userId: user?.userId,\n email: user?.email,\n ipAddress: ip,\n userAgent,\n countryCode: countryCode || undefined,\n requestPath: path,\n requestMethod: method,\n fingerprint\n })\n }\n } catch (error) {\n console.error('[SecurityAudit] Error logging auth event:', error)\n }\n}\n","import { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '../../types'\nimport { securityAuditAdminRoutes } from './routes/admin'\nimport { securityAuditApiRoutes } from './routes/api'\nimport { securityAuditMiddleware } from './middleware/audit-middleware'\n\nexport function createSecurityAuditPlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'security-audit',\n version: '1.0.0-beta.1',\n description: 'Security event logging, brute-force detection, and analytics dashboard'\n })\n\n builder.metadata({\n author: { name: 'SonicJS Team' },\n license: 'MIT'\n })\n\n // Admin dashboard and event log routes\n builder.addRoute('/admin/plugins/security-audit', securityAuditAdminRoutes as any, {\n description: 'Security audit dashboard and admin pages',\n requiresAuth: true,\n priority: 50\n })\n\n // API routes\n builder.addRoute('/api/security-audit', securityAuditApiRoutes as any, {\n description: 'Security audit API endpoints',\n requiresAuth: true,\n priority: 50\n })\n\n // Admin menu item — icon is raw SVG to match sidebar rendering\n builder.addMenuItem('Security', '/admin/plugins/security-audit', {\n icon: `<svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"/></svg>`,\n order: 85\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n install: async (context) => {\n console.log('[SecurityAudit] Plugin installed')\n },\n activate: async (context) => {\n console.log('[SecurityAudit] Plugin activated')\n },\n deactivate: async (context) => {\n console.log('[SecurityAudit] Plugin deactivated')\n },\n uninstall: async (context) => {\n console.log('[SecurityAudit] Plugin uninstalled')\n }\n })\n\n return builder.build()\n}\n\nexport const securityAuditPlugin = createSecurityAuditPlugin()\nexport { SecurityAuditService } from './services/security-audit-service'\nexport { BruteForceDetector } from './services/brute-force-detector'\nexport { securityAuditMiddleware } from './middleware/audit-middleware'\nexport default securityAuditPlugin\n","import type { D1Database } from '@cloudflare/workers-types'\nimport type {\n Subscription,\n SubscriptionInsert,\n SubscriptionFilters,\n SubscriptionStats,\n SubscriptionStatus\n} from '../types'\n\n/**\n * Manages subscription records in D1\n */\nexport class SubscriptionService {\n constructor(private db: D1Database) {}\n\n /**\n * Ensure the subscriptions table exists\n */\n async ensureTable(): Promise<void> {\n await this.db.prepare(`\n CREATE TABLE IF NOT EXISTS subscriptions (\n id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),\n user_id TEXT NOT NULL,\n stripe_customer_id TEXT NOT NULL,\n stripe_subscription_id TEXT NOT NULL UNIQUE,\n stripe_price_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'incomplete',\n current_period_start INTEGER NOT NULL DEFAULT 0,\n current_period_end INTEGER NOT NULL DEFAULT 0,\n cancel_at_period_end INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n updated_at INTEGER NOT NULL DEFAULT (unixepoch())\n )\n `).run()\n\n // Indexes for common lookups\n await this.db.prepare(`\n CREATE INDEX IF NOT EXISTS idx_subscriptions_user_id ON subscriptions(user_id)\n `).run()\n await this.db.prepare(`\n CREATE INDEX IF NOT EXISTS idx_subscriptions_stripe_customer_id ON subscriptions(stripe_customer_id)\n `).run()\n await this.db.prepare(`\n CREATE INDEX IF NOT EXISTS idx_subscriptions_stripe_subscription_id ON subscriptions(stripe_subscription_id)\n `).run()\n await this.db.prepare(`\n CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status)\n `).run()\n }\n\n /**\n * Create a new subscription record\n */\n async create(data: SubscriptionInsert): Promise<Subscription> {\n const result = await this.db.prepare(`\n INSERT INTO subscriptions (user_id, stripe_customer_id, stripe_subscription_id, stripe_price_id, status, current_period_start, current_period_end, cancel_at_period_end)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n RETURNING *\n `).bind(\n data.userId,\n data.stripeCustomerId,\n data.stripeSubscriptionId,\n data.stripePriceId,\n data.status,\n data.currentPeriodStart,\n data.currentPeriodEnd,\n data.cancelAtPeriodEnd ? 1 : 0\n ).first()\n\n return this.mapRow(result as any)\n }\n\n /**\n * Update a subscription by its Stripe subscription ID\n */\n async updateByStripeId(stripeSubscriptionId: string, data: Partial<SubscriptionInsert>): Promise<Subscription | null> {\n const sets: string[] = []\n const values: any[] = []\n\n if (data.status !== undefined) {\n sets.push('status = ?')\n values.push(data.status)\n }\n if (data.stripePriceId !== undefined) {\n sets.push('stripe_price_id = ?')\n values.push(data.stripePriceId)\n }\n if (data.currentPeriodStart !== undefined) {\n sets.push('current_period_start = ?')\n values.push(data.currentPeriodStart)\n }\n if (data.currentPeriodEnd !== undefined) {\n sets.push('current_period_end = ?')\n values.push(data.currentPeriodEnd)\n }\n if (data.cancelAtPeriodEnd !== undefined) {\n sets.push('cancel_at_period_end = ?')\n values.push(data.cancelAtPeriodEnd ? 1 : 0)\n }\n\n if (sets.length === 0) return this.getByStripeSubscriptionId(stripeSubscriptionId)\n\n sets.push('updated_at = unixepoch()')\n values.push(stripeSubscriptionId)\n\n const result = await this.db.prepare(`\n UPDATE subscriptions SET ${sets.join(', ')} WHERE stripe_subscription_id = ? RETURNING *\n `).bind(...values).first()\n\n return result ? this.mapRow(result as any) : null\n }\n\n /**\n * Get subscription by Stripe subscription ID\n */\n async getByStripeSubscriptionId(stripeSubscriptionId: string): Promise<Subscription | null> {\n const result = await this.db.prepare(\n 'SELECT * FROM subscriptions WHERE stripe_subscription_id = ?'\n ).bind(stripeSubscriptionId).first()\n return result ? this.mapRow(result as any) : null\n }\n\n /**\n * Get the active subscription for a user\n */\n async getByUserId(userId: string): Promise<Subscription | null> {\n const result = await this.db.prepare(\n \"SELECT * FROM subscriptions WHERE user_id = ? ORDER BY CASE WHEN status = 'active' THEN 0 WHEN status = 'trialing' THEN 1 ELSE 2 END, updated_at DESC LIMIT 1\"\n ).bind(userId).first()\n return result ? this.mapRow(result as any) : null\n }\n\n /**\n * Get subscription by Stripe customer ID\n */\n async getByStripeCustomerId(stripeCustomerId: string): Promise<Subscription | null> {\n const result = await this.db.prepare(\n 'SELECT * FROM subscriptions WHERE stripe_customer_id = ? ORDER BY updated_at DESC LIMIT 1'\n ).bind(stripeCustomerId).first()\n return result ? this.mapRow(result as any) : null\n }\n\n /**\n * Find the userId linked to a Stripe customer ID\n */\n async getUserIdByStripeCustomer(stripeCustomerId: string): Promise<string | null> {\n const result = await this.db.prepare(\n 'SELECT user_id FROM subscriptions WHERE stripe_customer_id = ? LIMIT 1'\n ).bind(stripeCustomerId).first() as { user_id: string } | null\n return result?.user_id ?? null\n }\n\n /**\n * List subscriptions with filters and pagination\n */\n async list(filters: SubscriptionFilters = {}): Promise<{ subscriptions: Subscription[]; total: number }> {\n const where: string[] = []\n const values: any[] = []\n\n if (filters.status) {\n where.push('status = ?')\n values.push(filters.status)\n }\n if (filters.userId) {\n where.push('user_id = ?')\n values.push(filters.userId)\n }\n if (filters.stripeCustomerId) {\n where.push('stripe_customer_id = ?')\n values.push(filters.stripeCustomerId)\n }\n\n const whereClause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''\n const sortBy = filters.sortBy || 'created_at'\n const sortOrder = filters.sortOrder || 'desc'\n const limit = Math.min(filters.limit || 50, 100)\n const page = filters.page || 1\n const offset = (page - 1) * limit\n\n // Get total count\n const countResult = await this.db.prepare(\n `SELECT COUNT(*) as count FROM subscriptions ${whereClause}`\n ).bind(...values).first() as { count: number }\n\n // Get paginated results\n const results = await this.db.prepare(\n `SELECT s.*, u.email as user_email FROM subscriptions s LEFT JOIN users u ON s.user_id = u.id ${whereClause} ORDER BY ${sortBy} ${sortOrder} LIMIT ? OFFSET ?`\n ).bind(...values, limit, offset).all()\n\n return {\n subscriptions: (results.results || []).map((r: any) => this.mapRow(r)),\n total: countResult?.count || 0\n }\n }\n\n /**\n * Get subscription stats\n */\n async getStats(): Promise<SubscriptionStats> {\n const result = await this.db.prepare(`\n SELECT\n COUNT(*) as total,\n SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active,\n SUM(CASE WHEN status = 'canceled' THEN 1 ELSE 0 END) as canceled,\n SUM(CASE WHEN status = 'past_due' THEN 1 ELSE 0 END) as past_due,\n SUM(CASE WHEN status = 'trialing' THEN 1 ELSE 0 END) as trialing\n FROM subscriptions\n `).first() as any\n\n return {\n total: result?.total || 0,\n active: result?.active || 0,\n canceled: result?.canceled || 0,\n pastDue: result?.past_due || 0,\n trialing: result?.trialing || 0\n }\n }\n\n /**\n * Delete a subscription record by Stripe subscription ID\n */\n async deleteByStripeId(stripeSubscriptionId: string): Promise<boolean> {\n const result = await this.db.prepare(\n 'DELETE FROM subscriptions WHERE stripe_subscription_id = ?'\n ).bind(stripeSubscriptionId).run()\n return (result.meta?.changes || 0) > 0\n }\n\n private mapRow(row: Record<string, any>): Subscription {\n return {\n id: row.id,\n userId: row.user_id,\n stripeCustomerId: row.stripe_customer_id,\n stripeSubscriptionId: row.stripe_subscription_id,\n stripePriceId: row.stripe_price_id,\n status: row.status as SubscriptionStatus,\n currentPeriodStart: row.current_period_start,\n currentPeriodEnd: row.current_period_end,\n cancelAtPeriodEnd: !!row.cancel_at_period_end,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n // Attach email if joined\n ...(row.user_email ? { userEmail: row.user_email } : {})\n } as Subscription\n }\n}\n","import type { Subscription, SubscriptionStats, SubscriptionStatus } from '../types'\n\nexport function renderSubscriptionsPage(\n subscriptions: (Subscription & { userEmail?: string })[],\n stats: SubscriptionStats,\n filters: { status?: string; page: number; totalPages: number }\n): string {\n return `\n <div class=\"space-y-6\">\n <!-- Stats Cards -->\n <div class=\"grid grid-cols-1 md:grid-cols-5 gap-4\">\n ${statsCard('Total', stats.total, 'text-gray-700')}\n ${statsCard('Active', stats.active, 'text-green-600')}\n ${statsCard('Trialing', stats.trialing, 'text-blue-600')}\n ${statsCard('Past Due', stats.pastDue, 'text-yellow-600')}\n ${statsCard('Canceled', stats.canceled, 'text-red-600')}\n </div>\n\n <!-- Filters -->\n <div class=\"bg-white rounded-lg shadow p-4\">\n <form method=\"GET\" class=\"flex items-center gap-4\">\n <label class=\"text-sm font-medium text-gray-700\">Status:</label>\n <select name=\"status\" class=\"border rounded px-3 py-1.5 text-sm\" onchange=\"this.form.submit()\">\n <option value=\"\">All</option>\n ${statusOption('active', filters.status)}\n ${statusOption('trialing', filters.status)}\n ${statusOption('past_due', filters.status)}\n ${statusOption('canceled', filters.status)}\n ${statusOption('unpaid', filters.status)}\n ${statusOption('paused', filters.status)}\n </select>\n </form>\n </div>\n\n <!-- Subscriptions Table -->\n <div class=\"bg-white rounded-lg shadow overflow-hidden\">\n <table class=\"min-w-full divide-y divide-gray-200\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">User</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Status</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Price ID</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Current Period</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Cancel at End</th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider\">Stripe</th>\n </tr>\n </thead>\n <tbody class=\"bg-white divide-y divide-gray-200\">\n ${subscriptions.length === 0\n ? '<tr><td colspan=\"6\" class=\"px-6 py-8 text-center text-gray-500\">No subscriptions found</td></tr>'\n : subscriptions.map(renderRow).join('')\n }\n </tbody>\n </table>\n\n ${renderPagination(filters.page, filters.totalPages, filters.status)}\n </div>\n </div>\n `\n}\n\nfunction statsCard(label: string, value: number, colorClass: string): string {\n return `\n <div class=\"bg-white rounded-lg shadow p-4\">\n <div class=\"text-sm font-medium text-gray-500\">${label}</div>\n <div class=\"text-2xl font-bold ${colorClass}\">${value}</div>\n </div>\n `\n}\n\nfunction statusOption(value: string, current?: string): string {\n const selected = value === current ? 'selected' : ''\n const label = value.replace('_', ' ').replace(/\\b\\w/g, c => c.toUpperCase())\n return `<option value=\"${value}\" ${selected}>${label}</option>`\n}\n\nfunction statusBadge(status: SubscriptionStatus): string {\n const colors: Record<string, string> = {\n active: 'bg-green-100 text-green-800',\n trialing: 'bg-blue-100 text-blue-800',\n past_due: 'bg-yellow-100 text-yellow-800',\n canceled: 'bg-red-100 text-red-800',\n unpaid: 'bg-orange-100 text-orange-800',\n paused: 'bg-gray-100 text-gray-800',\n incomplete: 'bg-gray-100 text-gray-500',\n incomplete_expired: 'bg-red-100 text-red-500'\n }\n const color = colors[status] || 'bg-gray-100 text-gray-800'\n const label = status.replace('_', ' ')\n return `<span class=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${color}\">${label}</span>`\n}\n\nfunction formatDate(timestamp: number): string {\n if (!timestamp) return '-'\n return new Date(timestamp * 1000).toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric'\n })\n}\n\nfunction renderRow(sub: Subscription & { userEmail?: string }): string {\n return `\n <tr>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <div class=\"text-sm font-medium text-gray-900\">${sub.userEmail || sub.userId}</div>\n <div class=\"text-xs text-gray-500\">${sub.stripeCustomerId}</div>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">${statusBadge(sub.status)}</td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\">${sub.stripePriceId}</td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-500\">\n ${formatDate(sub.currentPeriodStart)} - ${formatDate(sub.currentPeriodEnd)}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm\">\n ${sub.cancelAtPeriodEnd\n ? '<span class=\"text-yellow-600 font-medium\">Yes</span>'\n : '<span class=\"text-gray-400\">No</span>'\n }\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm\">\n <a href=\"https://dashboard.stripe.com/subscriptions/${sub.stripeSubscriptionId}\"\n target=\"_blank\" rel=\"noopener noreferrer\"\n class=\"text-indigo-600 hover:text-indigo-800\">\n View in Stripe\n </a>\n </td>\n </tr>\n `\n}\n\nfunction renderPagination(page: number, totalPages: number, status?: string): string {\n if (totalPages <= 1) return ''\n\n const params = status ? `&status=${status}` : ''\n return `\n <div class=\"bg-white px-4 py-3 flex items-center justify-between border-t border-gray-200 sm:px-6\">\n <div class=\"text-sm text-gray-700\">\n Page ${page} of ${totalPages}\n </div>\n <div class=\"flex gap-2\">\n ${page > 1\n ? `<a href=\"?page=${page - 1}${params}\" class=\"px-3 py-1 border rounded text-sm hover:bg-gray-50\">Previous</a>`\n : ''\n }\n ${page < totalPages\n ? `<a href=\"?page=${page + 1}${params}\" class=\"px-3 py-1 border rounded text-sm hover:bg-gray-50\">Next</a>`\n : ''\n }\n </div>\n </div>\n `\n}\n","// ============================================================================\n// Stripe Plugin Types\n// ============================================================================\n\nexport type SubscriptionStatus =\n | 'active'\n | 'canceled'\n | 'past_due'\n | 'trialing'\n | 'unpaid'\n | 'paused'\n | 'incomplete'\n | 'incomplete_expired'\n\nexport interface Subscription {\n id: string\n userId: string\n stripeCustomerId: string\n stripeSubscriptionId: string\n stripePriceId: string\n status: SubscriptionStatus\n currentPeriodStart: number\n currentPeriodEnd: number\n cancelAtPeriodEnd: boolean\n createdAt: number\n updatedAt: number\n}\n\nexport interface SubscriptionInsert {\n userId: string\n stripeCustomerId: string\n stripeSubscriptionId: string\n stripePriceId: string\n status: SubscriptionStatus\n currentPeriodStart: number\n currentPeriodEnd: number\n cancelAtPeriodEnd?: boolean\n}\n\nexport interface SubscriptionFilters {\n status?: SubscriptionStatus\n userId?: string\n stripeCustomerId?: string\n page?: number\n limit?: number\n sortBy?: 'created_at' | 'updated_at' | 'status'\n sortOrder?: 'asc' | 'desc'\n}\n\nexport interface SubscriptionStats {\n total: number\n active: number\n canceled: number\n pastDue: number\n trialing: number\n}\n\nexport interface StripePluginSettings {\n stripeSecretKey: string\n stripeWebhookSecret: string\n stripePriceId?: string\n successUrl: string\n cancelUrl: string\n}\n\nexport const DEFAULT_SETTINGS: StripePluginSettings = {\n stripeSecretKey: '',\n stripeWebhookSecret: '',\n stripePriceId: '',\n successUrl: '/admin/dashboard',\n cancelUrl: '/admin/dashboard'\n}\n\n// Stripe webhook event types we handle\nexport type StripeWebhookEventType =\n | 'customer.subscription.created'\n | 'customer.subscription.updated'\n | 'customer.subscription.deleted'\n | 'checkout.session.completed'\n | 'invoice.payment_succeeded'\n | 'invoice.payment_failed'\n\n// Minimal Stripe types (we use fetch, not the SDK)\nexport interface StripeEvent {\n id: string\n type: string\n data: {\n object: Record<string, any>\n }\n}\n\nexport interface StripeSubscriptionObject {\n id: string\n customer: string\n status: string\n items: {\n data: Array<{\n price: {\n id: string\n }\n }>\n }\n current_period_start: number\n current_period_end: number\n cancel_at_period_end: boolean\n metadata?: Record<string, string>\n}\n\nexport interface StripeCheckoutSession {\n id: string\n customer: string\n subscription: string\n metadata?: Record<string, string>\n}\n\nexport interface StripeInvoice {\n id: string\n customer: string\n subscription: string | null\n status: string\n amount_paid: number\n currency: string\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { PluginService } from '../../../../services'\nimport { SubscriptionService } from '../services/subscription-service'\nimport { renderSubscriptionsPage } from '../components/subscriptions-page'\nimport type { Bindings, Variables } from '../../../../app'\nimport type { StripePluginSettings, SubscriptionStatus } from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst adminRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\nadminRoutes.use('*', requireAuth())\n\n// Check admin role\nadminRoutes.use('*', async (c, next) => {\n const user = c.get('user')\n if (user?.role !== 'admin') {\n return c.text('Access denied', 403)\n }\n return next()\n})\n\nasync function getSettings(db: any): Promise<StripePluginSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('stripe')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\n// Subscriptions dashboard\nadminRoutes.get('/', async (c) => {\n const db = c.env.DB\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n const page = parseInt(c.req.query('page') || '1')\n const limit = 50\n const statusFilter = c.req.query('status') as SubscriptionStatus | undefined\n\n const [{ subscriptions, total }, stats] = await Promise.all([\n subscriptionService.list({ status: statusFilter, page, limit }),\n subscriptionService.getStats()\n ])\n\n const totalPages = Math.ceil(total / limit)\n\n const html = renderSubscriptionsPage(subscriptions as any, stats, {\n status: statusFilter,\n page,\n totalPages\n })\n\n return c.html(html)\n})\n\n// Save settings\nadminRoutes.post('/settings', async (c) => {\n try {\n const body = await c.req.json()\n const db = c.env.DB\n\n await db.prepare(`\n UPDATE plugins\n SET settings = ?,\n updated_at = unixepoch()\n WHERE id = 'stripe'\n `).bind(JSON.stringify(body)).run()\n\n return c.json({ success: true })\n } catch (error) {\n console.error('Error saving Stripe settings:', error)\n return c.json({ success: false, error: 'Failed to save settings' }, 500)\n }\n})\n\nexport { adminRoutes as stripeAdminRoutes }\n","import type { StripePluginSettings } from '../types'\n\n/**\n * Lightweight Stripe API client using fetch (CF Workers compatible, no SDK needed)\n */\nexport class StripeAPI {\n private baseUrl = 'https://api.stripe.com/v1'\n\n constructor(private secretKey: string) {}\n\n /**\n * Verify a webhook signature\n * Implements Stripe's v1 signature scheme using Web Crypto API\n */\n async verifyWebhookSignature(payload: string, sigHeader: string, secret: string): Promise<boolean> {\n const parts = sigHeader.split(',')\n const timestamp = parts.find(p => p.startsWith('t='))?.split('=')[1]\n const signatures = parts\n .filter(p => p.startsWith('v1='))\n .map(p => p.substring(3))\n\n if (!timestamp || signatures.length === 0) return false\n\n // Reject events older than 5 minutes (tolerance)\n const now = Math.floor(Date.now() / 1000)\n if (Math.abs(now - parseInt(timestamp)) > 300) return false\n\n // Compute expected signature\n const signedPayload = `${timestamp}.${payload}`\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n )\n const signatureBuffer = await crypto.subtle.sign('HMAC', key, encoder.encode(signedPayload))\n const expectedSignature = Array.from(new Uint8Array(signatureBuffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n\n return signatures.some(sig => timingSafeEqual(sig, expectedSignature))\n }\n\n /**\n * Create a Checkout Session\n */\n async createCheckoutSession(params: {\n priceId: string\n customerId?: string\n customerEmail?: string\n successUrl: string\n cancelUrl: string\n metadata?: Record<string, string>\n }): Promise<{ id: string; url: string }> {\n const body = new URLSearchParams()\n body.append('mode', 'subscription')\n body.append('line_items[0][price]', params.priceId)\n body.append('line_items[0][quantity]', '1')\n body.append('success_url', params.successUrl)\n body.append('cancel_url', params.cancelUrl)\n\n if (params.customerId) {\n body.append('customer', params.customerId)\n } else if (params.customerEmail) {\n body.append('customer_email', params.customerEmail)\n }\n\n if (params.metadata) {\n for (const [key, value] of Object.entries(params.metadata)) {\n body.append(`metadata[${key}]`, value)\n }\n }\n\n const response = await this.request('POST', '/checkout/sessions', body)\n return { id: response.id, url: response.url }\n }\n\n /**\n * Retrieve a Stripe subscription\n */\n async getSubscription(subscriptionId: string): Promise<any> {\n return this.request('GET', `/subscriptions/${subscriptionId}`)\n }\n\n /**\n * Create a Stripe customer\n */\n async createCustomer(params: { email: string; metadata?: Record<string, string> }): Promise<{ id: string }> {\n const body = new URLSearchParams()\n body.append('email', params.email)\n if (params.metadata) {\n for (const [key, value] of Object.entries(params.metadata)) {\n body.append(`metadata[${key}]`, value)\n }\n }\n return this.request('POST', '/customers', body)\n }\n\n /**\n * Search for a customer by email\n */\n async findCustomerByEmail(email: string): Promise<{ id: string } | null> {\n const params = new URLSearchParams()\n params.append('query', `email:'${email}'`)\n params.append('limit', '1')\n const result = await this.request('GET', `/customers/search?${params.toString()}`)\n return result.data?.[0] || null\n }\n\n private async request(method: string, path: string, body?: URLSearchParams): Promise<any> {\n const url = path.startsWith('http') ? path : `${this.baseUrl}${path}`\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${this.secretKey}`,\n ...(body ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {})\n },\n ...(body ? { body: body.toString() } : {})\n })\n\n const data = await response.json() as any\n if (!response.ok) {\n throw new Error(`Stripe API error: ${data.error?.message || response.statusText}`)\n }\n return data\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks on signature verification\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false\n let result = 0\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\n }\n return result === 0\n}\n","import { Hono } from 'hono'\nimport { requireAuth } from '../../../../middleware'\nimport { PluginService } from '../../../../services'\nimport { SubscriptionService } from '../services/subscription-service'\nimport { StripeAPI } from '../services/stripe-api'\nimport type { Bindings, Variables } from '../../../../app'\nimport type {\n StripePluginSettings,\n StripeEvent,\n StripeSubscriptionObject,\n StripeCheckoutSession,\n StripeInvoice,\n SubscriptionStatus,\n SubscriptionFilters\n} from '../types'\nimport { DEFAULT_SETTINGS } from '../types'\n\nconst apiRoutes = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nasync function getSettings(db: any): Promise<StripePluginSettings> {\n try {\n const pluginService = new PluginService(db)\n const plugin = await pluginService.getPlugin('stripe')\n if (plugin?.settings) {\n const settings = typeof plugin.settings === 'string' ? JSON.parse(plugin.settings) : plugin.settings\n return { ...DEFAULT_SETTINGS, ...settings }\n }\n } catch { /* ignore */ }\n return DEFAULT_SETTINGS\n}\n\nfunction mapStripeStatus(status: string): SubscriptionStatus {\n const map: Record<string, SubscriptionStatus> = {\n active: 'active',\n canceled: 'canceled',\n past_due: 'past_due',\n trialing: 'trialing',\n unpaid: 'unpaid',\n paused: 'paused',\n incomplete: 'incomplete',\n incomplete_expired: 'incomplete_expired'\n }\n return map[status] || 'incomplete'\n}\n\n// ============================================================================\n// Webhook — No auth, verified by Stripe signature\n// ============================================================================\n\napiRoutes.post('/webhook', async (c) => {\n const db = c.env.DB\n const settings = await getSettings(db)\n\n if (!settings.stripeWebhookSecret) {\n return c.json({ error: 'Webhook secret not configured' }, 500)\n }\n\n // Must read raw body for signature verification\n const rawBody = await c.req.text()\n const sigHeader = c.req.header('stripe-signature') || ''\n\n const stripeApi = new StripeAPI(settings.stripeSecretKey)\n const isValid = await stripeApi.verifyWebhookSignature(rawBody, sigHeader, settings.stripeWebhookSecret)\n\n if (!isValid) {\n return c.json({ error: 'Invalid signature' }, 400)\n }\n\n const event: StripeEvent = JSON.parse(rawBody)\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n try {\n switch (event.type) {\n case 'customer.subscription.created': {\n const sub = event.data.object as unknown as StripeSubscriptionObject\n const userId = sub.metadata?.sonicjs_user_id || await subscriptionService.getUserIdByStripeCustomer(sub.customer) || ''\n\n await subscriptionService.create({\n userId,\n stripeCustomerId: sub.customer,\n stripeSubscriptionId: sub.id,\n stripePriceId: sub.items.data[0]?.price.id || '',\n status: mapStripeStatus(sub.status),\n currentPeriodStart: sub.current_period_start,\n currentPeriodEnd: sub.current_period_end,\n cancelAtPeriodEnd: sub.cancel_at_period_end\n })\n\n console.log(`[Stripe] Subscription created: ${sub.id}`)\n break\n }\n\n case 'customer.subscription.updated': {\n const sub = event.data.object as unknown as StripeSubscriptionObject\n await subscriptionService.updateByStripeId(sub.id, {\n status: mapStripeStatus(sub.status),\n stripePriceId: sub.items.data[0]?.price.id || undefined,\n currentPeriodStart: sub.current_period_start,\n currentPeriodEnd: sub.current_period_end,\n cancelAtPeriodEnd: sub.cancel_at_period_end\n })\n\n console.log(`[Stripe] Subscription updated: ${sub.id} -> ${sub.status}`)\n break\n }\n\n case 'customer.subscription.deleted': {\n const sub = event.data.object as unknown as StripeSubscriptionObject\n await subscriptionService.updateByStripeId(sub.id, {\n status: 'canceled'\n })\n\n console.log(`[Stripe] Subscription deleted: ${sub.id}`)\n break\n }\n\n case 'checkout.session.completed': {\n const session = event.data.object as unknown as StripeCheckoutSession\n const userId = session.metadata?.sonicjs_user_id\n\n // Link the Stripe customer to the user if we have a userId and subscription\n if (userId && session.subscription) {\n const existing = await subscriptionService.getByStripeSubscriptionId(session.subscription)\n if (existing && !existing.userId) {\n await subscriptionService.updateByStripeId(session.subscription, {\n userId\n } as any)\n }\n }\n\n console.log(`[Stripe] Checkout completed: ${session.id}`)\n break\n }\n\n case 'invoice.payment_succeeded': {\n const invoice = event.data.object as unknown as StripeInvoice\n if (invoice.subscription) {\n await subscriptionService.updateByStripeId(invoice.subscription, {\n status: 'active'\n })\n }\n console.log(`[Stripe] Payment succeeded for invoice: ${invoice.id}`)\n break\n }\n\n case 'invoice.payment_failed': {\n const invoice = event.data.object as unknown as StripeInvoice\n if (invoice.subscription) {\n await subscriptionService.updateByStripeId(invoice.subscription, {\n status: 'past_due'\n })\n }\n console.log(`[Stripe] Payment failed for invoice: ${invoice.id}`)\n break\n }\n\n default:\n console.log(`[Stripe] Unhandled event type: ${event.type}`)\n }\n } catch (error) {\n console.error(`[Stripe] Error processing webhook event ${event.type}:`, error)\n return c.json({ error: 'Webhook processing failed' }, 500)\n }\n\n return c.json({ received: true })\n})\n\n// ============================================================================\n// Authenticated API Routes\n// ============================================================================\n\n// Create checkout session for current user\napiRoutes.post('/create-checkout-session', requireAuth(), async (c) => {\n const db = c.env.DB\n const user = c.get('user')\n if (!user) return c.json({ error: 'Unauthorized' }, 401)\n\n const settings = await getSettings(db)\n if (!settings.stripeSecretKey) {\n return c.json({ error: 'Stripe not configured' }, 500)\n }\n\n const body = await c.req.json().catch(() => ({})) as { priceId?: string }\n const priceId = body.priceId || settings.stripePriceId\n if (!priceId) {\n return c.json({ error: 'No price ID specified' }, 400)\n }\n\n const stripeApi = new StripeAPI(settings.stripeSecretKey)\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n // Check if user already has a Stripe customer ID\n const existingSub = await subscriptionService.getByUserId(user.userId)\n let customerId = existingSub?.stripeCustomerId\n\n if (!customerId) {\n // Try to find existing customer by email, or create one\n const existing = await stripeApi.findCustomerByEmail(user.email)\n if (existing) {\n customerId = existing.id\n } else {\n const customer = await stripeApi.createCustomer({\n email: user.email,\n metadata: { sonicjs_user_id: user.userId }\n })\n customerId = customer.id\n }\n }\n\n const origin = new URL(c.req.url).origin\n const session = await stripeApi.createCheckoutSession({\n priceId,\n customerId,\n successUrl: `${origin}${settings.successUrl}?session_id={CHECKOUT_SESSION_ID}`,\n cancelUrl: `${origin}${settings.cancelUrl}`,\n metadata: { sonicjs_user_id: user.userId }\n })\n\n return c.json({ sessionId: session.id, url: session.url })\n})\n\n// Get current user's subscription\napiRoutes.get('/subscription', requireAuth(), async (c) => {\n const user = c.get('user')\n if (!user) return c.json({ error: 'Unauthorized' }, 401)\n\n const db = c.env.DB\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n const subscription = await subscriptionService.getByUserId(user.userId)\n if (!subscription) {\n return c.json({ subscription: null })\n }\n\n return c.json({ subscription })\n})\n\n// ============================================================================\n// Admin API Routes\n// ============================================================================\n\n// List all subscriptions (admin only)\napiRoutes.get('/subscriptions', requireAuth(), async (c) => {\n const user = c.get('user')\n if (user?.role !== 'admin') return c.json({ error: 'Access denied' }, 403)\n\n const db = c.env.DB\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n const filters: SubscriptionFilters = {\n status: c.req.query('status') as SubscriptionStatus | undefined,\n page: c.req.query('page') ? parseInt(c.req.query('page')!) : 1,\n limit: c.req.query('limit') ? parseInt(c.req.query('limit')!) : 50,\n sortBy: (c.req.query('sortBy') as any) || 'created_at',\n sortOrder: (c.req.query('sortOrder') as any) || 'desc'\n }\n\n const result = await subscriptionService.list(filters)\n return c.json(result)\n})\n\n// Get subscription stats (admin only)\napiRoutes.get('/stats', requireAuth(), async (c) => {\n const user = c.get('user')\n if (user?.role !== 'admin') return c.json({ error: 'Access denied' }, 403)\n\n const db = c.env.DB\n const subscriptionService = new SubscriptionService(db)\n await subscriptionService.ensureTable()\n\n const stats = await subscriptionService.getStats()\n return c.json(stats)\n})\n\nexport { apiRoutes as stripeApiRoutes }\n","import { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '../../types'\nimport { stripeAdminRoutes } from './routes/admin'\nimport { stripeApiRoutes } from './routes/api'\n\nexport function createStripePlugin(): Plugin {\n const builder = PluginBuilder.create({\n name: 'stripe',\n version: '1.0.0-beta.1',\n description: 'Stripe subscription management with webhook handling, checkout sessions, and subscription gating'\n })\n\n builder.metadata({\n author: { name: 'SonicJS Team' },\n license: 'MIT'\n })\n\n // Admin dashboard — subscription management\n builder.addRoute('/admin/plugins/stripe', stripeAdminRoutes as any, {\n description: 'Stripe subscriptions admin dashboard',\n requiresAuth: true,\n priority: 50\n })\n\n // API routes — webhook, checkout, subscription status\n builder.addRoute('/api/stripe', stripeApiRoutes as any, {\n description: 'Stripe API endpoints (webhook, checkout, subscription)',\n requiresAuth: false, // Webhook route handles its own auth via signature\n priority: 50\n })\n\n // Admin menu item\n builder.addMenuItem('Stripe', '/admin/plugins/stripe', {\n icon: `<svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z\"/></svg>`,\n order: 75\n })\n\n // Lifecycle hooks\n builder.lifecycle({\n install: async () => {\n console.log('[Stripe] Plugin installed')\n },\n activate: async () => {\n console.log('[Stripe] Plugin activated')\n },\n deactivate: async () => {\n console.log('[Stripe] Plugin deactivated')\n },\n uninstall: async () => {\n console.log('[Stripe] Plugin uninstalled')\n }\n })\n\n return builder.build()\n}\n\nexport const stripePlugin = createStripePlugin()\nexport { SubscriptionService } from './services/subscription-service'\nexport { StripeAPI } from './services/stripe-api'\nexport { requireSubscription } from './middleware/require-subscription'\nexport default stripePlugin\n","import type { Context, Next } from 'hono'\nimport type { Bindings, Variables } from '../app'\nimport type { Plugin } from '../plugins/types'\n\n// All plugins that define menu items. The single source of truth for menu config\n// is each plugin's addMenuItem() call — this array just lists which plugins to check.\nimport { securityAuditPlugin } from '../plugins/core-plugins/security-audit-plugin'\n\nconst MENU_PLUGINS: Plugin[] = [\n securityAuditPlugin,\n]\n\nconst MARKER = '<!-- DYNAMIC_PLUGIN_MENU -->'\n\nfunction renderMenuItem(item: { label: string; path: string; icon?: string }, currentPath: string): string {\n const isActive = currentPath === item.path || currentPath.startsWith(item.path)\n const fallbackIcon = `<svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 10V3L4 14h7v7l9-11h-7z\"/></svg>`\n return `\n <span class=\"relative\">\n ${isActive ? '<span class=\"absolute inset-y-2 -left-4 w-0.5 rounded-full bg-cyan-500 dark:bg-cyan-400\"></span>' : ''}\n <a\n href=\"${item.path}\"\n class=\"flex w-full items-center gap-3 rounded-lg px-2 py-2.5 text-left text-sm/5 font-medium ${\n isActive\n ? 'text-zinc-950 dark:text-white'\n : 'text-zinc-950 hover:bg-zinc-950/5 dark:text-white dark:hover:bg-white/5'\n }\"\n ${isActive ? 'data-current=\"true\"' : ''}\n >\n <span class=\"shrink-0 ${isActive ? 'fill-zinc-950 dark:fill-white' : 'fill-zinc-500 dark:fill-zinc-400'}\">\n ${item.icon || fallbackIcon}\n </span>\n <span class=\"truncate\">${item.label}</span>\n </a>\n </span>`\n}\n\nexport function pluginMenuMiddleware() {\n return async (c: Context<{ Bindings: Bindings; Variables: Variables }>, next: Next) => {\n const path = new URL(c.req.url).pathname\n if (!path.startsWith('/admin')) {\n return next()\n }\n\n // Collect menu items from active plugins\n let activeMenuItems: Array<{ label: string; path: string; icon?: string }> = []\n try {\n const db = c.env.DB\n const pluginNames = MENU_PLUGINS.map(p => p.name)\n if (pluginNames.length > 0) {\n const placeholders = pluginNames.map(() => '?').join(',')\n const result = await db.prepare(\n `SELECT name FROM plugins WHERE name IN (${placeholders}) AND status = 'active'`\n ).bind(...pluginNames).all()\n\n const activeNames = new Set((result.results || []).map((r: any) => r.name))\n\n for (const plugin of MENU_PLUGINS) {\n if (activeNames.has(plugin.name) && plugin.menuItems) {\n activeMenuItems.push(...plugin.menuItems)\n }\n }\n\n // Sort by order\n activeMenuItems.sort((a, b) => ((a as any).order || 0) - ((b as any).order || 0))\n }\n } catch {\n // DB not ready or plugin table doesn't exist yet\n }\n\n c.set('pluginMenuItems', activeMenuItems.map(m => ({ label: m.label, path: m.path, icon: m.icon || '' })))\n\n await next()\n\n // Inject menu items into HTML response by replacing the marker\n if (activeMenuItems.length > 0 && c.res.headers.get('content-type')?.includes('text/html')) {\n const status = c.res.status\n const headers = new Headers(c.res.headers)\n const html = await c.res.text()\n\n if (html.includes(MARKER)) {\n const renderedItems = activeMenuItems.map(item => renderMenuItem(item, path)).join('')\n const newHtml = html.split(MARKER).join(renderedItems)\n c.res = new Response(newHtml, { status, headers })\n } else {\n // Body was consumed by .text(), must create new Response either way\n c.res = new Response(html, { status, headers })\n }\n }\n }\n}\n","/**\n * Cache Configuration\n *\n * Defines cache configurations for different entity types\n */\n\nexport interface CacheConfig {\n ttl: number // Time-to-live in seconds\n kvEnabled: boolean // Use KV cache tier\n memoryEnabled: boolean // Use in-memory cache tier\n namespace: string // Cache namespace/prefix\n invalidateOn: string[] // Events that invalidate this cache\n version?: string // Cache version for busting\n}\n\nexport interface CacheStats {\n memoryHits: number\n memoryMisses: number\n kvHits: number\n kvMisses: number\n dbHits: number\n totalRequests: number\n hitRate: number\n memorySize: number\n entryCount: number\n}\n\n/**\n * Default cache configurations by entity type\n */\nexport const CACHE_CONFIGS: Record<string, CacheConfig> = {\n // Content (high read, low write)\n content: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'content',\n invalidateOn: ['content.update', 'content.delete', 'content.publish'],\n version: 'v1'\n },\n\n // User data (medium read, medium write)\n user: {\n ttl: 900, // 15 minutes\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'user',\n invalidateOn: ['user.update', 'user.delete', 'auth.login'],\n version: 'v1'\n },\n\n // Configuration (high read, very low write)\n config: {\n ttl: 7200, // 2 hours\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'config',\n invalidateOn: ['config.update', 'plugin.activate', 'plugin.deactivate'],\n version: 'v1'\n },\n\n // Media metadata (high read, low write)\n media: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'media',\n invalidateOn: ['media.upload', 'media.delete', 'media.update'],\n version: 'v1'\n },\n\n // API responses (very high read, low write)\n api: {\n ttl: 300, // 5 minutes\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'api',\n invalidateOn: ['content.update', 'content.publish'],\n version: 'v1'\n },\n\n // Session data (very high read, medium write)\n session: {\n ttl: 1800, // 30 minutes\n kvEnabled: false, // Only in-memory for sessions\n memoryEnabled: true,\n namespace: 'session',\n invalidateOn: ['auth.logout'],\n version: 'v1'\n },\n\n // Plugin data\n plugin: {\n ttl: 3600, // 1 hour\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'plugin',\n invalidateOn: ['plugin.activate', 'plugin.deactivate', 'plugin.update'],\n version: 'v1'\n },\n\n // Collections/schema\n collection: {\n ttl: 7200, // 2 hours\n kvEnabled: true,\n memoryEnabled: true,\n namespace: 'collection',\n invalidateOn: ['collection.update', 'collection.delete'],\n version: 'v1'\n }\n}\n\n/**\n * Get cache configuration for a specific namespace\n */\nexport function getCacheConfig(namespace: string): CacheConfig {\n return CACHE_CONFIGS[namespace] || {\n ttl: 3600,\n kvEnabled: true,\n memoryEnabled: true,\n namespace,\n invalidateOn: [],\n version: 'v1'\n }\n}\n\n/**\n * Generate a cache key with consistent format\n * Format: {namespace}:{type}:{identifier}:{version}\n */\nexport function generateCacheKey(\n namespace: string,\n type: string,\n identifier: string,\n version?: string\n): string {\n const v = version || getCacheConfig(namespace).version || 'v1'\n return `${namespace}:${type}:${identifier}:${v}`\n}\n\n/**\n * Parse a cache key back into its components\n */\nexport function parseCacheKey(key: string): {\n namespace: string\n type: string\n identifier: string\n version: string\n} | null {\n const parts = key.split(':')\n if (parts.length !== 4) {\n return null\n }\n\n return {\n namespace: parts[0] || '',\n type: parts[1] || '',\n identifier: parts[2] || '',\n version: parts[3] || ''\n }\n}\n\n/**\n * Generate a hash for complex query parameters\n */\nexport function hashQueryParams(params: Record<string, any>): string {\n // Sort keys for consistent hashing\n const sortedKeys = Object.keys(params).sort()\n const normalized = sortedKeys.map(key => `${key}=${params[key]}`).join('&')\n\n // Simple hash function (for better performance, consider using crypto)\n let hash = 0\n for (let i = 0; i < normalized.length; i++) {\n const char = normalized.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32-bit integer\n }\n\n return Math.abs(hash).toString(36)\n}\n\n/**\n * Create a pattern for cache invalidation\n */\nexport function createCachePattern(\n namespace: string,\n type?: string,\n identifier?: string\n): string {\n let pattern = namespace\n if (type) pattern += `:${type}`\n if (identifier) pattern += `:${identifier}`\n return pattern + ':*'\n}\n","/**\n * Cache Service\n *\n * Three-tiered caching implementation:\n * 1. In-Memory Cache (fastest, region-specific)\n * 2. Cloudflare KV Cache (fast, global)\n * 3. Database (fallback, source of truth)\n */\n\nimport { CacheConfig, CacheStats, generateCacheKey } from './cache-config.js'\n\n/**\n * Cache entry with metadata\n */\ninterface CacheEntry<T> {\n data: T\n timestamp: number\n expiresAt: number\n version: string\n}\n\n/**\n * In-memory cache store\n */\nclass MemoryCache {\n private cache: Map<string, CacheEntry<any>> = new Map()\n private maxSize: number = 50 * 1024 * 1024 // 50MB\n private currentSize: number = 0\n\n /**\n * Get item from memory cache\n */\n get<T>(key: string): T | null {\n const entry = this.cache.get(key)\n\n if (!entry) {\n return null\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n this.delete(key)\n return null\n }\n\n return entry.data as T\n }\n\n /**\n * Set item in memory cache\n */\n set<T>(key: string, value: T, ttl: number, version: string = 'v1'): void {\n const now = Date.now()\n const entry: CacheEntry<T> = {\n data: value,\n timestamp: now,\n expiresAt: now + (ttl * 1000),\n version\n }\n\n // Estimate size (rough approximation)\n const entrySize = JSON.stringify(entry).length * 2 // UTF-16\n\n // Check if we need to evict\n if (this.currentSize + entrySize > this.maxSize) {\n this.evictLRU(entrySize)\n }\n\n // Delete old entry if exists\n if (this.cache.has(key)) {\n this.delete(key)\n }\n\n this.cache.set(key, entry)\n this.currentSize += entrySize\n }\n\n /**\n * Delete item from memory cache\n */\n delete(key: string): boolean {\n const entry = this.cache.get(key)\n if (entry) {\n const entrySize = JSON.stringify(entry).length * 2\n this.currentSize -= entrySize\n return this.cache.delete(key)\n }\n return false\n }\n\n /**\n * Clear all items from memory cache\n */\n clear(): void {\n this.cache.clear()\n this.currentSize = 0\n }\n\n /**\n * Get cache statistics\n */\n getStats(): { size: number; count: number } {\n return {\n size: this.currentSize,\n count: this.cache.size\n }\n }\n\n /**\n * Evict least recently used items to make space\n */\n private evictLRU(neededSpace: number): void {\n // Sort by timestamp (oldest first)\n const entries = Array.from(this.cache.entries()).sort(\n (a, b) => a[1].timestamp - b[1].timestamp\n )\n\n let freedSpace = 0\n for (const [key, entry] of entries) {\n if (freedSpace >= neededSpace) break\n\n const entrySize = JSON.stringify(entry).length * 2\n this.delete(key)\n freedSpace += entrySize\n }\n }\n\n /**\n * Delete items matching a pattern\n */\n invalidatePattern(pattern: string): number {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n )\n\n let count = 0\n for (const key of this.cache.keys()) {\n if (regex.test(key)) {\n this.delete(key)\n count++\n }\n }\n\n return count\n }\n}\n\n/**\n * Cache result with source information\n */\nexport interface CacheResult<T> {\n data: T | null\n source: 'memory' | 'kv' | 'miss'\n hit: boolean\n timestamp?: number\n ttl?: number\n}\n\n/**\n * Main cache service with multi-tier support\n */\nexport class CacheService {\n private memoryCache: MemoryCache\n private config: CacheConfig\n private stats: CacheStats\n private kvNamespace?: KVNamespace\n\n constructor(config: CacheConfig, kvNamespace?: KVNamespace) {\n this.memoryCache = new MemoryCache()\n this.config = config\n this.kvNamespace = kvNamespace\n this.stats = {\n memoryHits: 0,\n memoryMisses: 0,\n kvHits: 0,\n kvMisses: 0,\n dbHits: 0,\n totalRequests: 0,\n hitRate: 0,\n memorySize: 0,\n entryCount: 0\n }\n }\n\n /**\n * Get value from cache (tries memory first, then KV)\n */\n async get<T>(key: string): Promise<T | null> {\n this.stats.totalRequests++\n\n // Try memory cache first (Tier 1)\n if (this.config.memoryEnabled) {\n const memoryValue = this.memoryCache.get<T>(key)\n if (memoryValue !== null) {\n this.stats.memoryHits++\n this.updateHitRate()\n return memoryValue\n }\n this.stats.memoryMisses++\n }\n\n // Try KV cache (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const kvValue = await this.kvNamespace.get(key, 'json')\n if (kvValue !== null) {\n this.stats.kvHits++\n\n // Populate memory cache for faster subsequent access\n if (this.config.memoryEnabled) {\n this.memoryCache.set(key, kvValue as T, this.config.ttl, this.config.version)\n }\n\n this.updateHitRate()\n return kvValue as T\n }\n this.stats.kvMisses++\n } catch (error) {\n console.error('KV cache read error:', error)\n this.stats.kvMisses++\n }\n }\n\n this.updateHitRate()\n return null\n }\n\n /**\n * Get value from cache with source information\n */\n async getWithSource<T>(key: string): Promise<CacheResult<T>> {\n this.stats.totalRequests++\n\n // Try memory cache first (Tier 1)\n if (this.config.memoryEnabled) {\n const memoryValue = this.memoryCache.get<T>(key)\n if (memoryValue !== null) {\n this.stats.memoryHits++\n this.updateHitRate()\n\n const entry = await this.getEntry<T>(key)\n return {\n data: memoryValue,\n source: 'memory',\n hit: true,\n timestamp: entry?.timestamp,\n ttl: entry?.ttl\n }\n }\n this.stats.memoryMisses++\n }\n\n // Try KV cache (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const kvValue = await this.kvNamespace.get(key, 'json')\n if (kvValue !== null) {\n this.stats.kvHits++\n\n // Populate memory cache for faster subsequent access\n if (this.config.memoryEnabled) {\n this.memoryCache.set(key, kvValue as T, this.config.ttl, this.config.version)\n }\n\n this.updateHitRate()\n return {\n data: kvValue as T,\n source: 'kv',\n hit: true\n }\n }\n this.stats.kvMisses++\n } catch (error) {\n console.error('KV cache read error:', error)\n this.stats.kvMisses++\n }\n }\n\n this.updateHitRate()\n return {\n data: null,\n source: 'miss',\n hit: false\n }\n }\n\n /**\n * Set value in cache (stores in both memory and KV)\n */\n async set<T>(\n key: string,\n value: T,\n customConfig?: Partial<CacheConfig>\n ): Promise<void> {\n const config = { ...this.config, ...customConfig }\n\n // Store in memory cache (Tier 1)\n if (config.memoryEnabled) {\n this.memoryCache.set(key, value, config.ttl, config.version)\n }\n\n // Store in KV cache (Tier 2)\n if (config.kvEnabled && this.kvNamespace) {\n try {\n await this.kvNamespace.put(key, JSON.stringify(value), {\n expirationTtl: config.ttl\n })\n } catch (error) {\n console.error('KV cache write error:', error)\n }\n }\n }\n\n /**\n * Delete value from cache (removes from both memory and KV)\n */\n async delete(key: string): Promise<void> {\n // Delete from memory (Tier 1)\n if (this.config.memoryEnabled) {\n this.memoryCache.delete(key)\n }\n\n // Delete from KV (Tier 2)\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n await this.kvNamespace.delete(key)\n } catch (error) {\n console.error('KV cache delete error:', error)\n }\n }\n }\n\n /**\n * Clear all cache entries for this namespace\n */\n async clear(): Promise<void> {\n if (this.config.memoryEnabled) {\n this.memoryCache.clear()\n }\n\n // Reset stats\n this.stats = {\n memoryHits: 0,\n memoryMisses: 0,\n kvHits: 0,\n kvMisses: 0,\n dbHits: 0,\n totalRequests: 0,\n hitRate: 0,\n memorySize: 0,\n entryCount: 0\n }\n }\n\n /**\n * Invalidate cache entries matching a pattern\n */\n async invalidate(pattern: string): Promise<number> {\n let count = 0\n\n // Invalidate from memory (Tier 1)\n if (this.config.memoryEnabled) {\n count += this.memoryCache.invalidatePattern(pattern)\n }\n\n // Invalidate from KV (Tier 2)\n // Note: KV doesn't support pattern matching, so we need to list all keys\n // This is expensive and should be used sparingly\n if (this.config.kvEnabled && this.kvNamespace) {\n try {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*').replace(/\\?/g, '.') + '$'\n )\n\n // List all keys with the namespace prefix\n const prefix = this.config.namespace + ':'\n const list = await this.kvNamespace.list({ prefix })\n\n for (const key of list.keys) {\n if (regex.test(key.name)) {\n await this.kvNamespace.delete(key.name)\n count++\n }\n }\n } catch (error) {\n console.error('KV cache invalidation error:', error)\n }\n }\n\n return count\n }\n\n /**\n * Invalidate cache entries matching a pattern (alias for invalidate)\n */\n async invalidatePattern(pattern: string): Promise<number> {\n return this.invalidate(pattern)\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n const memStats = this.memoryCache.getStats()\n\n return {\n ...this.stats,\n memorySize: memStats.size,\n entryCount: memStats.count\n }\n }\n\n /**\n * Update hit rate calculation\n */\n private updateHitRate(): void {\n const totalHits = this.stats.memoryHits + this.stats.kvHits + this.stats.dbHits\n this.stats.hitRate = this.stats.totalRequests > 0\n ? (totalHits / this.stats.totalRequests) * 100\n : 0\n }\n\n /**\n * Generate a cache key using the configured namespace\n */\n generateKey(type: string, identifier: string): string {\n return generateCacheKey(\n this.config.namespace,\n type,\n identifier,\n this.config.version\n )\n }\n\n /**\n * Warm cache with multiple entries\n */\n async warmCache<T>(entries: Array<{ key: string; value: T }>): Promise<void> {\n for (const entry of entries) {\n await this.set(entry.key, entry.value)\n }\n }\n\n /**\n * Check if a key exists in cache\n */\n async has(key: string): Promise<boolean> {\n const value = await this.get(key)\n return value !== null\n }\n\n /**\n * Get multiple values at once\n */\n async getMany<T>(keys: string[]): Promise<Map<string, T>> {\n const results = new Map<string, T>()\n\n for (const key of keys) {\n const value = await this.get<T>(key)\n if (value !== null) {\n results.set(key, value)\n }\n }\n\n return results\n }\n\n /**\n * Set multiple values at once\n */\n async setMany<T>(\n entries: Array<{ key: string; value: T }>,\n customConfig?: Partial<CacheConfig>\n ): Promise<void> {\n for (const entry of entries) {\n await this.set(entry.key, entry.value, customConfig)\n }\n }\n\n /**\n * Delete multiple keys at once\n */\n async deleteMany(keys: string[]): Promise<void> {\n for (const key of keys) {\n await this.delete(key)\n }\n }\n\n /**\n * Get or set pattern - fetch from cache or compute if not found\n */\n async getOrSet<T>(\n key: string,\n fetcher: () => Promise<T>,\n customConfig?: Partial<CacheConfig>\n ): Promise<T> {\n // Try to get from cache\n const cached = await this.get<T>(key)\n if (cached !== null) {\n return cached\n }\n\n // Fetch from source\n const value = await fetcher()\n\n // Store in cache\n await this.set(key, value, customConfig)\n\n return value\n }\n\n /**\n * List all cache keys with metadata\n */\n async listKeys(): Promise<Array<{ key: string; size: number; expiresAt: number; age: number }>> {\n const keys: Array<{ key: string; size: number; expiresAt: number; age: number }> = []\n\n // Get keys from memory cache\n if (this.config.memoryEnabled) {\n const cache = (this.memoryCache as any).cache as Map<string, CacheEntry<any>>\n for (const [key, entry] of cache.entries()) {\n const size = JSON.stringify(entry).length * 2\n const age = Date.now() - entry.timestamp\n keys.push({\n key,\n size,\n expiresAt: entry.expiresAt,\n age\n })\n }\n }\n\n // Sort by age (newest first)\n return keys.sort((a, b) => a.age - b.age)\n }\n\n /**\n * Get cache entry with full metadata\n */\n async getEntry<T>(key: string): Promise<{\n data: T\n timestamp: number\n expiresAt: number\n ttl: number\n size: number\n } | null> {\n if (!this.config.memoryEnabled) {\n return null\n }\n\n const cache = (this.memoryCache as any).cache as Map<string, CacheEntry<any>>\n const entry = cache.get(key)\n\n if (!entry) {\n return null\n }\n\n // Check expiration\n if (Date.now() > entry.expiresAt) {\n await this.delete(key)\n return null\n }\n\n const size = JSON.stringify(entry).length * 2\n const ttl = Math.max(0, entry.expiresAt - Date.now()) / 1000\n\n return {\n data: entry.data as T,\n timestamp: entry.timestamp,\n expiresAt: entry.expiresAt,\n ttl,\n size\n }\n }\n}\n\n/**\n * Create a cache service instance with configuration\n */\nexport function createCacheService(config: CacheConfig, kvNamespace?: KVNamespace): CacheService {\n return new CacheService(config, kvNamespace)\n}\n\n/**\n * Global cache instances by namespace (singleton pattern)\n */\nconst cacheInstances = new Map<string, CacheService>()\nlet globalKVNamespace: KVNamespace | undefined\n\n/**\n * Set global KV namespace for all cache instances\n */\nexport function setGlobalKVNamespace(kvNamespace: KVNamespace): void {\n globalKVNamespace = kvNamespace\n}\n\n/**\n * Get or create a cache service for a namespace\n */\nexport function getCacheService(config: CacheConfig, kvNamespace?: KVNamespace): CacheService {\n const key = config.namespace\n\n if (!cacheInstances.has(key)) {\n // Use provided KV namespace or global one\n const kv = kvNamespace || globalKVNamespace\n cacheInstances.set(key, new CacheService(config, kv))\n }\n\n return cacheInstances.get(key)!\n}\n\n/**\n * Clear all cache instances\n */\nexport async function clearAllCaches(): Promise<void> {\n for (const cache of cacheInstances.values()) {\n await cache.clear()\n }\n}\n\n/**\n * Get stats from all cache instances\n */\nexport function getAllCacheStats(): Record<string, CacheStats> {\n const stats: Record<string, CacheStats> = {}\n\n for (const [namespace, cache] of cacheInstances.entries()) {\n stats[namespace] = cache.getStats()\n }\n\n return stats\n}\n","/**\n * Event Bus for Cache Invalidation\n *\n * Provides a centralized event system for triggering cache invalidation\n * based on application events.\n */\n\nexport type EventHandler = (data?: any) => Promise<void> | void\n\n// interface EventSubscription {\n// event: string\n// handler: EventHandler\n// }\n\nclass EventBus {\n private subscriptions: Map<string, EventHandler[]> = new Map()\n private eventLog: Array<{ event: string; timestamp: number; data?: any }> = []\n private maxLogSize: number = 100\n\n /**\n * Subscribe to an event\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this.subscriptions.has(event)) {\n this.subscriptions.set(event, [])\n }\n\n this.subscriptions.get(event)!.push(handler)\n\n // Return unsubscribe function\n return () => {\n const handlers = this.subscriptions.get(event)\n if (handlers) {\n const index = handlers.indexOf(handler)\n if (index > -1) {\n handlers.splice(index, 1)\n }\n }\n }\n }\n\n /**\n * Emit an event to all subscribers\n */\n async emit(event: string, data?: any): Promise<void> {\n // Log the event\n this.logEvent(event, data)\n\n const handlers = this.subscriptions.get(event) || []\n\n // Execute all handlers\n await Promise.all(\n handlers.map(async (handler) => {\n try {\n await handler(data)\n } catch (error) {\n console.error(`Error in event handler for ${event}:`, error)\n }\n })\n )\n\n // Also emit to wildcard subscribers\n const wildcardHandlers = this.subscriptions.get('*') || []\n await Promise.all(\n wildcardHandlers.map(async (handler) => {\n try {\n await handler({ event, data })\n } catch (error) {\n console.error(`Error in wildcard event handler for ${event}:`, error)\n }\n })\n )\n }\n\n /**\n * Remove all subscribers for an event\n */\n off(event: string): void {\n this.subscriptions.delete(event)\n }\n\n /**\n * Get all registered events\n */\n getEvents(): string[] {\n return Array.from(this.subscriptions.keys())\n }\n\n /**\n * Get subscriber count for an event\n */\n getSubscriberCount(event: string): number {\n return this.subscriptions.get(event)?.length || 0\n }\n\n /**\n * Log an event for debugging\n */\n private logEvent(event: string, data?: any): void {\n this.eventLog.push({\n event,\n timestamp: Date.now(),\n data\n })\n\n // Keep log size manageable\n if (this.eventLog.length > this.maxLogSize) {\n this.eventLog.shift()\n }\n }\n\n /**\n * Get recent event log\n */\n getEventLog(limit: number = 50): Array<{ event: string; timestamp: number; data?: any }> {\n return this.eventLog.slice(-limit)\n }\n\n /**\n * Clear event log\n */\n clearEventLog(): void {\n this.eventLog = []\n }\n\n /**\n * Get statistics\n */\n getStats(): {\n totalEvents: number\n totalSubscriptions: number\n eventCounts: Record<string, number>\n } {\n const eventCounts: Record<string, number> = {}\n\n for (const log of this.eventLog) {\n eventCounts[log.event] = (eventCounts[log.event] || 0) + 1\n }\n\n return {\n totalEvents: this.eventLog.length,\n totalSubscriptions: this.subscriptions.size,\n eventCounts\n }\n }\n}\n\n// Global event bus instance\nlet globalEventBus: EventBus | null = null\n\n/**\n * Get or create the global event bus\n */\nexport function getEventBus(): EventBus {\n if (!globalEventBus) {\n globalEventBus = new EventBus()\n }\n return globalEventBus\n}\n\n/**\n * Convenience function to emit an event\n */\nexport async function emitEvent(event: string, data?: any): Promise<void> {\n const bus = getEventBus()\n await bus.emit(event, data)\n}\n\n/**\n * Convenience function to subscribe to an event\n */\nexport function onEvent(event: string, handler: EventHandler): () => void {\n const bus = getEventBus()\n return bus.on(event, handler)\n}\n","/**\n * Cache Invalidation Service\n *\n * Automatically invalidates cache entries based on application events\n */\n\nimport { getCacheService } from './cache.js'\nimport { CACHE_CONFIGS } from './cache-config.js'\nimport { getEventBus, onEvent } from './event-bus.js'\n\n/**\n * Setup automatic cache invalidation based on events\n */\nexport function setupCacheInvalidation(): void {\n const _eventBus = getEventBus()\n\n // Content cache invalidation\n setupContentInvalidation()\n\n // User cache invalidation\n setupUserInvalidation()\n\n // Config cache invalidation\n setupConfigInvalidation()\n\n // Media cache invalidation\n setupMediaInvalidation()\n\n // API cache invalidation\n setupAPIInvalidation()\n\n // Collection cache invalidation\n setupCollectionInvalidation()\n\n console.log('Cache invalidation listeners registered')\n}\n\n/**\n * Content cache invalidation\n */\nfunction setupContentInvalidation(): void {\n const config = CACHE_CONFIGS.content\n if (!config) return\n const contentCache = getCacheService(config)\n\n // Invalidate on content updates\n onEvent('content.create', async (_data) => {\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.create')\n })\n\n onEvent('content.update', async (data) => {\n if (data?.id) {\n // Invalidate specific content item\n await contentCache.delete(contentCache.generateKey('item', data.id))\n }\n // Invalidate all content lists\n await contentCache.invalidate('content:list:*')\n console.log('Cache invalidated: content.update', data?.id)\n })\n\n onEvent('content.delete', async (data) => {\n if (data?.id) {\n await contentCache.delete(contentCache.generateKey('item', data.id))\n }\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.delete', data?.id)\n })\n\n onEvent('content.publish', async (_data) => {\n await contentCache.invalidate('content:*')\n console.log('Cache invalidated: content.publish')\n })\n}\n\n/**\n * User cache invalidation\n */\nfunction setupUserInvalidation(): void {\n const config = CACHE_CONFIGS.user\n if (!config) return\n const userCache = getCacheService(config)\n\n onEvent('user.update', async (data) => {\n if (data?.id) {\n await userCache.delete(userCache.generateKey('id', data.id))\n }\n if (data?.email) {\n await userCache.delete(userCache.generateKey('email', data.email))\n }\n console.log('Cache invalidated: user.update', data?.id)\n })\n\n onEvent('user.delete', async (data) => {\n if (data?.id) {\n await userCache.delete(userCache.generateKey('id', data.id))\n }\n if (data?.email) {\n await userCache.delete(userCache.generateKey('email', data.email))\n }\n console.log('Cache invalidated: user.delete', data?.id)\n })\n\n onEvent('auth.login', async (data) => {\n if (data?.userId) {\n await userCache.delete(userCache.generateKey('id', data.userId))\n }\n console.log('Cache invalidated: auth.login', data?.userId)\n })\n\n onEvent('auth.logout', async (data) => {\n // Clear session cache\n const sessionConfig = CACHE_CONFIGS.session\n if (sessionConfig) {\n const sessionCache = getCacheService(sessionConfig)\n if (data?.sessionId) {\n await sessionCache.delete(sessionCache.generateKey('session', data.sessionId))\n }\n }\n console.log('Cache invalidated: auth.logout')\n })\n}\n\n/**\n * Config cache invalidation\n */\nfunction setupConfigInvalidation(): void {\n const configConfig = CACHE_CONFIGS.config\n if (!configConfig) return\n const configCache = getCacheService(configConfig)\n\n onEvent('config.update', async (_data) => {\n await configCache.invalidate('config:*')\n console.log('Cache invalidated: config.update')\n })\n\n onEvent('plugin.activate', async (data) => {\n await configCache.invalidate('config:*')\n const pluginConfig = CACHE_CONFIGS.plugin\n if (pluginConfig) {\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n }\n console.log('Cache invalidated: plugin.activate', data?.pluginId)\n })\n\n onEvent('plugin.deactivate', async (data) => {\n await configCache.invalidate('config:*')\n const pluginConfig = CACHE_CONFIGS.plugin\n if (pluginConfig) {\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n }\n console.log('Cache invalidated: plugin.deactivate', data?.pluginId)\n })\n\n onEvent('plugin.update', async (data) => {\n const pluginConfig = CACHE_CONFIGS.plugin\n if (!pluginConfig) return\n const pluginCache = getCacheService(pluginConfig)\n await pluginCache.invalidate('plugin:*')\n console.log('Cache invalidated: plugin.update', data?.pluginId)\n })\n}\n\n/**\n * Media cache invalidation\n */\nfunction setupMediaInvalidation(): void {\n const config = CACHE_CONFIGS.media\n if (!config) return\n const mediaCache = getCacheService(config)\n\n onEvent('media.upload', async (_data) => {\n await mediaCache.invalidate('media:*')\n console.log('Cache invalidated: media.upload')\n })\n\n onEvent('media.delete', async (data) => {\n if (data?.id) {\n await mediaCache.delete(mediaCache.generateKey('item', data.id))\n }\n await mediaCache.invalidate('media:list:*')\n console.log('Cache invalidated: media.delete', data?.id)\n })\n\n onEvent('media.update', async (data) => {\n if (data?.id) {\n await mediaCache.delete(mediaCache.generateKey('item', data.id))\n }\n await mediaCache.invalidate('media:list:*')\n console.log('Cache invalidated: media.update', data?.id)\n })\n}\n\n/**\n * API cache invalidation (depends on content changes)\n */\nfunction setupAPIInvalidation(): void {\n const config = CACHE_CONFIGS.api\n if (!config) return\n const apiCache = getCacheService(config)\n\n onEvent('content.update', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.update)')\n })\n\n onEvent('content.publish', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.publish)')\n })\n\n onEvent('content.create', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.create)')\n })\n\n onEvent('content.delete', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (content.delete)')\n })\n\n onEvent('collection.update', async (_data) => {\n await apiCache.invalidate('api:*')\n console.log('Cache invalidated: api (collection.update)')\n })\n}\n\n/**\n * Collection cache invalidation\n */\nfunction setupCollectionInvalidation(): void {\n const config = CACHE_CONFIGS.collection\n if (!config) return\n const collectionCache = getCacheService(config)\n\n onEvent('collection.create', async (_data) => {\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.create')\n })\n\n onEvent('collection.update', async (data) => {\n if (data?.id) {\n await collectionCache.delete(collectionCache.generateKey('item', data.id))\n }\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.update', data?.id)\n })\n\n onEvent('collection.delete', async (data) => {\n await collectionCache.invalidate('collection:*')\n console.log('Cache invalidated: collection.delete', data?.id)\n })\n}\n\n/**\n * Get invalidation statistics\n */\nexport function getCacheInvalidationStats() {\n const eventBus = getEventBus()\n return eventBus.getStats()\n}\n\n/**\n * Get recent invalidation events\n */\nexport function getRecentInvalidations(limit: number = 50) {\n const eventBus = getEventBus()\n return eventBus.getEventLog(limit)\n}\n","/**\n * Cache Warming Utilities\n *\n * Utilities for preloading and warming cache entries\n */\n\nimport { getCacheService } from './cache.js'\nimport { CACHE_CONFIGS } from './cache-config.js'\n\n/**\n * Warm cache with common queries\n */\nexport async function warmCommonCaches(db: D1Database): Promise<{\n warmed: number\n errors: number\n details: Array<{ namespace: string; count: number }>\n}> {\n let totalWarmed = 0\n let totalErrors = 0\n const details: Array<{ namespace: string; count: number }> = []\n\n try {\n // Warm collection cache\n const collectionCount = await warmCollections(db)\n totalWarmed += collectionCount\n details.push({ namespace: 'collection', count: collectionCount })\n\n // Warm content cache (most recent items)\n const contentCount = await warmRecentContent(db)\n totalWarmed += contentCount\n details.push({ namespace: 'content', count: contentCount })\n\n // Warm media cache (most recent items)\n const mediaCount = await warmRecentMedia(db)\n totalWarmed += mediaCount\n details.push({ namespace: 'media', count: mediaCount })\n\n } catch (error) {\n console.error('Error warming caches:', error)\n totalErrors++\n }\n\n return {\n warmed: totalWarmed,\n errors: totalErrors,\n details\n }\n}\n\n/**\n * Warm collections cache\n */\nasync function warmCollections(db: D1Database): Promise<number> {\n const config = CACHE_CONFIGS.collection\n if (!config) return 0\n const collectionCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare('SELECT * FROM collections WHERE is_active = 1')\n const { results } = await stmt.all()\n\n for (const collection of results as any[]) {\n const key = collectionCache.generateKey('item', collection.id)\n await collectionCache.set(key, collection)\n count++\n }\n\n // Also cache the full list\n const listKey = collectionCache.generateKey('list', 'all')\n await collectionCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming collections cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm recent content cache\n */\nasync function warmRecentContent(db: D1Database, limit: number = 50): Promise<number> {\n const config = CACHE_CONFIGS.content\n if (!config) return 0\n const contentCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare(`SELECT * FROM content ORDER BY created_at DESC LIMIT ${limit}`)\n const { results } = await stmt.all()\n\n for (const content of results as any[]) {\n const key = contentCache.generateKey('item', content.id)\n await contentCache.set(key, content)\n count++\n }\n\n // Cache the list\n const listKey = contentCache.generateKey('list', 'recent')\n await contentCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming content cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm recent media cache\n */\nasync function warmRecentMedia(db: D1Database, limit: number = 50): Promise<number> {\n const config = CACHE_CONFIGS.media\n if (!config) return 0\n const mediaCache = getCacheService(config)\n let count = 0\n\n try {\n const stmt = db.prepare(`SELECT * FROM media WHERE deleted_at IS NULL ORDER BY uploaded_at DESC LIMIT ${limit}`)\n const { results } = await stmt.all()\n\n for (const media of results as any[]) {\n const key = mediaCache.generateKey('item', media.id)\n await mediaCache.set(key, media)\n count++\n }\n\n // Cache the list\n const listKey = mediaCache.generateKey('list', 'recent')\n await mediaCache.set(listKey, results)\n count++\n\n } catch (error) {\n console.error('Error warming media cache:', error)\n }\n\n return count\n}\n\n/**\n * Warm specific namespace with custom data\n */\nexport async function warmNamespace(\n namespace: string,\n entries: Array<{ key: string; value: any }>\n): Promise<number> {\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n throw new Error(`Unknown namespace: ${namespace}`)\n }\n\n const cache = getCacheService(config)\n await cache.setMany(entries)\n\n return entries.length\n}\n\n/**\n * Preload cache on application startup\n */\nexport async function preloadCache(db: D1Database): Promise<void> {\n console.log('🔥 Preloading cache...')\n\n const result = await warmCommonCaches(db)\n\n console.log(`✅ Cache preloaded: ${result.warmed} entries across ${result.details.length} namespaces`)\n result.details.forEach(detail => {\n console.log(` - ${detail.namespace}: ${detail.count} entries`)\n })\n\n if (result.errors > 0) {\n console.warn(`⚠️ ${result.errors} errors during cache preloading`)\n }\n}\n\n/**\n * Schedule periodic cache warming\n */\nexport function schedulePeriodicWarming(\n db: D1Database,\n intervalMs: number = 300000 // 5 minutes default\n): NodeJS.Timeout {\n console.log(`⏰ Scheduling periodic cache warming every ${intervalMs / 1000}s`)\n\n return setInterval(async () => {\n try {\n console.log('🔄 Running periodic cache warming...')\n await warmCommonCaches(db)\n } catch (error) {\n console.error('Error during periodic cache warming:', error)\n }\n }, intervalMs)\n}\n","/**\n * Admin Cache Dashboard Template\n *\n * Moved from @sonicjs-cms/templates to avoid circular dependency\n * during build (templates imports from core, core can't import from templates)\n */\n\nimport { renderAdminLayoutCatalyst, AdminLayoutCatalystData } from '../layouts/admin-layout-catalyst.template'\nimport { renderConfirmationDialog, getConfirmationDialogScript } from '../components/confirmation-dialog.template'\n\nexport interface CacheStats {\n memoryHits: number\n memoryMisses: number\n kvHits: number\n kvMisses: number\n dbHits: number\n totalRequests: number\n hitRate: number\n memorySize: number\n entryCount: number\n}\n\nexport interface CacheDashboardData {\n stats: Record<string, CacheStats>\n totals: {\n hits: number\n misses: number\n requests: number\n hitRate: string\n memorySize: number\n entryCount: number\n }\n namespaces: string[]\n user?: {\n name: string\n email: string\n role: string\n }\n version?: string\n}\n\nexport function renderCacheDashboard(data: CacheDashboardData): string {\n const pageContent = `\n <div class=\"space-y-6\">\n <!-- Header -->\n <div class=\"flex items-center justify-between\">\n <div>\n <h1 class=\"text-2xl font-semibold text-zinc-950 dark:text-white\">Cache System</h1>\n <p class=\"mt-1 text-sm text-zinc-600 dark:text-zinc-400\">\n Monitor and manage cache performance across all namespaces\n </p>\n </div>\n <div class=\"flex gap-3\">\n <button\n onclick=\"refreshStats()\"\n class=\"inline-flex items-center gap-2 rounded-lg bg-white dark:bg-zinc-900 px-4 py-2 text-sm font-medium text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"/>\n </svg>\n Refresh\n </button>\n <button\n onclick=\"clearAllCaches()\"\n class=\"inline-flex items-center gap-2 rounded-lg bg-red-600 dark:bg-red-500 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 dark:hover:bg-red-600\"\n >\n <svg class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"/>\n </svg>\n Clear All\n </button>\n </div>\n </div>\n\n <!-- Overall Stats Cards -->\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n ${renderStatCard('Total Requests', data.totals.requests.toLocaleString(), 'lime', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M13 7h8m0 0v8m0-8l-8 8-4-4-6 6\"/>\n </svg>\n `)}\n\n ${renderStatCard('Hit Rate', data.totals.hitRate + '%', 'blue', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>\n `, parseFloat(data.totals.hitRate) > 70 ? 'lime' : parseFloat(data.totals.hitRate) > 40 ? 'amber' : 'red')}\n\n ${renderStatCard('Memory Usage', formatBytes(data.totals.memorySize), 'purple', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z\"/>\n </svg>\n `)}\n\n ${renderStatCard('Cached Entries', data.totals.entryCount.toLocaleString(), 'sky', `\n <svg class=\"h-5 w-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01\"/>\n </svg>\n `)}\n </div>\n\n <!-- Namespace Statistics -->\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-4 border-b border-zinc-950/5 dark:border-white/10\">\n <h2 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Cache Namespaces</h2>\n </div>\n <div class=\"overflow-x-auto\">\n <table class=\"min-w-full divide-y divide-zinc-950/5 dark:divide-white/10\">\n <thead class=\"bg-zinc-50 dark:bg-zinc-800/50\">\n <tr>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Namespace\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Requests\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Hit Rate\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Memory Hits\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n KV Hits\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Entries\n </th>\n <th class=\"px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Size\n </th>\n <th class=\"px-6 py-3 text-right text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-zinc-950/5 dark:divide-white/10\">\n ${data.namespaces.map(namespace => {\n const stat = data.stats[namespace]\n if (!stat) return ''\n return renderNamespaceRow(namespace, stat)\n }).join('')}\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Performance Chart Placeholder -->\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"px-6 py-4 border-b border-zinc-950/5 dark:border-white/10\">\n <h2 class=\"text-lg font-semibold text-zinc-950 dark:text-white\">Performance Overview</h2>\n </div>\n <div class=\"p-6\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n ${renderPerformanceMetric('Memory Cache', data.totals.hits, data.totals.misses)}\n ${renderHealthStatus(parseFloat(data.totals.hitRate))}\n </div>\n </div>\n </div>\n </div>\n\n <script>\n async function refreshStats() {\n window.location.reload()\n }\n\n async function clearAllCaches() {\n showConfirmDialog('clear-all-cache-confirm')\n }\n\n async function performClearAllCaches() {\n try {\n const response = await fetch('/admin/cache/clear', {\n method: 'POST'\n })\n\n const result = await response.json()\n if (result.success) {\n alert('All caches cleared successfully')\n window.location.reload()\n } else {\n alert('Error clearing caches: ' + result.error)\n }\n } catch (error) {\n alert('Error clearing caches: ' + error.message)\n }\n }\n\n let namespaceToDelete = null\n\n async function clearNamespaceCache(namespace) {\n namespaceToDelete = namespace\n showConfirmDialog('clear-namespace-cache-confirm')\n }\n\n async function performClearNamespaceCache() {\n if (!namespaceToDelete) return\n\n try {\n const response = await fetch(\\`/admin/cache/clear/\\${namespaceToDelete}\\`, {\n method: 'POST'\n })\n\n const result = await response.json()\n if (result.success) {\n alert('Cache cleared successfully')\n window.location.reload()\n } else {\n alert('Error clearing cache: ' + result.error)\n }\n } catch (error) {\n alert('Error clearing cache: ' + error.message)\n } finally {\n namespaceToDelete = null\n }\n }\n </script>\n\n <!-- Confirmation Dialogs -->\n ${renderConfirmationDialog({\n id: 'clear-all-cache-confirm',\n title: 'Clear All Cache',\n message: 'Are you sure you want to clear all cache entries? This cannot be undone.',\n confirmText: 'Clear All',\n cancelText: 'Cancel',\n iconColor: 'yellow',\n confirmClass: 'bg-yellow-500 hover:bg-yellow-400',\n onConfirm: 'performClearAllCaches()'\n })}\n\n ${renderConfirmationDialog({\n id: 'clear-namespace-cache-confirm',\n title: 'Clear Namespace Cache',\n message: 'Clear cache for this namespace?',\n confirmText: 'Clear',\n cancelText: 'Cancel',\n iconColor: 'yellow',\n confirmClass: 'bg-yellow-500 hover:bg-yellow-400',\n onConfirm: 'performClearNamespaceCache()'\n })}\n\n ${getConfirmationDialogScript()}\n `\n\n const layoutData: AdminLayoutCatalystData = {\n title: 'Cache System',\n pageTitle: 'Cache System',\n currentPath: '/admin/cache',\n user: data.user,\n version: data.version,\n content: pageContent\n }\n\n return renderAdminLayoutCatalyst(layoutData)\n}\n\nfunction renderStatCard(label: string, value: string, color: string, icon: string, colorOverride?: string): string {\n const finalColor = colorOverride || color\n const colorClasses = {\n lime: 'bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20',\n blue: 'bg-blue-50 dark:bg-blue-500/10 text-blue-600 dark:text-blue-400 ring-blue-600/20 dark:ring-blue-500/20',\n purple: 'bg-purple-50 dark:bg-purple-500/10 text-purple-600 dark:text-purple-400 ring-purple-600/20 dark:ring-purple-500/20',\n sky: 'bg-sky-50 dark:bg-sky-500/10 text-sky-600 dark:text-sky-400 ring-sky-600/20 dark:ring-sky-500/20',\n amber: 'bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20',\n red: 'bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20'\n }\n\n return `\n <div class=\"overflow-hidden rounded-xl bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/5 dark:ring-white/10\">\n <div class=\"p-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3\">\n <div class=\"rounded-lg p-2 ring-1 ring-inset ${colorClasses[finalColor as keyof typeof colorClasses]}\">\n ${icon}\n </div>\n <div>\n <p class=\"text-sm text-zinc-600 dark:text-zinc-400\">${label}</p>\n <p class=\"mt-1 text-2xl font-semibold text-zinc-950 dark:text-white\">${value}</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n `\n}\n\nfunction renderNamespaceRow(namespace: string, stat: CacheStats): string {\n const hitRate = stat.hitRate.toFixed(1)\n const hitRateColor = stat.hitRate > 70 ? 'text-lime-600 dark:text-lime-400' :\n stat.hitRate > 40 ? 'text-amber-600 dark:text-amber-400' :\n 'text-red-600 dark:text-red-400'\n\n return `\n <tr class=\"hover:bg-zinc-50 dark:hover:bg-zinc-800/50\">\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-zinc-100 dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700\">\n ${namespace}\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100\">\n ${stat.totalRequests.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap\">\n <span class=\"text-sm font-medium ${hitRateColor}\">\n ${hitRate}%\n </span>\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.memoryHits.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.kvHits.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${stat.entryCount.toLocaleString()}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-sm text-zinc-600 dark:text-zinc-400\">\n ${formatBytes(stat.memorySize)}\n </td>\n <td class=\"px-6 py-4 whitespace-nowrap text-right text-sm\">\n <button\n onclick=\"clearNamespaceCache('${namespace}')\"\n class=\"text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300\"\n >\n Clear\n </button>\n </td>\n </tr>\n `\n}\n\nfunction renderPerformanceMetric(label: string, hits: number, misses: number): string {\n const total = hits + misses\n const hitPercentage = total > 0 ? (hits / total) * 100 : 0\n\n return `\n <div>\n <h3 class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3\">${label}</h3>\n <div class=\"space-y-2\">\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Hits</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${hits.toLocaleString()}</span>\n </div>\n <div class=\"flex items-center justify-between text-sm\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Misses</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${misses.toLocaleString()}</span>\n </div>\n <div class=\"mt-3\">\n <div class=\"flex items-center justify-between text-sm mb-1\">\n <span class=\"text-zinc-600 dark:text-zinc-400\">Hit Rate</span>\n <span class=\"font-medium text-zinc-900 dark:text-zinc-100\">${hitPercentage.toFixed(1)}%</span>\n </div>\n <div class=\"h-2 bg-zinc-200 dark:bg-zinc-700 rounded-full overflow-hidden\">\n <div class=\"h-full bg-lime-500 dark:bg-lime-400\" style=\"width: ${hitPercentage}%\"></div>\n </div>\n </div>\n </div>\n </div>\n `\n}\n\nfunction renderHealthStatus(hitRate: number): string {\n const status = hitRate > 70 ? 'healthy' : hitRate > 40 ? 'warning' : 'critical'\n const statusConfig = {\n healthy: {\n label: 'Healthy',\n color: 'lime',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>`\n },\n warning: {\n label: 'Needs Attention',\n color: 'amber',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"/>\n </svg>`\n },\n critical: {\n label: 'Critical',\n color: 'red',\n icon: `<svg class=\"h-6 w-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"/>\n </svg>`\n }\n }\n\n const config = statusConfig[status]\n const colorClasses = {\n lime: 'bg-lime-50 dark:bg-lime-500/10 text-lime-600 dark:text-lime-400 ring-lime-600/20 dark:ring-lime-500/20',\n amber: 'bg-amber-50 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 ring-amber-600/20 dark:ring-amber-500/20',\n red: 'bg-red-50 dark:bg-red-500/10 text-red-600 dark:text-red-400 ring-red-600/20 dark:ring-red-500/20'\n }\n\n return `\n <div>\n <h3 class=\"text-sm font-medium text-zinc-900 dark:text-zinc-100 mb-3\">System Health</h3>\n <div class=\"flex items-center gap-3 p-4 rounded-lg ring-1 ring-inset ${colorClasses[config.color as keyof typeof colorClasses]}\">\n ${config.icon}\n <div>\n <p class=\"text-sm font-medium\">${config.label}</p>\n <p class=\"text-xs mt-0.5 opacity-80\">\n ${status === 'healthy' ? 'Cache is performing well' :\n status === 'warning' ? 'Consider increasing cache TTL or capacity' :\n 'Cache hit rate is too low'}\n </p>\n </div>\n </div>\n </div>\n `\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`\n}\n","/**\n * Cache Plugin Routes\n *\n * Admin routes for cache management\n */\n\nimport { Hono } from 'hono'\nimport type { Context } from 'hono'\nimport { getAllCacheStats, clearAllCaches, getCacheService } from './services/cache.js'\nimport { CACHE_CONFIGS, parseCacheKey } from './services/cache-config.js'\nimport { getRecentInvalidations, getCacheInvalidationStats } from './services/cache-invalidation.js'\nimport { warmCommonCaches, warmNamespace } from './services/cache-warming.js'\nimport { renderCacheDashboard, CacheDashboardData } from '../../templates/pages/admin-cache.template'\n\nconst app = new Hono()\n\n/**\n * GET /admin/cache\n * Cache statistics dashboard\n */\napp.get('/', async (c: Context) => {\n const stats = getAllCacheStats()\n const user = c.get('user')\n\n // Calculate totals\n let totalHits = 0\n let totalMisses = 0\n let totalSize = 0\n let totalEntries = 0\n\n Object.values(stats).forEach(stat => {\n totalHits += stat.memoryHits + stat.kvHits\n totalMisses += stat.memoryMisses + stat.kvMisses\n totalSize += stat.memorySize\n totalEntries += stat.entryCount\n })\n\n const totalRequests = totalHits + totalMisses\n const overallHitRate = totalRequests > 0 ? (totalHits / totalRequests) * 100 : 0\n\n const dashboardData: CacheDashboardData = {\n stats,\n totals: {\n hits: totalHits,\n misses: totalMisses,\n requests: totalRequests,\n hitRate: overallHitRate.toFixed(2),\n memorySize: totalSize,\n entryCount: totalEntries\n },\n namespaces: Object.keys(stats),\n user: user ? {\n name: user.email,\n email: user.email,\n role: user.role\n } : undefined,\n version: c.get('appVersion')\n }\n\n return c.html(renderCacheDashboard(dashboardData))\n})\n\n/**\n * GET /admin/cache/stats\n * Detailed statistics for all namespaces\n */\napp.get('/stats', async (c: Context) => {\n const stats = getAllCacheStats()\n\n return c.json({\n success: true,\n data: stats,\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/stats/:namespace\n * Statistics for a specific namespace\n */\napp.get('/stats/:namespace', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const config = CACHE_CONFIGS[namespace]\n\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n const stats = cache.getStats()\n\n return c.json({\n success: true,\n data: {\n namespace,\n config,\n stats\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/clear\n * Clear all cache entries\n */\napp.post('/clear', async (c: Context) => {\n await clearAllCaches()\n\n return c.json({\n success: true,\n message: 'All cache entries cleared',\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/clear/:namespace\n * Clear cache for a specific namespace\n */\napp.post('/clear/:namespace', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const config = CACHE_CONFIGS[namespace]\n\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n await cache.clear()\n\n return c.json({\n success: true,\n message: `Cache cleared for namespace: ${namespace}`,\n namespace,\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/invalidate\n * Invalidate cache entries matching a pattern\n */\napp.post('/invalidate', async (c: Context) => {\n const body = await c.req.json()\n const { pattern, namespace } = body\n\n if (!pattern) {\n return c.json({\n success: false,\n error: 'Pattern is required'\n }, 400)\n }\n\n let totalInvalidated = 0\n\n if (namespace) {\n // Invalidate from specific namespace\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n totalInvalidated = await cache.invalidate(pattern)\n } else {\n // Invalidate from all namespaces\n for (const config of Object.values(CACHE_CONFIGS)) {\n const cache = getCacheService(config)\n totalInvalidated += await cache.invalidate(pattern)\n }\n }\n\n return c.json({\n success: true,\n invalidated: totalInvalidated,\n pattern,\n namespace: namespace || 'all',\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/health\n * Cache system health check\n */\napp.get('/health', async (c: Context) => {\n const stats = getAllCacheStats()\n\n // Calculate health metrics\n const namespaces = Object.entries(stats)\n const healthChecks = namespaces.map(([name, stat]) => {\n const hitRate = stat.hitRate\n const memoryUsage = stat.memorySize / (50 * 1024 * 1024) // Assume 50MB max\n\n return {\n namespace: name,\n status: hitRate > 70 ? 'healthy' : hitRate > 40 ? 'warning' : 'unhealthy',\n hitRate,\n memoryUsage: (memoryUsage * 100).toFixed(2) + '%',\n entryCount: stat.entryCount\n }\n })\n\n const overallStatus = healthChecks.every(h => h.status === 'healthy')\n ? 'healthy'\n : healthChecks.some(h => h.status === 'unhealthy')\n ? 'unhealthy'\n : 'warning'\n\n return c.json({\n success: true,\n data: {\n status: overallStatus,\n namespaces: healthChecks,\n timestamp: new Date().toISOString()\n }\n })\n})\n\n/**\n * GET /admin/cache/browser\n * Browse all cache entries across namespaces\n */\napp.get('/browser', async (c: Context) => {\n const namespace = c.req.query('namespace') || 'all'\n const search = c.req.query('search') || ''\n const sortBy = c.req.query('sort') || 'age' // age, size, key\n const limit = parseInt(c.req.query('limit') || '100')\n\n const entries: Array<{\n namespace: string\n key: string\n size: number\n age: number\n ttl: number\n expiresAt: number\n parsed: any\n }> = []\n\n const namespaces = namespace === 'all'\n ? Object.keys(CACHE_CONFIGS)\n : [namespace]\n\n for (const ns of namespaces) {\n const config = CACHE_CONFIGS[ns]\n if (!config) continue\n\n const cache = getCacheService(config)\n const keys = await cache.listKeys()\n\n for (const keyInfo of keys) {\n // Apply search filter\n if (search && !keyInfo.key.toLowerCase().includes(search.toLowerCase())) {\n continue\n }\n\n const parsed = parseCacheKey(keyInfo.key)\n const ttl = Math.max(0, keyInfo.expiresAt - Date.now()) / 1000\n\n entries.push({\n namespace: ns,\n key: keyInfo.key,\n size: keyInfo.size,\n age: keyInfo.age,\n ttl,\n expiresAt: keyInfo.expiresAt,\n parsed\n })\n }\n }\n\n // Sort entries\n if (sortBy === 'size') {\n entries.sort((a, b) => b.size - a.size)\n } else if (sortBy === 'age') {\n entries.sort((a, b) => a.age - b.age)\n } else if (sortBy === 'key') {\n entries.sort((a, b) => a.key.localeCompare(b.key))\n }\n\n // Limit results\n const limitedEntries = entries.slice(0, limit)\n\n return c.json({\n success: true,\n data: {\n entries: limitedEntries,\n total: entries.length,\n showing: limitedEntries.length,\n namespace,\n search,\n sortBy\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/browser/:namespace/:key\n * Get detailed information about a specific cache entry\n */\napp.get('/browser/:namespace/:key', async (c: Context) => {\n const namespace = c.req.param('namespace')!\n const key = decodeURIComponent(c.req.param('key')!)\n\n const config = CACHE_CONFIGS[namespace]\n if (!config) {\n return c.json({\n success: false,\n error: `Unknown namespace: ${namespace}`\n }, 404)\n }\n\n const cache = getCacheService(config)\n const entry = await cache.getEntry(key)\n\n if (!entry) {\n return c.json({\n success: false,\n error: 'Cache entry not found or expired'\n }, 404)\n }\n\n const parsed = parseCacheKey(key)\n\n return c.json({\n success: true,\n data: {\n key,\n namespace,\n parsed,\n ...entry,\n createdAt: new Date(entry.timestamp).toISOString(),\n expiresAt: new Date(entry.expiresAt).toISOString()\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics\n * Advanced cache analytics\n */\napp.get('/analytics', async (c: Context) => {\n const stats = getAllCacheStats()\n const invalidationStats = getCacheInvalidationStats()\n const recentInvalidations = getRecentInvalidations(20)\n\n // Calculate analytics\n let totalHits = 0\n let totalMisses = 0\n let totalSize = 0\n let totalEntries = 0\n\n const namespacesAnalytics = []\n\n for (const [namespace, stat] of Object.entries(stats)) {\n totalHits += stat.memoryHits + stat.kvHits\n totalMisses += stat.memoryMisses + stat.kvMisses\n totalSize += stat.memorySize\n totalEntries += stat.entryCount\n\n const totalRequests = stat.memoryHits + stat.kvHits + stat.memoryMisses + stat.kvMisses\n const hitRate = totalRequests > 0 ? ((stat.memoryHits + stat.kvHits) / totalRequests) * 100 : 0\n const avgEntrySize = stat.entryCount > 0 ? stat.memorySize / stat.entryCount : 0\n\n namespacesAnalytics.push({\n namespace,\n hitRate: hitRate.toFixed(2),\n totalRequests,\n memoryHitRate: totalRequests > 0 ? ((stat.memoryHits / totalRequests) * 100).toFixed(2) : '0',\n kvHitRate: totalRequests > 0 ? ((stat.kvHits / totalRequests) * 100).toFixed(2) : '0',\n avgEntrySize: Math.round(avgEntrySize),\n totalSize: stat.memorySize,\n entryCount: stat.entryCount,\n efficiency: totalRequests > 0 ? ((stat.memoryHits + stat.kvHits) / (stat.memoryHits + stat.kvHits + stat.dbHits + 1)).toFixed(2) : '0'\n })\n }\n\n // Sort by hit rate\n namespacesAnalytics.sort((a, b) => parseFloat(b.hitRate) - parseFloat(a.hitRate))\n\n const totalRequests = totalHits + totalMisses\n const overallHitRate = totalRequests > 0 ? (totalHits / totalRequests) * 100 : 0\n\n // Calculate cost savings (assume 50ms per DB query vs 2ms for cache)\n const dbQueriesAvoided = totalHits\n const timeSaved = dbQueriesAvoided * 48 // 48ms saved per cache hit\n const estimatedCostSavings = (dbQueriesAvoided / 1000000) * 0.50 // $0.50 per million queries\n\n return c.json({\n success: true,\n data: {\n overview: {\n totalHits,\n totalMisses,\n totalRequests,\n overallHitRate: overallHitRate.toFixed(2),\n totalSize,\n totalEntries,\n avgEntrySize: totalEntries > 0 ? Math.round(totalSize / totalEntries) : 0\n },\n performance: {\n dbQueriesAvoided,\n timeSavedMs: timeSaved,\n timeSavedMinutes: (timeSaved / 1000 / 60).toFixed(2),\n estimatedCostSavings: estimatedCostSavings.toFixed(4)\n },\n namespaces: namespacesAnalytics,\n invalidation: {\n ...invalidationStats,\n recent: recentInvalidations\n }\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics/trends\n * Cache trends over time (simplified - would need historical data storage)\n */\napp.get('/analytics/trends', async (c: Context) => {\n const stats = getAllCacheStats()\n\n // For now, return current snapshot as a data point\n // In production, this would query historical data\n const dataPoint = {\n timestamp: Date.now(),\n stats: Object.entries(stats).map(([namespace, stat]) => ({\n namespace,\n hitRate: stat.hitRate,\n entryCount: stat.entryCount,\n memorySize: stat.memorySize,\n totalRequests: stat.totalRequests\n }))\n }\n\n return c.json({\n success: true,\n data: {\n trends: [dataPoint],\n note: 'Historical trends require persistent storage. This returns current snapshot only.'\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * GET /admin/cache/analytics/top-keys\n * Most accessed cache keys (would need hit tracking)\n */\napp.get('/analytics/top-keys', async (c: Context) => {\n const _namespace = c.req.query('namespace') || 'all'\n const _limit = parseInt(c.req.query('limit') || '10')\n\n // This is a placeholder - would need per-key hit tracking\n return c.json({\n success: true,\n data: {\n topKeys: [],\n note: 'Top keys tracking requires per-key hit counting. Feature not yet implemented.'\n },\n timestamp: new Date().toISOString()\n })\n})\n\n/**\n * POST /admin/cache/warm\n * Warm cache with common queries\n */\napp.post('/warm', async (c: Context) => {\n try {\n const db = c.env.DB as D1Database\n const result = await warmCommonCaches(db)\n\n return c.json({\n success: true,\n message: 'Cache warming completed',\n ...result,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Cache warming error:', error)\n return c.json({\n success: false,\n error: 'Cache warming failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\n/**\n * POST /admin/cache/warm/:namespace\n * Warm specific namespace cache\n */\napp.post('/warm/:namespace', async (c: Context) => {\n try {\n const namespace = c.req.param('namespace')!\n const body = await c.req.json()\n const { entries } = body\n\n if (!entries || !Array.isArray(entries)) {\n return c.json({\n success: false,\n error: 'Entries array is required'\n }, 400)\n }\n\n const count = await warmNamespace(namespace, entries)\n\n return c.json({\n success: true,\n message: `Warmed ${count} entries in namespace: ${namespace}`,\n namespace,\n count,\n timestamp: new Date().toISOString()\n })\n } catch (error) {\n console.error('Namespace warming error:', error)\n return c.json({\n success: false,\n error: 'Namespace warming failed',\n details: error instanceof Error ? error.message : 'Unknown error'\n }, 500)\n }\n})\n\nexport default app\n","/**\n * Cache Plugin\n *\n * Three-tiered caching system for SonicJS\n * - Tier 1: In-Memory (fastest, region-specific)\n * - Tier 2: Cloudflare KV (fast, global)\n * - Tier 3: Database (source of truth)\n */\n\nimport type { Context } from 'hono'\nimport type { PluginContext } from '@sonicjs-cms/core'\nimport { getCacheService, clearAllCaches, getAllCacheStats } from './services/cache.js'\nimport { CACHE_CONFIGS } from './services/cache-config.js'\nimport { setupCacheInvalidation } from './services/cache-invalidation.js'\nimport cacheRoutes from './routes.js'\n\nexport class CachePlugin {\n private _context: PluginContext | null = null\n\n /**\n * Get plugin routes\n */\n getRoutes() {\n return cacheRoutes\n }\n\n /**\n * Activate the cache plugin\n */\n async activate(context: PluginContext): Promise<void> {\n this._context = context\n\n const settings = context.config || {}\n\n console.log('✅ Cache plugin activated', {\n memoryEnabled: settings.memoryEnabled ?? true,\n kvEnabled: settings.kvEnabled ?? false,\n defaultTTL: settings.defaultTTL ?? 3600\n })\n\n // Initialize default cache services\n for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {\n getCacheService({\n ...config,\n memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,\n kvEnabled: settings.kvEnabled ?? config.kvEnabled,\n ttl: settings.defaultTTL ?? config.ttl\n })\n }\n\n // Setup event-based cache invalidation\n setupCacheInvalidation()\n }\n\n /**\n * Deactivate the cache plugin\n */\n async deactivate(): Promise<void> {\n console.log('❌ Cache plugin deactivated - clearing all caches')\n await clearAllCaches()\n this._context = null\n }\n\n /**\n * Configure the cache plugin\n */\n async configure(settings: Record<string, any>): Promise<void> {\n console.log('⚙️ Cache plugin configured', settings)\n\n // Reconfigure all cache instances with new settings\n for (const [_namespace, config] of Object.entries(CACHE_CONFIGS)) {\n getCacheService({\n ...config,\n memoryEnabled: settings.memoryEnabled ?? config.memoryEnabled,\n kvEnabled: settings.kvEnabled ?? config.kvEnabled,\n ttl: settings.defaultTTL ?? config.ttl\n })\n }\n }\n\n /**\n * Get cache statistics\n */\n async getStats(c: Context): Promise<Response> {\n const stats = getAllCacheStats()\n\n return c.json({\n success: true,\n data: stats,\n timestamp: new Date().toISOString()\n })\n }\n\n /**\n * Clear all cache entries\n */\n async clearCache(c: Context): Promise<Response> {\n await clearAllCaches()\n\n return c.json({\n success: true,\n message: 'All cache entries cleared',\n timestamp: new Date().toISOString()\n })\n }\n\n /**\n * Invalidate cache entries matching pattern\n */\n async invalidatePattern(c: Context): Promise<Response> {\n const body = await c.req.json()\n const { pattern, namespace: _namespace } = body\n\n if (!pattern) {\n return c.json({\n success: false,\n error: 'Pattern is required'\n }, 400)\n }\n\n let totalInvalidated = 0\n\n if (_namespace) {\n // Invalidate from specific namespace\n const cache = getCacheService(CACHE_CONFIGS[_namespace] || {\n ttl: 3600,\n kvEnabled: false,\n memoryEnabled: true,\n namespace: _namespace,\n invalidateOn: [],\n version: 'v1'\n })\n totalInvalidated = await cache.invalidate(pattern)\n } else {\n // Invalidate from all namespaces\n for (const config of Object.values(CACHE_CONFIGS)) {\n const cache = getCacheService(config)\n totalInvalidated += await cache.invalidate(pattern)\n }\n }\n\n return c.json({\n success: true,\n invalidated: totalInvalidated,\n pattern,\n namespace: _namespace || 'all',\n timestamp: new Date().toISOString()\n })\n }\n}\n\n// Export cache services for use by other plugins/routes when cache plugin is active\nexport {\n getCacheService,\n clearAllCaches,\n getAllCacheStats,\n setGlobalKVNamespace\n} from './services/cache'\nexport { CACHE_CONFIGS, getCacheConfig, generateCacheKey } from './services/cache-config'\nexport type { CacheConfig, CacheStats } from './services/cache-config'\nexport { emitEvent, onEvent, getEventBus } from './services/event-bus'\nexport { getCacheInvalidationStats, getRecentInvalidations } from './services/cache-invalidation'\nexport { warmCommonCaches, warmNamespace, preloadCache } from './services/cache-warming'\n\n// Create and export plugin instance\nconst plugin = new CachePlugin()\nexport default plugin\n","/**\n * SonicJS Favicon SVG\n *\n * Embedded SVG favicon for the admin interface and auth pages.\n * This ensures the favicon is always available without external dependencies.\n */\n\nexport const faviconSvg = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n version=\"1.1\"\n id=\"Layer_1\"\n x=\"0px\"\n y=\"0px\"\n viewBox=\"380 1300 257.89001 278.8855\"\n xml:space=\"preserve\"\n width=\"257.89001\"\n height=\"278.8855\"\n xmlns=\"http://www.w3.org/2000/svg\">\n<g\n id=\"g10\"\n transform=\"translate(-383.935,-60.555509)\">\n\t<g\n id=\"g9\">\n\t\t<path\n fill=\"#f1f2f2\"\n d=\"m 974.78,1398.211 c -5.016,6.574 -10.034,13.146 -15.048,19.721 -1.828,2.398 -3.657,4.796 -5.487,7.194 1.994,1.719 3.958,3.51 5.873,5.424 18.724,18.731 28.089,41.216 28.089,67.459 0,26.251 -9.366,48.658 -28.089,67.237 -18.731,18.579 -41.215,27.868 -67.459,27.868 -9.848,0 -19.156,-1.308 -27.923,-3.923 l -4.185,3.354 c -8.587,6.885 -17.154,13.796 -25.725,20.702 17.52,8.967 36.86,13.487 58.054,13.487 35.533,0 65.91,-12.608 91.124,-37.821 25.214,-25.215 37.821,-55.584 37.821,-91.125 0,-35.534 -12.607,-65.911 -37.821,-91.126 -3,-2.999 -6.078,-5.808 -9.224,-8.451 z\"\n id=\"path2\" />\n\t\t<path\n fill=\"#34d399\"\n d=\"m 854.024,1585.195 20.001,-16.028 c 16.616,-13.507 33.04,-27.265 50.086,-40.251 1.13,-0.861 2.9,-1.686 2.003,-3.516 -0.843,-1.716 -2.481,-2.302 -4.484,-2.123 -8.514,0.765 -17.016,-0.538 -25.537,-0.353 -1.124,0.024 -2.768,0.221 -3.163,-1.25 -0.371,-1.369 1.088,-2.063 1.919,-2.894 6.26,-6.242 12.574,-12.43 18.816,-18.691 9.303,-9.327 18.565,-18.714 27.851,-28.066 1.848,-1.859 3.701,-3.713 5.549,-5.572 2.655,-2.661 5.309,-5.315 7.958,-7.982 0.574,-0.579 1.259,-1.141 1.246,-1.94 -0.004,-0.257 -0.078,-0.538 -0.254,-0.853 -0.556,-0.981 -1.441,-1.1 -2.469,-0.957 -0.658,0.096 -1.315,0.185 -1.973,0.275 -3.844,0.538 -7.689,1.076 -11.533,1.608 -3.641,0.505 -7.281,1.02 -10.922,1.529 -4.162,0.582 -8.324,1.158 -12.486,1.748 -1.142,0.161 -2.409,1.662 -3.354,0.508 -0.419,-0.508 -0.431,-1.028 -0.251,-1.531 0.269,-0.741 0.957,-1.441 1.387,-2.021 3.414,-4.58 6.882,-9.124 10.356,-13.662 1.74,-2.272 3.48,-4.544 5.214,-6.822 4.682,-6.141 9.369,-12.281 14.051,-18.422 0.09,-0.119 0.181,-0.237 0.271,-0.355 6.848,-8.98 13.7,-17.958 20.553,-26.936 0.488,-0.64 0.977,-1.28 1.465,-1.92 2.159,-2.828 4.315,-5.658 6.476,-8.486 4.197,-5.501 8.454,-10.954 12.67,-16.442 0.263,-0.347 0.538,-0.718 0.717,-1.106 0.269,-0.586 0.299,-1.196 -0.335,-1.776 -0.825,-0.753 -1.8,-0.15 -2.595,0.419 -0.67,0.472 -1.333,0.957 -1.955,1.489 -2.206,1.889 -4.401,3.797 -6.595,5.698 -3.958,3.438 -7.922,6.876 -11.976,10.194 -2.443,2.003 -4.865,4.028 -7.301,6.038 -18.689,-10.581 -39.53,-15.906 -62.549,-15.906 -35.54,0 -65.911,12.607 -91.125,37.82 -25.214,25.215 -37.821,55.592 -37.821,91.126 0,35.54 12.607,65.91 37.821,91.125 4.146,4.146 8.445,7.916 12.87,11.381 -9.015,11.14 -18.036,22.277 -27.034,33.429 -1.208,1.489 -3.755,3.151 -2.745,4.891 0.078,0.144 0.173,0.281 0.305,0.425 1.321,1.429 3.492,-1.303 4.933,-2.457 6.673,-5.333 13.333,-10.685 19.982,-16.042 3.707,-2.984 7.417,-5.965 11.124,-8.952 1.474,-1.188 2.951,-2.373 4.425,-3.561 6.41,-5.164 12.816,-10.333 19.238,-15.481 z m -56.472,-87.186 c 0,-26.243 9.29,-48.728 27.868,-67.459 18.579,-18.723 40.987,-28.089 67.238,-28.089 12.273,0 23.712,2.075 34.34,6.171 -3.37,2.905 -6.734,5.816 -10.069,8.762 -6.075,5.351 -12.365,10.469 -18.667,15.564 -4.179,3.378 -8.371,6.744 -12.514,10.164 -7.54,6.23 -15.037,12.52 -22.529,18.804 -7.091,5.955 -14.182,11.904 -21.19,17.949 -1.136,0.974 -3.055,1.907 -2.135,3.94 0.831,1.836 2.774,1.417 4.341,1.578 l 12.145,-0.599 14.151,-0.698 c 1.031,-0.102 2.192,-0.257 2.89,0.632 0.034,0.044 0.073,0.078 0.106,0.127 1.017,1.561 -0.67,2.105 -1.387,2.942 -6.308,7.318 -12.616,14.637 -18.978,21.907 -8.161,9.339 -16.353,18.649 -24.544,27.958 -2.146,2.433 -4.275,4.879 -6.422,7.312 -1.034,1.172 -2.129,2.272 -1.238,3.922 0.933,1.728 2.685,1.752 4.323,1.602 4.134,-0.367 8.263,-0.489 12.396,-0.492 0.242,0 0.485,-0.01 0.728,0 2.711,0.01 5.422,0.068 8.134,0.145 2.582,0.074 5.166,0.165 7.752,0.249 0.275,1.62 -0.879,2.356 -1.62,3.259 -1.333,1.626 -2.667,3.247 -4,4.867 -4.315,5.252 -8.62,10.514 -12.928,15.772 -3.562,-2.725 -7.007,-5.733 -10.324,-9.051 -18.577,-18.576 -27.867,-40.983 -27.867,-67.234 z\"\n id=\"path9\" />\n\t</g>\n</g>\n</svg>`;\n","/**\n * Main Application Factory\n *\n * Creates a configured SonicJS application with all core functionality\n */\n\nimport { Hono } from 'hono'\nimport type { Context } from 'hono'\nimport type { D1Database, KVNamespace, R2Bucket } from '@cloudflare/workers-types'\nimport {\n apiRoutes,\n apiMediaRoutes,\n apiSystemRoutes,\n adminApiRoutes,\n authRoutes,\n testCleanupRoutes,\n adminContentRoutes,\n adminUsersRoutes,\n adminMediaRoutes,\n adminPluginRoutes,\n adminLogsRoutes,\n adminDashboardRoutes,\n adminCollectionsRoutes,\n adminSettingsRoutes,\n adminFormsRoutes,\n publicFormsRoutes,\n adminApiReferenceRoutes\n} from './routes'\nimport { getCoreVersion } from './utils/version'\nimport { bootstrapMiddleware } from './middleware/bootstrap'\nimport { metricsMiddleware } from './middleware/metrics'\nimport { csrfProtection } from './middleware/csrf'\nimport { securityHeadersMiddleware } from './middleware/security-headers'\nimport { createDatabaseToolsAdminRoutes } from './plugins/core-plugins/database-tools-plugin/admin-routes'\nimport { createSeedDataAdminRoutes } from './plugins/core-plugins/seed-data-plugin/admin-routes'\nimport { emailPlugin } from './plugins/core-plugins/email-plugin'\nimport { otpLoginPlugin } from './plugins/core-plugins/otp-login-plugin'\nimport { oauthProvidersPlugin } from './plugins/core-plugins/oauth-providers'\nimport { userProfilesPlugin } from './plugins/core-plugins/user-profiles'\nimport { aiSearchPlugin } from './plugins/core-plugins/ai-search-plugin'\nimport { createMagicLinkAuthPlugin } from './plugins/available/magic-link-auth'\nimport { securityAuditPlugin } from './plugins/core-plugins/security-audit-plugin'\nimport { securityAuditMiddleware } from './plugins/core-plugins/security-audit-plugin'\nimport { stripePlugin } from './plugins/core-plugins/stripe-plugin'\nimport { pluginMenuMiddleware } from './middleware/plugin-menu'\nimport cachePlugin from './plugins/cache'\nimport { faviconSvg } from './assets/favicon'\nimport { setAppInstance } from './services/route-metadata'\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\nexport interface Bindings {\n DB: D1Database\n CACHE_KV: KVNamespace\n MEDIA_BUCKET: R2Bucket\n ASSETS: Fetcher\n EMAIL_QUEUE?: Queue\n SENDGRID_API_KEY?: string\n DEFAULT_FROM_EMAIL?: string\n IMAGES_ACCOUNT_ID?: string\n IMAGES_API_TOKEN?: string\n ENVIRONMENT?: string\n CORS_ORIGINS?: string\n JWT_SECRET?: string\n BUCKET_NAME?: string\n GOOGLE_MAPS_API_KEY?: string\n}\n\nexport interface Variables {\n user?: {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n }\n requestId?: string\n startTime?: number\n appVersion?: string\n csrfToken?: string\n pluginMenuItems?: Array<{ label: string; path: string; icon: string }>\n}\n\nexport interface SonicJSConfig {\n // Collections configuration\n collections?: {\n directory?: string\n autoSync?: boolean\n }\n\n // Plugins configuration\n plugins?: {\n directory?: string\n autoLoad?: boolean\n disableAll?: boolean // Disable all plugins including core plugins\n }\n\n // Custom routes\n routes?: Array<{\n path: string\n handler: Hono\n }>\n\n // Custom middleware\n middleware?: {\n beforeAuth?: Array<(c: Context, next: () => Promise<void>) => Promise<void>>\n afterAuth?: Array<(c: Context, next: () => Promise<void>) => Promise<void>>\n }\n\n // App metadata\n version?: string\n name?: string\n}\n\nexport type SonicJSApp = Hono<{ Bindings: Bindings; Variables: Variables }>\n\n// ============================================================================\n// Application Factory\n// ============================================================================\n\n/**\n * Create a SonicJS application with core functionality\n *\n * @param config - Application configuration\n * @returns Configured Hono application\n *\n * @example\n * ```typescript\n * import { createSonicJSApp } from '@sonicjs-cms/core'\n *\n * const app = createSonicJSApp({\n * collections: {\n * directory: './src/collections',\n * autoSync: true\n * },\n * plugins: {\n * directory: './src/plugins',\n * autoLoad: true\n * }\n * })\n *\n * export default app\n * ```\n */\nexport function createSonicJSApp(config: SonicJSConfig = {}): SonicJSApp {\n const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()\n\n // Set app metadata\n const appVersion = config.version || getCoreVersion()\n const appName = config.name || 'SonicJS AI'\n\n // App version middleware\n app.use('*', async (c, next) => {\n c.set('appVersion', appVersion)\n await next()\n })\n\n // Metrics middleware - track all requests for real-time analytics\n app.use('*', metricsMiddleware())\n\n // Bootstrap middleware - runs migrations, syncs collections, and initializes plugins\n app.use('*', bootstrapMiddleware(config))\n\n // Custom middleware - before auth\n if (config.middleware?.beforeAuth) {\n for (const middleware of config.middleware.beforeAuth) {\n app.use('*', middleware)\n }\n }\n\n // Logging middleware\n app.use('*', async (_c, next) => {\n // Logging logic here\n await next()\n })\n\n // Security middleware\n app.use('*', securityHeadersMiddleware())\n\n // CSRF protection middleware\n app.use('*', csrfProtection())\n\n // Custom middleware - after auth\n if (config.middleware?.afterAuth) {\n for (const middleware of config.middleware.afterAuth) {\n app.use('*', middleware)\n }\n }\n\n // Plugin dynamic menu items for admin sidebar\n app.use('/admin/*', pluginMenuMiddleware())\n\n // Core routes\n // Routes are being imported incrementally from routes/*\n // Each route is tested and migrated one-by-one\n app.route('/api', apiRoutes)\n app.route('/api/media', apiMediaRoutes)\n app.route('/api/system', apiSystemRoutes)\n app.route('/admin/api', adminApiRoutes)\n app.route('/admin/dashboard', adminDashboardRoutes)\n app.route('/admin/collections', adminCollectionsRoutes)\n app.route('/admin/forms', adminFormsRoutes)\n app.route('/admin/settings', adminSettingsRoutes)\n app.route('/forms', publicFormsRoutes)\n app.route('/api/forms', publicFormsRoutes) // API endpoint for form submissions\n app.route('/admin/api-reference', adminApiReferenceRoutes)\n app.route('/admin/database-tools', createDatabaseToolsAdminRoutes())\n app.route('/admin/seed-data', createSeedDataAdminRoutes())\n app.route('/admin/content', adminContentRoutes)\n app.route('/admin/media', adminMediaRoutes)\n // Security audit middleware - logs auth events (login, register, logout)\n app.use('/auth/*', securityAuditMiddleware())\n\n // Plugin routes - Security Audit (MUST be registered BEFORE admin/plugins to avoid route conflict)\n if (securityAuditPlugin.routes && securityAuditPlugin.routes.length > 0) {\n for (const route of securityAuditPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - AI Search (MUST be registered BEFORE admin/plugins to avoid route conflict)\n // Register AI Search routes first so they take precedence over the generic /:id handler\n if (aiSearchPlugin.routes && aiSearchPlugin.routes.length > 0) {\n for (const route of aiSearchPlugin.routes) {\n app.route(route.path, route.handler)\n }\n }\n\n // Plugin routes - Cache (dashboard and management API)\n // Fixes GitHub Issue #461: Cache routes were not registered\n app.route('/admin/cache', cachePlugin.getRoutes())\n\n // Plugin routes - OAuth Providers (MUST be registered BEFORE admin/plugins to avoid route conflict)\n if (oauthProvidersPlugin.routes && oauthProvidersPlugin.routes.length > 0) {\n for (const route of oauthProvidersPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - User Profiles\n if (userProfilesPlugin.routes && userProfilesPlugin.routes.length > 0) {\n for (const route of userProfilesPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - OTP Login (MUST be registered BEFORE admin/plugins to avoid route conflict)\n // Register OTP Login routes first so they take precedence over the generic /:id handler\n if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {\n for (const route of otpLoginPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n app.route('/admin/plugins', adminPluginRoutes)\n app.route('/admin/logs', adminLogsRoutes)\n app.route('/admin', adminUsersRoutes)\n app.route('/auth', authRoutes)\n\n // Test cleanup routes (only for development/test environments)\n app.route('/', testCleanupRoutes)\n\n // Plugin routes - Stripe (subscriptions, webhook, checkout)\n if (stripePlugin.routes && stripePlugin.routes.length > 0) {\n for (const route of stripePlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - Email\n if (emailPlugin.routes && emailPlugin.routes.length > 0) {\n for (const route of emailPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Plugin routes - Magic Link Auth (passwordless authentication via email links)\n const magicLinkPlugin = createMagicLinkAuthPlugin()\n if (magicLinkPlugin.routes && magicLinkPlugin.routes.length > 0) {\n for (const route of magicLinkPlugin.routes) {\n app.route(route.path, route.handler as any)\n }\n }\n\n // Serve favicon\n app.get('/favicon.svg', (c) => {\n return new Response(faviconSvg, {\n headers: {\n 'Content-Type': 'image/svg+xml',\n 'Cache-Control': 'public, max-age=31536000'\n }\n })\n })\n\n // Serve files from R2 storage (public file access)\n app.get('/files/*', async (c) => {\n try {\n // Extract the path from the URL pathname (everything after /files/)\n const url = new URL(c.req.url)\n const pathname = url.pathname\n\n // Remove the /files/ prefix to get the R2 object key\n const objectKey = pathname.replace(/^\\/files\\//, '')\n\n if (!objectKey) {\n return c.notFound()\n }\n\n // Get file from R2\n const object = await c.env.MEDIA_BUCKET.get(objectKey)\n\n if (!object) {\n return c.notFound()\n }\n\n // Set appropriate headers\n const headers = new Headers()\n object.httpMetadata?.contentType && headers.set('Content-Type', object.httpMetadata.contentType)\n object.httpMetadata?.contentDisposition && headers.set('Content-Disposition', object.httpMetadata.contentDisposition)\n headers.set('Cache-Control', 'public, max-age=31536000') // 1 year cache\n headers.set('Access-Control-Allow-Origin', '*') // Allow CORS for media files\n headers.set('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS')\n headers.set('Access-Control-Allow-Headers', 'Content-Type')\n\n return new Response(object.body as any, {\n headers\n })\n } catch (error) {\n console.error('Error serving file:', error)\n return c.notFound()\n }\n })\n\n // Custom routes - User-defined routes\n if (config.routes) {\n for (const route of config.routes) {\n app.route(route.path, route.handler)\n }\n }\n\n // Root redirect to login\n app.get('/', (c) => {\n return c.redirect('/auth/login')\n })\n\n // Health check\n app.get('/health', (c) => {\n return c.json({\n name: appName,\n version: appVersion,\n status: 'running',\n timestamp: new Date().toISOString()\n })\n })\n\n // Store app instance for route introspection (API reference auto-discovery)\n setAppInstance(app)\n\n // 404 handler\n app.notFound((c) => {\n return c.json({ error: 'Not Found', status: 404 }, 404)\n })\n\n // Error handler\n app.onError((err, c) => {\n console.error(err)\n return c.json({ error: 'Internal Server Error', status: 500 }, 500)\n })\n\n return app\n}\n\n/**\n * Setup core middleware (backward compatibility)\n *\n * @param _app - Hono application\n * @deprecated Use createSonicJSApp() instead\n */\nexport function setupCoreMiddleware(_app: SonicJSApp): void {\n console.warn('setupCoreMiddleware is deprecated. Use createSonicJSApp() instead.')\n // Backward compatibility implementation\n}\n\n/**\n * Setup core routes (backward compatibility)\n *\n * @param _app - Hono application\n * @deprecated Use createSonicJSApp() instead\n */\nexport function setupCoreRoutes(_app: SonicJSApp): void {\n console.warn('setupCoreRoutes is deprecated. Use createSonicJSApp() instead.')\n // Backward compatibility implementation\n}\n","import { drizzle } from 'drizzle-orm/d1';\nimport * as schema from './schema';\n\nexport function createDb(d1: D1Database) {\n return drizzle(d1, { schema });\n}\n\nexport * from './schema';","/**\n * @sonicjs/core - Main Entry Point\n *\n * Core framework for SonicJS headless CMS\n * Built for Cloudflare's edge platform with TypeScript\n *\n * Phase 2 Migration Status:\n * - Week 1: Types, Utils, Database (COMPLETED ✓)\n * - Week 2: Services, Middleware, Plugins (COMPLETED ✓)\n * - Week 3: Routes, Templates (COMPLETED ✓)\n * - Week 4: Integration & Testing (COMPLETED ✓)\n *\n * Test Coverage:\n * - Utilities: 48 tests (sanitize, query-filter, metrics)\n * - Middleware: 51 tests (auth, logging, security, performance)\n * - Total: 99 tests passing\n */\n\n// ============================================================================\n// Main Application API (Phase 2 Week 1)\n// ============================================================================\n\nexport { createSonicJSApp, setupCoreMiddleware, setupCoreRoutes } from './app'\nexport type { SonicJSConfig, SonicJSApp, Bindings, Variables } from './app'\n\n// ============================================================================\n// Placeholders - To be populated in Phase 2\n// ============================================================================\n\n// Services - Week 2 (COMPLETED)\nexport {\n // Collection Management\n loadCollectionConfigs,\n loadCollectionConfig,\n getAvailableCollectionNames,\n validateCollectionConfig,\n registerCollections,\n syncCollections,\n syncCollection,\n isCollectionManaged,\n getManagedCollections,\n cleanupRemovedCollections,\n fullCollectionSync,\n // Form-Collection Sync\n syncAllFormCollections,\n syncFormCollection,\n createContentFromSubmission,\n deriveCollectionSchemaFromFormio,\n deriveSubmissionTitle,\n mapFormStatusToContentStatus,\n backfillFormSubmissions,\n // Database Migrations\n MigrationService,\n // Logging\n Logger,\n getLogger,\n initLogger,\n // Plugin Services - Class implementations\n PluginService as PluginServiceClass,\n PluginBootstrapService,\n} from './services'\n\nexport type { Migration, MigrationStatus, LogLevel, LogCategory, LogEntry, LogFilter, CorePlugin } from './services'\n\n// Middleware - Week 2 (COMPLETED)\nexport {\n // Authentication\n AuthManager,\n requireAuth,\n requireRole,\n optionalAuth,\n // Logging\n loggingMiddleware,\n detailedLoggingMiddleware,\n securityLoggingMiddleware,\n performanceLoggingMiddleware,\n // Performance\n cacheHeaders,\n compressionMiddleware,\n securityHeaders,\n // Permissions\n PermissionManager,\n requirePermission,\n requireAnyPermission,\n logActivity,\n // Plugin middleware\n requireActivePlugin,\n requireActivePlugins,\n getActivePlugins,\n isPluginActive,\n // Bootstrap\n bootstrapMiddleware,\n} from './middleware'\n\nexport type { Permission, UserPermissions } from './middleware'\n\n// Plugins - Week 2 (COMPLETED)\nexport {\n // Hook System - Class implementations\n HookSystemImpl,\n ScopedHookSystem as ScopedHookSystemClass,\n HookUtils,\n // Plugin Registry\n PluginRegistryImpl,\n // Plugin Manager - Class implementation\n PluginManager as PluginManagerClass,\n // Plugin Validator - Class implementation\n PluginValidator as PluginValidatorClass,\n} from './plugins'\n\n// Routes - Week 3 (COMPLETED)\nexport {\n ROUTES_INFO,\n apiRoutes,\n apiContentCrudRoutes,\n apiMediaRoutes,\n apiSystemRoutes,\n adminApiRoutes,\n authRoutes,\n adminContentRoutes,\n adminUsersRoutes,\n adminMediaRoutes,\n adminLogsRoutes,\n adminPluginRoutes,\n adminDesignRoutes,\n adminCheckboxRoutes,\n adminTestimonialsRoutes,\n adminCodeExamplesRoutes,\n adminDashboardRoutes,\n adminCollectionsRoutes,\n adminSettingsRoutes,\n} from './routes'\n\n// Templates - Week 3 (COMPLETED)\nexport {\n // Form templates\n renderForm,\n renderFormField,\n // Table templates\n renderTable,\n // Pagination templates\n renderPagination,\n // Alert templates\n renderAlert,\n // Confirmation dialog templates\n renderConfirmationDialog,\n getConfirmationDialogScript,\n // Filter bar templates\n renderFilterBar,\n} from './templates'\n\nexport type {\n FormField,\n FormData,\n TableColumn,\n TableData,\n PaginationData,\n AlertData,\n ConfirmationDialogOptions,\n FilterBarData,\n Filter,\n FilterOption,\n} from './templates'\n\n// Types - Week 1 (COMPLETED)\nexport type {\n // Collection types\n FieldType,\n FieldConfig,\n CollectionSchema,\n CollectionConfig,\n CollectionConfigModule,\n CollectionSyncResult,\n // Plugin types\n Plugin,\n PluginContext,\n PluginConfig,\n PluginRoutes,\n PluginMiddleware,\n PluginModel,\n PluginService,\n PluginAdminPage,\n PluginComponent,\n PluginMenuItem,\n PluginHook,\n HookHandler,\n HookContext,\n HookSystem,\n ScopedHookSystem,\n PluginRegistry,\n PluginManager,\n PluginStatus,\n AuthService,\n ContentService,\n MediaService,\n PluginLogger,\n PluginBuilderOptions,\n PluginValidator,\n PluginValidationResult,\n HookName,\n // Plugin manifest\n PluginManifest,\n} from './types'\n\nexport { HOOKS } from './types'\n\n// Utils - Week 1 (COMPLETED)\nexport {\n // Sanitization\n escapeHtml,\n sanitizeInput,\n sanitizeObject,\n // Template rendering\n TemplateRenderer,\n templateRenderer,\n renderTemplate,\n // Query filtering\n QueryFilterBuilder,\n buildQuery,\n // Metrics\n metricsTracker,\n // Version\n SONICJS_VERSION,\n getCoreVersion,\n} from './utils'\n\nexport type {\n FilterOperator,\n FilterCondition,\n FilterGroup,\n QueryFilter,\n QueryResult,\n} from './utils'\n\n// Database - Week 1 (COMPLETED)\nexport {\n createDb,\n // Schema exports\n users,\n collections,\n content,\n contentVersions,\n media,\n apiTokens,\n workflowHistory,\n plugins,\n pluginHooks,\n pluginRoutes,\n pluginAssets,\n pluginActivityLog,\n systemLogs,\n logConfig,\n // Zod validation schemas\n insertUserSchema,\n selectUserSchema,\n insertCollectionSchema,\n selectCollectionSchema,\n insertContentSchema,\n selectContentSchema,\n insertMediaSchema,\n selectMediaSchema,\n insertWorkflowHistorySchema,\n selectWorkflowHistorySchema,\n insertPluginSchema,\n selectPluginSchema,\n insertPluginHookSchema,\n selectPluginHookSchema,\n insertPluginRouteSchema,\n selectPluginRouteSchema,\n insertPluginAssetSchema,\n selectPluginAssetSchema,\n insertPluginActivityLogSchema,\n selectPluginActivityLogSchema,\n insertSystemLogSchema,\n selectSystemLogSchema,\n insertLogConfigSchema,\n selectLogConfigSchema,\n} from './db'\n\nexport type {\n User,\n NewUser,\n Collection,\n NewCollection,\n Content,\n NewContent,\n Media,\n NewMedia,\n WorkflowHistory,\n NewWorkflowHistory,\n Plugin as DbPlugin,\n NewPlugin,\n PluginHook as DbPluginHook,\n NewPluginHook,\n PluginRoute,\n NewPluginRoute,\n PluginAsset,\n NewPluginAsset,\n PluginActivityLog,\n NewPluginActivityLog,\n SystemLog,\n NewSystemLog,\n LogConfig,\n NewLogConfig,\n} from './db'\n\n// Plugin SDK (Beta)\nexport { PluginBuilder, PluginHelpers } from './plugins/sdk'\n\n// OAuth Providers Plugin\nexport { oauthProvidersPlugin, createOAuthProvidersPlugin } from './plugins/core-plugins/oauth-providers'\nexport { OAuthService, BUILT_IN_PROVIDERS } from './plugins/core-plugins/oauth-providers/oauth-service'\n\n// User Profiles Plugin\nexport { userProfilesPlugin, createUserProfilesPlugin, defineUserProfile, getUserProfileConfig } from './plugins/core-plugins/user-profiles'\nexport type { ProfileFieldDefinition, UserProfileConfig } from './plugins/core-plugins/user-profiles'\n\n// ============================================================================\n// Version\n// ============================================================================\n\n// Import version from package.json\nimport packageJson from '../package.json'\nexport const VERSION = packageJson.version\n\n// ============================================================================\n// Phase 2 Migration Notes\n// ============================================================================\n\n/**\n * This is a work-in-progress package being extracted from the main SonicJS codebase.\n *\n * Current Phase: 2 (Core Module Migration)\n * Current Week: 1 (Types, Utils, Database)\n *\n * Expected completion: 4 weeks from 2025-01-17\n *\n * DO NOT USE IN PRODUCTION - Alpha release for development only\n */\n"]}
|