@sonicjs-cms/core 2.6.0 → 2.7.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-63K7XXRX.cjs → chunk-AYPF6C4D.cjs} +5 -5
- package/dist/{chunk-63K7XXRX.cjs.map → chunk-AYPF6C4D.cjs.map} +1 -1
- package/dist/{chunk-7DL5SPPX.js → chunk-DNHJS6RN.js} +3 -3
- package/dist/{chunk-7DL5SPPX.js.map → chunk-DNHJS6RN.js.map} +1 -1
- package/dist/{chunk-T3YIKW2A.cjs → chunk-E2BXLXPW.cjs} +4 -4
- package/dist/{chunk-T3YIKW2A.cjs.map → chunk-E2BXLXPW.cjs.map} +1 -1
- package/dist/{chunk-BZC4FYW7.cjs → chunk-EHSZ6TAN.cjs} +9 -2
- package/dist/chunk-EHSZ6TAN.cjs.map +1 -0
- package/dist/{chunk-KA2PDJNB.js → chunk-GRN3GHUG.js} +9 -2
- package/dist/chunk-GRN3GHUG.js.map +1 -0
- package/dist/{chunk-N7TDLOUE.cjs → chunk-J7F3NPAP.cjs} +208 -182
- package/dist/chunk-J7F3NPAP.cjs.map +1 -0
- package/dist/{chunk-EVZOVYLO.js → chunk-L2IDZI7F.js} +2 -2
- package/dist/{chunk-EVZOVYLO.js.map → chunk-L2IDZI7F.js.map} +1 -1
- package/dist/{chunk-YMTTGHEK.cjs → chunk-MYB5RY7H.cjs} +3 -3
- package/dist/{chunk-YMTTGHEK.cjs.map → chunk-MYB5RY7H.cjs.map} +1 -1
- package/dist/{chunk-F6GZURXJ.js → chunk-UISZ2MBW.js} +50 -26
- package/dist/chunk-UISZ2MBW.js.map +1 -0
- package/dist/{chunk-KAOWRIFD.js → chunk-V3KVSEG6.js} +3 -3
- package/dist/{chunk-KAOWRIFD.js.map → chunk-V3KVSEG6.js.map} +1 -1
- package/dist/{chunk-EYWR6UA2.js → chunk-Y3EWJQ4D.js} +3 -3
- package/dist/{chunk-EYWR6UA2.js.map → chunk-Y3EWJQ4D.js.map} +1 -1
- package/dist/{chunk-IIRVZSP2.cjs → chunk-YRFAQ6MI.cjs} +2 -2
- package/dist/{chunk-IIRVZSP2.cjs.map → chunk-YRFAQ6MI.cjs.map} +1 -1
- package/dist/index.cjs +1940 -122
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1874 -56
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +23 -23
- package/dist/middleware.js +2 -2
- package/dist/migrations-LEMFV2ND.cjs +13 -0
- package/dist/{migrations-QNYAWQLB.cjs.map → migrations-LEMFV2ND.cjs.map} +1 -1
- package/dist/migrations-RKQES6XY.js +4 -0
- package/dist/{migrations-R6NQBKQV.js.map → migrations-RKQES6XY.js.map} +1 -1
- package/dist/routes.cjs +25 -25
- package/dist/routes.js +5 -5
- package/dist/services.cjs +2 -2
- package/dist/services.js +1 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +14 -14
- package/dist/utils.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-BZC4FYW7.cjs.map +0 -1
- package/dist/chunk-F6GZURXJ.js.map +0 -1
- package/dist/chunk-KA2PDJNB.js.map +0 -1
- package/dist/chunk-N7TDLOUE.cjs.map +0 -1
- package/dist/migrations-QNYAWQLB.cjs +0 -13
- package/dist/migrations-R6NQBKQV.js +0 -4
package/dist/index.js.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/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/assets/favicon.ts","../src/app.ts","../src/db/index.ts","../src/index.ts"],"names":["escapeHtml","router","Hono","html","emailPlugin","adminRoutes","content","collections","api_default","z"],"mappings":"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","file":"index.js","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 { html } from 'hono/html'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\nimport { renderAdminLayout } from '../../../templates/layouts/admin-layout-v2.template'\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\n const emailRoutes = new Hono()\n\n emailRoutes.get('/settings', async (c: any) => {\n const user = c.get('user') as { email?: string; role?: string; name?: string } | undefined\n const db = c.env.DB\n\n // Load current 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 const settings = plugin?.settings ? JSON.parse(plugin.settings) : {}\n\n const contentHTML = await html`\n <div class=\"p-8\">\n <!-- Header -->\n <div class=\"mb-8\">\n <h1 class=\"text-3xl font-bold text-zinc-950 dark:text-white mb-2\">Email Settings</h1>\n <p class=\"text-zinc-600 dark:text-zinc-400\">Configure Resend API for sending transactional emails</p>\n </div>\n\n <!-- Settings Form -->\n <div class=\"max-w-3xl\">\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 <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">Resend Configuration</h2>\n\n <form id=\"emailSettingsForm\" class=\"space-y-6\">\n <!-- API Key -->\n <div>\n <label for=\"apiKey\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Resend API Key <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"password\"\n id=\"apiKey\"\n name=\"apiKey\"\n value=\"${settings.apiKey || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"re_...\"\n required\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Get your API key from <a href=\"https://resend.com/api-keys\" target=\"_blank\" class=\"text-indigo-600 dark:text-indigo-400 hover:underline\">resend.com/api-keys</a>\n </p>\n </div>\n\n <!-- From Email -->\n <div>\n <label for=\"fromEmail\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n From Email <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"email\"\n id=\"fromEmail\"\n name=\"fromEmail\"\n value=\"${settings.fromEmail || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"noreply@yourdomain.com\"\n required\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Must be a verified domain in Resend\n </p>\n </div>\n\n <!-- From Name -->\n <div>\n <label for=\"fromName\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n From Name <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n id=\"fromName\"\n name=\"fromName\"\n value=\"${settings.fromName || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"Your App Name\"\n required\n />\n </div>\n\n <!-- Reply To -->\n <div>\n <label for=\"replyTo\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Reply-To Email\n </label>\n <input\n type=\"email\"\n id=\"replyTo\"\n name=\"replyTo\"\n value=\"${settings.replyTo || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"support@yourdomain.com\"\n />\n </div>\n\n <!-- Logo URL -->\n <div>\n <label for=\"logoUrl\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Logo URL\n </label>\n <input\n type=\"url\"\n id=\"logoUrl\"\n name=\"logoUrl\"\n value=\"${settings.logoUrl || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"https://yourdomain.com/logo.png\"\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Logo to display in email templates\n </p>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"flex gap-3 pt-4\">\n <button\n type=\"submit\"\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 >\n Save Settings\n </button>\n <button\n type=\"button\"\n id=\"testEmailBtn\"\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 Send Test Email\n </button>\n <button\n type=\"button\"\n id=\"resetBtn\"\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 Reset\n </button>\n </div>\n </form>\n </div>\n\n <!-- Status Message -->\n <div id=\"statusMessage\" class=\"hidden rounded-xl p-4 mb-6\"></div>\n\n <!-- Info Card -->\n <div class=\"rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-6\">\n <h3 class=\"font-semibold text-indigo-900 dark:text-indigo-300 mb-3\">\n 📧 Email Templates Included\n </h3>\n <ul class=\"text-sm text-indigo-800 dark:text-indigo-200 space-y-2\">\n <li>✓ Registration confirmation</li>\n <li>✓ Email verification</li>\n <li>✓ Password reset</li>\n <li>✓ One-time code (2FA)</li>\n </ul>\n <p class=\"text-xs text-indigo-700 dark:text-indigo-300 mt-4\">\n Templates are code-based and can be customized by editing the plugin files.\n </p>\n </div>\n </div>\n </div>\n\n <script>\n // Form submission handler\n document.getElementById('emailSettingsForm').addEventListener('submit', async (e) => {\n e.preventDefault()\n const formData = new FormData(e.target)\n const data = Object.fromEntries(formData.entries())\n\n const statusEl = document.getElementById('statusMessage')\n\n try {\n const response = await fetch('/admin/plugins/email/settings', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data)\n })\n\n if (response.ok) {\n statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'\n statusEl.innerHTML = '✅ Settings saved successfully!'\n statusEl.classList.remove('hidden')\n setTimeout(() => statusEl.classList.add('hidden'), 3000)\n } else {\n throw new Error('Failed to save settings')\n }\n } catch (error) {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = '❌ Failed to save settings. Please try again.'\n statusEl.classList.remove('hidden')\n }\n })\n\n // Test email handler\n document.getElementById('testEmailBtn').addEventListener('click', async () => {\n // Prompt for destination email\n const toEmail = prompt('Enter destination email address for test:')\n if (!toEmail) return\n\n // Basic email validation\n if (!toEmail.match(/^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$/)) {\n alert('Please enter a valid email address')\n return\n }\n\n const statusEl = document.getElementById('statusMessage')\n\n statusEl.className = 'rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-4 mb-6 text-indigo-900 dark:text-indigo-200'\n statusEl.innerHTML = \\`📧 Sending test email to \\${toEmail}...\\`\n statusEl.classList.remove('hidden')\n\n try {\n const response = await fetch('/admin/plugins/email/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ toEmail })\n })\n\n const data = await response.json()\n\n if (response.ok) {\n statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'\n statusEl.innerHTML = \\`✅ \\${data.message || 'Test email sent! Check your inbox.'}\\`\n } else {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = \\`❌ \\${data.error || 'Failed to send test email. Check your settings.'}\\`\n }\n } catch (error) {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = '❌ Network error. Please try again.'\n }\n })\n\n // Reset button handler\n document.getElementById('resetBtn').addEventListener('click', () => {\n document.getElementById('emailSettingsForm').reset()\n })\n </script>\n `\n\n const templateUser = user ? {\n name: user.name ?? user.email ?? 'Admin',\n email: user.email ?? 'admin@sonicjs.com',\n role: user.role ?? 'admin'\n } : undefined\n\n return c.html(\n renderAdminLayout({\n title: 'Email Settings',\n content: contentHTML,\n user: templateUser,\n currentPath: '/admin/plugins/email/settings'\n })\n )\n })\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\n builder.addMenuItem('Email', '/admin/plugins/email/settings', {\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 appName: 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 { html } from 'hono/html'\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 { adminLayoutV2 } from '../../../templates/layouts/admin-layout-v2.template'\nimport { AuthManager } from '../../../middleware'\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\nconst DEFAULT_SETTINGS: OTPSettings = {\n codeLength: 6,\n codeExpiryMinutes: 10,\n maxAttempts: 3,\n rateLimitPerHour: 5,\n allowNewUserRegistration: false,\n appName: 'SonicJS'\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 const settings = { ...DEFAULT_SETTINGS } // TODO: Load from plugin settings\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: settings.appName\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 ${settings.appName}`,\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 const settings = { ...DEFAULT_SETTINGS } // TODO: Load from plugin settings\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 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) {\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)\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 // ==================== Admin UI Routes ====================\n\n const adminRoutes = new Hono()\n\n // Settings page\n adminRoutes.get('/settings', async (c: any) => {\n const user = c.get('user') as { email?: string; role?: string; name?: string } | undefined\n\n const contentHTML = await html`\n <div class=\"p-8\">\n <div class=\"mb-8\">\n <h1 class=\"text-3xl font-bold mb-2\">OTP Login Settings</h1>\n <p class=\"text-zinc-600 dark:text-zinc-400\">Configure passwordless authentication via email codes</p>\n </div>\n\n <div class=\"max-w-3xl\">\n <div class=\"backdrop-blur-md bg-black/20 border border-white/10 shadow-xl rounded-xl p-6 mb-6\">\n <h2 class=\"text-xl font-semibold mb-4\">Code Settings</h2>\n\n <form id=\"otpSettingsForm\" class=\"space-y-6\">\n <div>\n <label for=\"codeLength\" class=\"block text-sm font-medium mb-2\">\n Code Length\n </label>\n <input\n type=\"number\"\n id=\"codeLength\"\n name=\"codeLength\"\n min=\"4\"\n max=\"8\"\n value=\"6\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Number of digits in OTP code (4-8)</p>\n </div>\n\n <div>\n <label for=\"codeExpiryMinutes\" class=\"block text-sm font-medium mb-2\">\n Code Expiry (minutes)\n </label>\n <input\n type=\"number\"\n id=\"codeExpiryMinutes\"\n name=\"codeExpiryMinutes\"\n min=\"5\"\n max=\"60\"\n value=\"10\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">How long codes remain valid (5-60 minutes)</p>\n </div>\n\n <div>\n <label for=\"maxAttempts\" class=\"block text-sm font-medium mb-2\">\n Maximum Attempts\n </label>\n <input\n type=\"number\"\n id=\"maxAttempts\"\n name=\"maxAttempts\"\n min=\"3\"\n max=\"10\"\n value=\"3\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Max verification attempts before invalidation</p>\n </div>\n\n <div>\n <label for=\"rateLimitPerHour\" class=\"block text-sm font-medium mb-2\">\n Rate Limit (per hour)\n </label>\n <input\n type=\"number\"\n id=\"rateLimitPerHour\"\n name=\"rateLimitPerHour\"\n min=\"3\"\n max=\"20\"\n value=\"5\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Max code requests per email per hour</p>\n </div>\n\n <div class=\"flex items-center\">\n <input\n type=\"checkbox\"\n id=\"allowNewUserRegistration\"\n name=\"allowNewUserRegistration\"\n class=\"w-4 h-4 rounded border-white/10\"\n />\n <label for=\"allowNewUserRegistration\" class=\"ml-2 text-sm\">\n Allow new user registration via OTP\n </label>\n </div>\n\n <div class=\"flex gap-3 pt-4\">\n <button\n type=\"submit\"\n class=\"px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-purple-700 transition-all\"\n >\n Save Settings\n </button>\n <button\n type=\"button\"\n id=\"testOTPBtn\"\n class=\"px-6 py-2 bg-white/10 hover:bg-white/20 text-white rounded-lg font-medium transition-all\"\n >\n Send Test Code\n </button>\n </div>\n </form>\n </div>\n\n <div id=\"statusMessage\" class=\"hidden backdrop-blur-md bg-black/20 border border-white/10 rounded-xl p-4 mb-6\"></div>\n\n <div class=\"backdrop-blur-md bg-blue-500/10 border border-blue-500/20 rounded-xl p-6\">\n <h3 class=\"font-semibold text-blue-400 mb-3\">\n 🔢 Features\n </h3>\n <ul class=\"text-sm text-blue-200 space-y-2\">\n <li>✓ Passwordless authentication</li>\n <li>✓ Secure random code generation</li>\n <li>✓ Rate limiting protection</li>\n <li>✓ Brute force prevention</li>\n <li>✓ Mobile-friendly UX</li>\n </ul>\n </div>\n </div>\n </div>\n\n <script>\n document.getElementById('otpSettingsForm').addEventListener('submit', async (e) => {\n e.preventDefault()\n const statusEl = document.getElementById('statusMessage')\n statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '✅ Settings saved successfully!'\n statusEl.classList.remove('hidden')\n setTimeout(() => statusEl.classList.add('hidden'), 3000)\n })\n\n document.getElementById('testOTPBtn').addEventListener('click', async () => {\n const email = prompt('Enter email address for test:')\n if (!email) return\n\n const statusEl = document.getElementById('statusMessage')\n statusEl.className = 'backdrop-blur-md bg-blue-500/20 border border-blue-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '📧 Sending test code...'\n statusEl.classList.remove('hidden')\n\n try {\n const response = await fetch('/auth/otp/request', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email })\n })\n\n const data = await response.json()\n\n if (response.ok) {\n statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '✅ Test code sent!' + (data.dev_code ? \\` Code: <strong>\\${data.dev_code}</strong>\\` : '')\n } else {\n throw new Error(data.error || 'Failed')\n }\n } catch (error) {\n statusEl.className = 'backdrop-blur-md bg-red-500/20 border border-red-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '❌ Failed to send test code'\n }\n })\n </script>\n `\n\n const templateUser = user ? {\n name: user.name ?? user.email ?? 'Admin',\n email: user.email ?? 'admin@sonicjs.com',\n role: user.role ?? 'admin'\n } : undefined\n\n return c.html(\n adminLayoutV2({\n title: 'OTP Login Settings',\n content: contentHTML,\n user: templateUser,\n currentPath: '/admin/plugins/otp-login/settings'\n })\n )\n })\n\n // Register admin routes\n builder.addRoute('/admin/plugins/otp-login', adminRoutes, {\n description: 'OTP login admin interface',\n requiresAuth: true,\n priority: 85\n })\n\n // Add menu item\n builder.addMenuItem('OTP Login', '/admin/plugins/otp-login/settings', {\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 * 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\": \"search\",\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 )\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","/**\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} from './routes'\nimport { getCoreVersion } from './utils/version'\nimport { bootstrapMiddleware } from './middleware/bootstrap'\nimport { metricsMiddleware } from './middleware/metrics'\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 { aiSearchPlugin } from './plugins/core-plugins/ai-search-plugin'\nimport { createMagicLinkAuthPlugin } from './plugins/available/magic-link-auth'\nimport { faviconSvg } from './assets/favicon'\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 BUCKET_NAME?: 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}\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('*', async (_c, next) => {\n // Security headers, CORS, etc.\n await next()\n })\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 // 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/settings', adminSettingsRoutes)\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 // 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 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)\n }\n }\n\n // Plugin routes - OTP Login (passwordless authentication via email codes)\n if (otpLoginPlugin.routes && otpLoginPlugin.routes.length > 0) {\n for (const route of otpLoginPlugin.routes) {\n app.route(route.path, route.handler)\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)\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 // 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 // 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// ============================================================================\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/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/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":["escapeHtml","router","Hono","html","plugin","emailPlugin","adminRoutes","content","collections","api_default","z","media","renderConfirmationDialog","getConfirmationDialogScript","totalRequests","app"],"mappings":"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","file":"index.js","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 { html } from 'hono/html'\nimport { PluginBuilder } from '../../sdk/plugin-builder'\nimport type { Plugin } from '@sonicjs-cms/core'\nimport { renderAdminLayout } from '../../../templates/layouts/admin-layout-v2.template'\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\n const emailRoutes = new Hono()\n\n emailRoutes.get('/settings', async (c: any) => {\n const user = c.get('user') as { email?: string; role?: string; name?: string } | undefined\n const db = c.env.DB\n\n // Load current 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 const settings = plugin?.settings ? JSON.parse(plugin.settings) : {}\n\n const contentHTML = await html`\n <div class=\"p-8\">\n <!-- Header -->\n <div class=\"mb-8\">\n <h1 class=\"text-3xl font-bold text-zinc-950 dark:text-white mb-2\">Email Settings</h1>\n <p class=\"text-zinc-600 dark:text-zinc-400\">Configure Resend API for sending transactional emails</p>\n </div>\n\n <!-- Settings Form -->\n <div class=\"max-w-3xl\">\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 <h2 class=\"text-xl font-semibold text-zinc-950 dark:text-white mb-4\">Resend Configuration</h2>\n\n <form id=\"emailSettingsForm\" class=\"space-y-6\">\n <!-- API Key -->\n <div>\n <label for=\"apiKey\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Resend API Key <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"password\"\n id=\"apiKey\"\n name=\"apiKey\"\n value=\"${settings.apiKey || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"re_...\"\n required\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Get your API key from <a href=\"https://resend.com/api-keys\" target=\"_blank\" class=\"text-indigo-600 dark:text-indigo-400 hover:underline\">resend.com/api-keys</a>\n </p>\n </div>\n\n <!-- From Email -->\n <div>\n <label for=\"fromEmail\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n From Email <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"email\"\n id=\"fromEmail\"\n name=\"fromEmail\"\n value=\"${settings.fromEmail || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"noreply@yourdomain.com\"\n required\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Must be a verified domain in Resend\n </p>\n </div>\n\n <!-- From Name -->\n <div>\n <label for=\"fromName\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n From Name <span class=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n id=\"fromName\"\n name=\"fromName\"\n value=\"${settings.fromName || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"Your App Name\"\n required\n />\n </div>\n\n <!-- Reply To -->\n <div>\n <label for=\"replyTo\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Reply-To Email\n </label>\n <input\n type=\"email\"\n id=\"replyTo\"\n name=\"replyTo\"\n value=\"${settings.replyTo || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"support@yourdomain.com\"\n />\n </div>\n\n <!-- Logo URL -->\n <div>\n <label for=\"logoUrl\" class=\"block text-sm font-medium text-zinc-950 dark:text-white mb-2\">\n Logo URL\n </label>\n <input\n type=\"url\"\n id=\"logoUrl\"\n name=\"logoUrl\"\n value=\"${settings.logoUrl || ''}\"\n 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 placeholder:text-zinc-500 dark:placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 dark:focus:ring-indigo-400\"\n placeholder=\"https://yourdomain.com/logo.png\"\n />\n <p class=\"text-xs text-zinc-500 dark:text-zinc-400 mt-1\">\n Logo to display in email templates\n </p>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"flex gap-3 pt-4\">\n <button\n type=\"submit\"\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 >\n Save Settings\n </button>\n <button\n type=\"button\"\n id=\"testEmailBtn\"\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 Send Test Email\n </button>\n <button\n type=\"button\"\n id=\"resetBtn\"\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 Reset\n </button>\n </div>\n </form>\n </div>\n\n <!-- Status Message -->\n <div id=\"statusMessage\" class=\"hidden rounded-xl p-4 mb-6\"></div>\n\n <!-- Info Card -->\n <div class=\"rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-6\">\n <h3 class=\"font-semibold text-indigo-900 dark:text-indigo-300 mb-3\">\n 📧 Email Templates Included\n </h3>\n <ul class=\"text-sm text-indigo-800 dark:text-indigo-200 space-y-2\">\n <li>✓ Registration confirmation</li>\n <li>✓ Email verification</li>\n <li>✓ Password reset</li>\n <li>✓ One-time code (2FA)</li>\n </ul>\n <p class=\"text-xs text-indigo-700 dark:text-indigo-300 mt-4\">\n Templates are code-based and can be customized by editing the plugin files.\n </p>\n </div>\n </div>\n </div>\n\n <script>\n // Form submission handler\n document.getElementById('emailSettingsForm').addEventListener('submit', async (e) => {\n e.preventDefault()\n const formData = new FormData(e.target)\n const data = Object.fromEntries(formData.entries())\n\n const statusEl = document.getElementById('statusMessage')\n\n try {\n const response = await fetch('/admin/plugins/email/settings', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data)\n })\n\n if (response.ok) {\n statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'\n statusEl.innerHTML = '✅ Settings saved successfully!'\n statusEl.classList.remove('hidden')\n setTimeout(() => statusEl.classList.add('hidden'), 3000)\n } else {\n throw new Error('Failed to save settings')\n }\n } catch (error) {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = '❌ Failed to save settings. Please try again.'\n statusEl.classList.remove('hidden')\n }\n })\n\n // Test email handler\n document.getElementById('testEmailBtn').addEventListener('click', async () => {\n // Prompt for destination email\n const toEmail = prompt('Enter destination email address for test:')\n if (!toEmail) return\n\n // Basic email validation\n if (!toEmail.match(/^[^\\\\s@]+@[^\\\\s@]+\\\\.[^\\\\s@]+$/)) {\n alert('Please enter a valid email address')\n return\n }\n\n const statusEl = document.getElementById('statusMessage')\n\n statusEl.className = 'rounded-xl bg-indigo-50 dark:bg-indigo-950/30 ring-1 ring-indigo-100 dark:ring-indigo-900/50 p-4 mb-6 text-indigo-900 dark:text-indigo-200'\n statusEl.innerHTML = \\`📧 Sending test email to \\${toEmail}...\\`\n statusEl.classList.remove('hidden')\n\n try {\n const response = await fetch('/admin/plugins/email/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ toEmail })\n })\n\n const data = await response.json()\n\n if (response.ok) {\n statusEl.className = 'rounded-xl bg-green-50 dark:bg-green-950/30 ring-1 ring-green-100 dark:ring-green-900/50 p-4 mb-6 text-green-900 dark:text-green-200'\n statusEl.innerHTML = \\`✅ \\${data.message || 'Test email sent! Check your inbox.'}\\`\n } else {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = \\`❌ \\${data.error || 'Failed to send test email. Check your settings.'}\\`\n }\n } catch (error) {\n statusEl.className = 'rounded-xl bg-red-50 dark:bg-red-950/30 ring-1 ring-red-100 dark:ring-red-900/50 p-4 mb-6 text-red-900 dark:text-red-200'\n statusEl.innerHTML = '❌ Network error. Please try again.'\n }\n })\n\n // Reset button handler\n document.getElementById('resetBtn').addEventListener('click', () => {\n document.getElementById('emailSettingsForm').reset()\n })\n </script>\n `\n\n const templateUser = user ? {\n name: user.name ?? user.email ?? 'Admin',\n email: user.email ?? 'admin@sonicjs.com',\n role: user.role ?? 'admin'\n } : undefined\n\n return c.html(\n renderAdminLayout({\n title: 'Email Settings',\n content: contentHTML,\n user: templateUser,\n currentPath: '/admin/plugins/email/settings'\n })\n )\n })\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\n builder.addMenuItem('Email', '/admin/plugins/email/settings', {\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 appName: 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 { html } from 'hono/html'\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 { adminLayoutV2 } from '../../../templates/layouts/admin-layout-v2.template'\nimport { AuthManager } from '../../../middleware'\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\nconst DEFAULT_SETTINGS: OTPSettings = {\n codeLength: 6,\n codeExpiryMinutes: 10,\n maxAttempts: 3,\n rateLimitPerHour: 5,\n allowNewUserRegistration: false,\n appName: 'SonicJS'\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 const settings = { ...DEFAULT_SETTINGS } // TODO: Load from plugin settings\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: settings.appName\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 ${settings.appName}`,\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 const settings = { ...DEFAULT_SETTINGS } // TODO: Load from plugin settings\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 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) {\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)\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 // ==================== Admin UI Routes ====================\n\n const adminRoutes = new Hono()\n\n // Settings page\n adminRoutes.get('/settings', async (c: any) => {\n const user = c.get('user') as { email?: string; role?: string; name?: string } | undefined\n\n const contentHTML = await html`\n <div class=\"p-8\">\n <div class=\"mb-8\">\n <h1 class=\"text-3xl font-bold mb-2\">OTP Login Settings</h1>\n <p class=\"text-zinc-600 dark:text-zinc-400\">Configure passwordless authentication via email codes</p>\n </div>\n\n <div class=\"max-w-3xl\">\n <div class=\"backdrop-blur-md bg-black/20 border border-white/10 shadow-xl rounded-xl p-6 mb-6\">\n <h2 class=\"text-xl font-semibold mb-4\">Code Settings</h2>\n\n <form id=\"otpSettingsForm\" class=\"space-y-6\">\n <div>\n <label for=\"codeLength\" class=\"block text-sm font-medium mb-2\">\n Code Length\n </label>\n <input\n type=\"number\"\n id=\"codeLength\"\n name=\"codeLength\"\n min=\"4\"\n max=\"8\"\n value=\"6\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Number of digits in OTP code (4-8)</p>\n </div>\n\n <div>\n <label for=\"codeExpiryMinutes\" class=\"block text-sm font-medium mb-2\">\n Code Expiry (minutes)\n </label>\n <input\n type=\"number\"\n id=\"codeExpiryMinutes\"\n name=\"codeExpiryMinutes\"\n min=\"5\"\n max=\"60\"\n value=\"10\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">How long codes remain valid (5-60 minutes)</p>\n </div>\n\n <div>\n <label for=\"maxAttempts\" class=\"block text-sm font-medium mb-2\">\n Maximum Attempts\n </label>\n <input\n type=\"number\"\n id=\"maxAttempts\"\n name=\"maxAttempts\"\n min=\"3\"\n max=\"10\"\n value=\"3\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Max verification attempts before invalidation</p>\n </div>\n\n <div>\n <label for=\"rateLimitPerHour\" class=\"block text-sm font-medium mb-2\">\n Rate Limit (per hour)\n </label>\n <input\n type=\"number\"\n id=\"rateLimitPerHour\"\n name=\"rateLimitPerHour\"\n min=\"3\"\n max=\"20\"\n value=\"5\"\n class=\"w-full px-4 py-2 rounded-lg bg-white/5 border border-white/10 focus:border-blue-500 focus:outline-none\"\n />\n <p class=\"text-xs text-zinc-500 mt-1\">Max code requests per email per hour</p>\n </div>\n\n <div class=\"flex items-center\">\n <input\n type=\"checkbox\"\n id=\"allowNewUserRegistration\"\n name=\"allowNewUserRegistration\"\n class=\"w-4 h-4 rounded border-white/10\"\n />\n <label for=\"allowNewUserRegistration\" class=\"ml-2 text-sm\">\n Allow new user registration via OTP\n </label>\n </div>\n\n <div class=\"flex gap-3 pt-4\">\n <button\n type=\"submit\"\n class=\"px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-lg font-medium hover:from-blue-600 hover:to-purple-700 transition-all\"\n >\n Save Settings\n </button>\n <button\n type=\"button\"\n id=\"testOTPBtn\"\n class=\"px-6 py-2 bg-white/10 hover:bg-white/20 text-white rounded-lg font-medium transition-all\"\n >\n Send Test Code\n </button>\n </div>\n </form>\n </div>\n\n <div id=\"statusMessage\" class=\"hidden backdrop-blur-md bg-black/20 border border-white/10 rounded-xl p-4 mb-6\"></div>\n\n <div class=\"backdrop-blur-md bg-blue-500/10 border border-blue-500/20 rounded-xl p-6\">\n <h3 class=\"font-semibold text-blue-400 mb-3\">\n 🔢 Features\n </h3>\n <ul class=\"text-sm text-blue-200 space-y-2\">\n <li>✓ Passwordless authentication</li>\n <li>✓ Secure random code generation</li>\n <li>✓ Rate limiting protection</li>\n <li>✓ Brute force prevention</li>\n <li>✓ Mobile-friendly UX</li>\n </ul>\n </div>\n </div>\n </div>\n\n <script>\n document.getElementById('otpSettingsForm').addEventListener('submit', async (e) => {\n e.preventDefault()\n const statusEl = document.getElementById('statusMessage')\n statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '✅ Settings saved successfully!'\n statusEl.classList.remove('hidden')\n setTimeout(() => statusEl.classList.add('hidden'), 3000)\n })\n\n document.getElementById('testOTPBtn').addEventListener('click', async () => {\n const email = prompt('Enter email address for test:')\n if (!email) return\n\n const statusEl = document.getElementById('statusMessage')\n statusEl.className = 'backdrop-blur-md bg-blue-500/20 border border-blue-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '📧 Sending test code...'\n statusEl.classList.remove('hidden')\n\n try {\n const response = await fetch('/auth/otp/request', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email })\n })\n\n const data = await response.json()\n\n if (response.ok) {\n statusEl.className = 'backdrop-blur-md bg-green-500/20 border border-green-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '✅ Test code sent!' + (data.dev_code ? \\` Code: <strong>\\${data.dev_code}</strong>\\` : '')\n } else {\n throw new Error(data.error || 'Failed')\n }\n } catch (error) {\n statusEl.className = 'backdrop-blur-md bg-red-500/20 border border-red-500/30 rounded-xl p-4 mb-6'\n statusEl.innerHTML = '❌ Failed to send test code'\n }\n })\n </script>\n `\n\n const templateUser = user ? {\n name: user.name ?? user.email ?? 'Admin',\n email: user.email ?? 'admin@sonicjs.com',\n role: user.role ?? 'admin'\n } : undefined\n\n return c.html(\n adminLayoutV2({\n title: 'OTP Login Settings',\n content: contentHTML,\n user: templateUser,\n currentPath: '/admin/plugins/otp-login/settings'\n })\n )\n })\n\n // Register admin routes\n builder.addRoute('/admin/plugins/otp-login', adminRoutes, {\n description: 'OTP login admin interface',\n requiresAuth: true,\n priority: 85\n })\n\n // Add menu item\n builder.addMenuItem('OTP Login', '/admin/plugins/otp-login/settings', {\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 * 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\": \"search\",\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 )\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","/**\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} from './routes'\nimport { getCoreVersion } from './utils/version'\nimport { bootstrapMiddleware } from './middleware/bootstrap'\nimport { metricsMiddleware } from './middleware/metrics'\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 { aiSearchPlugin } from './plugins/core-plugins/ai-search-plugin'\nimport { createMagicLinkAuthPlugin } from './plugins/available/magic-link-auth'\nimport cachePlugin from './plugins/cache'\nimport { faviconSvg } from './assets/favicon'\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 BUCKET_NAME?: 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}\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('*', async (_c, next) => {\n // Security headers, CORS, etc.\n await next()\n })\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 // 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/settings', adminSettingsRoutes)\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 // 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 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 - OTP Login (passwordless authentication via email codes)\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 // 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 // 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 // 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// ============================================================================\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"]}
|