@eldrin-project/eldrin-app-core 0.0.1

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.
@@ -0,0 +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"],"names":["trimmed","existsSync","readdir","readFile","resolve","basename","createContext","jsx","useContext","createElement"],"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"]}
@@ -0,0 +1,485 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Core types for @eldrin-project/eldrin-app-core
6
+ */
7
+ /**
8
+ * Migration file representation
9
+ */
10
+ interface MigrationFile {
11
+ /** Full filename including timestamp and description (e.g., "20250115120000-create-invoices.sql") */
12
+ name: string;
13
+ /** Raw SQL content of the migration file */
14
+ content: string;
15
+ }
16
+ /**
17
+ * Record of an executed migration stored in _eldrin_migrations table
18
+ */
19
+ interface MigrationRecord {
20
+ id: number;
21
+ filename: string;
22
+ checksum: string;
23
+ executed_at: number;
24
+ execution_time_ms: number | null;
25
+ }
26
+ /**
27
+ * Result of running migrations
28
+ */
29
+ interface MigrationResult {
30
+ /** Whether all migrations succeeded */
31
+ success: boolean;
32
+ /** Number of migrations that were executed */
33
+ executed: number;
34
+ /** Details about executed migrations */
35
+ migrations: Array<{
36
+ name: string;
37
+ executionTimeMs: number;
38
+ }>;
39
+ /** Error if migration failed */
40
+ error?: {
41
+ migration: string;
42
+ message: string;
43
+ sql?: string;
44
+ };
45
+ }
46
+ /**
47
+ * Migration runner options
48
+ */
49
+ interface MigrationOptions {
50
+ /** Directory containing migration files (for CLI/build-time) */
51
+ migrationsDir?: string;
52
+ /** Pre-loaded migration files (for Workers runtime) */
53
+ migrations?: MigrationFile[];
54
+ /** Skip checksum verification (development only) */
55
+ skipChecksumVerification?: boolean;
56
+ /** Callback for logging */
57
+ onLog?: (message: string, level: 'info' | 'warn' | 'error') => void;
58
+ }
59
+ /**
60
+ * App configuration from eldrin-app.manifest.json
61
+ */
62
+ interface AppManifest {
63
+ name: string;
64
+ version: string;
65
+ displayName?: string;
66
+ description?: string;
67
+ permissions?: string[];
68
+ hooks?: Record<string, string>;
69
+ events?: {
70
+ emits?: string[];
71
+ subscribes?: string[];
72
+ };
73
+ }
74
+ /**
75
+ * Options for createApp factory
76
+ */
77
+ interface CreateAppOptions {
78
+ /** Unique app identifier */
79
+ name: string;
80
+ /** Root React component */
81
+ root: React.ComponentType<unknown>;
82
+ /** App manifest (optional, can be loaded from file) */
83
+ manifest?: AppManifest;
84
+ /** Migration files (loaded at build time via Vite plugin) */
85
+ migrations?: MigrationFile[];
86
+ /** Called when migrations complete successfully */
87
+ onMigrationsComplete?: (result: MigrationResult) => void;
88
+ /** Called when migrations fail */
89
+ onMigrationError?: (error: Error) => void;
90
+ }
91
+ /**
92
+ * Database context passed to app components
93
+ */
94
+ interface DatabaseContext {
95
+ /** D1 database instance (null if app has no database) */
96
+ db: D1Database | null;
97
+ /** Whether migrations have completed */
98
+ migrationsComplete: boolean;
99
+ /** Migration result (if migrations were run) */
100
+ migrationResult?: MigrationResult;
101
+ }
102
+ /**
103
+ * Eldrin context provided to apps
104
+ */
105
+ interface EldrinContext {
106
+ /** App ID */
107
+ appId: string;
108
+ /** Database context */
109
+ database: DatabaseContext;
110
+ /** Environment variables */
111
+ env: Record<string, string>;
112
+ }
113
+
114
+ /**
115
+ * App factory for creating Eldrin apps
116
+ *
117
+ * Returns single-spa compatible lifecycle functions with:
118
+ * - Automatic migration execution on bootstrap
119
+ * - Database provider wrapping
120
+ * - Error boundary integration
121
+ */
122
+
123
+ /**
124
+ * Single-spa lifecycle props passed to lifecycle functions
125
+ */
126
+ interface LifecycleProps {
127
+ /** DOM element to mount the app into */
128
+ domElement?: HTMLElement;
129
+ /** App name */
130
+ name?: string;
131
+ /** D1 Database instance (provided by shell) */
132
+ db?: D1Database;
133
+ /** Custom props from shell */
134
+ customProps?: Record<string, unknown>;
135
+ }
136
+ /**
137
+ * Single-spa compatible lifecycle object
138
+ */
139
+ interface AppLifecycle {
140
+ bootstrap: (props: LifecycleProps) => Promise<void>;
141
+ mount: (props: LifecycleProps) => Promise<void>;
142
+ unmount: (props: LifecycleProps) => Promise<void>;
143
+ }
144
+ /**
145
+ * Create an Eldrin app with single-spa compatible lifecycle
146
+ *
147
+ * @param options - App configuration
148
+ * @returns Object with bootstrap, mount, and unmount lifecycle functions
149
+ *
150
+ * @example
151
+ * ```tsx
152
+ * // src/index.tsx
153
+ * import { createApp } from '@eldrin-project/eldrin-app-core';
154
+ * import App from './App';
155
+ *
156
+ * export const { bootstrap, mount, unmount } = createApp({
157
+ * name: 'invoicing',
158
+ * root: App,
159
+ * // Migrations loaded via Vite plugin
160
+ * });
161
+ * ```
162
+ */
163
+ declare function createApp(options: CreateAppOptions): AppLifecycle;
164
+ /**
165
+ * Type helper for migration files loaded via Vite plugin
166
+ *
167
+ * @example
168
+ * ```tsx
169
+ * // With Vite plugin
170
+ * import { createApp, type MigrationFiles } from '@eldrin-project/eldrin-app-core';
171
+ * import migrations from 'virtual:eldrin/migrations';
172
+ *
173
+ * export const { bootstrap, mount, unmount } = createApp({
174
+ * name: 'invoicing',
175
+ * root: App,
176
+ * migrations: migrations as MigrationFiles,
177
+ * });
178
+ * ```
179
+ */
180
+ type MigrationFiles = MigrationFile[];
181
+
182
+ /**
183
+ * Props for DatabaseProvider
184
+ */
185
+ interface DatabaseProviderProps {
186
+ /** D1 database instance (null if app has no database) */
187
+ db: D1Database | null;
188
+ /** Whether migrations have completed */
189
+ migrationsComplete: boolean;
190
+ /** Migration result */
191
+ migrationResult?: MigrationResult;
192
+ /** Child components */
193
+ children: ReactNode;
194
+ }
195
+ /**
196
+ * Provider component for database context
197
+ */
198
+ declare function DatabaseProvider({ db, migrationsComplete, migrationResult, children, }: DatabaseProviderProps): react_jsx_runtime.JSX.Element;
199
+ /**
200
+ * Hook to access the app's D1 database
201
+ *
202
+ * @returns D1Database instance or null if app has no database
203
+ * @throws Error if used outside of DatabaseProvider
204
+ *
205
+ * @example
206
+ * ```tsx
207
+ * function InvoiceList() {
208
+ * const db = useDatabase();
209
+ *
210
+ * if (!db) {
211
+ * return <div>No database configured</div>;
212
+ * }
213
+ *
214
+ * const { results } = await db.prepare(
215
+ * 'SELECT * FROM invoices ORDER BY created_at DESC'
216
+ * ).all();
217
+ *
218
+ * return <div>{results.map(invoice => ...)}</div>;
219
+ * }
220
+ * ```
221
+ */
222
+ declare function useDatabase(): D1Database | null;
223
+ /**
224
+ * Hook to access full database context including migration status
225
+ *
226
+ * @returns DatabaseContext object
227
+ * @throws Error if used outside of DatabaseProvider
228
+ */
229
+ declare function useDatabaseContext(): DatabaseContext;
230
+ /**
231
+ * Hook to check if migrations have completed
232
+ *
233
+ * Useful for showing loading states while migrations run
234
+ *
235
+ * @returns true if migrations are complete
236
+ */
237
+ declare function useMigrationsComplete(): boolean;
238
+
239
+ /**
240
+ * Migration runner for Eldrin apps
241
+ *
242
+ * Executes SQL migrations against a D1 database with:
243
+ * - Automatic tracking table creation
244
+ * - Checksum verification for integrity
245
+ * - Sequential execution (one migration at a time)
246
+ * - Transaction-based execution per migration
247
+ */
248
+
249
+ /**
250
+ * Run pending migrations against the database
251
+ *
252
+ * @param db - D1 Database instance
253
+ * @param options - Migration options
254
+ * @returns Result of migration execution
255
+ */
256
+ declare function runMigrations(db: D1Database, options?: MigrationOptions): Promise<MigrationResult>;
257
+ /**
258
+ * Get migration status (pending and executed migrations)
259
+ *
260
+ * @param db - D1 Database instance
261
+ * @param migrations - Available migration files
262
+ * @returns Status information
263
+ */
264
+ declare function getMigrationStatus(db: D1Database, migrations: MigrationFile[]): Promise<{
265
+ pending: string[];
266
+ executed: MigrationRecord[];
267
+ orphaned: string[];
268
+ checksumMismatches: string[];
269
+ }>;
270
+
271
+ /**
272
+ * Migration rollback functionality
273
+ *
274
+ * Rolls back migrations using .rollback.sql files in reverse order
275
+ */
276
+
277
+ /**
278
+ * Result of a rollback operation
279
+ */
280
+ interface RollbackResult {
281
+ success: boolean;
282
+ rolledBack: string[];
283
+ error?: {
284
+ migration: string;
285
+ message: string;
286
+ };
287
+ }
288
+ /**
289
+ * Rollback migrations to a specific target (or just the last one)
290
+ *
291
+ * @param db - D1 Database instance
292
+ * @param options - Rollback options
293
+ * @returns Result of rollback operation
294
+ */
295
+ declare function rollbackMigrations(db: D1Database, options: {
296
+ /** Rollback files (.rollback.sql) */
297
+ rollbackFiles: MigrationFile[];
298
+ /** Target migration to rollback TO (exclusive - this migration stays) */
299
+ targetMigration?: string;
300
+ /** Callback for logging */
301
+ onLog?: (message: string, level: 'info' | 'warn' | 'error') => void;
302
+ }): Promise<RollbackResult>;
303
+
304
+ /**
305
+ * Checksum utilities for migration integrity verification
306
+ *
307
+ * Uses SHA-256 for content hashing via Web Crypto API
308
+ * (compatible with Cloudflare Workers runtime)
309
+ */
310
+ /** Prefix for SHA-256 checksums in marketplace format */
311
+ declare const CHECKSUM_PREFIX = "sha256:";
312
+ /**
313
+ * Calculate SHA-256 checksum of content
314
+ *
315
+ * @param content - String content to hash
316
+ * @param options - Options for checksum calculation
317
+ * @param options.prefixed - If true, returns "sha256:..." format (default: false for backwards compatibility)
318
+ * @returns Hex-encoded SHA-256 hash, optionally with prefix
319
+ */
320
+ declare function calculateChecksum(content: string, options?: {
321
+ prefixed?: boolean;
322
+ }): Promise<string>;
323
+ /**
324
+ * Calculate SHA-256 checksum with sha256: prefix
325
+ *
326
+ * Convenience function for marketplace format
327
+ *
328
+ * @param content - String content to hash
329
+ * @returns Prefixed checksum (e.g., "sha256:abc123...")
330
+ */
331
+ declare function calculatePrefixedChecksum(content: string): Promise<string>;
332
+ /**
333
+ * Verify that content matches an expected checksum
334
+ *
335
+ * Handles both prefixed ("sha256:...") and unprefixed checksums
336
+ *
337
+ * @param content - Content to verify
338
+ * @param expectedChecksum - Expected SHA-256 hex string (with or without prefix)
339
+ * @returns true if checksums match
340
+ */
341
+ declare function verifyChecksum(content: string, expectedChecksum: string): Promise<boolean>;
342
+
343
+ /**
344
+ * SQL statement parser for migration files
345
+ *
346
+ * Parses SQL content into individual statements for execution via db.batch()
347
+ */
348
+ /**
349
+ * Parse SQL content into individual statements
350
+ *
351
+ * - Removes SQL comments (-- style)
352
+ * - Splits by semicolon
353
+ * - Handles multi-line statements
354
+ * - Preserves string literals containing semicolons
355
+ *
356
+ * @param sql - Raw SQL content
357
+ * @returns Array of individual SQL statements
358
+ */
359
+ declare function parseSQLStatements(sql: string): string[];
360
+ /**
361
+ * Validate that a filename follows the migration naming convention
362
+ *
363
+ * Expected format: TIMESTAMP-description.sql
364
+ * - TIMESTAMP: 14 digits (YYYYMMDDHHmmss)
365
+ * - description: kebab-case
366
+ *
367
+ * @param filename - Filename to validate
368
+ * @returns true if valid, false otherwise
369
+ */
370
+ declare function isValidMigrationFilename(filename: string): boolean;
371
+ /**
372
+ * Validate that a filename follows the rollback naming convention
373
+ *
374
+ * Expected format: TIMESTAMP-description.rollback.sql
375
+ *
376
+ * @param filename - Filename to validate
377
+ * @returns true if valid rollback file, false otherwise
378
+ */
379
+ declare function isValidRollbackFilename(filename: string): boolean;
380
+ /**
381
+ * Extract timestamp from migration filename
382
+ *
383
+ * @param filename - Migration filename
384
+ * @returns Timestamp string or null if invalid
385
+ */
386
+ declare function extractTimestamp(filename: string): string | null;
387
+ /**
388
+ * Get the rollback filename for a migration
389
+ *
390
+ * @param migrationFilename - Migration filename (e.g., "20250115120000-create-table.sql")
391
+ * @returns Rollback filename (e.g., "20250115120000-create-table.rollback.sql")
392
+ */
393
+ declare function getRollbackFilename(migrationFilename: string): string;
394
+
395
+ /**
396
+ * Marketplace utilities for migration packaging
397
+ *
398
+ * Provides tools to generate migration manifests for marketplace distribution.
399
+ * This is used at build time to prepare apps for submission.
400
+ */
401
+
402
+ /**
403
+ * Migration entry in the marketplace manifest
404
+ */
405
+ interface MigrationManifestEntry {
406
+ /** Migration ID (timestamp) */
407
+ id: string;
408
+ /** Full filename */
409
+ file: string;
410
+ /** SHA-256 checksum with prefix */
411
+ checksum: string;
412
+ }
413
+ /**
414
+ * Marketplace migration manifest format
415
+ */
416
+ interface MigrationManifest {
417
+ /** Logical database name (used for table prefixing) */
418
+ database: string;
419
+ /** List of migrations in order */
420
+ migrations: MigrationManifestEntry[];
421
+ }
422
+ /**
423
+ * Options for generating migration manifest
424
+ */
425
+ interface GenerateMigrationManifestOptions {
426
+ /** Directory containing migration SQL files */
427
+ migrationsDir: string;
428
+ /** Logical database name for the app */
429
+ database: string;
430
+ }
431
+ /**
432
+ * Result of migration manifest generation
433
+ */
434
+ interface GenerateMigrationManifestResult {
435
+ /** The generated manifest */
436
+ manifest: MigrationManifest;
437
+ /** Migration files with content (for copying to output) */
438
+ files: MigrationFile[];
439
+ }
440
+ /**
441
+ * Generate a marketplace migration manifest from migration files
442
+ *
443
+ * Reads migration files from the specified directory and generates
444
+ * a manifest with checksums suitable for marketplace distribution.
445
+ *
446
+ * @param options - Generation options
447
+ * @returns Manifest and file contents
448
+ *
449
+ * @example
450
+ * ```typescript
451
+ * import { generateMigrationManifest } from '@eldrin-project/eldrin-app-core';
452
+ *
453
+ * const result = await generateMigrationManifest({
454
+ * migrationsDir: './migrations',
455
+ * database: 'invoicing',
456
+ * });
457
+ *
458
+ * // Write manifest to output directory
459
+ * await writeFile(
460
+ * 'dist/migrations/index.json',
461
+ * JSON.stringify(result.manifest, null, 2)
462
+ * );
463
+ *
464
+ * // Copy migration files
465
+ * for (const file of result.files) {
466
+ * await writeFile(`dist/migrations/${file.name}`, file.content);
467
+ * }
468
+ * ```
469
+ */
470
+ declare function generateMigrationManifest(options: GenerateMigrationManifestOptions): Promise<GenerateMigrationManifestResult>;
471
+ /**
472
+ * Validate a migration manifest against actual files
473
+ *
474
+ * Useful for CI/CD validation in the marketplace-dist repository.
475
+ *
476
+ * @param manifest - The manifest to validate
477
+ * @param files - The actual migration files
478
+ * @returns Validation result with any errors
479
+ */
480
+ declare function validateMigrationManifest(manifest: MigrationManifest, files: MigrationFile[]): Promise<{
481
+ valid: boolean;
482
+ errors: string[];
483
+ }>;
484
+
485
+ export { type AppLifecycle, type AppManifest, CHECKSUM_PREFIX, type CreateAppOptions, type DatabaseContext, DatabaseProvider, type DatabaseProviderProps, type EldrinContext, type GenerateMigrationManifestOptions, type GenerateMigrationManifestResult, type LifecycleProps, type MigrationFile, type MigrationFiles, type MigrationManifest, type MigrationManifestEntry, type MigrationOptions, type MigrationRecord, type MigrationResult, type RollbackResult, calculateChecksum, calculatePrefixedChecksum, createApp, extractTimestamp, generateMigrationManifest, getMigrationStatus, getRollbackFilename, isValidMigrationFilename, isValidRollbackFilename, parseSQLStatements, rollbackMigrations, runMigrations, useDatabase, useDatabaseContext, useMigrationsComplete, validateMigrationManifest, verifyChecksum };