Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements

- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
This commit is contained in:
defiQUG
2025-12-12 18:01:35 -08:00
parent e01131efaf
commit 9daf1fd378
968 changed files with 160890 additions and 1092 deletions

163
api/src/db/migrate.ts Normal file
View File

@@ -0,0 +1,163 @@
import 'dotenv/config'
import { Pool } from 'pg'
import { readdir } from 'fs/promises'
import { join, dirname } from 'path'
import { fileURLToPath } from 'url'
import { getDb } from './index.js'
import { logger } from '../lib/logger.js'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
export interface Migration {
up: (db: Pool) => Promise<void>
down: (db: Pool) => Promise<void>
}
const MIGRATIONS_TABLE = 'schema_migrations'
async function ensureMigrationsTable(db: Pool): Promise<void> {
await db.query(`
CREATE TABLE IF NOT EXISTS ${MIGRATIONS_TABLE} (
version VARCHAR(255) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`)
}
async function getExecutedMigrations(db: Pool): Promise<string[]> {
await ensureMigrationsTable(db)
const result = await db.query(`SELECT version FROM ${MIGRATIONS_TABLE} ORDER BY version`)
return result.rows.map((row) => row.version)
}
async function recordMigration(db: Pool, version: string, name: string): Promise<void> {
await db.query(
`INSERT INTO ${MIGRATIONS_TABLE} (version, name) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING`,
[version, name]
)
}
async function removeMigration(db: Pool, version: string): Promise<void> {
await db.query(`DELETE FROM ${MIGRATIONS_TABLE} WHERE version = $1`, [version])
}
async function loadMigration(version: string): Promise<Migration> {
const migrationPath = join(__dirname, 'migrations', `${version}.ts`)
try {
const migration = await import(migrationPath)
return {
up: migration.up,
down: migration.down,
}
} catch (error) {
throw new Error(`Failed to load migration ${version}: ${error}`)
}
}
async function getAllMigrations(): Promise<string[]> {
const migrationsDir = join(__dirname, 'migrations')
const files = await readdir(migrationsDir)
return files
.filter((file) => file.endsWith('.ts') && file !== 'index.ts')
.map((file) => file.replace('.ts', ''))
.sort()
}
async function migrateUp(db: Pool): Promise<void> {
await ensureMigrationsTable(db)
const executed = await getExecutedMigrations(db)
const allMigrations = await getAllMigrations()
const pending = allMigrations.filter((m) => !executed.includes(m))
logger.info(`Found ${pending.length} pending migrations`)
for (const version of pending) {
logger.info(`Running migration ${version}...`)
const migration = await loadMigration(version)
await migration.up(db)
const name = version.replace(/^\d+_/, '').replace(/_/g, ' ')
await recordMigration(db, version, name)
logger.info(`✓ Migration ${version} completed`)
}
if (pending.length === 0) {
logger.info('No pending migrations')
}
}
async function migrateDown(db: Pool, targetVersion?: string): Promise<void> {
await ensureMigrationsTable(db)
const executed = await getExecutedMigrations(db)
if (executed.length === 0) {
logger.info('No migrations to roll back')
return
}
const toRollback = targetVersion
? executed.slice(executed.indexOf(targetVersion) + 1).reverse()
: [executed[executed.length - 1]]
for (const version of toRollback) {
logger.info(`Rolling back migration ${version}...`)
const migration = await loadMigration(version)
await migration.down(db)
await removeMigration(db, version)
logger.info(`✓ Migration ${version} rolled back`)
}
}
async function showStatus(db: Pool): Promise<void> {
await ensureMigrationsTable(db)
const executed = await getExecutedMigrations(db)
const allMigrations = await getAllMigrations()
logger.info('\nMigration Status:')
logger.info('================\n')
for (const migration of allMigrations) {
const status = executed.includes(migration) ? '✓' : '✗'
const name = migration.replace(/^\d+_/, '').replace(/_/g, ' ')
logger.info(`${status} ${migration} - ${name}`)
}
logger.info(`\nTotal: ${executed.length}/${allMigrations.length} executed\n`)
}
async function main(): Promise<void> {
const command = process.argv[2]
const db = getDb()
try {
switch (command) {
case 'up':
await migrateUp(db)
break
case 'down':
const targetVersion = process.argv[3]
await migrateDown(db, targetVersion)
break
case 'status':
await showStatus(db)
break
default:
logger.info('Usage: npm run db:migrate [up|down|status]')
logger.info(' up - Run all pending migrations')
logger.info(' down - Roll back the last migration')
logger.info(' status - Show migration status')
process.exit(1)
}
} catch (error) {
logger.error('Migration error', { error })
process.exit(1)
} finally {
await db.end()
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
main()
}