@eldrin-project/eldrin-app-core 0.0.3 → 0.0.4

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/migrations/checksum.ts","../src/migrations/sql-parser.ts","../src/migrations/runner.ts","../src/migrations/rollback.ts","../src/migrations/marketplace.ts","../src/database/context.tsx","../src/app/createApp.tsx","../src/events/client.ts","../src/auth/index.ts","../src/middleware/matcher.ts","../src/middleware/index.ts"],"names":["trimmed","existsSync","readdir","readFile","resolve","basename","createContext","jsx","useContext","createElement","authResult"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Checksum utilities for migration integrity verification\n *\n * Uses SHA-256 for content hashing via Web Crypto API\n * (compatible with Cloudflare Workers runtime)\n */\n\n/** Prefix for SHA-256 checksums in marketplace format */\nexport const CHECKSUM_PREFIX = 'sha256:';\n\n/**\n * Calculate SHA-256 checksum of content\n *\n * @param content - String content to hash\n * @param options - Options for checksum calculation\n * @param options.prefixed - If true, returns \"sha256:...\" format (default: false for backwards compatibility)\n * @returns Hex-encoded SHA-256 hash, optionally with prefix\n */\nexport async function calculateChecksum(\n content: string,\n options: { prefixed?: boolean } = {}\n): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n return options.prefixed ? `${CHECKSUM_PREFIX}${hex}` : hex;\n}\n\n/**\n * Calculate SHA-256 checksum with sha256: prefix\n *\n * Convenience function for marketplace format\n *\n * @param content - String content to hash\n * @returns Prefixed checksum (e.g., \"sha256:abc123...\")\n */\nexport async function calculatePrefixedChecksum(content: string): Promise<string> {\n return calculateChecksum(content, { prefixed: true });\n}\n\n/**\n * Verify that content matches an expected checksum\n *\n * Handles both prefixed (\"sha256:...\") and unprefixed checksums\n *\n * @param content - Content to verify\n * @param expectedChecksum - Expected SHA-256 hex string (with or without prefix)\n * @returns true if checksums match\n */\nexport async function verifyChecksum(\n content: string,\n expectedChecksum: string\n): Promise<boolean> {\n // Strip prefix if present for comparison\n const normalizedExpected = expectedChecksum.startsWith(CHECKSUM_PREFIX)\n ? expectedChecksum.slice(CHECKSUM_PREFIX.length)\n : expectedChecksum;\n\n const actualChecksum = await calculateChecksum(content);\n return actualChecksum === normalizedExpected;\n}\n","/**\n * SQL statement parser for migration files\n *\n * Parses SQL content into individual statements for execution via db.batch()\n */\n\n/**\n * Parse SQL content into individual statements\n *\n * - Removes SQL comments (-- style)\n * - Splits by semicolon\n * - Handles multi-line statements\n * - Preserves string literals containing semicolons\n *\n * @param sql - Raw SQL content\n * @returns Array of individual SQL statements\n */\nexport function parseSQLStatements(sql: string): string[] {\n // First, handle the content preserving strings\n const statements: string[] = [];\n let current = '';\n let inString = false;\n let stringChar = '';\n let i = 0;\n\n // Pre-process: remove single-line comments\n const lines = sql.split('\\n');\n const cleanedLines: string[] = [];\n\n for (const line of lines) {\n let cleanLine = '';\n let lineInString = false;\n let lineStringChar = '';\n\n for (let j = 0; j < line.length; j++) {\n const char = line[j];\n const nextChar = line[j + 1];\n\n if (!lineInString) {\n // Check for comment start\n if (char === '-' && nextChar === '-') {\n // Rest of line is a comment, skip it\n break;\n }\n // Check for string start\n if (char === \"'\" || char === '\"') {\n lineInString = true;\n lineStringChar = char;\n }\n } else {\n // Check for string end (handle escaped quotes)\n if (char === lineStringChar) {\n // Check if it's an escaped quote\n if (nextChar === lineStringChar) {\n cleanLine += char;\n j++; // Skip the next char\n cleanLine += line[j];\n continue;\n }\n lineInString = false;\n }\n }\n\n cleanLine += char;\n }\n\n cleanedLines.push(cleanLine);\n }\n\n const cleanedSql = cleanedLines.join('\\n');\n\n // Now split by semicolons, respecting string literals\n for (i = 0; i < cleanedSql.length; i++) {\n const char = cleanedSql[i];\n\n if (!inString) {\n if (char === \"'\" || char === '\"') {\n inString = true;\n stringChar = char;\n current += char;\n } else if (char === ';') {\n // End of statement\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n statements.push(trimmed);\n }\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n\n // Check for end of string\n if (char === stringChar) {\n // Check for escaped quote\n const nextChar = cleanedSql[i + 1];\n if (nextChar === stringChar) {\n // Escaped quote, skip next char\n i++;\n current += nextChar;\n } else {\n inString = false;\n }\n }\n }\n }\n\n // Don't forget any remaining content\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n statements.push(trimmed);\n }\n\n return statements;\n}\n\n/**\n * Validate that a filename follows the migration naming convention\n *\n * Expected format: TIMESTAMP-description.sql\n * - TIMESTAMP: 14 digits (YYYYMMDDHHmmss)\n * - description: kebab-case\n *\n * @param filename - Filename to validate\n * @returns true if valid, false otherwise\n */\nexport function isValidMigrationFilename(filename: string): boolean {\n // Must end with .sql (but not .rollback.sql)\n if (!filename.endsWith('.sql') || filename.endsWith('.rollback.sql')) {\n return false;\n }\n\n // Pattern: 14-digit timestamp, hyphen, description, .sql\n const pattern = /^\\d{14}-[a-z0-9-]+\\.sql$/;\n return pattern.test(filename);\n}\n\n/**\n * Validate that a filename follows the rollback naming convention\n *\n * Expected format: TIMESTAMP-description.rollback.sql\n *\n * @param filename - Filename to validate\n * @returns true if valid rollback file, false otherwise\n */\nexport function isValidRollbackFilename(filename: string): boolean {\n // Must end with .rollback.sql\n if (!filename.endsWith('.rollback.sql')) {\n return false;\n }\n\n // Pattern: 14-digit timestamp, hyphen, description, .rollback.sql\n const pattern = /^\\d{14}-[a-z0-9-]+\\.rollback\\.sql$/;\n return pattern.test(filename);\n}\n\n/**\n * Extract timestamp from migration filename\n *\n * @param filename - Migration filename\n * @returns Timestamp string or null if invalid\n */\nexport function extractTimestamp(filename: string): string | null {\n const match = filename.match(/^(\\d{14})-/);\n return match ? match[1] : null;\n}\n\n/**\n * Get the rollback filename for a migration\n *\n * @param migrationFilename - Migration filename (e.g., \"20250115120000-create-table.sql\")\n * @returns Rollback filename (e.g., \"20250115120000-create-table.rollback.sql\")\n */\nexport function getRollbackFilename(migrationFilename: string): string {\n return migrationFilename.replace(/\\.sql$/, '.rollback.sql');\n}\n","/**\n * Migration runner for Eldrin apps\n *\n * Executes SQL migrations against a D1 database with:\n * - Automatic tracking table creation\n * - Checksum verification for integrity\n * - Sequential execution (one migration at a time)\n * - Transaction-based execution per migration\n */\n\nimport type { MigrationFile, MigrationRecord, MigrationResult, MigrationOptions } from '../types';\nimport { calculateChecksum } from './checksum';\nimport { parseSQLStatements, isValidMigrationFilename } from './sql-parser';\n\n/**\n * SQL to create the migration tracking table\n */\nconst CREATE_MIGRATIONS_TABLE = `\nCREATE TABLE IF NOT EXISTS _eldrin_migrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n filename TEXT NOT NULL UNIQUE,\n checksum TEXT NOT NULL,\n executed_at INTEGER NOT NULL,\n execution_time_ms INTEGER\n)\n`;\n\n/**\n * Default logger that does nothing\n */\nconst defaultLogger = () => {};\n\n/**\n * Run pending migrations against the database\n *\n * @param db - D1 Database instance\n * @param options - Migration options\n * @returns Result of migration execution\n */\nexport async function runMigrations(\n db: D1Database,\n options: MigrationOptions = {}\n): Promise<MigrationResult> {\n const { migrations = [], skipChecksumVerification = false, onLog = defaultLogger } = options;\n\n const log = (message: string, level: 'info' | 'warn' | 'error' = 'info') => {\n onLog(message, level);\n };\n\n const result: MigrationResult = {\n success: true,\n executed: 0,\n migrations: [],\n };\n\n try {\n // 1. Ensure tracking table exists\n log('Creating migrations tracking table if not exists...');\n await db.batch([db.prepare(CREATE_MIGRATIONS_TABLE)]);\n\n // 2. Filter and sort migration files\n const validMigrations = migrations\n .filter((m) => isValidMigrationFilename(m.name))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n if (validMigrations.length === 0) {\n log('No migration files found');\n return result;\n }\n\n log(`Found ${validMigrations.length} migration file(s)`);\n\n // 3. Query executed migrations\n const { results: executed } = await db\n .prepare('SELECT filename, checksum FROM _eldrin_migrations ORDER BY filename')\n .all<Pick<MigrationRecord, 'filename' | 'checksum'>>();\n\n const executedMap = new Map(executed?.map((e) => [e.filename, e.checksum]) ?? []);\n\n // 4. Verify checksums of executed migrations (unless skipped)\n if (!skipChecksumVerification) {\n for (const migration of validMigrations) {\n const storedChecksum = executedMap.get(migration.name);\n if (storedChecksum) {\n const currentChecksum = await calculateChecksum(migration.content);\n if (currentChecksum !== storedChecksum) {\n const error = new Error(\n `Migration ${migration.name} has been modified after execution! ` +\n `Expected checksum: ${storedChecksum}, got: ${currentChecksum}`\n );\n log(error.message, 'error');\n return {\n success: false,\n executed: 0,\n migrations: [],\n error: {\n migration: migration.name,\n message: error.message,\n },\n };\n }\n }\n }\n }\n\n // 5. Check for orphaned migrations (in DB but file deleted)\n for (const [filename] of executedMap) {\n const hasFile = validMigrations.some((m) => m.name === filename);\n if (!hasFile) {\n log(`Warning: Orphaned migration in database: ${filename}`, 'warn');\n }\n }\n\n // 6. Calculate pending migrations\n const pending = validMigrations.filter((m) => !executedMap.has(m.name));\n\n if (pending.length === 0) {\n log('No pending migrations');\n return result;\n }\n\n log(`Found ${pending.length} pending migration(s)`);\n\n // 7. Execute pending migrations ONE AT A TIME\n for (const migration of pending) {\n log(`Executing migration: ${migration.name}`);\n const startTime = Date.now();\n\n try {\n // Parse SQL into statements\n const statements = parseSQLStatements(migration.content);\n\n if (statements.length === 0) {\n log(`Warning: Migration ${migration.name} contains no SQL statements`, 'warn');\n continue;\n }\n\n // Calculate checksum before execution\n const checksum = await calculateChecksum(migration.content);\n\n // Build batch with all statements + tracking record\n const batch: D1PreparedStatement[] = [\n // Execute all statements from the migration\n ...statements.map((sql) => db.prepare(sql)),\n\n // Record execution in tracking table\n db\n .prepare(\n `INSERT INTO _eldrin_migrations\n (filename, checksum, executed_at, execution_time_ms)\n VALUES (?, ?, ?, ?)`\n )\n .bind(migration.name, checksum, Date.now(), Date.now() - startTime),\n ];\n\n // Execute in a single transaction via batch\n await db.batch(batch);\n\n const executionTime = Date.now() - startTime;\n log(`Migration ${migration.name} completed (${executionTime}ms)`);\n\n result.executed++;\n result.migrations.push({\n name: migration.name,\n executionTimeMs: executionTime,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Migration ${migration.name} failed: ${errorMessage}`, 'error');\n\n // Transaction auto-rolls back on error\n // Previous migrations remain intact\n return {\n success: false,\n executed: result.executed,\n migrations: result.migrations,\n error: {\n migration: migration.name,\n message: errorMessage,\n },\n };\n }\n }\n\n log(`Successfully executed ${result.executed} migration(s)`);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Migration system error: ${errorMessage}`, 'error');\n return {\n success: false,\n executed: result.executed,\n migrations: result.migrations,\n error: {\n migration: 'system',\n message: errorMessage,\n },\n };\n }\n}\n\n/**\n * Get migration status (pending and executed migrations)\n *\n * @param db - D1 Database instance\n * @param migrations - Available migration files\n * @returns Status information\n */\nexport async function getMigrationStatus(\n db: D1Database,\n migrations: MigrationFile[]\n): Promise<{\n pending: string[];\n executed: MigrationRecord[];\n orphaned: string[];\n checksumMismatches: string[];\n}> {\n // Ensure table exists\n await db.batch([db.prepare(CREATE_MIGRATIONS_TABLE)]);\n\n // Get executed migrations\n const { results: executed } = await db\n .prepare('SELECT * FROM _eldrin_migrations ORDER BY filename')\n .all<MigrationRecord>();\n\n const executedMap = new Map(executed?.map((e) => [e.filename, e]) ?? []);\n\n // Filter valid migrations\n const validMigrations = migrations.filter((m) => isValidMigrationFilename(m.name));\n\n // Calculate pending\n const pending = validMigrations\n .filter((m) => !executedMap.has(m.name))\n .map((m) => m.name)\n .sort();\n\n // Check for orphaned migrations\n const orphaned: string[] = [];\n for (const [filename] of executedMap) {\n if (!validMigrations.some((m) => m.name === filename)) {\n orphaned.push(filename);\n }\n }\n\n // Check for checksum mismatches\n const checksumMismatches: string[] = [];\n for (const migration of validMigrations) {\n const record = executedMap.get(migration.name);\n if (record) {\n const currentChecksum = await calculateChecksum(migration.content);\n if (currentChecksum !== record.checksum) {\n checksumMismatches.push(migration.name);\n }\n }\n }\n\n return {\n pending,\n executed: executed ?? [],\n orphaned,\n checksumMismatches,\n };\n}\n","/**\n * Migration rollback functionality\n *\n * Rolls back migrations using .rollback.sql files in reverse order\n */\n\nimport type { MigrationFile, MigrationRecord } from '../types';\nimport { parseSQLStatements, isValidRollbackFilename, getRollbackFilename } from './sql-parser';\n\n/**\n * Result of a rollback operation\n */\nexport interface RollbackResult {\n success: boolean;\n rolledBack: string[];\n error?: {\n migration: string;\n message: string;\n };\n}\n\n/**\n * Rollback migrations to a specific target (or just the last one)\n *\n * @param db - D1 Database instance\n * @param options - Rollback options\n * @returns Result of rollback operation\n */\nexport async function rollbackMigrations(\n db: D1Database,\n options: {\n /** Rollback files (.rollback.sql) */\n rollbackFiles: MigrationFile[];\n /** Target migration to rollback TO (exclusive - this migration stays) */\n targetMigration?: string;\n /** Callback for logging */\n onLog?: (message: string, level: 'info' | 'warn' | 'error') => void;\n }\n): Promise<RollbackResult> {\n const { rollbackFiles, targetMigration, onLog = () => {} } = options;\n\n const log = (message: string, level: 'info' | 'warn' | 'error' = 'info') => {\n onLog(message, level);\n };\n\n const result: RollbackResult = {\n success: true,\n rolledBack: [],\n };\n\n try {\n // 1. Get executed migrations in reverse order\n const { results: executed } = await db\n .prepare('SELECT filename FROM _eldrin_migrations ORDER BY filename DESC')\n .all<Pick<MigrationRecord, 'filename'>>();\n\n if (!executed || executed.length === 0) {\n log('No migrations to rollback');\n return result;\n }\n\n // 2. Determine which migrations to rollback\n let toRollback: string[];\n\n if (targetMigration) {\n // Find the target migration\n const targetIndex = executed.findIndex((m) => m.filename === targetMigration);\n if (targetIndex === -1) {\n return {\n success: false,\n rolledBack: [],\n error: {\n migration: targetMigration,\n message: `Target migration not found: ${targetMigration}`,\n },\n };\n }\n // Rollback everything before the target (in the DESC sorted list, that means indices 0 to targetIndex-1)\n toRollback = executed.slice(0, targetIndex).map((m) => m.filename);\n } else {\n // Rollback only the last migration\n toRollback = [executed[0].filename];\n }\n\n if (toRollback.length === 0) {\n log('No migrations to rollback');\n return result;\n }\n\n // 3. Build rollback file map\n const rollbackMap = new Map(\n rollbackFiles.filter((f) => isValidRollbackFilename(f.name)).map((f) => [f.name, f])\n );\n\n // 4. Execute rollbacks in order (they're already in DESC order from query)\n for (const migrationFilename of toRollback) {\n const rollbackFilename = getRollbackFilename(migrationFilename);\n const rollbackFile = rollbackMap.get(rollbackFilename);\n\n if (!rollbackFile) {\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: migrationFilename,\n message: `Rollback file not found: ${rollbackFilename}`,\n },\n };\n }\n\n log(`Rolling back: ${migrationFilename}`);\n\n try {\n const statements = parseSQLStatements(rollbackFile.content);\n\n if (statements.length === 0) {\n log(`Warning: Rollback file ${rollbackFilename} contains no SQL statements`, 'warn');\n }\n\n // Build batch: rollback statements + remove tracking record\n const batch: D1PreparedStatement[] = [\n ...statements.map((sql) => db.prepare(sql)),\n db.prepare('DELETE FROM _eldrin_migrations WHERE filename = ?').bind(migrationFilename),\n ];\n\n await db.batch(batch);\n\n log(`Rolled back: ${migrationFilename}`);\n result.rolledBack.push(migrationFilename);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Rollback failed for ${migrationFilename}: ${errorMessage}`, 'error');\n\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: migrationFilename,\n message: errorMessage,\n },\n };\n }\n }\n\n log(`Successfully rolled back ${result.rolledBack.length} migration(s)`);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Rollback system error: ${errorMessage}`, 'error');\n\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: 'system',\n message: errorMessage,\n },\n };\n }\n}\n","/**\n * Marketplace utilities for migration packaging\n *\n * Provides tools to generate migration manifests for marketplace distribution.\n * This is used at build time to prepare apps for submission.\n */\n\nimport { readdir, readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { resolve, basename } from 'path';\nimport { calculatePrefixedChecksum } from './checksum';\nimport { isValidMigrationFilename, extractTimestamp } from './sql-parser';\nimport type { MigrationFile } from '../types';\n\n/**\n * Migration entry in the marketplace manifest\n */\nexport interface MigrationManifestEntry {\n /** Migration ID (timestamp) */\n id: string;\n /** Full filename */\n file: string;\n /** SHA-256 checksum with prefix */\n checksum: string;\n}\n\n/**\n * Marketplace migration manifest format\n */\nexport interface MigrationManifest {\n /** Logical database name (used for table prefixing) */\n database: string;\n /** List of migrations in order */\n migrations: MigrationManifestEntry[];\n}\n\n/**\n * Options for generating migration manifest\n */\nexport interface GenerateMigrationManifestOptions {\n /** Directory containing migration SQL files */\n migrationsDir: string;\n /** Logical database name for the app */\n database: string;\n}\n\n/**\n * Result of migration manifest generation\n */\nexport interface GenerateMigrationManifestResult {\n /** The generated manifest */\n manifest: MigrationManifest;\n /** Migration files with content (for copying to output) */\n files: MigrationFile[];\n}\n\n/**\n * Read migration files from a directory\n *\n * @param dir - Directory containing migration files\n * @returns Array of migration files sorted by name\n */\nasync function readMigrationFiles(dir: string): Promise<MigrationFile[]> {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = await readdir(dir);\n const sqlFiles = files\n .filter((f) => isValidMigrationFilename(f))\n .sort();\n\n const migrations: MigrationFile[] = [];\n\n for (const file of sqlFiles) {\n const content = await readFile(resolve(dir, file), 'utf-8');\n migrations.push({\n name: basename(file),\n content,\n });\n }\n\n return migrations;\n}\n\n/**\n * Generate a marketplace migration manifest from migration files\n *\n * Reads migration files from the specified directory and generates\n * a manifest with checksums suitable for marketplace distribution.\n *\n * @param options - Generation options\n * @returns Manifest and file contents\n *\n * @example\n * ```typescript\n * import { generateMigrationManifest } from '@eldrin-project/eldrin-app-core';\n *\n * const result = await generateMigrationManifest({\n * migrationsDir: './migrations',\n * database: 'invoicing',\n * });\n *\n * // Write manifest to output directory\n * await writeFile(\n * 'dist/migrations/index.json',\n * JSON.stringify(result.manifest, null, 2)\n * );\n *\n * // Copy migration files\n * for (const file of result.files) {\n * await writeFile(`dist/migrations/${file.name}`, file.content);\n * }\n * ```\n */\nexport async function generateMigrationManifest(\n options: GenerateMigrationManifestOptions\n): Promise<GenerateMigrationManifestResult> {\n const { migrationsDir, database } = options;\n\n const files = await readMigrationFiles(migrationsDir);\n\n const migrations: MigrationManifestEntry[] = await Promise.all(\n files.map(async (file) => {\n const timestamp = extractTimestamp(file.name);\n const checksum = await calculatePrefixedChecksum(file.content);\n\n return {\n id: timestamp || file.name.replace('.sql', ''),\n file: file.name,\n checksum,\n };\n })\n );\n\n return {\n manifest: {\n database,\n migrations,\n },\n files,\n };\n}\n\n/**\n * Validate a migration manifest against actual files\n *\n * Useful for CI/CD validation in the marketplace-dist repository.\n *\n * @param manifest - The manifest to validate\n * @param files - The actual migration files\n * @returns Validation result with any errors\n */\nexport async function validateMigrationManifest(\n manifest: MigrationManifest,\n files: MigrationFile[]\n): Promise<{\n valid: boolean;\n errors: string[];\n}> {\n const errors: string[] = [];\n\n // Check all manifest entries have corresponding files\n for (const entry of manifest.migrations) {\n const file = files.find((f) => f.name === entry.file);\n\n if (!file) {\n errors.push(`Missing file: ${entry.file}`);\n continue;\n }\n\n // Verify checksum\n const actualChecksum = await calculatePrefixedChecksum(file.content);\n if (actualChecksum !== entry.checksum) {\n errors.push(\n `Checksum mismatch for ${entry.file}: ` +\n `expected ${entry.checksum}, got ${actualChecksum}`\n );\n }\n\n // Verify ID matches timestamp\n const timestamp = extractTimestamp(file.name);\n if (timestamp !== entry.id) {\n errors.push(\n `ID mismatch for ${entry.file}: ` +\n `expected ${timestamp}, got ${entry.id}`\n );\n }\n }\n\n // Check all files are in manifest\n for (const file of files) {\n if (!manifest.migrations.some((m) => m.file === file.name)) {\n errors.push(`File not in manifest: ${file.name}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Database context and hooks for Eldrin apps\n *\n * Provides access to the app's isolated D1 database instance\n */\n\nimport { createContext, useContext, type ReactNode } from 'react';\nimport type { DatabaseContext, MigrationResult } from '../types';\n\n/**\n * React context for database access\n */\nconst EldrinDatabaseContext = createContext<DatabaseContext | null>(null);\n\n/**\n * Props for DatabaseProvider\n */\nexport interface DatabaseProviderProps {\n /** D1 database instance (null if app has no database) */\n db: D1Database | null;\n /** Whether migrations have completed */\n migrationsComplete: boolean;\n /** Migration result */\n migrationResult?: MigrationResult;\n /** Child components */\n children: ReactNode;\n}\n\n/**\n * Provider component for database context\n */\nexport function DatabaseProvider({\n db,\n migrationsComplete,\n migrationResult,\n children,\n}: DatabaseProviderProps) {\n const value: DatabaseContext = {\n db,\n migrationsComplete,\n migrationResult,\n };\n\n return (\n <EldrinDatabaseContext.Provider value={value}>{children}</EldrinDatabaseContext.Provider>\n );\n}\n\n/**\n * Hook to access the app's D1 database\n *\n * @returns D1Database instance or null if app has no database\n * @throws Error if used outside of DatabaseProvider\n *\n * @example\n * ```tsx\n * function InvoiceList() {\n * const db = useDatabase();\n *\n * if (!db) {\n * return <div>No database configured</div>;\n * }\n *\n * const { results } = await db.prepare(\n * 'SELECT * FROM invoices ORDER BY created_at DESC'\n * ).all();\n *\n * return <div>{results.map(invoice => ...)}</div>;\n * }\n * ```\n */\nexport function useDatabase(): D1Database | null {\n const context = useContext(EldrinDatabaseContext);\n\n if (context === null) {\n throw new Error('useDatabase must be used within a DatabaseProvider (via createApp)');\n }\n\n return context.db;\n}\n\n/**\n * Hook to access full database context including migration status\n *\n * @returns DatabaseContext object\n * @throws Error if used outside of DatabaseProvider\n */\nexport function useDatabaseContext(): DatabaseContext {\n const context = useContext(EldrinDatabaseContext);\n\n if (context === null) {\n throw new Error('useDatabaseContext must be used within a DatabaseProvider (via createApp)');\n }\n\n return context;\n}\n\n/**\n * Hook to check if migrations have completed\n *\n * Useful for showing loading states while migrations run\n *\n * @returns true if migrations are complete\n */\nexport function useMigrationsComplete(): boolean {\n const context = useContext(EldrinDatabaseContext);\n return context?.migrationsComplete ?? false;\n}\n","/**\n * App factory for creating Eldrin apps\n *\n * Returns single-spa compatible lifecycle functions with:\n * - Automatic migration execution on bootstrap\n * - Database provider wrapping\n * - Error boundary integration\n */\n\nimport { createElement, type ComponentType, type ReactNode } from 'react';\nimport type { CreateAppOptions, MigrationResult, MigrationFile } from '../types';\nimport { runMigrations } from '../migrations';\nimport { DatabaseProvider } from '../database';\n\n/**\n * Single-spa lifecycle props passed to lifecycle functions\n */\nexport interface LifecycleProps {\n /** DOM element to mount the app into */\n domElement?: HTMLElement;\n /** App name */\n name?: string;\n /** D1 Database instance (provided by shell) */\n db?: D1Database;\n /** Custom props from shell */\n customProps?: Record<string, unknown>;\n}\n\n/**\n * Single-spa compatible lifecycle object\n */\nexport interface AppLifecycle {\n bootstrap: (props: LifecycleProps) => Promise<void>;\n mount: (props: LifecycleProps) => Promise<void>;\n unmount: (props: LifecycleProps) => Promise<void>;\n}\n\n/**\n * Internal state for the app\n */\ninterface AppState {\n db: D1Database | null;\n migrationsComplete: boolean;\n migrationResult?: MigrationResult;\n mountedElement?: HTMLElement;\n reactRoot?: {\n render: (element: ReactNode) => void;\n unmount: () => void;\n };\n}\n\n/**\n * Create an Eldrin app with single-spa compatible lifecycle\n *\n * @param options - App configuration\n * @returns Object with bootstrap, mount, and unmount lifecycle functions\n *\n * @example\n * ```tsx\n * // src/index.tsx\n * import { createApp } from '@eldrin-project/eldrin-app-core';\n * import App from './App';\n *\n * export const { bootstrap, mount, unmount } = createApp({\n * name: 'invoicing',\n * root: App,\n * // Migrations loaded via Vite plugin\n * });\n * ```\n */\nexport function createApp(options: CreateAppOptions): AppLifecycle {\n const { name, root: RootComponent, migrations = [], onMigrationsComplete, onMigrationError } = options;\n\n // App state persists across mount/unmount cycles\n const state: AppState = {\n db: null,\n migrationsComplete: false,\n migrationResult: undefined,\n mountedElement: undefined,\n reactRoot: undefined,\n };\n\n /**\n * Bootstrap phase - runs once when app is first loaded\n * Executes migrations here before any mounting\n */\n async function bootstrap(props: LifecycleProps): Promise<void> {\n const db = props.db ?? null;\n state.db = db;\n\n // Run migrations if we have a database and migrations\n if (db && migrations.length > 0) {\n try {\n const result = await runMigrations(db, {\n migrations,\n onLog: (message, level) => {\n const prefix = `[${name}]`;\n if (level === 'error') {\n console.error(prefix, message);\n } else if (level === 'warn') {\n console.warn(prefix, message);\n } else {\n console.log(prefix, message);\n }\n },\n });\n\n state.migrationResult = result;\n\n if (result.success) {\n state.migrationsComplete = true;\n onMigrationsComplete?.(result);\n } else {\n const error = new Error(result.error?.message ?? 'Migration failed');\n onMigrationError?.(error);\n throw error;\n }\n } catch (error) {\n state.migrationsComplete = false;\n const err = error instanceof Error ? error : new Error(String(error));\n onMigrationError?.(err);\n throw err;\n }\n } else {\n // No database or no migrations - mark as complete\n state.migrationsComplete = true;\n }\n }\n\n /**\n * Mount phase - renders the app into the DOM\n */\n async function mount(props: LifecycleProps): Promise<void> {\n const domElement = props.domElement ?? document.getElementById(`app-${name}`);\n\n if (!domElement) {\n throw new Error(`No DOM element found for app \"${name}\". Expected element with id=\"app-${name}\" or domElement prop.`);\n }\n\n state.mountedElement = domElement;\n\n // Create the app element with providers\n const rootElement = createElement(RootComponent as ComponentType, props.customProps ?? {});\n const appElement = createElement(DatabaseProvider, {\n db: state.db,\n migrationsComplete: state.migrationsComplete,\n migrationResult: state.migrationResult,\n children: rootElement,\n });\n\n // Dynamically import React DOM to avoid bundling issues\n // Apps using this library will have React DOM in their dependencies\n const ReactDOM = await import('react-dom/client');\n const root = ReactDOM.createRoot(domElement);\n root.render(appElement);\n\n state.reactRoot = root;\n }\n\n /**\n * Unmount phase - removes the app from the DOM\n */\n async function unmount(_props: LifecycleProps): Promise<void> {\n if (state.reactRoot) {\n state.reactRoot.unmount();\n state.reactRoot = undefined;\n }\n\n if (state.mountedElement) {\n state.mountedElement.innerHTML = '';\n state.mountedElement = undefined;\n }\n }\n\n return {\n bootstrap,\n mount,\n unmount,\n };\n}\n\n/**\n * Type helper for migration files loaded via Vite plugin\n *\n * @example\n * ```tsx\n * // With Vite plugin\n * import { createApp, type MigrationFiles } from '@eldrin-project/eldrin-app-core';\n * import migrations from 'virtual:eldrin/migrations';\n *\n * export const { bootstrap, mount, unmount } = createApp({\n * name: 'invoicing',\n * root: App,\n * migrations: migrations as MigrationFiles,\n * });\n * ```\n */\nexport type MigrationFiles = MigrationFile[];\n","/**\n * Eldrin Event Client\n * SDK for app workers to emit and consume events\n */\n\nimport type {\n EldrinEvent,\n EmitOptions,\n EmitResult,\n EventDelivery,\n PollOptions,\n PollResult,\n EventClientConfig,\n SubscriptionInfo,\n RegisteredEventType,\n} from './types';\n\n/**\n * Client for interacting with the Eldrin event bus\n *\n * @example\n * ```typescript\n * const events = new EldrinEventClient({\n * appId: 'invoicing',\n * coreApiUrl: 'https://your-eldrin-core.workers.dev'\n * });\n *\n * // Emit an event\n * await events.emit('invoice.created', { invoiceId: 'inv_123', total: 1500 });\n *\n * // Poll for events\n * const pending = await events.poll();\n * for (const delivery of pending.events) {\n * await processEvent(delivery.event);\n * await events.ack(delivery.id);\n * }\n * ```\n */\nexport class EldrinEventClient {\n private readonly appId: string;\n private readonly coreApiUrl: string;\n\n constructor(config: EventClientConfig) {\n this.appId = config.appId;\n this.coreApiUrl = config.coreApiUrl.replace(/\\/$/, ''); // Remove trailing slash\n }\n\n /**\n * Emit an event to the event bus\n *\n * @param type - Event type (must be declared in app's manifest emits)\n * @param payload - Event payload data\n * @param options - Optional emit configuration\n * @returns Result containing the event ID\n * @throws Error if app is not authorized to emit this event type\n */\n async emit<T>(\n type: string,\n payload: T,\n options: EmitOptions = {}\n ): Promise<EmitResult> {\n const response = await fetch(`${this.coreApiUrl}/api/events/emit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({\n type,\n payload,\n version: options.version ?? 1,\n idempotencyKey: options.idempotencyKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(errorData.error || `Failed to emit event: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Poll for pending events\n *\n * @param options - Optional polling configuration\n * @returns List of pending event deliveries\n */\n async poll<T = unknown>(options: PollOptions = {}): Promise<PollResult<T>> {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.types?.length) params.set('types', options.types.join(','));\n\n const url = `${this.coreApiUrl}/api/events/poll${params.toString() ? `?${params}` : ''}`;\n const response = await fetch(url, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to poll events: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Acknowledge successful event processing\n *\n * @param deliveryId - The delivery record ID to acknowledge\n */\n async ack(deliveryId: number): Promise<void> {\n const response = await fetch(`${this.coreApiUrl}/api/events/ack`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({ deliveryId }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to acknowledge event: ${response.status}`);\n }\n }\n\n /**\n * Negative acknowledge - event will be retried later\n *\n * @param deliveryId - The delivery record ID\n * @param error - Optional error message for logging\n */\n async nack(deliveryId: number, error?: string): Promise<void> {\n const response = await fetch(`${this.coreApiUrl}/api/events/nack`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({ deliveryId, error }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to nack event: ${response.status}`);\n }\n }\n\n /**\n * Get all registered event types\n *\n * @returns List of all registered event types across all apps\n */\n async getEventTypes(): Promise<RegisteredEventType[]> {\n const response = await fetch(`${this.coreApiUrl}/api/events/types`, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get event types: ${response.status}`);\n }\n\n const data = await response.json() as { types: RegisteredEventType[] };\n return data.types;\n }\n\n /**\n * Get subscriptions for this app\n *\n * @returns List of active subscriptions\n */\n async getSubscriptions(): Promise<SubscriptionInfo[]> {\n const response = await fetch(`${this.coreApiUrl}/api/events/subscriptions`, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get subscriptions: ${response.status}`);\n }\n\n const data = await response.json() as { subscriptions: SubscriptionInfo[] };\n return data.subscriptions;\n }\n}\n\n/**\n * Environment bindings that may include Eldrin Core URL\n */\nexport interface EldrinEnv {\n ELDRIN_CORE_URL?: string;\n [key: string]: unknown;\n}\n\n/**\n * Create an event client for use in app workers\n *\n * @param env - Worker environment bindings (must have optional ELDRIN_CORE_URL)\n * @param appId - The app's identifier\n * @returns Configured event client\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const events = createEventClient(env, 'invoicing');\n * await events.emit('invoice.created', { invoiceId: 'inv_123' });\n * }\n * };\n * ```\n */\nexport function createEventClient(env: EldrinEnv, appId: string): EldrinEventClient {\n const coreApiUrl = (env.ELDRIN_CORE_URL as string | undefined) || 'http://localhost:4000';\n return new EldrinEventClient({ appId, coreApiUrl });\n}\n","/**\n * Auth utilities for Eldrin apps\n *\n * Supports two authentication methods:\n *\n * 1. JWT Token (Authorization header):\n * - Direct API calls with JWT token in Authorization: Bearer <token>\n * - JWT is verified using shared secret (JWT_SECRET env var)\n * - Permissions extracted from JWT payload\n *\n * 2. Proxy Headers (X-Eldrin-User-* headers):\n * - Requests proxied through eldrin-core shell\n * - Shell verifies JWT and injects user context headers\n * - Legacy support for proxied requests\n *\n * JWT takes precedence if Authorization header is present.\n */\n\n/**\n * Auth context extracted from JWT or shell-injected headers\n */\nexport interface AppAuthContext {\n /** User ID */\n userId: string;\n /** User email */\n email: string;\n /** User display name */\n name: string;\n /** Platform roles (admin, editor, viewer) */\n platformRoles: string[];\n /** App-specific permissions (e.g., [\"invoices:read\", \"invoices:write\"]) */\n permissions: string[];\n}\n\n/**\n * JWT payload structure (matches eldrin-core JWT format)\n */\nexport interface JWTPayload {\n /** User ID */\n sub: string;\n /** Email */\n email: string;\n /** First name */\n firstName: string;\n /** Last name */\n lastName: string;\n /** Platform role names */\n platformRoles: string[];\n /** Platform permission names */\n platformPermissions: string[];\n /**\n * App permissions in compact format\n * Key: \"developer_id:app_id\", Value: [\"resource:action\", ...]\n */\n appPermissions: Record<string, string[]>;\n /** Issued at (timestamp) */\n iat: number;\n /** Expiration (timestamp) */\n exp: number;\n}\n\n/**\n * Options for JWT verification\n */\nexport interface JWTVerifyOptions {\n /** JWT secret key (from env.JWT_SECRET) */\n secret: string;\n /** App ID for extracting app-specific permissions */\n appId: string;\n /** Developer ID (optional, uses wildcard matching if not provided) */\n developerId?: string;\n}\n\n/**\n * Header names used by the shell for auth context injection\n */\nexport const AUTH_HEADERS = {\n USER_ID: 'x-eldrin-user-id',\n USER_EMAIL: 'x-eldrin-user-email',\n USER_NAME: 'x-eldrin-user-name',\n USER_ROLES: 'x-eldrin-user-roles',\n USER_PERMISSIONS: 'x-eldrin-user-permissions',\n} as const;\n\n// ============================================================================\n// JWT Verification (Web Crypto API)\n// ============================================================================\n\n/**\n * Base64URL decode (JWT uses URL-safe base64)\n */\nfunction base64UrlDecode(str: string): Uint8Array {\n // Convert base64url to base64\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n // Pad if necessary\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Decode\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Verify JWT signature using HMAC-SHA256\n */\nasync function verifyJWTSignature(\n token: string,\n secret: string\n): Promise<{ valid: boolean; payload?: JWTPayload; error?: string }> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return { valid: false, error: 'Invalid JWT format' };\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n try {\n // Import the secret key\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify']\n );\n\n // Verify the signature\n const signedData = encoder.encode(`${headerB64}.${payloadB64}`);\n const signature = base64UrlDecode(signatureB64);\n\n const isValid = await crypto.subtle.verify(\n 'HMAC',\n key,\n signature.buffer as ArrayBuffer,\n signedData\n );\n\n if (!isValid) {\n return { valid: false, error: 'Invalid signature' };\n }\n\n // Decode payload\n const payloadJson = new TextDecoder().decode(base64UrlDecode(payloadB64));\n const payload = JSON.parse(payloadJson) as JWTPayload;\n\n // Check expiration\n const now = Date.now();\n if (payload.exp && payload.exp < now) {\n return { valid: false, error: 'Token expired' };\n }\n\n return { valid: true, payload };\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : 'JWT verification failed',\n };\n }\n}\n\n/**\n * Extract app-specific permissions from JWT payload\n *\n * Matches permissions using appId, checking both:\n * - Exact match: \"developer_id:app_id\"\n * - Wildcard match: \"*:app_id\" or entries ending with \":app_id\"\n */\nfunction extractAppPermissions(\n payload: JWTPayload,\n appId: string,\n developerId?: string\n): string[] {\n const permissions: string[] = [];\n\n for (const [key, perms] of Object.entries(payload.appPermissions)) {\n // Check if this entry matches the app\n if (developerId) {\n // Exact match with developer ID\n if (key === `${developerId}:${appId}`) {\n permissions.push(...perms);\n }\n } else {\n // Wildcard match - any entry ending with :appId\n if (key.endsWith(`:${appId}`)) {\n permissions.push(...perms);\n }\n }\n }\n\n return permissions;\n}\n\n/**\n * Convert JWT payload to AppAuthContext\n */\nfunction jwtPayloadToAuthContext(\n payload: JWTPayload,\n appId: string,\n developerId?: string\n): AppAuthContext {\n return {\n userId: payload.sub,\n email: payload.email,\n name: `${payload.firstName} ${payload.lastName}`.trim(),\n platformRoles: payload.platformRoles,\n permissions: extractAppPermissions(payload, appId, developerId),\n };\n}\n\n/**\n * Verify JWT token and extract auth context\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const result = await verifyJWT(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (!result.success) {\n * return new Response(JSON.stringify({ error: result.error }), {\n * status: 401,\n * headers: { 'Content-Type': 'application/json' },\n * });\n * }\n *\n * // result.auth contains the AppAuthContext\n * console.log('User:', result.auth.email);\n * }\n * }\n * ```\n */\nexport async function verifyJWT(\n request: Request,\n options: JWTVerifyOptions\n): Promise<{ success: true; auth: AppAuthContext } | { success: false; error: string }> {\n const authHeader = request.headers.get('Authorization');\n\n if (!authHeader) {\n return { success: false, error: 'Missing Authorization header' };\n }\n\n if (!authHeader.startsWith('Bearer ')) {\n return { success: false, error: 'Invalid Authorization header format' };\n }\n\n const token = authHeader.slice(7); // Remove 'Bearer ' prefix\n\n const result = await verifyJWTSignature(token, options.secret);\n\n if (!result.valid || !result.payload) {\n return { success: false, error: result.error || 'JWT verification failed' };\n }\n\n const auth = jwtPayloadToAuthContext(result.payload, options.appId, options.developerId);\n return { success: true, auth };\n}\n\n/**\n * Get auth context from JWT token or fall back to proxy headers\n *\n * This is the recommended way to get auth context as it supports both:\n * - Direct API calls with JWT token\n * - Proxied requests with shell-injected headers\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await getAuthContextFromJWT(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (!auth) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n *\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport async function getAuthContextFromJWT(\n request: Request,\n options: JWTVerifyOptions\n): Promise<AppAuthContext | null> {\n // Try JWT first if Authorization header is present\n const authHeader = request.headers.get('Authorization');\n\n if (authHeader?.startsWith('Bearer ')) {\n const result = await verifyJWT(request, options);\n if (result.success) {\n return result.auth;\n }\n // JWT verification failed - don't fall back to headers\n // (if user sent a token, they expect JWT auth)\n return null;\n }\n\n // Fall back to proxy headers\n return getAuthContext(request);\n}\n\n/**\n * Require JWT authentication - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await requireJWTAuth(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (auth instanceof Response) {\n * return auth; // 401 Unauthorized\n * }\n *\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport async function requireJWTAuth(\n request: Request,\n options: JWTVerifyOptions\n): Promise<AppAuthContext | Response> {\n const auth = await getAuthContextFromJWT(request, options);\n\n if (!auth) {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return auth;\n}\n\n/**\n * Require JWT auth with specific permission - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await requireJWTPermission(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * }, 'categories', 'create');\n *\n * if (auth instanceof Response) {\n * return auth; // 401 or 403\n * }\n *\n * // User has categories:create permission\n * }\n * }\n * ```\n */\nexport async function requireJWTPermission(\n request: Request,\n options: JWTVerifyOptions,\n resource: string,\n action: string\n): Promise<AppAuthContext | Response> {\n const auth = await requireJWTAuth(request, options);\n\n if (auth instanceof Response) {\n return auth; // 401 Unauthorized\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check specific permission\n if (!hasPermission(auth, resource, action)) {\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permission: ${resource}:${action}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n// ============================================================================\n// Header-based Auth (Legacy/Proxy support)\n// ============================================================================\n\n/**\n * Extract auth context from request headers (proxy mode)\n *\n * Returns null if the user is not authenticated (no user ID header).\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = getAuthContext(request);\n * if (!auth) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport function getAuthContext(request: Request): AppAuthContext | null {\n const userId = request.headers.get(AUTH_HEADERS.USER_ID);\n\n // No user ID means not authenticated\n if (!userId) {\n return null;\n }\n\n const email = request.headers.get(AUTH_HEADERS.USER_EMAIL) || '';\n const name = request.headers.get(AUTH_HEADERS.USER_NAME) || '';\n const rolesHeader = request.headers.get(AUTH_HEADERS.USER_ROLES) || '';\n const permissionsHeader = request.headers.get(AUTH_HEADERS.USER_PERMISSIONS) || '';\n\n return {\n userId,\n email,\n name,\n platformRoles: rolesHeader ? rolesHeader.split(',').map((r) => r.trim()) : [],\n permissions: permissionsHeader ? permissionsHeader.split(',').map((p) => p.trim()) : [],\n };\n}\n\n/**\n * Require authentication - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = requireAuth(request);\n * if (auth instanceof Response) {\n * return auth; // 401 Unauthorized\n * }\n * // auth is AppAuthContext\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport function requireAuth(request: Request): AppAuthContext | Response {\n const auth = getAuthContext(request);\n\n if (!auth) {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return auth;\n}\n\n/**\n * Check if auth context has a specific permission\n *\n * Supports wildcard matching:\n * - \"invoices:*\" matches any action on invoices\n * - \"*:*\" matches all permissions\n *\n * @example\n * ```typescript\n * const auth = getAuthContext(request);\n * if (auth && hasPermission(auth, 'invoices', 'write')) {\n * // User can write invoices\n * }\n * ```\n */\nexport function hasPermission(\n auth: AppAuthContext,\n resource: string,\n action: string\n): boolean {\n const required = `${resource}:${action}`;\n\n // Check exact match\n if (auth.permissions.includes(required)) {\n return true;\n }\n\n // Check resource wildcard (e.g., \"invoices:*\")\n if (auth.permissions.includes(`${resource}:*`)) {\n return true;\n }\n\n // Check full wildcard\n if (auth.permissions.includes('*:*')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if auth context has a platform role\n *\n * @example\n * ```typescript\n * const auth = getAuthContext(request);\n * if (auth && hasPlatformRole(auth, 'admin')) {\n * // User is platform admin\n * }\n * ```\n */\nexport function hasPlatformRole(auth: AppAuthContext, role: string): boolean {\n return auth.platformRoles.includes(role);\n}\n\n/**\n * Check if auth context is a platform admin\n *\n * Platform admins have full access to all apps and resources.\n */\nexport function isPlatformAdmin(auth: AppAuthContext): boolean {\n return auth.platformRoles.includes('admin');\n}\n\n/**\n * Require a specific permission - returns auth context or error response\n *\n * Also grants access if user is a platform admin.\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = requirePermission(request, 'invoices', 'write');\n * if (auth instanceof Response) {\n * return auth; // 401 or 403\n * }\n * // User has invoices:write permission\n * }\n * }\n * ```\n */\nexport function requirePermission(\n request: Request,\n resource: string,\n action: string\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth; // 401 Unauthorized\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check specific permission\n if (!hasPermission(auth, resource, action)) {\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permission: ${resource}:${action}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n/**\n * Require any of the specified permissions - returns auth context or error response\n *\n * @example\n * ```typescript\n * const auth = requireAnyPermission(request, [\n * ['invoices', 'read'],\n * ['invoices', 'write'],\n * ]);\n * ```\n */\nexport function requireAnyPermission(\n request: Request,\n permissions: Array<[resource: string, action: string]>\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth;\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check if user has any of the required permissions\n const hasAny = permissions.some(([resource, action]) =>\n hasPermission(auth, resource, action)\n );\n\n if (!hasAny) {\n const permList = permissions.map(([r, a]) => `${r}:${a}`).join(', ');\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing one of permissions: ${permList}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n/**\n * Require all of the specified permissions - returns auth context or error response\n *\n * @example\n * ```typescript\n * const auth = requireAllPermissions(request, [\n * ['invoices', 'read'],\n * ['customers', 'read'],\n * ]);\n * ```\n */\nexport function requireAllPermissions(\n request: Request,\n permissions: Array<[resource: string, action: string]>\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth;\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check if user has all required permissions\n const missing = permissions.filter(\n ([resource, action]) => !hasPermission(auth, resource, action)\n );\n\n if (missing.length > 0) {\n const permList = missing.map(([r, a]) => `${r}:${a}`).join(', ');\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permissions: ${permList}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n","/**\n * Route matching utilities for permission middleware\n *\n * Compiles manifest route patterns into efficient regex matchers\n * and provides path matching with parameter extraction.\n */\n\nimport type { ManifestRoute, CompiledRoute } from './types';\n\n/**\n * Compile manifest routes into efficient matchers\n *\n * Converts manifest route patterns like:\n * - \"/todos\" -> exact match\n * - \"/todos/*\" -> matches one segment (e.g., /todos/123)\n * - \"/todos/:id\" -> matches one segment and captures as param\n *\n * @param routes - Route definitions from manifest\n * @param apiPrefix - API path prefix (e.g., \"/api\")\n * @returns Array of compiled routes ready for matching\n */\nexport function compileRoutes(routes: ManifestRoute[], apiPrefix: string): CompiledRoute[] {\n return routes.map((route) => {\n // Normalize methods to uppercase Set\n const methods = new Set(\n Array.isArray(route.method)\n ? route.method.map((m) => m.toUpperCase())\n : [route.method.toUpperCase()]\n );\n\n // Build full path with prefix\n const fullPath = `${apiPrefix}${route.path}`;\n const paramNames: string[] = [];\n\n // Convert path pattern to regex\n let regexPattern = fullPath\n // Escape special regex chars except * and :\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n // Convert :param to named capture group\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n })\n // Convert * wildcard to match segment (non-capturing)\n .replace(/\\*/g, '[^/]+');\n\n const pattern = new RegExp(`^${regexPattern}$`);\n\n // Parse permission into resource:action\n let permission: { resource: string; action: string } | null = null;\n if (route.permission) {\n const colonIndex = route.permission.indexOf(':');\n if (colonIndex > 0) {\n permission = {\n resource: route.permission.substring(0, colonIndex),\n action: route.permission.substring(colonIndex + 1),\n };\n }\n }\n\n return {\n methods,\n pattern,\n paramNames,\n permission,\n originalPath: route.path,\n };\n });\n}\n\n/**\n * Match a request against compiled routes\n *\n * Iterates through routes in order and returns the first match.\n * Order matters - more specific routes should come before wildcards.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param pathname - Request path (e.g., \"/api/todos/123\")\n * @param compiledRoutes - Pre-compiled route patterns\n * @returns Matched route with extracted params, or null if no match\n */\nexport function matchRoute(\n method: string,\n pathname: string,\n compiledRoutes: CompiledRoute[]\n): { route: CompiledRoute; params: Record<string, string> } | null {\n const upperMethod = method.toUpperCase();\n\n for (const route of compiledRoutes) {\n // Check method first (fast path)\n if (!route.methods.has(upperMethod)) continue;\n\n // Check path pattern\n const match = pathname.match(route.pattern);\n if (match) {\n // Extract named params from capture groups\n const params: Record<string, string> = {};\n route.paramNames.forEach((name, index) => {\n params[name] = match[index + 1];\n });\n return { route, params };\n }\n }\n\n return null;\n}\n\n/**\n * Check if path matches a public route pattern\n *\n * Public routes bypass authentication entirely.\n * Supports exact matches and wildcard suffixes.\n *\n * @param pathname - Request path\n * @param publicRoutes - Array of public route patterns\n * @param apiPrefix - API path prefix\n * @returns True if path is public\n */\nexport function isPublicRoute(\n pathname: string,\n publicRoutes: string[],\n apiPrefix: string\n): boolean {\n for (const publicPath of publicRoutes) {\n const fullPath = `${apiPrefix}${publicPath}`;\n\n // Exact match\n if (pathname === fullPath) return true;\n\n // Wildcard match (e.g., \"/public/*\")\n if (publicPath.endsWith('/*')) {\n const prefix = `${apiPrefix}${publicPath.slice(0, -2)}`;\n if (pathname.startsWith(prefix + '/')) return true;\n }\n }\n\n return false;\n}\n","/**\n * Permission Middleware\n *\n * Manifest-driven request middleware that:\n * 1. Loads route permissions from app manifest\n * 2. Intercepts requests before handlers\n * 3. Extracts and verifies JWT tokens\n * 4. Matches requests to defined routes\n * 5. Checks user permissions against requirements\n * 6. Returns auth context to handlers if authorized\n *\n * @example\n * ```typescript\n * import { createPermissionMiddleware } from '@eldrin-project/eldrin-app-core';\n * import manifest from '../public/eldrin-app.manifest.json';\n *\n * const middleware = createPermissionMiddleware<Env>({\n * manifest,\n * getSecret: (env) => env.JWT_SECRET,\n * cors: {\n * allowOrigin: '*',\n * allowMethods: 'GET, POST, PUT, PATCH, DELETE, OPTIONS',\n * allowHeaders: 'Content-Type, Authorization',\n * },\n * });\n *\n * export default {\n * async fetch(request: Request, env: Env): Promise<Response> {\n * const result = await middleware.handle(request, env);\n *\n * if (result.response) {\n * return result.response; // Rejected or CORS preflight\n * }\n *\n * const { auth, url, params } = result;\n * // Authorized - handle the request\n * }\n * }\n * ```\n */\n\nimport {\n verifyJWT,\n hasPermission,\n isPlatformAdmin,\n type AppAuthContext,\n type JWTVerifyOptions,\n} from '../auth';\nimport type {\n MiddlewareConfig,\n MiddlewareResult,\n PermissionMiddleware,\n MiddlewareError,\n CompiledRoute,\n} from './types';\nimport { compileRoutes, matchRoute, isPublicRoute } from './matcher';\n\n/**\n * Create a permission middleware instance\n *\n * The middleware is configured once with the app manifest and secret getter,\n * then used to handle each incoming request.\n *\n * @param config - Middleware configuration\n * @returns Permission middleware instance\n */\nexport function createPermissionMiddleware<TEnv = unknown>(\n config: MiddlewareConfig<TEnv>\n): PermissionMiddleware<TEnv> {\n const apiPrefix = config.apiPrefix ?? '/api';\n const manifest = config.manifest;\n const api = manifest.api;\n\n // Pre-compile routes for efficient matching\n const compiledRoutes: CompiledRoute[] = api?.routes\n ? compileRoutes(api.routes, apiPrefix)\n : [];\n\n const defaultPolicy = api?.defaultPolicy ?? 'deny';\n const publicRoutes = api?.publicRoutes ?? [];\n\n // Empty auth context for public routes\n const emptyAuth: AppAuthContext = {\n userId: '',\n email: '',\n name: '',\n platformRoles: [],\n permissions: [],\n };\n\n function createCorsHeaders(): HeadersInit {\n if (!config.cors) return {};\n return {\n 'Access-Control-Allow-Origin': config.cors.allowOrigin,\n 'Access-Control-Allow-Methods': config.cors.allowMethods,\n 'Access-Control-Allow-Headers': config.cors.allowHeaders,\n };\n }\n\n function withCors(response: Response): Response {\n if (!config.cors) return response;\n\n const newHeaders = new Headers(response.headers);\n Object.entries(createCorsHeaders()).forEach(([key, value]) => {\n newHeaders.set(key, value);\n });\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n\n function errorResponse(error: MiddlewareError): Response {\n // Allow custom error handling\n if (config.onError) {\n return withCors(config.onError(error));\n }\n\n // Default error responses\n switch (error.type) {\n case 'unauthorized':\n return withCors(\n Response.json(\n { error: 'Unauthorized', message: error.message },\n { status: 401 }\n )\n );\n case 'forbidden':\n return withCors(\n Response.json(\n {\n error: 'Forbidden',\n message: error.message,\n permission: error.permission,\n },\n { status: 403 }\n )\n );\n case 'route_not_found':\n return withCors(\n Response.json(\n { error: 'Not Found', message: error.message },\n { status: 404 }\n )\n );\n }\n }\n\n async function verifyAndGetAuth(\n request: Request,\n env: TEnv\n ): Promise<AppAuthContext | Response> {\n const jwtOptions: JWTVerifyOptions = {\n secret: config.getSecret(env),\n appId: manifest.id,\n developerId: manifest.developer_id,\n };\n\n const result = await verifyJWT(request, jwtOptions);\n\n if (!result.success) {\n return errorResponse({\n type: 'unauthorized',\n message: result.error,\n });\n }\n\n return result.auth;\n }\n\n return {\n async handle(request: Request, env: TEnv): Promise<MiddlewareResult> {\n const url = new URL(request.url);\n const method = request.method;\n const pathname = url.pathname;\n\n // Check skip routes (e.g., static assets)\n if (config.skipRoutes) {\n for (const skipPattern of config.skipRoutes) {\n if (pathname.startsWith(skipPattern)) {\n return { auth: emptyAuth, url, params: {} };\n }\n }\n }\n\n // Handle CORS preflight\n if (method === 'OPTIONS') {\n return {\n response: new Response(null, {\n status: 204,\n headers: createCorsHeaders(),\n }),\n };\n }\n\n // Only process API routes\n if (!pathname.startsWith(apiPrefix)) {\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Check if it's a public route\n if (isPublicRoute(pathname, publicRoutes, apiPrefix)) {\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Match against compiled routes\n const match = matchRoute(method, pathname, compiledRoutes);\n\n if (!match) {\n // No matching route defined in manifest\n if (defaultPolicy === 'allow') {\n // Allow policy: let unmatched routes through without auth\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Deny policy: require auth for unmatched routes\n const authResult = await verifyAndGetAuth(request, env);\n if (authResult instanceof Response) {\n return { response: authResult };\n }\n return { auth: authResult, url, params: {} };\n }\n\n // Route matched - check if public (permission: null)\n if (match.route.permission === null) {\n return { auth: emptyAuth, url, params: match.params };\n }\n\n // Protected route - verify JWT\n const authResult = await verifyAndGetAuth(request, env);\n if (authResult instanceof Response) {\n return { response: authResult };\n }\n\n const auth = authResult;\n\n // Platform admins bypass permission checks\n if (isPlatformAdmin(auth)) {\n return { auth, url, params: match.params };\n }\n\n // Check specific permission\n const { resource, action } = match.route.permission;\n if (!hasPermission(auth, resource, action)) {\n return {\n response: errorResponse({\n type: 'forbidden',\n message: `Missing permission: ${resource}:${action}`,\n permission: `${resource}:${action}`,\n }),\n };\n }\n\n // Authorized!\n return { auth, url, params: match.params };\n },\n };\n}\n\n// Re-export types for consumers\nexport type {\n ManifestRoute,\n ManifestApi,\n ManifestForMiddleware,\n CorsConfig,\n MiddlewareConfig,\n MiddlewareError,\n MiddlewareErrorType,\n MiddlewareResult,\n MiddlewareResponseResult,\n MiddlewareAuthResult,\n PermissionMiddleware,\n CompiledRoute,\n} from './types';\n\n// Export matcher utilities (useful for testing)\nexport { compileRoutes, matchRoute, isPublicRoute } from './matcher';\n"]}
1
+ {"version":3,"sources":["../src/migrations/checksum.ts","../src/migrations/sql-parser.ts","../src/migrations/runner.ts","../src/migrations/rollback.ts","../src/migrations/marketplace.ts","../src/events/client.ts","../src/auth/index.ts","../src/middleware/matcher.ts","../src/middleware/index.ts"],"names":["trimmed","existsSync","readdir","readFile","resolve","basename","authResult"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Checksum utilities for migration integrity verification\n *\n * Uses SHA-256 for content hashing via Web Crypto API\n * (compatible with Cloudflare Workers runtime)\n */\n\n/** Prefix for SHA-256 checksums in marketplace format */\nexport const CHECKSUM_PREFIX = 'sha256:';\n\n/**\n * Calculate SHA-256 checksum of content\n *\n * @param content - String content to hash\n * @param options - Options for checksum calculation\n * @param options.prefixed - If true, returns \"sha256:...\" format (default: false for backwards compatibility)\n * @returns Hex-encoded SHA-256 hash, optionally with prefix\n */\nexport async function calculateChecksum(\n content: string,\n options: { prefixed?: boolean } = {}\n): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n\n return options.prefixed ? `${CHECKSUM_PREFIX}${hex}` : hex;\n}\n\n/**\n * Calculate SHA-256 checksum with sha256: prefix\n *\n * Convenience function for marketplace format\n *\n * @param content - String content to hash\n * @returns Prefixed checksum (e.g., \"sha256:abc123...\")\n */\nexport async function calculatePrefixedChecksum(content: string): Promise<string> {\n return calculateChecksum(content, { prefixed: true });\n}\n\n/**\n * Verify that content matches an expected checksum\n *\n * Handles both prefixed (\"sha256:...\") and unprefixed checksums\n *\n * @param content - Content to verify\n * @param expectedChecksum - Expected SHA-256 hex string (with or without prefix)\n * @returns true if checksums match\n */\nexport async function verifyChecksum(\n content: string,\n expectedChecksum: string\n): Promise<boolean> {\n // Strip prefix if present for comparison\n const normalizedExpected = expectedChecksum.startsWith(CHECKSUM_PREFIX)\n ? expectedChecksum.slice(CHECKSUM_PREFIX.length)\n : expectedChecksum;\n\n const actualChecksum = await calculateChecksum(content);\n return actualChecksum === normalizedExpected;\n}\n","/**\n * SQL statement parser for migration files\n *\n * Parses SQL content into individual statements for execution via db.batch()\n */\n\n/**\n * Parse SQL content into individual statements\n *\n * - Removes SQL comments (-- style)\n * - Splits by semicolon\n * - Handles multi-line statements\n * - Preserves string literals containing semicolons\n *\n * @param sql - Raw SQL content\n * @returns Array of individual SQL statements\n */\nexport function parseSQLStatements(sql: string): string[] {\n // First, handle the content preserving strings\n const statements: string[] = [];\n let current = '';\n let inString = false;\n let stringChar = '';\n let i = 0;\n\n // Pre-process: remove single-line comments\n const lines = sql.split('\\n');\n const cleanedLines: string[] = [];\n\n for (const line of lines) {\n let cleanLine = '';\n let lineInString = false;\n let lineStringChar = '';\n\n for (let j = 0; j < line.length; j++) {\n const char = line[j];\n const nextChar = line[j + 1];\n\n if (!lineInString) {\n // Check for comment start\n if (char === '-' && nextChar === '-') {\n // Rest of line is a comment, skip it\n break;\n }\n // Check for string start\n if (char === \"'\" || char === '\"') {\n lineInString = true;\n lineStringChar = char;\n }\n } else {\n // Check for string end (handle escaped quotes)\n if (char === lineStringChar) {\n // Check if it's an escaped quote\n if (nextChar === lineStringChar) {\n cleanLine += char;\n j++; // Skip the next char\n cleanLine += line[j];\n continue;\n }\n lineInString = false;\n }\n }\n\n cleanLine += char;\n }\n\n cleanedLines.push(cleanLine);\n }\n\n const cleanedSql = cleanedLines.join('\\n');\n\n // Now split by semicolons, respecting string literals\n for (i = 0; i < cleanedSql.length; i++) {\n const char = cleanedSql[i];\n\n if (!inString) {\n if (char === \"'\" || char === '\"') {\n inString = true;\n stringChar = char;\n current += char;\n } else if (char === ';') {\n // End of statement\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n statements.push(trimmed);\n }\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n\n // Check for end of string\n if (char === stringChar) {\n // Check for escaped quote\n const nextChar = cleanedSql[i + 1];\n if (nextChar === stringChar) {\n // Escaped quote, skip next char\n i++;\n current += nextChar;\n } else {\n inString = false;\n }\n }\n }\n }\n\n // Don't forget any remaining content\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n statements.push(trimmed);\n }\n\n return statements;\n}\n\n/**\n * Validate that a filename follows the migration naming convention\n *\n * Expected format: TIMESTAMP-description.sql\n * - TIMESTAMP: 14 digits (YYYYMMDDHHmmss)\n * - description: kebab-case\n *\n * @param filename - Filename to validate\n * @returns true if valid, false otherwise\n */\nexport function isValidMigrationFilename(filename: string): boolean {\n // Must end with .sql (but not .rollback.sql)\n if (!filename.endsWith('.sql') || filename.endsWith('.rollback.sql')) {\n return false;\n }\n\n // Pattern: 14-digit timestamp, hyphen, description, .sql\n const pattern = /^\\d{14}-[a-z0-9-]+\\.sql$/;\n return pattern.test(filename);\n}\n\n/**\n * Validate that a filename follows the rollback naming convention\n *\n * Expected format: TIMESTAMP-description.rollback.sql\n *\n * @param filename - Filename to validate\n * @returns true if valid rollback file, false otherwise\n */\nexport function isValidRollbackFilename(filename: string): boolean {\n // Must end with .rollback.sql\n if (!filename.endsWith('.rollback.sql')) {\n return false;\n }\n\n // Pattern: 14-digit timestamp, hyphen, description, .rollback.sql\n const pattern = /^\\d{14}-[a-z0-9-]+\\.rollback\\.sql$/;\n return pattern.test(filename);\n}\n\n/**\n * Extract timestamp from migration filename\n *\n * @param filename - Migration filename\n * @returns Timestamp string or null if invalid\n */\nexport function extractTimestamp(filename: string): string | null {\n const match = filename.match(/^(\\d{14})-/);\n return match ? match[1] : null;\n}\n\n/**\n * Get the rollback filename for a migration\n *\n * @param migrationFilename - Migration filename (e.g., \"20250115120000-create-table.sql\")\n * @returns Rollback filename (e.g., \"20250115120000-create-table.rollback.sql\")\n */\nexport function getRollbackFilename(migrationFilename: string): string {\n return migrationFilename.replace(/\\.sql$/, '.rollback.sql');\n}\n","/**\n * Migration runner for Eldrin apps\n *\n * Executes SQL migrations against a D1 database with:\n * - Automatic tracking table creation\n * - Checksum verification for integrity\n * - Sequential execution (one migration at a time)\n * - Transaction-based execution per migration\n */\n\nimport type { MigrationFile, MigrationRecord, MigrationResult, MigrationOptions } from '../types';\nimport { calculateChecksum } from './checksum';\nimport { parseSQLStatements, isValidMigrationFilename } from './sql-parser';\n\n/**\n * SQL to create the migration tracking table\n */\nconst CREATE_MIGRATIONS_TABLE = `\nCREATE TABLE IF NOT EXISTS _eldrin_migrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n filename TEXT NOT NULL UNIQUE,\n checksum TEXT NOT NULL,\n executed_at INTEGER NOT NULL,\n execution_time_ms INTEGER\n)\n`;\n\n/**\n * Default logger that does nothing\n */\nconst defaultLogger = () => {};\n\n/**\n * Run pending migrations against the database\n *\n * @param db - D1 Database instance\n * @param options - Migration options\n * @returns Result of migration execution\n */\nexport async function runMigrations(\n db: D1Database,\n options: MigrationOptions = {}\n): Promise<MigrationResult> {\n const { migrations = [], skipChecksumVerification = false, onLog = defaultLogger } = options;\n\n const log = (message: string, level: 'info' | 'warn' | 'error' = 'info') => {\n onLog(message, level);\n };\n\n const result: MigrationResult = {\n success: true,\n executed: 0,\n migrations: [],\n };\n\n try {\n // 1. Ensure tracking table exists\n log('Creating migrations tracking table if not exists...');\n await db.batch([db.prepare(CREATE_MIGRATIONS_TABLE)]);\n\n // 2. Filter and sort migration files\n const validMigrations = migrations\n .filter((m) => isValidMigrationFilename(m.name))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n if (validMigrations.length === 0) {\n log('No migration files found');\n return result;\n }\n\n log(`Found ${validMigrations.length} migration file(s)`);\n\n // 3. Query executed migrations\n const { results: executed } = await db\n .prepare('SELECT filename, checksum FROM _eldrin_migrations ORDER BY filename')\n .all<Pick<MigrationRecord, 'filename' | 'checksum'>>();\n\n const executedMap = new Map(executed?.map((e) => [e.filename, e.checksum]) ?? []);\n\n // 4. Verify checksums of executed migrations (unless skipped)\n if (!skipChecksumVerification) {\n for (const migration of validMigrations) {\n const storedChecksum = executedMap.get(migration.name);\n if (storedChecksum) {\n const currentChecksum = await calculateChecksum(migration.content);\n if (currentChecksum !== storedChecksum) {\n const error = new Error(\n `Migration ${migration.name} has been modified after execution! ` +\n `Expected checksum: ${storedChecksum}, got: ${currentChecksum}`\n );\n log(error.message, 'error');\n return {\n success: false,\n executed: 0,\n migrations: [],\n error: {\n migration: migration.name,\n message: error.message,\n },\n };\n }\n }\n }\n }\n\n // 5. Check for orphaned migrations (in DB but file deleted)\n for (const [filename] of executedMap) {\n const hasFile = validMigrations.some((m) => m.name === filename);\n if (!hasFile) {\n log(`Warning: Orphaned migration in database: ${filename}`, 'warn');\n }\n }\n\n // 6. Calculate pending migrations\n const pending = validMigrations.filter((m) => !executedMap.has(m.name));\n\n if (pending.length === 0) {\n log('No pending migrations');\n return result;\n }\n\n log(`Found ${pending.length} pending migration(s)`);\n\n // 7. Execute pending migrations ONE AT A TIME\n for (const migration of pending) {\n log(`Executing migration: ${migration.name}`);\n const startTime = Date.now();\n\n try {\n // Parse SQL into statements\n const statements = parseSQLStatements(migration.content);\n\n if (statements.length === 0) {\n log(`Warning: Migration ${migration.name} contains no SQL statements`, 'warn');\n continue;\n }\n\n // Calculate checksum before execution\n const checksum = await calculateChecksum(migration.content);\n\n // Build batch with all statements + tracking record\n const batch: D1PreparedStatement[] = [\n // Execute all statements from the migration\n ...statements.map((sql) => db.prepare(sql)),\n\n // Record execution in tracking table\n db\n .prepare(\n `INSERT INTO _eldrin_migrations\n (filename, checksum, executed_at, execution_time_ms)\n VALUES (?, ?, ?, ?)`\n )\n .bind(migration.name, checksum, Date.now(), Date.now() - startTime),\n ];\n\n // Execute in a single transaction via batch\n await db.batch(batch);\n\n const executionTime = Date.now() - startTime;\n log(`Migration ${migration.name} completed (${executionTime}ms)`);\n\n result.executed++;\n result.migrations.push({\n name: migration.name,\n executionTimeMs: executionTime,\n });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Migration ${migration.name} failed: ${errorMessage}`, 'error');\n\n // Transaction auto-rolls back on error\n // Previous migrations remain intact\n return {\n success: false,\n executed: result.executed,\n migrations: result.migrations,\n error: {\n migration: migration.name,\n message: errorMessage,\n },\n };\n }\n }\n\n log(`Successfully executed ${result.executed} migration(s)`);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Migration system error: ${errorMessage}`, 'error');\n return {\n success: false,\n executed: result.executed,\n migrations: result.migrations,\n error: {\n migration: 'system',\n message: errorMessage,\n },\n };\n }\n}\n\n/**\n * Get migration status (pending and executed migrations)\n *\n * @param db - D1 Database instance\n * @param migrations - Available migration files\n * @returns Status information\n */\nexport async function getMigrationStatus(\n db: D1Database,\n migrations: MigrationFile[]\n): Promise<{\n pending: string[];\n executed: MigrationRecord[];\n orphaned: string[];\n checksumMismatches: string[];\n}> {\n // Ensure table exists\n await db.batch([db.prepare(CREATE_MIGRATIONS_TABLE)]);\n\n // Get executed migrations\n const { results: executed } = await db\n .prepare('SELECT * FROM _eldrin_migrations ORDER BY filename')\n .all<MigrationRecord>();\n\n const executedMap = new Map(executed?.map((e) => [e.filename, e]) ?? []);\n\n // Filter valid migrations\n const validMigrations = migrations.filter((m) => isValidMigrationFilename(m.name));\n\n // Calculate pending\n const pending = validMigrations\n .filter((m) => !executedMap.has(m.name))\n .map((m) => m.name)\n .sort();\n\n // Check for orphaned migrations\n const orphaned: string[] = [];\n for (const [filename] of executedMap) {\n if (!validMigrations.some((m) => m.name === filename)) {\n orphaned.push(filename);\n }\n }\n\n // Check for checksum mismatches\n const checksumMismatches: string[] = [];\n for (const migration of validMigrations) {\n const record = executedMap.get(migration.name);\n if (record) {\n const currentChecksum = await calculateChecksum(migration.content);\n if (currentChecksum !== record.checksum) {\n checksumMismatches.push(migration.name);\n }\n }\n }\n\n return {\n pending,\n executed: executed ?? [],\n orphaned,\n checksumMismatches,\n };\n}\n","/**\n * Migration rollback functionality\n *\n * Rolls back migrations using .rollback.sql files in reverse order\n */\n\nimport type { MigrationFile, MigrationRecord } from '../types';\nimport { parseSQLStatements, isValidRollbackFilename, getRollbackFilename } from './sql-parser';\n\n/**\n * Result of a rollback operation\n */\nexport interface RollbackResult {\n success: boolean;\n rolledBack: string[];\n error?: {\n migration: string;\n message: string;\n };\n}\n\n/**\n * Rollback migrations to a specific target (or just the last one)\n *\n * @param db - D1 Database instance\n * @param options - Rollback options\n * @returns Result of rollback operation\n */\nexport async function rollbackMigrations(\n db: D1Database,\n options: {\n /** Rollback files (.rollback.sql) */\n rollbackFiles: MigrationFile[];\n /** Target migration to rollback TO (exclusive - this migration stays) */\n targetMigration?: string;\n /** Callback for logging */\n onLog?: (message: string, level: 'info' | 'warn' | 'error') => void;\n }\n): Promise<RollbackResult> {\n const { rollbackFiles, targetMigration, onLog = () => {} } = options;\n\n const log = (message: string, level: 'info' | 'warn' | 'error' = 'info') => {\n onLog(message, level);\n };\n\n const result: RollbackResult = {\n success: true,\n rolledBack: [],\n };\n\n try {\n // 1. Get executed migrations in reverse order\n const { results: executed } = await db\n .prepare('SELECT filename FROM _eldrin_migrations ORDER BY filename DESC')\n .all<Pick<MigrationRecord, 'filename'>>();\n\n if (!executed || executed.length === 0) {\n log('No migrations to rollback');\n return result;\n }\n\n // 2. Determine which migrations to rollback\n let toRollback: string[];\n\n if (targetMigration) {\n // Find the target migration\n const targetIndex = executed.findIndex((m) => m.filename === targetMigration);\n if (targetIndex === -1) {\n return {\n success: false,\n rolledBack: [],\n error: {\n migration: targetMigration,\n message: `Target migration not found: ${targetMigration}`,\n },\n };\n }\n // Rollback everything before the target (in the DESC sorted list, that means indices 0 to targetIndex-1)\n toRollback = executed.slice(0, targetIndex).map((m) => m.filename);\n } else {\n // Rollback only the last migration\n toRollback = [executed[0].filename];\n }\n\n if (toRollback.length === 0) {\n log('No migrations to rollback');\n return result;\n }\n\n // 3. Build rollback file map\n const rollbackMap = new Map(\n rollbackFiles.filter((f) => isValidRollbackFilename(f.name)).map((f) => [f.name, f])\n );\n\n // 4. Execute rollbacks in order (they're already in DESC order from query)\n for (const migrationFilename of toRollback) {\n const rollbackFilename = getRollbackFilename(migrationFilename);\n const rollbackFile = rollbackMap.get(rollbackFilename);\n\n if (!rollbackFile) {\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: migrationFilename,\n message: `Rollback file not found: ${rollbackFilename}`,\n },\n };\n }\n\n log(`Rolling back: ${migrationFilename}`);\n\n try {\n const statements = parseSQLStatements(rollbackFile.content);\n\n if (statements.length === 0) {\n log(`Warning: Rollback file ${rollbackFilename} contains no SQL statements`, 'warn');\n }\n\n // Build batch: rollback statements + remove tracking record\n const batch: D1PreparedStatement[] = [\n ...statements.map((sql) => db.prepare(sql)),\n db.prepare('DELETE FROM _eldrin_migrations WHERE filename = ?').bind(migrationFilename),\n ];\n\n await db.batch(batch);\n\n log(`Rolled back: ${migrationFilename}`);\n result.rolledBack.push(migrationFilename);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Rollback failed for ${migrationFilename}: ${errorMessage}`, 'error');\n\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: migrationFilename,\n message: errorMessage,\n },\n };\n }\n }\n\n log(`Successfully rolled back ${result.rolledBack.length} migration(s)`);\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log(`Rollback system error: ${errorMessage}`, 'error');\n\n return {\n success: false,\n rolledBack: result.rolledBack,\n error: {\n migration: 'system',\n message: errorMessage,\n },\n };\n }\n}\n","/**\n * Marketplace utilities for migration packaging\n *\n * Provides tools to generate migration manifests for marketplace distribution.\n * This is used at build time to prepare apps for submission.\n */\n\nimport { readdir, readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { resolve, basename } from 'path';\nimport { calculatePrefixedChecksum } from './checksum';\nimport { isValidMigrationFilename, extractTimestamp } from './sql-parser';\nimport type { MigrationFile } from '../types';\n\n/**\n * Migration entry in the marketplace manifest\n */\nexport interface MigrationManifestEntry {\n /** Migration ID (timestamp) */\n id: string;\n /** Full filename */\n file: string;\n /** SHA-256 checksum with prefix */\n checksum: string;\n}\n\n/**\n * Marketplace migration manifest format\n */\nexport interface MigrationManifest {\n /** Logical database name (used for table prefixing) */\n database: string;\n /** List of migrations in order */\n migrations: MigrationManifestEntry[];\n}\n\n/**\n * Options for generating migration manifest\n */\nexport interface GenerateMigrationManifestOptions {\n /** Directory containing migration SQL files */\n migrationsDir: string;\n /** Logical database name for the app */\n database: string;\n}\n\n/**\n * Result of migration manifest generation\n */\nexport interface GenerateMigrationManifestResult {\n /** The generated manifest */\n manifest: MigrationManifest;\n /** Migration files with content (for copying to output) */\n files: MigrationFile[];\n}\n\n/**\n * Read migration files from a directory\n *\n * @param dir - Directory containing migration files\n * @returns Array of migration files sorted by name\n */\nasync function readMigrationFiles(dir: string): Promise<MigrationFile[]> {\n if (!existsSync(dir)) {\n return [];\n }\n\n const files = await readdir(dir);\n const sqlFiles = files\n .filter((f) => isValidMigrationFilename(f))\n .sort();\n\n const migrations: MigrationFile[] = [];\n\n for (const file of sqlFiles) {\n const content = await readFile(resolve(dir, file), 'utf-8');\n migrations.push({\n name: basename(file),\n content,\n });\n }\n\n return migrations;\n}\n\n/**\n * Generate a marketplace migration manifest from migration files\n *\n * Reads migration files from the specified directory and generates\n * a manifest with checksums suitable for marketplace distribution.\n *\n * @param options - Generation options\n * @returns Manifest and file contents\n *\n * @example\n * ```typescript\n * import { generateMigrationManifest } from '@eldrin-project/eldrin-app-core';\n *\n * const result = await generateMigrationManifest({\n * migrationsDir: './migrations',\n * database: 'invoicing',\n * });\n *\n * // Write manifest to output directory\n * await writeFile(\n * 'dist/migrations/index.json',\n * JSON.stringify(result.manifest, null, 2)\n * );\n *\n * // Copy migration files\n * for (const file of result.files) {\n * await writeFile(`dist/migrations/${file.name}`, file.content);\n * }\n * ```\n */\nexport async function generateMigrationManifest(\n options: GenerateMigrationManifestOptions\n): Promise<GenerateMigrationManifestResult> {\n const { migrationsDir, database } = options;\n\n const files = await readMigrationFiles(migrationsDir);\n\n const migrations: MigrationManifestEntry[] = await Promise.all(\n files.map(async (file) => {\n const timestamp = extractTimestamp(file.name);\n const checksum = await calculatePrefixedChecksum(file.content);\n\n return {\n id: timestamp || file.name.replace('.sql', ''),\n file: file.name,\n checksum,\n };\n })\n );\n\n return {\n manifest: {\n database,\n migrations,\n },\n files,\n };\n}\n\n/**\n * Validate a migration manifest against actual files\n *\n * Useful for CI/CD validation in the marketplace-dist repository.\n *\n * @param manifest - The manifest to validate\n * @param files - The actual migration files\n * @returns Validation result with any errors\n */\nexport async function validateMigrationManifest(\n manifest: MigrationManifest,\n files: MigrationFile[]\n): Promise<{\n valid: boolean;\n errors: string[];\n}> {\n const errors: string[] = [];\n\n // Check all manifest entries have corresponding files\n for (const entry of manifest.migrations) {\n const file = files.find((f) => f.name === entry.file);\n\n if (!file) {\n errors.push(`Missing file: ${entry.file}`);\n continue;\n }\n\n // Verify checksum\n const actualChecksum = await calculatePrefixedChecksum(file.content);\n if (actualChecksum !== entry.checksum) {\n errors.push(\n `Checksum mismatch for ${entry.file}: ` +\n `expected ${entry.checksum}, got ${actualChecksum}`\n );\n }\n\n // Verify ID matches timestamp\n const timestamp = extractTimestamp(file.name);\n if (timestamp !== entry.id) {\n errors.push(\n `ID mismatch for ${entry.file}: ` +\n `expected ${timestamp}, got ${entry.id}`\n );\n }\n }\n\n // Check all files are in manifest\n for (const file of files) {\n if (!manifest.migrations.some((m) => m.file === file.name)) {\n errors.push(`File not in manifest: ${file.name}`);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Eldrin Event Client\n * SDK for app workers to emit and consume events\n */\n\nimport type {\n EldrinEvent,\n EmitOptions,\n EmitResult,\n EventDelivery,\n PollOptions,\n PollResult,\n EventClientConfig,\n SubscriptionInfo,\n RegisteredEventType,\n} from './types';\n\n/**\n * Client for interacting with the Eldrin event bus\n *\n * @example\n * ```typescript\n * const events = new EldrinEventClient({\n * appId: 'invoicing',\n * coreApiUrl: 'https://your-eldrin-core.workers.dev'\n * });\n *\n * // Emit an event\n * await events.emit('invoice.created', { invoiceId: 'inv_123', total: 1500 });\n *\n * // Poll for events\n * const pending = await events.poll();\n * for (const delivery of pending.events) {\n * await processEvent(delivery.event);\n * await events.ack(delivery.id);\n * }\n * ```\n */\nexport class EldrinEventClient {\n private readonly appId: string;\n private readonly coreApiUrl: string;\n\n constructor(config: EventClientConfig) {\n this.appId = config.appId;\n this.coreApiUrl = config.coreApiUrl.replace(/\\/$/, ''); // Remove trailing slash\n }\n\n /**\n * Emit an event to the event bus\n *\n * @param type - Event type (must be declared in app's manifest emits)\n * @param payload - Event payload data\n * @param options - Optional emit configuration\n * @returns Result containing the event ID\n * @throws Error if app is not authorized to emit this event type\n */\n async emit<T>(\n type: string,\n payload: T,\n options: EmitOptions = {}\n ): Promise<EmitResult> {\n const response = await fetch(`${this.coreApiUrl}/api/events/emit`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({\n type,\n payload,\n version: options.version ?? 1,\n idempotencyKey: options.idempotencyKey,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' })) as { error?: string };\n throw new Error(errorData.error || `Failed to emit event: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Poll for pending events\n *\n * @param options - Optional polling configuration\n * @returns List of pending event deliveries\n */\n async poll<T = unknown>(options: PollOptions = {}): Promise<PollResult<T>> {\n const params = new URLSearchParams();\n if (options.limit) params.set('limit', String(options.limit));\n if (options.types?.length) params.set('types', options.types.join(','));\n\n const url = `${this.coreApiUrl}/api/events/poll${params.toString() ? `?${params}` : ''}`;\n const response = await fetch(url, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to poll events: ${response.status}`);\n }\n\n return response.json();\n }\n\n /**\n * Acknowledge successful event processing\n *\n * @param deliveryId - The delivery record ID to acknowledge\n */\n async ack(deliveryId: number): Promise<void> {\n const response = await fetch(`${this.coreApiUrl}/api/events/ack`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({ deliveryId }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to acknowledge event: ${response.status}`);\n }\n }\n\n /**\n * Negative acknowledge - event will be retried later\n *\n * @param deliveryId - The delivery record ID\n * @param error - Optional error message for logging\n */\n async nack(deliveryId: number, error?: string): Promise<void> {\n const response = await fetch(`${this.coreApiUrl}/api/events/nack`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Eldrin-App-Id': this.appId,\n },\n body: JSON.stringify({ deliveryId, error }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to nack event: ${response.status}`);\n }\n }\n\n /**\n * Get all registered event types\n *\n * @returns List of all registered event types across all apps\n */\n async getEventTypes(): Promise<RegisteredEventType[]> {\n const response = await fetch(`${this.coreApiUrl}/api/events/types`, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get event types: ${response.status}`);\n }\n\n const data = await response.json() as { types: RegisteredEventType[] };\n return data.types;\n }\n\n /**\n * Get subscriptions for this app\n *\n * @returns List of active subscriptions\n */\n async getSubscriptions(): Promise<SubscriptionInfo[]> {\n const response = await fetch(`${this.coreApiUrl}/api/events/subscriptions`, {\n headers: {\n 'X-Eldrin-App-Id': this.appId,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get subscriptions: ${response.status}`);\n }\n\n const data = await response.json() as { subscriptions: SubscriptionInfo[] };\n return data.subscriptions;\n }\n}\n\n/**\n * Environment bindings that may include Eldrin Core URL\n */\nexport interface EldrinEnv {\n ELDRIN_CORE_URL?: string;\n [key: string]: unknown;\n}\n\n/**\n * Create an event client for use in app workers\n *\n * @param env - Worker environment bindings (must have optional ELDRIN_CORE_URL)\n * @param appId - The app's identifier\n * @returns Configured event client\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const events = createEventClient(env, 'invoicing');\n * await events.emit('invoice.created', { invoiceId: 'inv_123' });\n * }\n * };\n * ```\n */\nexport function createEventClient(env: EldrinEnv, appId: string): EldrinEventClient {\n const coreApiUrl = (env.ELDRIN_CORE_URL as string | undefined) || 'http://localhost:4000';\n return new EldrinEventClient({ appId, coreApiUrl });\n}\n","/**\n * Auth utilities for Eldrin apps\n *\n * Supports two authentication methods:\n *\n * 1. JWT Token (Authorization header):\n * - Direct API calls with JWT token in Authorization: Bearer <token>\n * - JWT is verified using shared secret (JWT_SECRET env var)\n * - Permissions extracted from JWT payload\n *\n * 2. Proxy Headers (X-Eldrin-User-* headers):\n * - Requests proxied through eldrin-core shell\n * - Shell verifies JWT and injects user context headers\n * - Legacy support for proxied requests\n *\n * JWT takes precedence if Authorization header is present.\n */\n\n/**\n * Auth context extracted from JWT or shell-injected headers\n */\nexport interface AppAuthContext {\n /** User ID */\n userId: string;\n /** User email */\n email: string;\n /** User display name */\n name: string;\n /** Platform roles (admin, editor, viewer) */\n platformRoles: string[];\n /** App-specific permissions (e.g., [\"invoices:read\", \"invoices:write\"]) */\n permissions: string[];\n}\n\n/**\n * JWT payload structure (matches eldrin-core JWT format)\n */\nexport interface JWTPayload {\n /** User ID */\n sub: string;\n /** Email */\n email: string;\n /** First name */\n firstName: string;\n /** Last name */\n lastName: string;\n /** Platform role names */\n platformRoles: string[];\n /** Platform permission names */\n platformPermissions: string[];\n /**\n * App permissions in compact format\n * Key: \"developer_id:app_id\", Value: [\"resource:action\", ...]\n */\n appPermissions: Record<string, string[]>;\n /** Issued at (timestamp) */\n iat: number;\n /** Expiration (timestamp) */\n exp: number;\n}\n\n/**\n * Options for JWT verification\n */\nexport interface JWTVerifyOptions {\n /** JWT secret key (from env.JWT_SECRET) */\n secret: string;\n /** App ID for extracting app-specific permissions */\n appId: string;\n /** Developer ID (optional, uses wildcard matching if not provided) */\n developerId?: string;\n}\n\n/**\n * Header names used by the shell for auth context injection\n */\nexport const AUTH_HEADERS = {\n USER_ID: 'x-eldrin-user-id',\n USER_EMAIL: 'x-eldrin-user-email',\n USER_NAME: 'x-eldrin-user-name',\n USER_ROLES: 'x-eldrin-user-roles',\n USER_PERMISSIONS: 'x-eldrin-user-permissions',\n} as const;\n\n// ============================================================================\n// JWT Verification (Web Crypto API)\n// ============================================================================\n\n/**\n * Base64URL decode (JWT uses URL-safe base64)\n */\nfunction base64UrlDecode(str: string): Uint8Array {\n // Convert base64url to base64\n const base64 = str.replace(/-/g, '+').replace(/_/g, '/');\n // Pad if necessary\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4);\n // Decode\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Verify JWT signature using HMAC-SHA256\n */\nasync function verifyJWTSignature(\n token: string,\n secret: string\n): Promise<{ valid: boolean; payload?: JWTPayload; error?: string }> {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return { valid: false, error: 'Invalid JWT format' };\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n try {\n // Import the secret key\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify']\n );\n\n // Verify the signature\n const signedData = encoder.encode(`${headerB64}.${payloadB64}`);\n const signature = base64UrlDecode(signatureB64);\n\n const isValid = await crypto.subtle.verify(\n 'HMAC',\n key,\n signature.buffer as ArrayBuffer,\n signedData\n );\n\n if (!isValid) {\n return { valid: false, error: 'Invalid signature' };\n }\n\n // Decode payload\n const payloadJson = new TextDecoder().decode(base64UrlDecode(payloadB64));\n const payload = JSON.parse(payloadJson) as JWTPayload;\n\n // Check expiration\n const now = Date.now();\n if (payload.exp && payload.exp < now) {\n return { valid: false, error: 'Token expired' };\n }\n\n return { valid: true, payload };\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : 'JWT verification failed',\n };\n }\n}\n\n/**\n * Extract app-specific permissions from JWT payload\n *\n * Matches permissions using appId, checking both:\n * - Exact match: \"developer_id:app_id\"\n * - Wildcard match: \"*:app_id\" or entries ending with \":app_id\"\n */\nfunction extractAppPermissions(\n payload: JWTPayload,\n appId: string,\n developerId?: string\n): string[] {\n const permissions: string[] = [];\n\n for (const [key, perms] of Object.entries(payload.appPermissions)) {\n // Check if this entry matches the app\n if (developerId) {\n // Exact match with developer ID\n if (key === `${developerId}:${appId}`) {\n permissions.push(...perms);\n }\n } else {\n // Wildcard match - any entry ending with :appId\n if (key.endsWith(`:${appId}`)) {\n permissions.push(...perms);\n }\n }\n }\n\n return permissions;\n}\n\n/**\n * Convert JWT payload to AppAuthContext\n */\nfunction jwtPayloadToAuthContext(\n payload: JWTPayload,\n appId: string,\n developerId?: string\n): AppAuthContext {\n return {\n userId: payload.sub,\n email: payload.email,\n name: `${payload.firstName} ${payload.lastName}`.trim(),\n platformRoles: payload.platformRoles,\n permissions: extractAppPermissions(payload, appId, developerId),\n };\n}\n\n/**\n * Verify JWT token and extract auth context\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const result = await verifyJWT(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (!result.success) {\n * return new Response(JSON.stringify({ error: result.error }), {\n * status: 401,\n * headers: { 'Content-Type': 'application/json' },\n * });\n * }\n *\n * // result.auth contains the AppAuthContext\n * console.log('User:', result.auth.email);\n * }\n * }\n * ```\n */\nexport async function verifyJWT(\n request: Request,\n options: JWTVerifyOptions\n): Promise<{ success: true; auth: AppAuthContext } | { success: false; error: string }> {\n const authHeader = request.headers.get('Authorization');\n\n if (!authHeader) {\n return { success: false, error: 'Missing Authorization header' };\n }\n\n if (!authHeader.startsWith('Bearer ')) {\n return { success: false, error: 'Invalid Authorization header format' };\n }\n\n const token = authHeader.slice(7); // Remove 'Bearer ' prefix\n\n const result = await verifyJWTSignature(token, options.secret);\n\n if (!result.valid || !result.payload) {\n return { success: false, error: result.error || 'JWT verification failed' };\n }\n\n const auth = jwtPayloadToAuthContext(result.payload, options.appId, options.developerId);\n return { success: true, auth };\n}\n\n/**\n * Get auth context from JWT token or fall back to proxy headers\n *\n * This is the recommended way to get auth context as it supports both:\n * - Direct API calls with JWT token\n * - Proxied requests with shell-injected headers\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await getAuthContextFromJWT(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (!auth) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n *\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport async function getAuthContextFromJWT(\n request: Request,\n options: JWTVerifyOptions\n): Promise<AppAuthContext | null> {\n // Try JWT first if Authorization header is present\n const authHeader = request.headers.get('Authorization');\n\n if (authHeader?.startsWith('Bearer ')) {\n const result = await verifyJWT(request, options);\n if (result.success) {\n return result.auth;\n }\n // JWT verification failed - don't fall back to headers\n // (if user sent a token, they expect JWT auth)\n return null;\n }\n\n // Fall back to proxy headers\n return getAuthContext(request);\n}\n\n/**\n * Require JWT authentication - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await requireJWTAuth(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * });\n *\n * if (auth instanceof Response) {\n * return auth; // 401 Unauthorized\n * }\n *\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport async function requireJWTAuth(\n request: Request,\n options: JWTVerifyOptions\n): Promise<AppAuthContext | Response> {\n const auth = await getAuthContextFromJWT(request, options);\n\n if (!auth) {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return auth;\n}\n\n/**\n * Require JWT auth with specific permission - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request, env: Env) {\n * const auth = await requireJWTPermission(request, {\n * secret: env.JWT_SECRET,\n * appId: 'react-todo',\n * }, 'categories', 'create');\n *\n * if (auth instanceof Response) {\n * return auth; // 401 or 403\n * }\n *\n * // User has categories:create permission\n * }\n * }\n * ```\n */\nexport async function requireJWTPermission(\n request: Request,\n options: JWTVerifyOptions,\n resource: string,\n action: string\n): Promise<AppAuthContext | Response> {\n const auth = await requireJWTAuth(request, options);\n\n if (auth instanceof Response) {\n return auth; // 401 Unauthorized\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check specific permission\n if (!hasPermission(auth, resource, action)) {\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permission: ${resource}:${action}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n// ============================================================================\n// Header-based Auth (Legacy/Proxy support)\n// ============================================================================\n\n/**\n * Extract auth context from request headers (proxy mode)\n *\n * Returns null if the user is not authenticated (no user ID header).\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = getAuthContext(request);\n * if (!auth) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport function getAuthContext(request: Request): AppAuthContext | null {\n const userId = request.headers.get(AUTH_HEADERS.USER_ID);\n\n // No user ID means not authenticated\n if (!userId) {\n return null;\n }\n\n const email = request.headers.get(AUTH_HEADERS.USER_EMAIL) || '';\n const name = request.headers.get(AUTH_HEADERS.USER_NAME) || '';\n const rolesHeader = request.headers.get(AUTH_HEADERS.USER_ROLES) || '';\n const permissionsHeader = request.headers.get(AUTH_HEADERS.USER_PERMISSIONS) || '';\n\n return {\n userId,\n email,\n name,\n platformRoles: rolesHeader ? rolesHeader.split(',').map((r) => r.trim()) : [],\n permissions: permissionsHeader ? permissionsHeader.split(',').map((p) => p.trim()) : [],\n };\n}\n\n/**\n * Require authentication - returns auth context or error response\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = requireAuth(request);\n * if (auth instanceof Response) {\n * return auth; // 401 Unauthorized\n * }\n * // auth is AppAuthContext\n * console.log('User:', auth.email);\n * }\n * }\n * ```\n */\nexport function requireAuth(request: Request): AppAuthContext | Response {\n const auth = getAuthContext(request);\n\n if (!auth) {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return auth;\n}\n\n/**\n * Check if auth context has a specific permission\n *\n * Supports wildcard matching:\n * - \"invoices:*\" matches any action on invoices\n * - \"*:*\" matches all permissions\n *\n * @example\n * ```typescript\n * const auth = getAuthContext(request);\n * if (auth && hasPermission(auth, 'invoices', 'write')) {\n * // User can write invoices\n * }\n * ```\n */\nexport function hasPermission(\n auth: AppAuthContext,\n resource: string,\n action: string\n): boolean {\n const required = `${resource}:${action}`;\n\n // Check exact match\n if (auth.permissions.includes(required)) {\n return true;\n }\n\n // Check resource wildcard (e.g., \"invoices:*\")\n if (auth.permissions.includes(`${resource}:*`)) {\n return true;\n }\n\n // Check full wildcard\n if (auth.permissions.includes('*:*')) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Check if auth context has a platform role\n *\n * @example\n * ```typescript\n * const auth = getAuthContext(request);\n * if (auth && hasPlatformRole(auth, 'admin')) {\n * // User is platform admin\n * }\n * ```\n */\nexport function hasPlatformRole(auth: AppAuthContext, role: string): boolean {\n return auth.platformRoles.includes(role);\n}\n\n/**\n * Check if auth context is a platform admin\n *\n * Platform admins have full access to all apps and resources.\n */\nexport function isPlatformAdmin(auth: AppAuthContext): boolean {\n return auth.platformRoles.includes('admin');\n}\n\n/**\n * Require a specific permission - returns auth context or error response\n *\n * Also grants access if user is a platform admin.\n *\n * @example\n * ```typescript\n * export default {\n * async fetch(request: Request) {\n * const auth = requirePermission(request, 'invoices', 'write');\n * if (auth instanceof Response) {\n * return auth; // 401 or 403\n * }\n * // User has invoices:write permission\n * }\n * }\n * ```\n */\nexport function requirePermission(\n request: Request,\n resource: string,\n action: string\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth; // 401 Unauthorized\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check specific permission\n if (!hasPermission(auth, resource, action)) {\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permission: ${resource}:${action}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n/**\n * Require any of the specified permissions - returns auth context or error response\n *\n * @example\n * ```typescript\n * const auth = requireAnyPermission(request, [\n * ['invoices', 'read'],\n * ['invoices', 'write'],\n * ]);\n * ```\n */\nexport function requireAnyPermission(\n request: Request,\n permissions: Array<[resource: string, action: string]>\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth;\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check if user has any of the required permissions\n const hasAny = permissions.some(([resource, action]) =>\n hasPermission(auth, resource, action)\n );\n\n if (!hasAny) {\n const permList = permissions.map(([r, a]) => `${r}:${a}`).join(', ');\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing one of permissions: ${permList}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n\n/**\n * Require all of the specified permissions - returns auth context or error response\n *\n * @example\n * ```typescript\n * const auth = requireAllPermissions(request, [\n * ['invoices', 'read'],\n * ['customers', 'read'],\n * ]);\n * ```\n */\nexport function requireAllPermissions(\n request: Request,\n permissions: Array<[resource: string, action: string]>\n): AppAuthContext | Response {\n const auth = requireAuth(request);\n\n if (auth instanceof Response) {\n return auth;\n }\n\n // Platform admins have all permissions\n if (isPlatformAdmin(auth)) {\n return auth;\n }\n\n // Check if user has all required permissions\n const missing = permissions.filter(\n ([resource, action]) => !hasPermission(auth, resource, action)\n );\n\n if (missing.length > 0) {\n const permList = missing.map(([r, a]) => `${r}:${a}`).join(', ');\n return new Response(\n JSON.stringify({\n error: 'Forbidden',\n message: `Missing permissions: ${permList}`,\n }),\n {\n status: 403,\n headers: { 'Content-Type': 'application/json' },\n }\n );\n }\n\n return auth;\n}\n","/**\n * Route matching utilities for permission middleware\n *\n * Compiles manifest route patterns into efficient regex matchers\n * and provides path matching with parameter extraction.\n */\n\nimport type { ManifestRoute, CompiledRoute } from './types';\n\n/**\n * Compile manifest routes into efficient matchers\n *\n * Converts manifest route patterns like:\n * - \"/todos\" -> exact match\n * - \"/todos/*\" -> matches one segment (e.g., /todos/123)\n * - \"/todos/:id\" -> matches one segment and captures as param\n *\n * @param routes - Route definitions from manifest\n * @param apiPrefix - API path prefix (e.g., \"/api\")\n * @returns Array of compiled routes ready for matching\n */\nexport function compileRoutes(routes: ManifestRoute[], apiPrefix: string): CompiledRoute[] {\n return routes.map((route) => {\n // Normalize methods to uppercase Set\n const methods = new Set(\n Array.isArray(route.method)\n ? route.method.map((m) => m.toUpperCase())\n : [route.method.toUpperCase()]\n );\n\n // Build full path with prefix\n const fullPath = `${apiPrefix}${route.path}`;\n const paramNames: string[] = [];\n\n // Convert path pattern to regex\n let regexPattern = fullPath\n // Escape special regex chars except * and :\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n // Convert :param to named capture group\n .replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, (_, name) => {\n paramNames.push(name);\n return '([^/]+)';\n })\n // Convert * wildcard to match segment (non-capturing)\n .replace(/\\*/g, '[^/]+');\n\n const pattern = new RegExp(`^${regexPattern}$`);\n\n // Parse permission into resource:action\n let permission: { resource: string; action: string } | null = null;\n if (route.permission) {\n const colonIndex = route.permission.indexOf(':');\n if (colonIndex > 0) {\n permission = {\n resource: route.permission.substring(0, colonIndex),\n action: route.permission.substring(colonIndex + 1),\n };\n }\n }\n\n return {\n methods,\n pattern,\n paramNames,\n permission,\n originalPath: route.path,\n };\n });\n}\n\n/**\n * Match a request against compiled routes\n *\n * Iterates through routes in order and returns the first match.\n * Order matters - more specific routes should come before wildcards.\n *\n * @param method - HTTP method (GET, POST, etc.)\n * @param pathname - Request path (e.g., \"/api/todos/123\")\n * @param compiledRoutes - Pre-compiled route patterns\n * @returns Matched route with extracted params, or null if no match\n */\nexport function matchRoute(\n method: string,\n pathname: string,\n compiledRoutes: CompiledRoute[]\n): { route: CompiledRoute; params: Record<string, string> } | null {\n const upperMethod = method.toUpperCase();\n\n for (const route of compiledRoutes) {\n // Check method first (fast path)\n if (!route.methods.has(upperMethod)) continue;\n\n // Check path pattern\n const match = pathname.match(route.pattern);\n if (match) {\n // Extract named params from capture groups\n const params: Record<string, string> = {};\n route.paramNames.forEach((name, index) => {\n params[name] = match[index + 1];\n });\n return { route, params };\n }\n }\n\n return null;\n}\n\n/**\n * Check if path matches a public route pattern\n *\n * Public routes bypass authentication entirely.\n * Supports exact matches and wildcard suffixes.\n *\n * @param pathname - Request path\n * @param publicRoutes - Array of public route patterns\n * @param apiPrefix - API path prefix\n * @returns True if path is public\n */\nexport function isPublicRoute(\n pathname: string,\n publicRoutes: string[],\n apiPrefix: string\n): boolean {\n for (const publicPath of publicRoutes) {\n const fullPath = `${apiPrefix}${publicPath}`;\n\n // Exact match\n if (pathname === fullPath) return true;\n\n // Wildcard match (e.g., \"/public/*\")\n if (publicPath.endsWith('/*')) {\n const prefix = `${apiPrefix}${publicPath.slice(0, -2)}`;\n if (pathname.startsWith(prefix + '/')) return true;\n }\n }\n\n return false;\n}\n","/**\n * Permission Middleware\n *\n * Manifest-driven request middleware that:\n * 1. Loads route permissions from app manifest\n * 2. Intercepts requests before handlers\n * 3. Extracts and verifies JWT tokens\n * 4. Matches requests to defined routes\n * 5. Checks user permissions against requirements\n * 6. Returns auth context to handlers if authorized\n *\n * @example\n * ```typescript\n * import { createPermissionMiddleware } from '@eldrin-project/eldrin-app-core';\n * import manifest from '../public/eldrin-app.manifest.json';\n *\n * const middleware = createPermissionMiddleware<Env>({\n * manifest,\n * getSecret: (env) => env.JWT_SECRET,\n * cors: {\n * allowOrigin: '*',\n * allowMethods: 'GET, POST, PUT, PATCH, DELETE, OPTIONS',\n * allowHeaders: 'Content-Type, Authorization',\n * },\n * });\n *\n * export default {\n * async fetch(request: Request, env: Env): Promise<Response> {\n * const result = await middleware.handle(request, env);\n *\n * if (result.response) {\n * return result.response; // Rejected or CORS preflight\n * }\n *\n * const { auth, url, params } = result;\n * // Authorized - handle the request\n * }\n * }\n * ```\n */\n\nimport {\n verifyJWT,\n hasPermission,\n isPlatformAdmin,\n type AppAuthContext,\n type JWTVerifyOptions,\n} from '../auth';\nimport type {\n MiddlewareConfig,\n MiddlewareResult,\n PermissionMiddleware,\n MiddlewareError,\n CompiledRoute,\n} from './types';\nimport { compileRoutes, matchRoute, isPublicRoute } from './matcher';\n\n/**\n * Create a permission middleware instance\n *\n * The middleware is configured once with the app manifest and secret getter,\n * then used to handle each incoming request.\n *\n * @param config - Middleware configuration\n * @returns Permission middleware instance\n */\nexport function createPermissionMiddleware<TEnv = unknown>(\n config: MiddlewareConfig<TEnv>\n): PermissionMiddleware<TEnv> {\n const apiPrefix = config.apiPrefix ?? '/api';\n const manifest = config.manifest;\n const api = manifest.api;\n\n // Pre-compile routes for efficient matching\n const compiledRoutes: CompiledRoute[] = api?.routes\n ? compileRoutes(api.routes, apiPrefix)\n : [];\n\n const defaultPolicy = api?.defaultPolicy ?? 'deny';\n const publicRoutes = api?.publicRoutes ?? [];\n\n // Empty auth context for public routes\n const emptyAuth: AppAuthContext = {\n userId: '',\n email: '',\n name: '',\n platformRoles: [],\n permissions: [],\n };\n\n function createCorsHeaders(): HeadersInit {\n if (!config.cors) return {};\n return {\n 'Access-Control-Allow-Origin': config.cors.allowOrigin,\n 'Access-Control-Allow-Methods': config.cors.allowMethods,\n 'Access-Control-Allow-Headers': config.cors.allowHeaders,\n };\n }\n\n function withCors(response: Response): Response {\n if (!config.cors) return response;\n\n const newHeaders = new Headers(response.headers);\n Object.entries(createCorsHeaders()).forEach(([key, value]) => {\n newHeaders.set(key, value);\n });\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: newHeaders,\n });\n }\n\n function errorResponse(error: MiddlewareError): Response {\n // Allow custom error handling\n if (config.onError) {\n return withCors(config.onError(error));\n }\n\n // Default error responses\n switch (error.type) {\n case 'unauthorized':\n return withCors(\n Response.json(\n { error: 'Unauthorized', message: error.message },\n { status: 401 }\n )\n );\n case 'forbidden':\n return withCors(\n Response.json(\n {\n error: 'Forbidden',\n message: error.message,\n permission: error.permission,\n },\n { status: 403 }\n )\n );\n case 'route_not_found':\n return withCors(\n Response.json(\n { error: 'Not Found', message: error.message },\n { status: 404 }\n )\n );\n }\n }\n\n async function verifyAndGetAuth(\n request: Request,\n env: TEnv\n ): Promise<AppAuthContext | Response> {\n const jwtOptions: JWTVerifyOptions = {\n secret: config.getSecret(env),\n appId: manifest.id,\n developerId: manifest.developer_id,\n };\n\n const result = await verifyJWT(request, jwtOptions);\n\n if (!result.success) {\n return errorResponse({\n type: 'unauthorized',\n message: result.error,\n });\n }\n\n return result.auth;\n }\n\n return {\n async handle(request: Request, env: TEnv): Promise<MiddlewareResult> {\n const url = new URL(request.url);\n const method = request.method;\n const pathname = url.pathname;\n\n // Check skip routes (e.g., static assets)\n if (config.skipRoutes) {\n for (const skipPattern of config.skipRoutes) {\n if (pathname.startsWith(skipPattern)) {\n return { auth: emptyAuth, url, params: {} };\n }\n }\n }\n\n // Handle CORS preflight\n if (method === 'OPTIONS') {\n return {\n response: new Response(null, {\n status: 204,\n headers: createCorsHeaders(),\n }),\n };\n }\n\n // Only process API routes\n if (!pathname.startsWith(apiPrefix)) {\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Check if it's a public route\n if (isPublicRoute(pathname, publicRoutes, apiPrefix)) {\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Match against compiled routes\n const match = matchRoute(method, pathname, compiledRoutes);\n\n if (!match) {\n // No matching route defined in manifest\n if (defaultPolicy === 'allow') {\n // Allow policy: let unmatched routes through without auth\n return { auth: emptyAuth, url, params: {} };\n }\n\n // Deny policy: require auth for unmatched routes\n const authResult = await verifyAndGetAuth(request, env);\n if (authResult instanceof Response) {\n return { response: authResult };\n }\n return { auth: authResult, url, params: {} };\n }\n\n // Route matched - check if public (permission: null)\n if (match.route.permission === null) {\n return { auth: emptyAuth, url, params: match.params };\n }\n\n // Protected route - verify JWT\n const authResult = await verifyAndGetAuth(request, env);\n if (authResult instanceof Response) {\n return { response: authResult };\n }\n\n const auth = authResult;\n\n // Platform admins bypass permission checks\n if (isPlatformAdmin(auth)) {\n return { auth, url, params: match.params };\n }\n\n // Check specific permission\n const { resource, action } = match.route.permission;\n if (!hasPermission(auth, resource, action)) {\n return {\n response: errorResponse({\n type: 'forbidden',\n message: `Missing permission: ${resource}:${action}`,\n permission: `${resource}:${action}`,\n }),\n };\n }\n\n // Authorized!\n return { auth, url, params: match.params };\n },\n };\n}\n\n// Re-export types for consumers\nexport type {\n ManifestRoute,\n ManifestApi,\n ManifestForMiddleware,\n CorsConfig,\n MiddlewareConfig,\n MiddlewareError,\n MiddlewareErrorType,\n MiddlewareResult,\n MiddlewareResponseResult,\n MiddlewareAuthResult,\n PermissionMiddleware,\n CompiledRoute,\n} from './types';\n\n// Export matcher utilities (useful for testing)\nexport { compileRoutes, matchRoute, isPublicRoute } from './matcher';\n"]}