@sonicjs-cms/core 2.0.9 → 2.1.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-22EFGHAX.cjs +801 -0
- package/dist/chunk-22EFGHAX.cjs.map +1 -0
- package/dist/{chunk-TMIRVVQ7.cjs → chunk-2MBNRFS5.cjs} +7 -5
- package/dist/chunk-2MBNRFS5.cjs.map +1 -0
- package/dist/{chunk-VEC5MLT3.js → chunk-5RKQB2JG.js} +10 -228
- package/dist/chunk-5RKQB2JG.js.map +1 -0
- package/dist/{chunk-DYYAXDXI.cjs → chunk-7EGKU7OO.cjs} +31 -11
- package/dist/chunk-7EGKU7OO.cjs.map +1 -0
- package/dist/{chunk-6FR25MPC.js → chunk-F4K5QAN6.js} +246 -3
- package/dist/chunk-F4K5QAN6.js.map +1 -0
- package/dist/{chunk-WRRLB6KG.js → chunk-K5JZ4JI3.js} +7 -5
- package/dist/chunk-K5JZ4JI3.js.map +1 -0
- package/dist/{chunk-ABYMIXRN.js → chunk-KZ5XDGE6.js} +11891 -10589
- package/dist/chunk-KZ5XDGE6.js.map +1 -0
- package/dist/{chunk-4I25AGUR.cjs → chunk-LPM3NPAX.cjs} +12083 -10780
- package/dist/chunk-LPM3NPAX.cjs.map +1 -0
- package/dist/chunk-LWMMMW43.js +787 -0
- package/dist/chunk-LWMMMW43.js.map +1 -0
- package/dist/chunk-NMVOTNSL.js +61 -0
- package/dist/chunk-NMVOTNSL.js.map +1 -0
- package/dist/{chunk-OPGDMS7L.js → chunk-QNWYQZ55.js} +3 -3
- package/dist/{chunk-OPGDMS7L.js.map → chunk-QNWYQZ55.js.map} +1 -1
- package/dist/{chunk-COBUPOMD.js → chunk-T7IYBGGO.cjs} +5 -770
- package/dist/chunk-T7IYBGGO.cjs.map +1 -0
- package/dist/{chunk-OKPDQO2Y.js → chunk-UJ4K4B23.js} +30 -10
- package/dist/chunk-UJ4K4B23.js.map +1 -0
- package/dist/chunk-WBX5YMTB.cjs +70 -0
- package/dist/chunk-WBX5YMTB.cjs.map +1 -0
- package/dist/{chunk-DOR2IU73.cjs → chunk-YP52USGX.cjs} +249 -2
- package/dist/chunk-YP52USGX.cjs.map +1 -0
- package/dist/{chunk-EYMHWJTW.cjs → chunk-YU6QFFI4.cjs} +9 -228
- package/dist/chunk-YU6QFFI4.cjs.map +1 -0
- package/dist/{chunk-MABBKINE.cjs → chunk-ZMSYKV62.cjs} +5 -5
- package/dist/{chunk-MABBKINE.cjs.map → chunk-ZMSYKV62.cjs.map} +1 -1
- package/dist/{chunk-NBDPIRQS.cjs → chunk-ZPMFT2JW.js} +4 -786
- package/dist/chunk-ZPMFT2JW.js.map +1 -0
- package/dist/index.cjs +520 -147
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +390 -13
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +24 -23
- package/dist/middleware.js +3 -2
- package/dist/migrations-IHERIQVD.js +4 -0
- package/dist/migrations-IHERIQVD.js.map +1 -0
- package/dist/migrations-POFD5KNG.cjs +13 -0
- package/dist/migrations-POFD5KNG.cjs.map +1 -0
- package/dist/routes.cjs +31 -29
- package/dist/routes.js +8 -6
- package/dist/services.cjs +42 -24
- package/dist/services.js +4 -2
- package/dist/templates.cjs +17 -21
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +44 -11
- package/dist/utils.js +2 -1
- package/migrations/001_initial_schema.sql +2 -2
- package/migrations/007_demo_login_plugin.sql +1 -1
- package/migrations/020_add_email_plugin.sql +22 -0
- package/migrations/021_add_magic_link_auth_plugin.sql +42 -0
- package/migrations/021_add_otp_login.sql +42 -0
- package/migrations/022_add_tinymce_plugin.sql +25 -0
- package/migrations/023_add_easy_mdx_plugin.sql +25 -0
- package/migrations/024_add_quill_editor_plugin.sql +25 -0
- package/migrations/025_rename_mdxeditor_to_easy_mdx.sql +22 -0
- package/package.json +5 -3
- package/dist/chunk-4I25AGUR.cjs.map +0 -1
- package/dist/chunk-6FR25MPC.js.map +0 -1
- package/dist/chunk-ABYMIXRN.js.map +0 -1
- package/dist/chunk-COBUPOMD.js.map +0 -1
- package/dist/chunk-DOR2IU73.cjs.map +0 -1
- package/dist/chunk-DYYAXDXI.cjs.map +0 -1
- package/dist/chunk-EYMHWJTW.cjs.map +0 -1
- package/dist/chunk-NBDPIRQS.cjs.map +0 -1
- package/dist/chunk-OKPDQO2Y.js.map +0 -1
- package/dist/chunk-TMIRVVQ7.cjs.map +0 -1
- package/dist/chunk-VEC5MLT3.js.map +0 -1
- package/dist/chunk-WRRLB6KG.js.map +0 -1
- package/migrations/002_faq_plugin.sql +0 -86
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/migrations.ts"],"names":[],"mappings":"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","file":"chunk-T7IYBGGO.cjs","sourcesContent":["import { D1Database } from '@cloudflare/workers-types'\n// Note: fs and path are not available in Cloudflare Workers\n// Migration files should be bundled with the application\n\nexport interface Migration {\n id: string\n name: string\n filename: string\n description?: string\n applied: boolean\n appliedAt?: string\n size?: number\n}\n\nexport interface MigrationStatus {\n totalMigrations: number\n appliedMigrations: number\n pendingMigrations: number\n lastApplied?: string\n migrations: Migration[]\n}\n\nexport class MigrationService {\n constructor(private db: D1Database) {}\n\n /**\n * Initialize the migrations tracking table\n */\n async initializeMigrationsTable(): Promise<void> {\n const createTableQuery = `\n CREATE TABLE IF NOT EXISTS migrations (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n filename TEXT NOT NULL,\n applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n checksum TEXT\n )\n `\n \n await this.db.prepare(createTableQuery).run()\n }\n\n /**\n * Get all available migrations from the migrations directory\n */\n async getAvailableMigrations(): Promise<Migration[]> {\n const migrations: Migration[] = []\n \n // In a real implementation, this would read from the migrations directory\n // For now, we'll use a hardcoded list based on the existing migrations\n const migrationFiles = [\n { id: '001', name: 'Initial Schema', filename: '001_initial_schema.sql', description: 'Initial database schema with users, content, collections, and media tables' },\n { id: '002', name: 'FAQ Plugin', filename: '002_faq_plugin.sql', description: 'FAQ plugin tables and initial data' },\n { id: '003', name: 'Stage 5 Enhancements', filename: '003_stage5_enhancements.sql', description: 'Enhanced content management and media handling' },\n { id: '004', name: 'User Management', filename: '004_stage6_user_management.sql', description: 'Advanced user management with roles and permissions' },\n { id: '005', name: 'Workflow & Automation', filename: '005_stage7_workflow_automation.sql', description: 'Workflow states, automation rules, and scheduled content' },\n { id: '006', name: 'Plugin System', filename: '006_plugin_system.sql', description: 'Plugin registration and configuration system' },\n { id: '007', name: 'Demo Login Plugin', filename: '007_demo_login_plugin.sql', description: 'Demo login functionality' },\n { id: '008', name: 'Fix Slug Validation', filename: '008_fix_slug_validation.sql', description: 'Fix slug validation in content' },\n { id: '009', name: 'System Logging', filename: '009_system_logging.sql', description: 'System logging and audit trails' },\n { id: '011', name: 'Config Managed Collections', filename: '011_config_managed_collections.sql', description: 'Configuration for managed collections' },\n { id: '012', name: 'Testimonials Plugin', filename: '012_testimonials_plugin.sql', description: 'Testimonials plugin and collection' },\n { id: '013', name: 'Code Examples Plugin', filename: '013_code_examples_plugin.sql', description: 'Code examples plugin and collection' },\n { id: '014', name: 'Fix Plugin Registry', filename: '014_fix_plugin_registry.sql', description: 'Fix plugin registry issues' },\n { id: '015', name: 'Add Remaining Plugins', filename: '015_add_remaining_plugins.sql', description: 'Add remaining core plugins' },\n { id: '016', name: 'Remove Duplicate Cache Plugin', filename: '016_remove_duplicate_cache_plugin.sql', description: 'Remove duplicate cache plugin entries' },\n { id: '017', name: 'Auth Configurable Fields', filename: '017_auth_configurable_fields.sql', description: 'Configurable authentication fields' }\n ]\n\n // Get applied migrations from database\n const appliedResult = await this.db.prepare(\n 'SELECT id, name, filename, applied_at FROM migrations ORDER BY applied_at ASC'\n ).all()\n \n const appliedMigrations = new Map(\n appliedResult.results?.map((row: any) => [row.id, row]) || []\n )\n\n // Auto-detect applied migrations by checking if their tables exist\n await this.autoDetectAppliedMigrations(appliedMigrations)\n\n // Combine with migration files to create complete status\n for (const file of migrationFiles) {\n const applied = appliedMigrations.has(file.id)\n const appliedData = appliedMigrations.get(file.id)\n \n migrations.push({\n id: file.id,\n name: file.name,\n filename: file.filename,\n description: file.description,\n applied,\n appliedAt: applied ? appliedData?.applied_at : undefined,\n size: await this.getMigrationFileSize(file.filename)\n })\n }\n\n return migrations\n }\n\n /**\n * Auto-detect applied migrations by checking if their tables exist\n */\n private async autoDetectAppliedMigrations(appliedMigrations: Map<string, any>): Promise<void> {\n // Check if basic schema tables exist (migration 001)\n if (!appliedMigrations.has('001')) {\n const hasBasicTables = await this.checkTablesExist(['users', 'content', 'collections', 'media'])\n if (hasBasicTables) {\n appliedMigrations.set('001', { \n id: '001', \n applied_at: new Date().toISOString(),\n name: 'Initial Schema',\n filename: '001_initial_schema.sql'\n })\n // Mark as applied in database\n await this.markMigrationApplied('001', 'Initial Schema', '001_initial_schema.sql')\n }\n }\n\n // Check if FAQ tables exist (migration 002) \n if (!appliedMigrations.has('002')) {\n const hasFaqTables = await this.checkTablesExist(['faqs', 'faq_categories'])\n if (hasFaqTables) {\n appliedMigrations.set('002', { \n id: '002', \n applied_at: new Date().toISOString(),\n name: 'FAQ Plugin',\n filename: '002_faq_plugin.sql'\n })\n await this.markMigrationApplied('002', 'FAQ Plugin', '002_faq_plugin.sql')\n }\n }\n\n // Check if enhanced tables exist (migration 003)\n if (!appliedMigrations.has('003')) {\n const hasEnhancedTables = await this.checkTablesExist(['content_versions', 'email_themes', 'email_templates'])\n if (hasEnhancedTables) {\n appliedMigrations.set('003', { \n id: '003', \n applied_at: new Date().toISOString(),\n name: 'Stage 5 Enhancements',\n filename: '003_stage5_enhancements.sql'\n })\n await this.markMigrationApplied('003', 'Stage 5 Enhancements', '003_stage5_enhancements.sql')\n }\n }\n\n // Check if user management tables exist (migration 004)\n if (!appliedMigrations.has('004')) {\n const hasUserTables = await this.checkTablesExist(['api_tokens', 'workflow_history'])\n if (hasUserTables) {\n appliedMigrations.set('004', { \n id: '004', \n applied_at: new Date().toISOString(),\n name: 'User Management',\n filename: '004_stage6_user_management.sql'\n })\n await this.markMigrationApplied('004', 'User Management', '004_stage6_user_management.sql')\n }\n }\n\n // Check if plugin system tables exist (migration 006)\n if (!appliedMigrations.has('006')) {\n const hasPluginTables = await this.checkTablesExist(['plugins', 'plugin_hooks'])\n if (hasPluginTables) {\n appliedMigrations.set('006', { \n id: '006', \n applied_at: new Date().toISOString(),\n name: 'Plugin System',\n filename: '006_plugin_system.sql'\n })\n await this.markMigrationApplied('006', 'Plugin System', '006_plugin_system.sql')\n }\n }\n }\n\n /**\n * Check if specific tables exist in the database\n */\n private async checkTablesExist(tableNames: string[]): Promise<boolean> {\n try {\n for (const tableName of tableNames) {\n const result = await this.db.prepare(\n `SELECT name FROM sqlite_master WHERE type='table' AND name=?`\n ).bind(tableName).first()\n \n if (!result) {\n return false\n }\n }\n return true\n } catch (error) {\n return false\n }\n }\n\n /**\n * Get migration status summary\n */\n async getMigrationStatus(): Promise<MigrationStatus> {\n await this.initializeMigrationsTable()\n \n const migrations = await this.getAvailableMigrations()\n const appliedMigrations = migrations.filter(m => m.applied)\n const pendingMigrations = migrations.filter(m => !m.applied)\n \n const lastApplied = appliedMigrations.length > 0 \n ? appliedMigrations[appliedMigrations.length - 1]?.appliedAt \n : undefined\n\n return {\n totalMigrations: migrations.length,\n appliedMigrations: appliedMigrations.length,\n pendingMigrations: pendingMigrations.length,\n lastApplied,\n migrations\n }\n }\n\n /**\n * Mark a migration as applied\n */\n async markMigrationApplied(migrationId: string, name: string, filename: string): Promise<void> {\n await this.initializeMigrationsTable()\n \n await this.db.prepare(\n 'INSERT OR REPLACE INTO migrations (id, name, filename, applied_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)'\n ).bind(migrationId, name, filename).run()\n }\n\n /**\n * Check if a specific migration has been applied\n */\n async isMigrationApplied(migrationId: string): Promise<boolean> {\n await this.initializeMigrationsTable()\n \n const result = await this.db.prepare(\n 'SELECT COUNT(*) as count FROM migrations WHERE id = ?'\n ).bind(migrationId).first()\n \n return (result?.count as number) > 0\n }\n\n /**\n * Get the last applied migration\n */\n async getLastAppliedMigration(): Promise<Migration | null> {\n await this.initializeMigrationsTable()\n \n const result = await this.db.prepare(\n 'SELECT id, name, filename, applied_at FROM migrations ORDER BY applied_at DESC LIMIT 1'\n ).first()\n \n if (!result) return null\n \n return {\n id: result.id as string,\n name: result.name as string,\n filename: result.filename as string,\n applied: true,\n appliedAt: result.applied_at as string\n }\n }\n\n /**\n * Get migration file size (simulated)\n */\n private async getMigrationFileSize(filename: string): Promise<number> {\n // In a real implementation, this would read the actual file size\n // For now, return a simulated size\n const sizesMap: Record<string, number> = {\n '001_initial_schema.sql': 15420,\n '002_faq_plugin.sql': 2340,\n '003_stage5_enhancements.sql': 8920,\n '004_stage6_user_management.sql': 12680,\n '005_stage7_workflow_automation.sql': 18750,\n '006_plugin_system.sql': 5430\n }\n \n return sizesMap[filename] || 1000\n }\n\n /**\n * Run pending migrations\n */\n async runPendingMigrations(): Promise<{ success: boolean; message: string; applied: string[] }> {\n const status = await this.getMigrationStatus()\n const pendingMigrations = status.migrations.filter(m => !m.applied)\n \n if (pendingMigrations.length === 0) {\n return {\n success: true,\n message: 'All migrations are up to date',\n applied: []\n }\n }\n\n // Actually execute the migration files\n const applied: string[] = []\n \n for (const migration of pendingMigrations) {\n try {\n await this.applyMigration(migration)\n await this.markMigrationApplied(migration.id, migration.name, migration.filename)\n applied.push(migration.id)\n } catch (error) {\n console.error(`Failed to apply migration ${migration.id}:`, error)\n // Stop on first failure\n break\n }\n }\n\n return {\n success: true,\n message: `Applied ${applied.length} migration(s)`,\n applied\n }\n }\n\n /**\n * Apply a specific migration\n */\n private async applyMigration(migration: Migration): Promise<void> {\n console.log(`Applying migration ${migration.id}: ${migration.name}`)\n\n // Get the actual migration SQL\n const migrationSQL = await this.getMigrationSQL(migration.id)\n\n if (migrationSQL === null) {\n throw new Error(`Migration SQL not found for ${migration.id}`)\n }\n\n // Skip empty migrations (migrations that are no longer needed)\n if (migrationSQL === '') {\n console.log(`Skipping migration ${migration.id} (empty/obsolete)`)\n return\n }\n\n // Split SQL into individual statements, handling triggers properly\n const statements = this.splitSQLStatements(migrationSQL)\n\n for (const statement of statements) {\n if (statement.trim()) {\n try {\n await this.db.prepare(statement).run()\n } catch (error) {\n console.error(`Error executing statement: ${statement}`, error)\n throw error\n }\n }\n }\n }\n\n /**\n * Split SQL into statements, handling CREATE TRIGGER properly\n */\n private splitSQLStatements(sql: string): string[] {\n const statements: string[] = []\n let current = ''\n let inTrigger = false\n\n const lines = sql.split('\\n')\n\n for (const line of lines) {\n const trimmed = line.trim()\n\n // Skip comments and empty lines\n if (trimmed.startsWith('--') || trimmed.length === 0) {\n continue\n }\n\n // Check if we're entering a trigger\n if (trimmed.toUpperCase().includes('CREATE TRIGGER')) {\n inTrigger = true\n }\n\n current += line + '\\n'\n\n // Check if we're exiting a trigger\n if (inTrigger && trimmed.toUpperCase() === 'END;') {\n statements.push(current.trim())\n current = ''\n inTrigger = false\n }\n // Check for regular statement end (not in trigger)\n else if (!inTrigger && trimmed.endsWith(';')) {\n statements.push(current.trim())\n current = ''\n }\n }\n\n // Add any remaining statement\n if (current.trim()) {\n statements.push(current.trim())\n }\n\n return statements.filter(s => s.length > 0)\n }\n\n /**\n * Get migration SQL by ID\n */\n private async getMigrationSQL(migrationId: string): Promise<string | null> {\n // Import actual migration SQL based on ID\n switch (migrationId) {\n case '001':\n // Initial schema migration\n return `\n-- Initial schema for SonicJS AI\n-- Create users table for authentication\nCREATE TABLE IF NOT EXISTS users (\n id TEXT PRIMARY KEY,\n email TEXT NOT NULL UNIQUE,\n username TEXT NOT NULL UNIQUE,\n first_name TEXT NOT NULL,\n last_name TEXT NOT NULL,\n password_hash TEXT,\n role TEXT NOT NULL DEFAULT 'viewer',\n avatar TEXT,\n is_active INTEGER NOT NULL DEFAULT 1,\n last_login_at INTEGER,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\n\n-- Create collections table for content schema definitions\nCREATE TABLE IF NOT EXISTS collections (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n display_name TEXT NOT NULL,\n description TEXT,\n schema TEXT NOT NULL,\n is_active INTEGER NOT NULL DEFAULT 1,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\n\n-- Create content table for actual content data\nCREATE TABLE IF NOT EXISTS content (\n id TEXT PRIMARY KEY,\n collection_id TEXT NOT NULL REFERENCES collections(id),\n slug TEXT NOT NULL,\n title TEXT NOT NULL,\n data TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'draft',\n published_at INTEGER,\n author_id TEXT NOT NULL REFERENCES users(id),\n created_by TEXT NOT NULL REFERENCES users(id),\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL\n);\n\n-- Create content_versions table for versioning\nCREATE TABLE IF NOT EXISTS content_versions (\n id TEXT PRIMARY KEY,\n content_id TEXT NOT NULL REFERENCES content(id),\n version INTEGER NOT NULL,\n data TEXT NOT NULL,\n author_id TEXT NOT NULL REFERENCES users(id),\n created_at INTEGER NOT NULL\n);\n\n-- Create media/files table with comprehensive R2 integration\nCREATE TABLE IF NOT EXISTS media (\n id TEXT PRIMARY KEY,\n filename TEXT NOT NULL,\n original_name TEXT NOT NULL,\n mime_type TEXT NOT NULL,\n size INTEGER NOT NULL,\n width INTEGER,\n height INTEGER,\n folder TEXT NOT NULL DEFAULT 'uploads',\n r2_key TEXT NOT NULL,\n public_url TEXT NOT NULL,\n thumbnail_url TEXT,\n alt TEXT,\n caption TEXT,\n tags TEXT,\n uploaded_by TEXT NOT NULL REFERENCES users(id),\n uploaded_at INTEGER NOT NULL,\n updated_at INTEGER,\n published_at INTEGER,\n scheduled_at INTEGER,\n archived_at INTEGER,\n deleted_at INTEGER\n);\n\n-- Create API tokens table for programmatic access\nCREATE TABLE IF NOT EXISTS api_tokens (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n token TEXT NOT NULL UNIQUE,\n user_id TEXT NOT NULL REFERENCES users(id),\n permissions TEXT NOT NULL,\n expires_at INTEGER,\n last_used_at INTEGER,\n created_at INTEGER NOT NULL\n);\n\n-- Create workflow history table for content workflow tracking\nCREATE TABLE IF NOT EXISTS workflow_history (\n id TEXT PRIMARY KEY,\n content_id TEXT NOT NULL REFERENCES content(id),\n action TEXT NOT NULL,\n from_status TEXT NOT NULL,\n to_status TEXT NOT NULL,\n user_id TEXT NOT NULL REFERENCES users(id),\n comment TEXT,\n created_at INTEGER NOT NULL\n);\n\n-- Create indexes for better performance\nCREATE INDEX IF NOT EXISTS idx_users_email ON users(email);\nCREATE INDEX IF NOT EXISTS idx_users_username ON users(username);\nCREATE INDEX IF NOT EXISTS idx_users_role ON users(role);\n\nCREATE INDEX IF NOT EXISTS idx_collections_name ON collections(name);\nCREATE INDEX IF NOT EXISTS idx_collections_active ON collections(is_active);\n\nCREATE INDEX IF NOT EXISTS idx_content_collection ON content(collection_id);\nCREATE INDEX IF NOT EXISTS idx_content_author ON content(author_id);\nCREATE INDEX IF NOT EXISTS idx_content_status ON content(status);\nCREATE INDEX IF NOT EXISTS idx_content_published ON content(published_at);\nCREATE INDEX IF NOT EXISTS idx_content_slug ON content(slug);\n\nCREATE INDEX IF NOT EXISTS idx_content_versions_content ON content_versions(content_id);\nCREATE INDEX IF NOT EXISTS idx_content_versions_version ON content_versions(version);\n\nCREATE INDEX IF NOT EXISTS idx_media_folder ON media(folder);\nCREATE INDEX IF NOT EXISTS idx_media_type ON media(mime_type);\nCREATE INDEX IF NOT EXISTS idx_media_uploaded_by ON media(uploaded_by);\nCREATE INDEX IF NOT EXISTS idx_media_uploaded_at ON media(uploaded_at);\nCREATE INDEX IF NOT EXISTS idx_media_deleted ON media(deleted_at);\n\nCREATE INDEX IF NOT EXISTS idx_api_tokens_user ON api_tokens(user_id);\nCREATE INDEX IF NOT EXISTS idx_api_tokens_token ON api_tokens(token);\n\nCREATE INDEX IF NOT EXISTS idx_workflow_history_content ON workflow_history(content_id);\nCREATE INDEX IF NOT EXISTS idx_workflow_history_user ON workflow_history(user_id);\n\n-- Insert default admin user (password: sonicjs!)\nINSERT OR IGNORE INTO users (\n id, email, username, first_name, last_name, password_hash,\n role, is_active, created_at, updated_at\n) VALUES (\n 'admin-user-id',\n 'admin@sonicjs.com',\n 'admin',\n 'Admin',\n 'User',\n 'd1c379e871838f44e21d5a55841349e50636f06df139bfef11870eec74c381db',\n 'admin',\n 1,\n strftime('%s', 'now') * 1000,\n strftime('%s', 'now') * 1000\n);\n\n-- Insert sample collections\nINSERT OR IGNORE INTO collections (\n id, name, display_name, description, schema,\n is_active, created_at, updated_at\n) VALUES (\n 'blog-posts-collection',\n 'blog_posts',\n 'Blog Posts',\n 'Blog post content collection',\n '{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\",\"title\":\"Title\",\"required\":true},\"content\":{\"type\":\"string\",\"title\":\"Content\",\"format\":\"richtext\"},\"excerpt\":{\"type\":\"string\",\"title\":\"Excerpt\"},\"featured_image\":{\"type\":\"string\",\"title\":\"Featured Image\",\"format\":\"media\"},\"tags\":{\"type\":\"array\",\"title\":\"Tags\",\"items\":{\"type\":\"string\"}},\"status\":{\"type\":\"string\",\"title\":\"Status\",\"enum\":[\"draft\",\"published\",\"archived\"],\"default\":\"draft\"}},\"required\":[\"title\"]}',\n 1,\n strftime('%s', 'now') * 1000,\n strftime('%s', 'now') * 1000\n),\n(\n 'pages-collection',\n 'pages',\n 'Pages',\n 'Static page content collection',\n '{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\",\"title\":\"Title\",\"required\":true},\"content\":{\"type\":\"string\",\"title\":\"Content\",\"format\":\"richtext\"},\"slug\":{\"type\":\"string\",\"title\":\"Slug\"},\"meta_description\":{\"type\":\"string\",\"title\":\"Meta Description\"},\"featured_image\":{\"type\":\"string\",\"title\":\"Featured Image\",\"format\":\"media\"}},\"required\":[\"title\"]}',\n 1,\n strftime('%s', 'now') * 1000,\n strftime('%s', 'now') * 1000\n),\n(\n 'news-collection',\n 'news',\n 'News',\n 'News article content collection',\n '{\"type\":\"object\",\"properties\":{\"title\":{\"type\":\"string\",\"title\":\"Title\",\"required\":true},\"content\":{\"type\":\"string\",\"title\":\"Content\",\"format\":\"richtext\"},\"publish_date\":{\"type\":\"string\",\"title\":\"Publish Date\",\"format\":\"date\"},\"author\":{\"type\":\"string\",\"title\":\"Author\"},\"category\":{\"type\":\"string\",\"title\":\"Category\",\"enum\":[\"technology\",\"business\",\"general\"]}},\"required\":[\"title\"]}',\n 1,\n strftime('%s', 'now') * 1000,\n strftime('%s', 'now') * 1000\n);\n\n-- Insert sample content\nINSERT OR IGNORE INTO content (\n id, collection_id, slug, title, data, status,\n author_id, created_by, created_at, updated_at\n) VALUES (\n 'welcome-blog-post',\n 'blog-posts-collection',\n 'welcome-to-sonicjs-ai',\n 'Welcome to SonicJS AI',\n '{\"title\":\"Welcome to SonicJS AI\",\"content\":\"<h1>Welcome to SonicJS AI</h1><p>This is your first blog post created with SonicJS AI, a modern headless CMS built on Cloudflare Workers.</p><h2>Features</h2><ul><li>Cloudflare-native architecture</li><li>TypeScript-first development</li><li>Hono.js framework</li><li>D1 database</li><li>R2 media storage</li><li>Edge computing</li></ul><p>Get started by exploring the admin interface and creating your own content!</p>\",\"excerpt\":\"Welcome to SonicJS AI, a modern headless CMS built on Cloudflare Workers with TypeScript and Hono.js.\",\"status\":\"published\",\"tags\":[\"welcome\",\"cms\",\"cloudflare\"]}',\n 'published',\n 'admin-user-id',\n 'admin-user-id',\n strftime('%s', 'now') * 1000,\n strftime('%s', 'now') * 1000\n);\n `\n case '002':\n // FAQ Plugin migration\n return `\n CREATE TABLE IF NOT EXISTS faqs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n question TEXT NOT NULL,\n answer TEXT NOT NULL,\n category TEXT,\n tags TEXT,\n isPublished INTEGER NOT NULL DEFAULT 1,\n sortOrder INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))\n );\n\n CREATE INDEX IF NOT EXISTS idx_faqs_category ON faqs(category);\n CREATE INDEX IF NOT EXISTS idx_faqs_published ON faqs(isPublished);\n CREATE INDEX IF NOT EXISTS idx_faqs_sort_order ON faqs(sortOrder);\n\n CREATE TRIGGER IF NOT EXISTS faqs_updated_at\n AFTER UPDATE ON faqs\n BEGIN\n UPDATE faqs SET updated_at = strftime('%s', 'now') WHERE id = NEW.id;\n END;\n `\n case '006':\n // Plugin system migration\n return `\n -- Plugin System Tables\n CREATE TABLE IF NOT EXISTS plugins (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n display_name TEXT NOT NULL,\n description TEXT,\n version TEXT NOT NULL,\n author TEXT NOT NULL,\n category TEXT NOT NULL,\n icon TEXT,\n status TEXT DEFAULT 'inactive' CHECK (status IN ('active', 'inactive', 'error')),\n is_core BOOLEAN DEFAULT FALSE,\n settings JSON,\n permissions JSON,\n dependencies JSON,\n download_count INTEGER DEFAULT 0,\n rating REAL DEFAULT 0,\n installed_at INTEGER NOT NULL,\n activated_at INTEGER,\n last_updated INTEGER NOT NULL,\n error_message TEXT,\n created_at INTEGER DEFAULT (unixepoch()),\n updated_at INTEGER DEFAULT (unixepoch())\n );\n\n CREATE TABLE IF NOT EXISTS plugin_hooks (\n id TEXT PRIMARY KEY,\n plugin_id TEXT NOT NULL,\n hook_name TEXT NOT NULL,\n handler_name TEXT NOT NULL,\n priority INTEGER DEFAULT 10,\n is_active BOOLEAN DEFAULT TRUE,\n created_at INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE,\n UNIQUE(plugin_id, hook_name, handler_name)\n );\n\n CREATE TABLE IF NOT EXISTS plugin_routes (\n id TEXT PRIMARY KEY,\n plugin_id TEXT NOT NULL,\n path TEXT NOT NULL,\n method TEXT NOT NULL,\n handler_name TEXT NOT NULL,\n middleware JSON,\n is_active BOOLEAN DEFAULT TRUE,\n created_at INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE,\n UNIQUE(plugin_id, path, method)\n );\n\n CREATE TABLE IF NOT EXISTS plugin_assets (\n id TEXT PRIMARY KEY,\n plugin_id TEXT NOT NULL,\n asset_type TEXT NOT NULL CHECK (asset_type IN ('css', 'js', 'image', 'font')),\n asset_path TEXT NOT NULL,\n load_order INTEGER DEFAULT 100,\n load_location TEXT DEFAULT 'footer' CHECK (load_location IN ('header', 'footer')),\n is_active BOOLEAN DEFAULT TRUE,\n created_at INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE\n );\n\n CREATE TABLE IF NOT EXISTS plugin_activity_log (\n id TEXT PRIMARY KEY,\n plugin_id TEXT NOT NULL,\n action TEXT NOT NULL,\n user_id TEXT,\n details JSON,\n timestamp INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE\n );\n\n -- Create indexes\n CREATE INDEX IF NOT EXISTS idx_plugins_status ON plugins(status);\n CREATE INDEX IF NOT EXISTS idx_plugins_category ON plugins(category);\n CREATE INDEX IF NOT EXISTS idx_plugin_hooks_plugin ON plugin_hooks(plugin_id);\n CREATE INDEX IF NOT EXISTS idx_plugin_routes_plugin ON plugin_routes(plugin_id);\n CREATE INDEX IF NOT EXISTS idx_plugin_assets_plugin ON plugin_assets(plugin_id);\n CREATE INDEX IF NOT EXISTS idx_plugin_activity_plugin ON plugin_activity_log(plugin_id);\n CREATE INDEX IF NOT EXISTS idx_plugin_activity_timestamp ON plugin_activity_log(timestamp);\n\n -- Insert core plugins\n INSERT OR IGNORE INTO plugins (\n id, name, display_name, description, version, author, category, icon,\n status, is_core, permissions, installed_at, last_updated\n ) VALUES \n (\n 'core-auth',\n 'core-auth',\n 'Authentication System',\n 'Core authentication and user management system',\n '1.0.0',\n 'SonicJS Team',\n 'security',\n '🔐',\n 'active',\n TRUE,\n '[\"manage:users\", \"manage:roles\", \"manage:permissions\"]',\n unixepoch(),\n unixepoch()\n ),\n (\n 'core-media',\n 'core-media', \n 'Media Manager',\n 'Core media upload and management system',\n '1.0.0',\n 'SonicJS Team',\n 'media',\n '📸',\n 'active',\n TRUE,\n '[\"manage:media\", \"upload:files\"]',\n unixepoch(),\n unixepoch()\n ),\n (\n 'core-workflow',\n 'core-workflow',\n 'Workflow Engine',\n 'Content workflow and approval system',\n '1.0.0',\n 'SonicJS Team',\n 'content',\n '🔄',\n 'active',\n TRUE,\n '[\"manage:workflows\", \"approve:content\"]',\n unixepoch(),\n unixepoch()\n ),\n (\n 'cache',\n 'cache',\n 'Cache System',\n 'Three-tiered caching system with memory, KV, and database layers',\n '1.0.0',\n 'SonicJS Team',\n 'performance',\n '⚡',\n 'active',\n TRUE,\n '[\"manage:cache\",\"view:stats\"]',\n unixepoch(),\n unixepoch()\n ),\n (\n 'design',\n 'design-plugin',\n 'Design System',\n 'Design system management including themes, components, and UI customization. Provides a visual interface for managing design tokens, typography, colors, and component library.',\n '1.0.0',\n 'SonicJS',\n 'ui',\n '🎨',\n 'active',\n TRUE,\n '[\"design.view\", \"design.edit\"]',\n unixepoch(),\n unixepoch()\n );\n `\n case '003':\n case '004':\n case '005':\n case '007':\n case '008':\n case '009':\n case '011':\n case '012':\n case '013':\n case '014':\n case '015':\n case '016':\n case '017':\n // These migrations are skipped - either obsolete or have errors\n // Migrations should be run via: wrangler d1 migrations apply DB --local\n return ''\n default:\n return null\n }\n }\n\n /**\n * Validate database schema (placeholder)\n */\n async validateSchema(): Promise<{ valid: boolean; issues: string[] }> {\n const issues: string[] = []\n \n // Basic table existence checks\n const requiredTables = [\n 'users', 'content', 'collections', 'media', 'sessions'\n ]\n \n for (const table of requiredTables) {\n try {\n await this.db.prepare(`SELECT COUNT(*) FROM ${table} LIMIT 1`).first()\n } catch (error) {\n issues.push(`Missing table: ${table}`)\n }\n }\n\n return {\n valid: issues.length === 0,\n issues\n }\n }\n}"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { syncCollections, PluginBootstrapService } from './chunk-LWMMMW43.js';
|
|
2
|
+
import { MigrationService } from './chunk-ZPMFT2JW.js';
|
|
2
3
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
3
4
|
import { sign, verify } from 'hono/jwt';
|
|
4
|
-
import { getCookie } from 'hono/cookie';
|
|
5
|
+
import { setCookie, getCookie } from 'hono/cookie';
|
|
5
6
|
|
|
6
7
|
// src/middleware/bootstrap.ts
|
|
7
8
|
var bootstrapComplete = false;
|
|
8
|
-
function bootstrapMiddleware() {
|
|
9
|
+
function bootstrapMiddleware(config = {}) {
|
|
9
10
|
return async (c, next) => {
|
|
10
11
|
if (bootstrapComplete) {
|
|
11
12
|
return next();
|
|
@@ -25,11 +26,15 @@ function bootstrapMiddleware() {
|
|
|
25
26
|
} catch (error) {
|
|
26
27
|
console.error("[Bootstrap] Error syncing collections:", error);
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
if (!config.plugins?.disableAll) {
|
|
30
|
+
console.log("[Bootstrap] Bootstrapping core plugins...");
|
|
31
|
+
const bootstrapService = new PluginBootstrapService(c.env.DB);
|
|
32
|
+
const needsBootstrap = await bootstrapService.isBootstrapNeeded();
|
|
33
|
+
if (needsBootstrap) {
|
|
34
|
+
await bootstrapService.bootstrapCorePlugins();
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.log("[Bootstrap] Plugin bootstrap skipped (disableAll is true)");
|
|
33
38
|
}
|
|
34
39
|
bootstrapComplete = true;
|
|
35
40
|
console.log("[Bootstrap] System initialization completed");
|
|
@@ -75,6 +80,21 @@ var AuthManager = class {
|
|
|
75
80
|
const passwordHash = await this.hashPassword(password);
|
|
76
81
|
return passwordHash === hash;
|
|
77
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Set authentication cookie - useful for plugins implementing alternative auth methods
|
|
85
|
+
* @param c - Hono context
|
|
86
|
+
* @param token - JWT token to set in cookie
|
|
87
|
+
* @param options - Optional cookie configuration
|
|
88
|
+
*/
|
|
89
|
+
static setAuthCookie(c, token, options) {
|
|
90
|
+
setCookie(c, "auth_token", token, {
|
|
91
|
+
httpOnly: options?.httpOnly ?? true,
|
|
92
|
+
secure: options?.secure ?? true,
|
|
93
|
+
sameSite: options?.sameSite ?? "Strict",
|
|
94
|
+
maxAge: options?.maxAge ?? 60 * 60 * 24
|
|
95
|
+
// 24 hours default
|
|
96
|
+
});
|
|
97
|
+
}
|
|
78
98
|
};
|
|
79
99
|
var requireAuth = () => {
|
|
80
100
|
return async (c, next) => {
|
|
@@ -197,5 +217,5 @@ var getActivePlugins = () => [];
|
|
|
197
217
|
var isPluginActive = () => false;
|
|
198
218
|
|
|
199
219
|
export { AuthManager, PermissionManager, bootstrapMiddleware, cacheHeaders, compressionMiddleware, detailedLoggingMiddleware, getActivePlugins, isPluginActive, logActivity, loggingMiddleware, metricsMiddleware, optionalAuth, performanceLoggingMiddleware, requireActivePlugin, requireActivePlugins, requireAnyPermission, requireAuth, requirePermission, requireRole, securityHeaders, securityLoggingMiddleware };
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
201
|
-
//# sourceMappingURL=chunk-
|
|
220
|
+
//# sourceMappingURL=chunk-UJ4K4B23.js.map
|
|
221
|
+
//# sourceMappingURL=chunk-UJ4K4B23.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/bootstrap.ts","../src/middleware/auth.ts","../src/middleware/metrics.ts","../src/middleware/index.ts"],"names":[],"mappings":"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","file":"chunk-UJ4K4B23.js","sourcesContent":["import { Context, Next } from \"hono\";\nimport { syncCollections } from \"../services/collection-sync\";\nimport { MigrationService } from \"../services/migrations\";\nimport { PluginBootstrapService } from \"../services/plugin-bootstrap\";\nimport type { SonicJSConfig } from \"../app\";\n\ntype Bindings = {\n DB: D1Database;\n KV: KVNamespace;\n};\n\n// Track if bootstrap has been run in this worker instance\nlet bootstrapComplete = false;\n\n/**\n * Bootstrap middleware that ensures system initialization\n * Runs once per worker instance\n */\nexport function bootstrapMiddleware(config: SonicJSConfig = {}) {\n return async (c: Context<{ Bindings: Bindings }>, next: Next) => {\n // Skip if already bootstrapped in this worker instance\n if (bootstrapComplete) {\n return next();\n }\n\n // Skip bootstrap for static assets and health checks\n const path = c.req.path;\n if (\n path.startsWith(\"/images/\") ||\n path.startsWith(\"/assets/\") ||\n path === \"/health\" ||\n path.endsWith(\".js\") ||\n path.endsWith(\".css\") ||\n path.endsWith(\".png\") ||\n path.endsWith(\".jpg\") ||\n path.endsWith(\".ico\")\n ) {\n return next();\n }\n\n try {\n console.log(\"[Bootstrap] Starting system initialization...\");\n\n // 1. Run database migrations first\n console.log(\"[Bootstrap] Running database migrations...\");\n const migrationService = new MigrationService(c.env.DB);\n await migrationService.runPendingMigrations();\n\n // 2. Sync collection configurations\n console.log(\"[Bootstrap] Syncing collection configurations...\");\n try {\n await syncCollections(c.env.DB);\n } catch (error) {\n console.error(\"[Bootstrap] Error syncing collections:\", error);\n // Continue bootstrap even if collection sync fails\n }\n\n // 3. Bootstrap core plugins (unless disableAll is set)\n if (!config.plugins?.disableAll) {\n console.log(\"[Bootstrap] Bootstrapping core plugins...\");\n const bootstrapService = new PluginBootstrapService(c.env.DB);\n\n // Check if bootstrap is needed\n const needsBootstrap = await bootstrapService.isBootstrapNeeded();\n if (needsBootstrap) {\n await bootstrapService.bootstrapCorePlugins();\n }\n } else {\n console.log(\"[Bootstrap] Plugin bootstrap skipped (disableAll is true)\");\n }\n\n // Mark bootstrap as complete for this worker instance\n bootstrapComplete = true;\n console.log(\"[Bootstrap] System initialization completed\");\n } catch (error) {\n console.error(\"[Bootstrap] Error during system initialization:\", error);\n // Don't prevent the app from starting, but log the error\n }\n\n return next();\n };\n}\n\n/**\n * Reset bootstrap flag (useful for testing)\n */\nexport function resetBootstrap() {\n bootstrapComplete = false;\n}\n","import { sign, verify } from 'hono/jwt'\nimport { Context, Next } from 'hono'\nimport { getCookie, setCookie } from 'hono/cookie'\n\ntype JWTPayload = {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n}\n\n// JWT secret - in production this should come from environment variables\nconst JWT_SECRET = 'your-super-secret-jwt-key-change-in-production'\n\nexport class AuthManager {\n static async generateToken(userId: string, email: string, role: string): Promise<string> {\n const payload: JWTPayload = {\n userId,\n email,\n role,\n exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24), // 24 hours\n iat: Math.floor(Date.now() / 1000)\n }\n \n return await sign(payload, JWT_SECRET)\n }\n\n static async verifyToken(token: string): Promise<JWTPayload | null> {\n try {\n const payload = await verify(token, JWT_SECRET) as JWTPayload\n \n // Check if token is expired\n if (payload.exp < Math.floor(Date.now() / 1000)) {\n return null\n }\n \n return payload\n } catch (error) {\n console.error('Token verification failed:', error)\n return null\n }\n }\n\n static async hashPassword(password: string): Promise<string> {\n // In Cloudflare Workers, we'll use Web Crypto API\n const encoder = new TextEncoder()\n const data = encoder.encode(password + 'salt-change-in-production')\n const hashBuffer = await crypto.subtle.digest('SHA-256', data)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\n }\n\n static async verifyPassword(password: string, hash: string): Promise<boolean> {\n const passwordHash = await this.hashPassword(password)\n return passwordHash === hash\n }\n\n /**\n * Set authentication cookie - useful for plugins implementing alternative auth methods\n * @param c - Hono context\n * @param token - JWT token to set in cookie\n * @param options - Optional cookie configuration\n */\n static setAuthCookie(c: Context, token: string, options?: {\n maxAge?: number\n secure?: boolean\n httpOnly?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n }): void {\n setCookie(c, 'auth_token', token, {\n httpOnly: options?.httpOnly ?? true,\n secure: options?.secure ?? true,\n sameSite: options?.sameSite ?? 'Strict',\n maxAge: options?.maxAge ?? (60 * 60 * 24) // 24 hours default\n })\n }\n}\n\n// Middleware to require authentication\nexport const requireAuth = () => {\n return async (c: Context, next: Next) => {\n try {\n // Try to get token from Authorization header\n let token = c.req.header('Authorization')?.replace('Bearer ', '')\n\n // If no header token, try cookie\n if (!token) {\n token = getCookie(c, 'auth_token')\n }\n\n if (!token) {\n // Check if this is a browser request (HTML accept header)\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Please login to access the admin area')\n }\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n // Try to get cached token verification from KV\n const kv = c.env?.KV\n let payload: JWTPayload | null = null\n\n if (kv) {\n const cacheKey = `auth:${token.substring(0, 20)}` // Use token prefix as key\n const cached = await kv.get(cacheKey, 'json')\n if (cached) {\n payload = cached as JWTPayload\n }\n }\n\n // If not cached, verify token\n if (!payload) {\n payload = await AuthManager.verifyToken(token)\n\n // Cache the verified payload for 5 minutes\n if (payload && kv) {\n const cacheKey = `auth:${token.substring(0, 20)}`\n await kv.put(cacheKey, JSON.stringify(payload), { expirationTtl: 300 })\n }\n }\n\n if (!payload) {\n // Check if this is a browser request (HTML accept header)\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Your session has expired, please login again')\n }\n return c.json({ error: 'Invalid or expired token' }, 401)\n }\n\n // Add user info to context\n c.set('user', payload)\n\n return await next()\n } catch (error) {\n console.error('Auth middleware error:', error)\n // Check if this is a browser request (HTML accept header)\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Authentication failed, please login again')\n }\n return c.json({ error: 'Authentication failed' }, 401)\n }\n }\n}\n\n// Middleware to require specific role\nexport const requireRole = (requiredRole: string | string[]) => {\n return async (c: Context, next: Next) => {\n const user = c.get('user') as JWTPayload\n \n if (!user) {\n // Check if this is a browser request (HTML accept header)\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Please login to access the admin area')\n }\n return c.json({ error: 'Authentication required' }, 401)\n }\n \n const roles = Array.isArray(requiredRole) ? requiredRole : [requiredRole]\n \n if (!roles.includes(user.role)) {\n // Check if this is a browser request (HTML accept header)\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=You do not have permission to access this area')\n }\n return c.json({ error: 'Insufficient permissions' }, 403)\n }\n \n return await next()\n }\n}\n\n// Optional auth middleware (doesn't block if no token)\nexport const optionalAuth = () => {\n return async (c: Context, next: Next) => {\n try {\n let token = c.req.header('Authorization')?.replace('Bearer ', '')\n \n if (!token) {\n token = getCookie(c, 'auth_token')\n }\n \n if (token) {\n const payload = await AuthManager.verifyToken(token)\n if (payload) {\n c.set('user', payload)\n }\n }\n \n return await next()\n } catch (error) {\n // Don't block on auth errors in optional auth\n console.error('Optional auth error:', error)\n return await next()\n }\n }\n}","import { MiddlewareHandler } from 'hono'\nimport { metricsTracker } from '../utils/metrics'\n\n/**\n * Middleware to track all HTTP requests for real-time analytics\n * Excludes the metrics endpoint itself to avoid inflating the count\n */\nexport const metricsMiddleware = (): MiddlewareHandler => {\n return async (c, next) => {\n const path = new URL(c.req.url).pathname\n\n // Don't track the metrics endpoint itself to avoid self-inflating counts\n if (path !== '/admin/dashboard/api/metrics') {\n metricsTracker.recordRequest()\n }\n\n // Continue with the request\n await next()\n }\n}\n","/**\n * Middleware Module Exports\n *\n * Request processing middleware for SonicJS\n *\n * Note: Most middleware is currently in the monolith and will be migrated later.\n * For now, we only export the bootstrap middleware which is used for system initialization.\n */\n\n// Bootstrap middleware\nexport { bootstrapMiddleware } from './bootstrap'\n\n// Auth middleware\nexport { AuthManager, requireAuth, requireRole, optionalAuth } from './auth'\n\n// Metrics middleware\nexport { metricsMiddleware } from './metrics'\n\n// Re-export types and functions that are referenced but implemented in monolith\n// These are placeholder exports to maintain API compatibility\nexport type Permission = string\nexport type UserPermissions = {\n userId: string\n permissions: Permission[]\n}\n\n// Middleware stubs - these return pass-through middleware that call next()\nexport const loggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const detailedLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const securityLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const performanceLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const cacheHeaders: any = () => async (_c: any, next: any) => await next()\nexport const compressionMiddleware: any = async (_c: any, next: any) => await next()\nexport const securityHeaders: any = () => async (_c: any, next: any) => await next()\n\n// Other stubs\nexport const PermissionManager: any = {}\nexport const requirePermission: any = () => async (_c: any, next: any) => await next()\nexport const requireAnyPermission: any = () => async (_c: any, next: any) => await next()\nexport const logActivity: any = () => {}\nexport const requireActivePlugin: any = () => async (_c: any, next: any) => await next()\nexport const requireActivePlugins: any = () => async (_c: any, next: any) => await next()\nexport const getActivePlugins: any = () => []\nexport const isPluginActive: any = () => false\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
// src/utils/telemetry-config.ts
|
|
6
|
+
var DEFAULT_TELEMETRY_CONFIG = {
|
|
7
|
+
enabled: true,
|
|
8
|
+
apiKey: process.env.POSTHOG_API_KEY || "phc_VuhFUIJLXzwyGjlgQ67dbNeSh5x4cp9F8i15hZFIDhs",
|
|
9
|
+
host: process.env.POSTHOG_HOST || "https://us.i.posthog.com",
|
|
10
|
+
debug: process.env.NODE_ENV === "development"
|
|
11
|
+
};
|
|
12
|
+
function isTelemetryEnabled() {
|
|
13
|
+
const telemetryEnv = process.env.SONICJS_TELEMETRY;
|
|
14
|
+
if (telemetryEnv === "false" || telemetryEnv === "0" || telemetryEnv === "disabled") {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const doNotTrack = process.env.DO_NOT_TRACK;
|
|
18
|
+
if (doNotTrack === "1" || doNotTrack === "true") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
function getTelemetryConfig() {
|
|
24
|
+
return {
|
|
25
|
+
...DEFAULT_TELEMETRY_CONFIG,
|
|
26
|
+
enabled: isTelemetryEnabled()
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function shouldSkipEvent(eventName, sampleRate = 1) {
|
|
30
|
+
if (sampleRate >= 1) return false;
|
|
31
|
+
if (sampleRate <= 0) return true;
|
|
32
|
+
let hash = 0;
|
|
33
|
+
for (let i = 0; i < eventName.length; i++) {
|
|
34
|
+
hash = (hash << 5) - hash + eventName.charCodeAt(i);
|
|
35
|
+
hash = hash & hash;
|
|
36
|
+
}
|
|
37
|
+
return Math.abs(hash % 100) / 100 > sampleRate;
|
|
38
|
+
}
|
|
39
|
+
function generateInstallationId() {
|
|
40
|
+
return crypto.randomUUID();
|
|
41
|
+
}
|
|
42
|
+
function generateProjectId(projectName) {
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (let i = 0; i < projectName.length; i++) {
|
|
45
|
+
const char = projectName.charCodeAt(i);
|
|
46
|
+
hash = (hash << 5) - hash + char;
|
|
47
|
+
hash = hash & hash;
|
|
48
|
+
}
|
|
49
|
+
return `proj_${Math.abs(hash).toString(36)}`;
|
|
50
|
+
}
|
|
51
|
+
function sanitizeErrorMessage(error) {
|
|
52
|
+
const message = typeof error === "string" ? error : error.message;
|
|
53
|
+
const errorType = message.split(":")[0].trim();
|
|
54
|
+
const sanitized = errorType.replace(/\/Users\/[^/]+/g, "/Users/***").replace(/\/home\/[^/]+/g, "/home/***").replace(/C:\\Users\\[^\\]+/g, "C:\\Users\\***").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "***@***.***");
|
|
55
|
+
return sanitized;
|
|
56
|
+
}
|
|
57
|
+
function sanitizeRoute(route) {
|
|
58
|
+
return route.replace(/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi, ":id").replace(/\/\d+/g, "/:id").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, ":email");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.DEFAULT_TELEMETRY_CONFIG = DEFAULT_TELEMETRY_CONFIG;
|
|
62
|
+
exports.generateInstallationId = generateInstallationId;
|
|
63
|
+
exports.generateProjectId = generateProjectId;
|
|
64
|
+
exports.getTelemetryConfig = getTelemetryConfig;
|
|
65
|
+
exports.isTelemetryEnabled = isTelemetryEnabled;
|
|
66
|
+
exports.sanitizeErrorMessage = sanitizeErrorMessage;
|
|
67
|
+
exports.sanitizeRoute = sanitizeRoute;
|
|
68
|
+
exports.shouldSkipEvent = shouldSkipEvent;
|
|
69
|
+
//# sourceMappingURL=chunk-WBX5YMTB.cjs.map
|
|
70
|
+
//# sourceMappingURL=chunk-WBX5YMTB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/telemetry-config.ts","../src/utils/telemetry-id.ts"],"names":["randomUUID"],"mappings":"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","file":"chunk-WBX5YMTB.cjs","sourcesContent":["/**\n * Telemetry Configuration Utilities\n *\n * Manages telemetry settings and opt-out mechanisms\n */\n\nimport type { TelemetryConfig } from '../types/telemetry'\n\n/**\n * Default telemetry configuration\n */\nexport const DEFAULT_TELEMETRY_CONFIG: TelemetryConfig = {\n enabled: true,\n apiKey: process.env.POSTHOG_API_KEY || 'phc_VuhFUIJLXzwyGjlgQ67dbNeSh5x4cp9F8i15hZFIDhs',\n host: process.env.POSTHOG_HOST || 'https://us.i.posthog.com',\n debug: process.env.NODE_ENV === 'development'\n}\n\n/**\n * Check if telemetry is enabled via environment variables\n */\nexport function isTelemetryEnabled(): boolean {\n // Check for explicit opt-out\n const telemetryEnv = process.env.SONICJS_TELEMETRY\n if (telemetryEnv === 'false' || telemetryEnv === '0' || telemetryEnv === 'disabled') {\n return false\n }\n\n // Check for DO_NOT_TRACK environment variable (common standard)\n const doNotTrack = process.env.DO_NOT_TRACK\n if (doNotTrack === '1' || doNotTrack === 'true') {\n return false\n }\n\n // Default to enabled (opt-out model)\n return true\n}\n\n/**\n * Get telemetry configuration from environment\n */\nexport function getTelemetryConfig(): TelemetryConfig {\n return {\n ...DEFAULT_TELEMETRY_CONFIG,\n enabled: isTelemetryEnabled()\n }\n}\n\n/**\n * Check if telemetry should be skipped for this event\n * Used to implement sampling or rate limiting if needed\n */\nexport function shouldSkipEvent(eventName: string, sampleRate: number = 1.0): boolean {\n if (sampleRate >= 1.0) return false\n if (sampleRate <= 0) return true\n\n // Use a consistent hash of the event name for deterministic sampling\n let hash = 0\n for (let i = 0; i < eventName.length; i++) {\n hash = ((hash << 5) - hash) + eventName.charCodeAt(i)\n hash = hash & hash\n }\n\n return Math.abs(hash % 100) / 100 > sampleRate\n}\n","/**\n * Telemetry ID Utilities\n *\n * Generates and manages anonymous installation IDs\n */\n\nimport { randomUUID } from 'crypto'\n\n/**\n * Generate a new anonymous installation ID\n */\nexport function generateInstallationId(): string {\n return randomUUID()\n}\n\n/**\n * Generate a project-specific ID from project name\n * Uses a simple hash to anonymize while maintaining consistency\n */\nexport function generateProjectId(projectName: string): string {\n // Simple hash function to anonymize project names\n let hash = 0\n for (let i = 0; i < projectName.length; i++) {\n const char = projectName.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32bit integer\n }\n return `proj_${Math.abs(hash).toString(36)}`\n}\n\n/**\n * Sanitize error messages to remove any potential PII\n */\nexport function sanitizeErrorMessage(error: Error | string): string {\n const message = typeof error === 'string' ? error : error.message\n\n // Extract error type/category only\n const errorType = message.split(':')[0].trim()\n\n // Remove file paths that might contain usernames\n const sanitized = errorType\n .replace(/\\/Users\\/[^/]+/g, '/Users/***')\n .replace(/\\/home\\/[^/]+/g, '/home/***')\n .replace(/C:\\\\Users\\\\[^\\\\]+/g, 'C:\\\\Users\\\\***')\n .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, '***@***.***')\n\n return sanitized\n}\n\n/**\n * Sanitize route to remove any user-specific data\n */\nexport function sanitizeRoute(route: string): string {\n return route\n // Remove UUIDs\n .replace(/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi, ':id')\n // Remove numeric IDs\n .replace(/\\/\\d+/g, '/:id')\n // Remove email patterns\n .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, ':email')\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkWBX5YMTB_cjs = require('./chunk-WBX5YMTB.cjs');
|
|
3
4
|
var chunkIGJUBJBW_cjs = require('./chunk-IGJUBJBW.cjs');
|
|
4
5
|
var sqliteCore = require('drizzle-orm/sqlite-core');
|
|
5
6
|
var v4 = require('zod/v4');
|
|
@@ -1135,17 +1136,263 @@ var SettingsService = class {
|
|
|
1135
1136
|
}
|
|
1136
1137
|
};
|
|
1137
1138
|
|
|
1139
|
+
// src/services/telemetry-service.ts
|
|
1140
|
+
var TelemetryService = class {
|
|
1141
|
+
config;
|
|
1142
|
+
identity = null;
|
|
1143
|
+
client = null;
|
|
1144
|
+
enabled = true;
|
|
1145
|
+
eventQueue = [];
|
|
1146
|
+
isInitialized = false;
|
|
1147
|
+
constructor(config) {
|
|
1148
|
+
this.config = {
|
|
1149
|
+
...chunkWBX5YMTB_cjs.getTelemetryConfig(),
|
|
1150
|
+
...config
|
|
1151
|
+
};
|
|
1152
|
+
this.enabled = this.config.enabled;
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Initialize the telemetry service
|
|
1156
|
+
*/
|
|
1157
|
+
async initialize(identity) {
|
|
1158
|
+
if (!this.enabled) {
|
|
1159
|
+
if (this.config.debug) {
|
|
1160
|
+
console.log("[Telemetry] Disabled via configuration");
|
|
1161
|
+
}
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
try {
|
|
1165
|
+
this.identity = identity;
|
|
1166
|
+
if (this.config.apiKey) {
|
|
1167
|
+
const { PostHog } = await import('posthog-node');
|
|
1168
|
+
this.client = new PostHog(this.config.apiKey, {
|
|
1169
|
+
host: this.config.host,
|
|
1170
|
+
flushAt: 20,
|
|
1171
|
+
// Batch events
|
|
1172
|
+
flushInterval: 1e4
|
|
1173
|
+
// Flush every 10 seconds
|
|
1174
|
+
});
|
|
1175
|
+
if (this.config.debug) {
|
|
1176
|
+
console.log("[Telemetry] Initialized with installation ID:", identity.installationId);
|
|
1177
|
+
}
|
|
1178
|
+
} else if (this.config.debug) {
|
|
1179
|
+
console.log("[Telemetry] No API key provided, tracking will be logged only");
|
|
1180
|
+
}
|
|
1181
|
+
this.isInitialized = true;
|
|
1182
|
+
await this.flushQueue();
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
if (this.config.debug) {
|
|
1185
|
+
console.error("[Telemetry] Initialization failed:", error);
|
|
1186
|
+
}
|
|
1187
|
+
this.enabled = false;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Track a telemetry event
|
|
1192
|
+
*/
|
|
1193
|
+
async track(event, properties) {
|
|
1194
|
+
if (!this.enabled) return;
|
|
1195
|
+
try {
|
|
1196
|
+
const sanitizedProps = this.sanitizeProperties(properties);
|
|
1197
|
+
const enrichedProps = {
|
|
1198
|
+
...sanitizedProps,
|
|
1199
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1200
|
+
version: this.getVersion()
|
|
1201
|
+
};
|
|
1202
|
+
if (!this.isInitialized) {
|
|
1203
|
+
this.eventQueue.push({ event, properties: enrichedProps });
|
|
1204
|
+
if (this.config.debug) {
|
|
1205
|
+
console.log("[Telemetry] Queued event:", event, enrichedProps);
|
|
1206
|
+
}
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
if (this.client && this.identity) {
|
|
1210
|
+
this.client.capture({
|
|
1211
|
+
distinctId: this.identity.installationId,
|
|
1212
|
+
event,
|
|
1213
|
+
properties: enrichedProps
|
|
1214
|
+
});
|
|
1215
|
+
if (this.config.debug) {
|
|
1216
|
+
console.log("[Telemetry] Tracked event:", event, enrichedProps);
|
|
1217
|
+
}
|
|
1218
|
+
} else if (this.config.debug) {
|
|
1219
|
+
console.log("[Telemetry] Event (no client):", event, enrichedProps);
|
|
1220
|
+
}
|
|
1221
|
+
} catch (error) {
|
|
1222
|
+
if (this.config.debug) {
|
|
1223
|
+
console.error("[Telemetry] Failed to track event:", error);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Track installation started
|
|
1229
|
+
*/
|
|
1230
|
+
async trackInstallationStarted(properties) {
|
|
1231
|
+
await this.track("installation_started", properties);
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Track installation completed
|
|
1235
|
+
*/
|
|
1236
|
+
async trackInstallationCompleted(properties) {
|
|
1237
|
+
await this.track("installation_completed", properties);
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Track installation failed
|
|
1241
|
+
*/
|
|
1242
|
+
async trackInstallationFailed(error, properties) {
|
|
1243
|
+
await this.track("installation_failed", {
|
|
1244
|
+
...properties,
|
|
1245
|
+
errorType: chunkWBX5YMTB_cjs.sanitizeErrorMessage(error)
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Track dev server started
|
|
1250
|
+
*/
|
|
1251
|
+
async trackDevServerStarted(properties) {
|
|
1252
|
+
await this.track("dev_server_started", properties);
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Track page view in admin UI
|
|
1256
|
+
*/
|
|
1257
|
+
async trackPageView(route, properties) {
|
|
1258
|
+
await this.track("page_viewed", {
|
|
1259
|
+
...properties,
|
|
1260
|
+
route: chunkWBX5YMTB_cjs.sanitizeRoute(route)
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Track error (sanitized)
|
|
1265
|
+
*/
|
|
1266
|
+
async trackError(error, properties) {
|
|
1267
|
+
await this.track("error_occurred", {
|
|
1268
|
+
...properties,
|
|
1269
|
+
errorType: chunkWBX5YMTB_cjs.sanitizeErrorMessage(error)
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Track plugin activation
|
|
1274
|
+
*/
|
|
1275
|
+
async trackPluginActivated(properties) {
|
|
1276
|
+
await this.track("plugin_activated", properties);
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Track migration run
|
|
1280
|
+
*/
|
|
1281
|
+
async trackMigrationRun(properties) {
|
|
1282
|
+
await this.track("migration_run", properties);
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Flush queued events
|
|
1286
|
+
*/
|
|
1287
|
+
async flushQueue() {
|
|
1288
|
+
if (this.eventQueue.length === 0) return;
|
|
1289
|
+
const queue = [...this.eventQueue];
|
|
1290
|
+
this.eventQueue = [];
|
|
1291
|
+
for (const { event, properties } of queue) {
|
|
1292
|
+
await this.track(event, properties);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Sanitize properties to ensure no PII
|
|
1297
|
+
*/
|
|
1298
|
+
sanitizeProperties(properties) {
|
|
1299
|
+
if (!properties) return {};
|
|
1300
|
+
const sanitized = {};
|
|
1301
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
1302
|
+
if (value === void 0) continue;
|
|
1303
|
+
if (key === "route" && typeof value === "string") {
|
|
1304
|
+
sanitized[key] = chunkWBX5YMTB_cjs.sanitizeRoute(value);
|
|
1305
|
+
continue;
|
|
1306
|
+
}
|
|
1307
|
+
if (key.toLowerCase().includes("error") && typeof value === "string") {
|
|
1308
|
+
sanitized[key] = chunkWBX5YMTB_cjs.sanitizeErrorMessage(value);
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
1312
|
+
sanitized[key] = value;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
return sanitized;
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Get SonicJS version
|
|
1319
|
+
*/
|
|
1320
|
+
getVersion() {
|
|
1321
|
+
try {
|
|
1322
|
+
return process.env.SONICJS_VERSION || "2.0.0";
|
|
1323
|
+
} catch {
|
|
1324
|
+
return "unknown";
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Shutdown the telemetry service
|
|
1329
|
+
*/
|
|
1330
|
+
async shutdown() {
|
|
1331
|
+
try {
|
|
1332
|
+
if (this.client) {
|
|
1333
|
+
await this.client.shutdown();
|
|
1334
|
+
}
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
if (this.config.debug) {
|
|
1337
|
+
console.error("[Telemetry] Shutdown failed:", error);
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Enable telemetry
|
|
1343
|
+
*/
|
|
1344
|
+
enable() {
|
|
1345
|
+
this.enabled = true;
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Disable telemetry
|
|
1349
|
+
*/
|
|
1350
|
+
disable() {
|
|
1351
|
+
this.enabled = false;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Check if telemetry is enabled
|
|
1355
|
+
*/
|
|
1356
|
+
isEnabled() {
|
|
1357
|
+
return this.enabled;
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
var telemetryInstance = null;
|
|
1361
|
+
function getTelemetryService(config) {
|
|
1362
|
+
if (!telemetryInstance) {
|
|
1363
|
+
telemetryInstance = new TelemetryService(config);
|
|
1364
|
+
}
|
|
1365
|
+
return telemetryInstance;
|
|
1366
|
+
}
|
|
1367
|
+
async function initTelemetry(identity, config) {
|
|
1368
|
+
const service = getTelemetryService(config);
|
|
1369
|
+
await service.initialize(identity);
|
|
1370
|
+
return service;
|
|
1371
|
+
}
|
|
1372
|
+
function createInstallationIdentity(projectName) {
|
|
1373
|
+
const installationId = chunkWBX5YMTB_cjs.generateInstallationId();
|
|
1374
|
+
const identity = { installationId };
|
|
1375
|
+
if (projectName) {
|
|
1376
|
+
identity.projectId = chunkWBX5YMTB_cjs.generateProjectId(projectName);
|
|
1377
|
+
}
|
|
1378
|
+
return identity;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1138
1381
|
exports.CACHE_CONFIGS = CACHE_CONFIGS;
|
|
1139
1382
|
exports.CacheService = CacheService;
|
|
1140
1383
|
exports.Logger = Logger;
|
|
1141
1384
|
exports.SettingsService = SettingsService;
|
|
1385
|
+
exports.TelemetryService = TelemetryService;
|
|
1142
1386
|
exports.apiTokens = apiTokens;
|
|
1143
1387
|
exports.collections = collections;
|
|
1144
1388
|
exports.content = content;
|
|
1145
1389
|
exports.contentVersions = contentVersions;
|
|
1390
|
+
exports.createInstallationIdentity = createInstallationIdentity;
|
|
1146
1391
|
exports.getCacheService = getCacheService;
|
|
1147
1392
|
exports.getLogger = getLogger;
|
|
1393
|
+
exports.getTelemetryService = getTelemetryService;
|
|
1148
1394
|
exports.initLogger = initLogger;
|
|
1395
|
+
exports.initTelemetry = initTelemetry;
|
|
1149
1396
|
exports.insertCollectionSchema = insertCollectionSchema;
|
|
1150
1397
|
exports.insertContentSchema = insertContentSchema;
|
|
1151
1398
|
exports.insertLogConfigSchema = insertLogConfigSchema;
|
|
@@ -1181,5 +1428,5 @@ exports.selectWorkflowHistorySchema = selectWorkflowHistorySchema;
|
|
|
1181
1428
|
exports.systemLogs = systemLogs;
|
|
1182
1429
|
exports.users = users;
|
|
1183
1430
|
exports.workflowHistory = workflowHistory;
|
|
1184
|
-
//# sourceMappingURL=chunk-
|
|
1185
|
-
//# sourceMappingURL=chunk-
|
|
1431
|
+
//# sourceMappingURL=chunk-YP52USGX.cjs.map
|
|
1432
|
+
//# sourceMappingURL=chunk-YP52USGX.cjs.map
|