@famgia/omnify-gui 1.0.30 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Omnify GUI</title>
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-PVj19yVg.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/vendor-react-GrtO722N.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-antd-BBx18Sww.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/vendor-i18n-fCMqBMNi.js">
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/index.ts","../../src/server/app.ts","../../src/server/api/schemas.ts","../../src/server/services/schemaService.ts","../../src/server/api/validate.ts","../../src/server/services/validationService.ts","../../src/server/api/preview.ts","../../src/server/services/previewService.ts","../../src/server/api/config.ts","../../src/shared/constants.ts","../../src/server/api/versions.ts","../../src/server/services/versionService.ts","../../src/server/api/plugins.ts","../../src/server/ws/handler.ts","../../src/server/watcher/fileWatcher.ts"],"sourcesContent":["/**\n * @famgia/omnify-gui - Server Entry Point\n *\n * Starts the local development server for Omnify GUI.\n */\n\nimport { createServer } from 'http';\nimport { join, resolve } from 'path';\nimport { existsSync, unlinkSync } from 'fs';\nimport open from 'open';\nimport { loadConfig } from '@famgia/omnify-cli';\nimport { createApp } from './app.js';\nimport { createWsHandler } from './ws/handler.js';\nimport { createFileWatcher } from './watcher/fileWatcher.js';\nimport { DEFAULT_PORT, DEFAULT_HOST } from '../shared/constants.js';\n\n// fileURLToPath and dirname imported for potential future use with static files\n// Currently not needed as Vite handles static serving\n\n// Restart marker file path\nconst RESTART_MARKER = join(process.cwd(), '.omnify-restart');\n\nasync function main(): Promise<void> {\n const port = Number(process.env.PORT) || DEFAULT_PORT;\n const host = process.env.HOST ?? DEFAULT_HOST;\n const cwd = process.cwd();\n\n // Check if this is a restart (marker file exists)\n const isRestart = existsSync(RESTART_MARKER);\n console.log(` Restart marker: ${RESTART_MARKER}, exists: ${isRestart}`);\n if (isRestart) {\n console.log(' Detected restart - will not open browser');\n try {\n unlinkSync(RESTART_MARKER);\n } catch {\n // Ignore\n }\n }\n\n // Resolve schemas directory and custom types from omnify config\n let schemasDir: string;\n let customTypes: string[] = [];\n\n if (process.env.SCHEMAS_DIR) {\n schemasDir = process.env.SCHEMAS_DIR;\n } else {\n try {\n const { config } = await loadConfig(cwd);\n schemasDir = resolve(cwd, config.schemasDir);\n // Extract custom type names from plugins\n customTypes = (config.plugins ?? [])\n .flatMap((p) => p.types ?? [])\n .filter((t) => t && typeof t === 'object' && 'name' in t)\n .map((t) => t.name);\n } catch (error) {\n // Fall back to default if no config file found\n console.error(' Failed to load config:', error instanceof Error ? error.message : error);\n schemasDir = join(cwd, 'schemas');\n }\n }\n\n console.log('Starting Omnify GUI...');\n console.log(` Schemas directory: ${schemasDir}`);\n\n // Create Express app\n const app = createApp({ schemasDir, cwd, customTypes });\n\n // Create HTTP server\n const server = createServer(app);\n\n // Create WebSocket handler\n const wsHandler = createWsHandler(server);\n\n // Create file watcher\n const watcher = createFileWatcher(schemasDir, wsHandler);\n\n // Start server\n server.listen(port, host, () => {\n const url = `http://${host}:${port}`;\n console.log(` GUI running at: ${url}`);\n console.log(' Press Ctrl+C to stop\\n');\n\n // Auto-open browser in development (skip if restarting)\n if (process.env.NODE_ENV !== 'production' && !isRestart) {\n open(url).catch(() => {\n // Ignore errors if browser fails to open\n });\n }\n });\n\n // Graceful shutdown\n const shutdown = (): void => {\n console.log('\\nShutting down...');\n watcher.close();\n wsHandler.close();\n server.close(() => {\n console.log('Server closed');\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nmain().catch((error: unknown) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n});\n","/**\n * Express application configuration\n */\n\nimport express, { type Express, type Request, type Response, type NextFunction } from 'express';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { schemasRouter } from './api/schemas.js';\nimport { validateRouter } from './api/validate.js';\nimport { previewRouter } from './api/preview.js';\nimport { configRouter } from './api/config.js';\nimport { versionsRouter } from './api/versions.js';\nimport { pluginsRouter } from './api/plugins.js';\nimport { initVersionStore } from './services/versionService.js';\nimport type { ApiResponse } from '../shared/types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface AppConfig {\n schemasDir: string;\n cwd: string;\n customTypes?: string[];\n}\n\nexport function createApp(config: AppConfig): Express {\n const app = express();\n\n // Store config in app locals for access in routes\n app.locals.config = config;\n\n // Initialize version store with project root and schemas directory\n initVersionStore(config.cwd, config.schemasDir);\n\n // Middleware\n app.use(express.json());\n\n // API routes\n app.use('/api/schemas', schemasRouter);\n app.use('/api/validate', validateRouter);\n app.use('/api/preview', previewRouter);\n app.use('/api/config', configRouter);\n app.use('/api/versions', versionsRouter);\n app.use('/api/plugins', pluginsRouter);\n\n // Serve static files (client build)\n const clientDist = join(__dirname, '../client');\n app.use(express.static(clientDist));\n\n // SPA fallback - serve index.html for all non-API routes\n app.get('*', (_req: Request, res: Response) => {\n res.sendFile(join(clientDist, 'index.html'));\n });\n\n // Error handler\n app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {\n console.error('Server error:', err);\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: err.message,\n },\n };\n res.status(500).json(response);\n });\n\n return app;\n}\n","/**\n * Schema CRUD API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { schemaService } from '../services/schemaService.js';\nimport type { ApiResponse, GuiSchema } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const schemasRouter: IRouter = Router();\n\n// GET /api/schemas - List all schemas\nschemasRouter.get('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const schemas = await schemaService.loadAll(config.schemasDir);\n const response: ApiResponse<Record<string, GuiSchema>> = {\n success: true,\n data: schemas,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'LOAD_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// GET /api/schemas/:name - Get single schema\nschemasRouter.get('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const schema = await schemaService.load(config.schemasDir, name!);\n\n if (!schema) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'NOT_FOUND',\n message: `Schema \"${name}\" not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: schema,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'LOAD_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/schemas - Create new schema\nschemasRouter.post('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const schema = req.body as GuiSchema;\n\n if (!schema.name) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VALIDATION_ERROR',\n message: 'Schema name is required',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const saved = await schemaService.save(config.schemasDir, schema);\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: saved,\n };\n res.status(201).json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'SAVE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// PUT /api/schemas/:name - Update schema\nschemasRouter.put('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const schema = req.body as GuiSchema;\n\n // Ensure name matches\n schema.name = name!;\n\n const saved = await schemaService.save(config.schemasDir, schema);\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: saved,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'SAVE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// DELETE /api/schemas/:name - Delete schema\nschemasRouter.delete('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n\n await schemaService.delete(config.schemasDir, name!);\n const response: ApiResponse = {\n success: true,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DELETE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Schema CRUD service using omnify-core\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport { writeFile, unlink } from 'fs/promises';\nimport { join } from 'path';\nimport { stringify } from 'yaml';\nimport type { GuiSchema, GuiEnumValue, GuiIndexDefinition } from '../../shared/types.js';\n\n/**\n * Convert indexes from various formats to GuiIndexDefinition[]\n * Indexes can be:\n * - string: \"column_name\" -> { columns: [\"column_name\"] }\n * - string[]: [\"col1\", \"col2\"] -> { columns: [\"col1\", \"col2\"] }\n * - object: { columns: [...], unique: true } -> as-is\n */\nfunction normalizeIndexes(indexes: unknown): GuiIndexDefinition[] | undefined {\n if (!indexes || !Array.isArray(indexes)) return undefined;\n\n return indexes.map((idx) => {\n // Already an object with columns property\n if (typeof idx === 'object' && idx !== null && 'columns' in idx) {\n return idx as GuiIndexDefinition;\n }\n // Array of column names (composite index)\n if (Array.isArray(idx)) {\n return { columns: idx.map(String) };\n }\n // Single column name as string\n return { columns: [String(idx)] };\n });\n}\n\n/**\n * Convert enum values from various formats to GuiEnumValue[]\n */\nfunction normalizeEnumValues(values: unknown): GuiEnumValue[] | undefined {\n if (!values || !Array.isArray(values)) return undefined;\n\n return values.map((v) => {\n // Already an object with value property\n if (typeof v === 'object' && v !== null && 'value' in v) {\n const obj = v as Record<string, unknown>;\n return {\n value: String(obj.value),\n label: obj.label ? String(obj.label) : undefined,\n extra: obj.extra as GuiEnumValue['extra'],\n };\n }\n // Simple string value\n return { value: String(v) };\n });\n}\n\nclass SchemaService {\n private cache: Map<string, Record<string, GuiSchema>> = new Map();\n\n async loadAll(schemasDir: string): Promise<Record<string, GuiSchema>> {\n try {\n const schemas = await loadSchemas(schemasDir);\n const guiSchemas: Record<string, GuiSchema> = {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n // Normalize options with indexes\n const normalizedOptions = schema.options ? {\n ...schema.options,\n indexes: normalizeIndexes(schema.options.indexes),\n } : undefined;\n\n guiSchemas[name] = {\n name: schema.name,\n kind: schema.kind ?? 'object',\n displayName: resolveLocalizedString(schema.displayName),\n filePath: schema.filePath,\n relativePath: schema.relativePath,\n properties: schema.properties as GuiSchema['properties'],\n options: normalizedOptions as GuiSchema['options'],\n values: normalizeEnumValues(schema.values),\n isDirty: false,\n validationErrors: [],\n };\n }\n\n this.cache.set(schemasDir, guiSchemas);\n return guiSchemas;\n } catch (error) {\n // Return empty if no schemas found\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw error;\n }\n }\n\n async load(schemasDir: string, name: string): Promise<GuiSchema | null> {\n const schemas = await this.loadAll(schemasDir);\n return schemas[name] ?? null;\n }\n\n async save(schemasDir: string, schema: GuiSchema): Promise<GuiSchema> {\n // Extract fields that shouldn't be saved to YAML\n const {\n isDirty: _isDirty,\n validationErrors: _validationErrors,\n filePath,\n relativePath,\n name, // Derived from filename, don't save\n kind, // Only save if enum (object is default)\n ...yamlData\n } = schema;\n\n // Build YAML data - only include kind for enums\n const dataToSave = kind === 'enum'\n ? { kind, ...yamlData }\n : yamlData;\n\n // Use existing path if available (update), otherwise create at root (new)\n let targetPath: string;\n let targetRelativePath: string;\n\n if (filePath && relativePath) {\n // Updating existing schema - keep original location\n targetPath = filePath;\n targetRelativePath = relativePath;\n } else {\n // New schema - create at root of schemasDir\n const fileName = `${name}.yaml`;\n targetPath = join(schemasDir, fileName);\n targetRelativePath = fileName;\n }\n\n // Convert to YAML\n const yamlContent = stringify(dataToSave, {\n lineWidth: 120,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n });\n\n await writeFile(targetPath, yamlContent, 'utf-8');\n\n // Return updated schema with file path\n return {\n ...schema,\n filePath: targetPath,\n relativePath: targetRelativePath,\n isDirty: false,\n validationErrors: [],\n };\n }\n\n async delete(schemasDir: string, name: string): Promise<void> {\n // Find the schema to get its actual file path\n const schemas = await this.loadAll(schemasDir);\n const schema = schemas[name];\n\n if (!schema?.filePath) {\n throw new Error(`Schema \"${name}\" not found`);\n }\n\n await unlink(schema.filePath);\n\n // Clear cache\n this.cache.delete(schemasDir);\n }\n\n clearCache(schemasDir?: string): void {\n if (schemasDir) {\n this.cache.delete(schemasDir);\n } else {\n this.cache.clear();\n }\n }\n}\n\nexport const schemaService = new SchemaService();\n","/**\n * Schema validation API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { validationService } from '../services/validationService.js';\nimport type { ApiResponse, GuiSchema, ValidationError } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const validateRouter: IRouter = Router();\n\ninterface ValidateRequest {\n schema?: GuiSchema;\n schemas?: Record<string, GuiSchema>;\n}\n\ninterface ValidateResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n// POST /api/validate - Validate schema(s)\nvalidateRouter.post('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const body = req.body as ValidateRequest;\n\n let result: ValidateResult;\n\n if (body.schema) {\n // Validate single schema\n result = await validationService.validateSchema(body.schema, config.schemasDir);\n } else if (body.schemas) {\n // Validate all schemas\n result = await validationService.validateAll(body.schemas);\n } else {\n // Load and validate all from disk\n result = await validationService.validateFromDisk(config.schemasDir);\n }\n\n const response: ApiResponse<ValidateResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VALIDATION_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Schema validation service using omnify-core\n */\n\nimport { loadSchemas, validateSchemas, OmnifyError } from '@famgia/omnify-core';\nimport type { LoadedSchema, SchemaCollection, SchemaOptions } from '@famgia/omnify-types';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport type { GuiSchema, ValidationError } from '../../shared/types.js';\n\ninterface ValidateResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Convert GuiSchema to LoadedSchema format\n * Handles exactOptionalPropertyTypes by only setting defined properties\n */\nfunction toLoadedSchema(schema: GuiSchema): LoadedSchema {\n // Start with required fields only\n const result = {\n name: schema.name,\n kind: schema.kind,\n filePath: schema.filePath,\n relativePath: schema.relativePath ?? schema.name + '.yaml',\n } as LoadedSchema;\n\n // Only add optional fields if they're defined\n if (schema.displayName !== undefined) {\n (result as { displayName: string }).displayName = schema.displayName;\n }\n if (schema.properties !== undefined) {\n (result as { properties: LoadedSchema['properties'] }).properties = schema.properties as LoadedSchema['properties'];\n }\n if (schema.options !== undefined) {\n (result as { options: SchemaOptions }).options = schema.options as SchemaOptions;\n }\n if (schema.values !== undefined) {\n // Convert GuiEnumValue[] to readonly string[] for validation\n (result as { values: readonly string[] }).values = schema.values.map((v) => v.value);\n }\n\n return result;\n}\n\nclass ValidationService {\n async validateSchema(schema: GuiSchema, schemasDir: string): Promise<ValidateResult> {\n try {\n // Load all schemas to validate references\n const allSchemas = await loadSchemas(schemasDir);\n\n // Convert GuiSchema to LoadedSchema format\n const loadedSchema = toLoadedSchema(schema);\n\n // Create mutable copy and add the schema\n const schemasToValidate: Record<string, LoadedSchema> = { ...allSchemas };\n schemasToValidate[schema.name] = loadedSchema;\n\n // Validate all schemas together\n const result = validateSchemas(schemasToValidate);\n\n // Filter errors for this schema from schema results\n const schemaResult = result.schemas.find((s) => s.schemaName === schema.name);\n const schemaErrors: ValidationError[] = [];\n\n if (schemaResult) {\n for (const e of schemaResult.errors) {\n schemaErrors.push({\n path: this.getErrorPath(e, schema.name),\n message: e.message,\n severity: 'error' as const,\n });\n }\n }\n\n return {\n valid: schemaErrors.length === 0,\n errors: schemaErrors,\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: schema.name,\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n async validateAll(schemas: Record<string, GuiSchema>): Promise<ValidateResult> {\n try {\n // Convert GuiSchemas to LoadedSchemas\n const loadedSchemas: SchemaCollection = {};\n for (const [name, schema] of Object.entries(schemas)) {\n (loadedSchemas as Record<string, LoadedSchema>)[name] = toLoadedSchema(schema);\n }\n\n const result = validateSchemas(loadedSchemas);\n\n const errors: ValidationError[] = [];\n for (const schemaResult of result.schemas) {\n for (const e of schemaResult.errors) {\n errors.push({\n path: this.getErrorPath(e, schemaResult.schemaName),\n message: e.message,\n severity: 'error' as const,\n });\n }\n }\n\n return {\n valid: result.valid,\n errors,\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n async validateFromDisk(schemasDir: string): Promise<ValidateResult> {\n try {\n const schemas = await loadSchemas(schemasDir);\n\n // Convert to GuiSchemas\n const guiSchemas: Record<string, GuiSchema> = {};\n for (const [name, schema] of Object.entries(schemas)) {\n guiSchemas[name] = {\n name: schema.name,\n kind: schema.kind ?? 'object',\n displayName: resolveLocalizedString(schema.displayName),\n filePath: schema.filePath,\n relativePath: schema.relativePath,\n properties: schema.properties as GuiSchema['properties'],\n options: schema.options as GuiSchema['options'],\n // Convert readonly string[] to GuiEnumValue[]\n values: schema.values?.map((v) => ({ value: v })),\n };\n }\n\n return this.validateAll(guiSchemas);\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n private getErrorPath(error: OmnifyError, schemaName: string): string {\n // Try to extract property name from the error message or details\n const details = error.details;\n if (details && 'propertyName' in details && details.propertyName) {\n return `${schemaName}.${String(details.propertyName)}`;\n }\n return schemaName;\n }\n}\n\nexport const validationService = new ValidationService();\n","/**\n * Code preview API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { previewService } from '../services/previewService.js';\nimport type { ApiResponse, PreviewResult, PreviewType } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const previewRouter: IRouter = Router();\n\n// GET /api/preview/:type - Get code preview for all schemas\npreviewRouter.get('/:type', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { type } = req.params;\n\n if (!['laravel', 'typescript', 'sql'].includes(type!)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_TYPE',\n message: `Invalid preview type: ${type}. Valid types: laravel, typescript, sql`,\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const previews = await previewService.generateAll(config.schemasDir, type as PreviewType);\n const response: ApiResponse<PreviewResult[]> = {\n success: true,\n data: previews,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PREVIEW_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// GET /api/preview/:type/:name - Get code preview for single schema\npreviewRouter.get('/:type/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { type, name } = req.params;\n\n if (!['laravel', 'typescript', 'sql'].includes(type!)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_TYPE',\n message: `Invalid preview type: ${type}. Valid types: laravel, typescript, sql`,\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const preview = await previewService.generateForSchema(\n config.schemasDir,\n name!,\n type as PreviewType\n );\n\n if (!preview) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'NOT_FOUND',\n message: `Schema \"${name}\" not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<PreviewResult> = {\n success: true,\n data: preview,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PREVIEW_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Code preview generation service\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { generateMigrations as generateLaravelMigrations } from '@famgia/omnify-laravel';\nimport { generateMigrations as generateSqlMigrations } from '@famgia/omnify-sql';\nimport type { PreviewResult, PreviewType } from '../../shared/types.js';\n\ninterface EnumSchema {\n kind: 'enum';\n values?: readonly string[];\n}\n\ninterface ObjectSchema {\n kind: 'object';\n properties?: Record<string, { type: string; nullable?: boolean }>;\n}\n\nclass PreviewService {\n async generateAll(schemasDir: string, type: PreviewType): Promise<PreviewResult[]> {\n const schemas = await loadSchemas(schemasDir);\n const previews: PreviewResult[] = [];\n\n switch (type) {\n case 'laravel': {\n const migrations = await generateLaravelMigrations(schemas);\n for (const migration of migrations) {\n previews.push({\n type: 'laravel',\n content: migration.content,\n fileName: migration.fileName,\n });\n }\n break;\n }\n\n case 'sql': {\n const migrations = generateSqlMigrations(schemas, { dialect: 'mysql' });\n for (const migration of migrations) {\n previews.push({\n type: 'sql',\n content: migration.content,\n fileName: migration.fileName,\n });\n }\n break;\n }\n\n case 'typescript': {\n // Generate TypeScript interfaces from schemas\n for (const [name, schema] of Object.entries(schemas)) {\n if (schema.kind === 'enum') {\n previews.push({\n type: 'typescript',\n content: this.generateEnumType(name, schema as EnumSchema),\n fileName: `${name}.ts`,\n });\n } else {\n previews.push({\n type: 'typescript',\n content: this.generateInterfaceType(name, schema as ObjectSchema),\n fileName: `${name}.ts`,\n });\n }\n }\n break;\n }\n }\n\n return previews;\n }\n\n async generateForSchema(\n schemasDir: string,\n schemaName: string,\n type: PreviewType\n ): Promise<PreviewResult | null> {\n const schemas = await loadSchemas(schemasDir);\n const schema = schemas[schemaName];\n\n if (!schema) {\n return null;\n }\n\n switch (type) {\n case 'laravel': {\n const migrations = await generateLaravelMigrations({ [schemaName]: schema });\n const migration = migrations[0];\n return migration\n ? {\n type: 'laravel',\n content: migration.content,\n fileName: migration.fileName,\n }\n : null;\n }\n\n case 'sql': {\n const migrations = generateSqlMigrations({ [schemaName]: schema }, { dialect: 'mysql' });\n const migration = migrations[0];\n return migration\n ? {\n type: 'sql',\n content: migration.content,\n fileName: migration.fileName,\n }\n : null;\n }\n\n case 'typescript': {\n if (schema.kind === 'enum') {\n return {\n type: 'typescript',\n content: this.generateEnumType(schemaName, schema as EnumSchema),\n fileName: `${schemaName}.ts`,\n };\n }\n return {\n type: 'typescript',\n content: this.generateInterfaceType(schemaName, schema as ObjectSchema),\n fileName: `${schemaName}.ts`,\n };\n }\n }\n }\n\n private generateEnumType(name: string, schema: EnumSchema): string {\n const values = schema.values ?? [];\n return `export type ${name} = ${values.map((v) => `'${v}'`).join(' | ') || 'never'};\\n`;\n }\n\n private generateInterfaceType(name: string, schema: ObjectSchema): string {\n const lines: string[] = [`export interface ${name} {`];\n\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n const tsType = this.mapToTsType(prop.type);\n const optional = prop.nullable ? '?' : '';\n lines.push(` ${propName}${optional}: ${tsType};`);\n }\n }\n\n lines.push('}');\n return lines.join('\\n') + '\\n';\n }\n\n private mapToTsType(omnifyType: string): string {\n const typeMap: Record<string, string> = {\n String: 'string',\n Int: 'number',\n BigInt: 'number',\n Float: 'number',\n Decimal: 'number',\n Boolean: 'boolean',\n Text: 'string',\n LongText: 'string',\n Date: 'string',\n Time: 'string',\n Timestamp: 'string',\n Json: 'Record<string, unknown>',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'string[]',\n Point: '{ lat: number; lng: number }',\n Coordinates: '{ latitude: number; longitude: number }',\n };\n\n return typeMap[omnifyType] ?? 'unknown';\n }\n}\n\nexport const previewService = new PreviewService();\n","/**\n * Config API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport type { ApiResponse, GuiConfig } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\nimport { DEFAULT_PORT, DEFAULT_HOST } from '../../shared/constants.js';\n\nexport const configRouter: IRouter = Router();\n\n// GET /api/config - Get current configuration\nconfigRouter.get('/', (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n\n const config: GuiConfig = {\n schemasDir: appConfig.schemasDir,\n port: Number(process.env.PORT) || DEFAULT_PORT,\n host: process.env.HOST ?? DEFAULT_HOST,\n customTypes: appConfig.customTypes ?? [],\n plugins: [], // Plugins are fetched via /api/plugins\n };\n\n const response: ApiResponse<GuiConfig> = {\n success: true,\n data: config,\n };\n res.json(response);\n});\n","/**\n * Shared constants for @famgia/omnify-gui\n */\n\nexport const DEFAULT_PORT = 3456;\nexport const DEFAULT_HOST = 'localhost';\n\nexport const API_ROUTES = {\n SCHEMAS: '/api/schemas',\n SCHEMA: '/api/schemas/:name',\n VALIDATE: '/api/validate',\n PREVIEW: '/api/preview/:type',\n CONFIG: '/api/config',\n} as const;\n\nexport const WS_EVENTS = {\n // Server → Client\n SCHEMA_CHANGED: 'schema:changed',\n SCHEMA_VALIDATED: 'schema:validated',\n SCHEMAS_RELOADED: 'schemas:reloaded',\n CONNECTION_READY: 'connection:ready',\n\n // Client → Server\n SCHEMA_SAVE: 'schema:save',\n SCHEMA_VALIDATE: 'schema:validate',\n} as const;\n\n// Primary key types - only for ID fields, not shown in regular property dropdown\nexport const PK_TYPES = ['Id', 'Uuid'] as const;\n\n// Regular property types - shown in property dropdown\nexport const PROPERTY_TYPES = [\n 'String',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'Boolean',\n 'Text',\n 'LongText',\n 'Date',\n 'Time',\n 'Timestamp',\n 'Json',\n 'Email',\n 'Password',\n 'File',\n 'Point',\n 'Coordinates',\n 'Enum',\n 'EnumRef',\n] as const;\n\n// All types including PK types - for loading/displaying existing schemas\nexport const ALL_PROPERTY_TYPES = [...PK_TYPES, ...PROPERTY_TYPES] as const;\n\nexport const RELATION_TYPES = [\n 'OneToOne',\n 'OneToMany',\n 'ManyToOne',\n 'ManyToMany',\n] as const;\n\nexport const POLYMORPHIC_RELATION_TYPES = [\n 'MorphTo',\n 'MorphOne',\n 'MorphMany',\n 'MorphToMany',\n 'MorphedByMany',\n] as const;\n\nexport const REFERENTIAL_ACTIONS = [\n 'CASCADE',\n 'SET NULL',\n 'SET DEFAULT',\n 'RESTRICT',\n 'NO ACTION',\n] as const;\n\n// Types allowed for pivot fields (basic types only, no Association)\nexport const PIVOT_FIELD_TYPES = [\n 'String',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'Boolean',\n 'Text',\n 'Date',\n 'Time',\n 'Timestamp',\n 'Json',\n] as const;\n","/**\n * Version history API routes\n */\n\nimport { Router, type Request, type Response, type Router as RouterType } from 'express';\nimport type { ApiResponse } from '../../shared/types.js';\nimport {\n listVersions,\n getVersion,\n getLatestVersion,\n diffVersions,\n getPendingChanges,\n createVersion,\n discardChanges,\n type PendingChangesResult,\n type CreateVersionResult,\n type DiscardChangesResult,\n} from '../services/versionService.js';\nimport type { VersionSummary, VersionFile, VersionDiff } from '@famgia/omnify-core';\n\nexport const versionsRouter: RouterType = Router();\n\n/**\n * GET /api/versions - List all versions\n */\nversionsRouter.get('/', async (_req: Request, res: Response) => {\n try {\n const versions = await listVersions();\n const response: ApiResponse<VersionSummary[]> = {\n success: true,\n data: versions,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_LIST_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * POST /api/versions - Create a new version\n */\nversionsRouter.post('/', async (req: Request, res: Response) => {\n try {\n const { description } = req.body as { description?: string };\n const result = await createVersion(description);\n const response: ApiResponse<CreateVersionResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_CREATE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/pending - Get pending changes (current vs latest)\n */\nversionsRouter.get('/pending', async (_req: Request, res: Response) => {\n try {\n const pending = await getPendingChanges();\n const response: ApiResponse<PendingChangesResult> = {\n success: true,\n data: pending,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PENDING_CHANGES_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * POST /api/versions/discard - Discard pending changes and restore from latest version\n */\nversionsRouter.post('/discard', async (_req: Request, res: Response) => {\n try {\n const result = await discardChanges();\n const response: ApiResponse<DiscardChangesResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DISCARD_CHANGES_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/latest - Get latest version\n */\nversionsRouter.get('/latest', async (_req: Request, res: Response) => {\n try {\n const version = await getLatestVersion();\n const response: ApiResponse<VersionFile | null> = {\n success: true,\n data: version,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_READ_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/:version - Get specific version\n */\nversionsRouter.get('/:version', async (req: Request, res: Response) => {\n try {\n const versionNum = parseInt(req.params.version ?? '', 10);\n if (isNaN(versionNum)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_VERSION',\n message: 'Version must be a number',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const version = await getVersion(versionNum);\n if (!version) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_NOT_FOUND',\n message: `Version ${versionNum} not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<VersionFile> = {\n success: true,\n data: version,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_READ_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/diff/:from/:to - Get diff between versions\n */\nversionsRouter.get('/diff/:from/:to', async (req: Request, res: Response) => {\n try {\n const fromVersion = parseInt(req.params.from ?? '', 10);\n const toVersion = parseInt(req.params.to ?? '', 10);\n\n if (isNaN(fromVersion) || isNaN(toVersion)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_VERSION',\n message: 'Version numbers must be integers',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const diff = await diffVersions(fromVersion, toVersion);\n if (!diff) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DIFF_ERROR',\n message: 'Could not compute diff. One or both versions may not exist.',\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<VersionDiff> = {\n success: true,\n data: diff,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DIFF_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Version history service for GUI\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { writeFile, unlink, readdir } from 'fs/promises';\nimport { join } from 'path';\nimport { stringify } from 'yaml';\nimport {\n createVersionStore,\n type VersionStore,\n type VersionSummary,\n type VersionFile,\n type VersionDiff,\n type VersionChange,\n type VersionSchemaSnapshot,\n type VersionPropertySnapshot,\n} from '@famgia/omnify-core';\n\nlet store: VersionStore | null = null;\nlet schemasDir: string | null = null;\n\n/**\n * Initialize the version store with the project base directory.\n */\nexport function initVersionStore(baseDir: string, schemasDirPath: string): void {\n store = createVersionStore({ baseDir, maxVersions: 100 });\n schemasDir = schemasDirPath;\n}\n\n/**\n * Get the version store instance.\n */\nfunction getStore(): VersionStore {\n if (!store) {\n throw new Error('Version store not initialized. Call initVersionStore first.');\n }\n return store;\n}\n\n/**\n * List all versions.\n */\nexport async function listVersions(): Promise<VersionSummary[]> {\n return getStore().listVersions();\n}\n\n/**\n * Get a specific version.\n */\nexport async function getVersion(version: number): Promise<VersionFile | null> {\n return getStore().readVersion(version);\n}\n\n/**\n * Get the latest version.\n */\nexport async function getLatestVersion(): Promise<VersionFile | null> {\n return getStore().readLatestVersion();\n}\n\n/**\n * Get diff between two versions.\n */\nexport async function diffVersions(fromVersion: number, toVersion: number): Promise<VersionDiff | null> {\n return getStore().diffVersions(fromVersion, toVersion);\n}\n\n/**\n * Get the version store for direct access.\n */\nexport function getVersionStore(): VersionStore {\n return getStore();\n}\n\n/**\n * Convert property to version snapshot format.\n */\nfunction propertyToSnapshot(prop: Record<string, unknown>): VersionPropertySnapshot {\n return {\n type: prop.type as string,\n ...(prop.displayName !== undefined && { displayName: prop.displayName as string }),\n ...(prop.description !== undefined && { description: prop.description as string }),\n ...(prop.nullable !== undefined && { nullable: prop.nullable as boolean }),\n ...(prop.unique !== undefined && { unique: prop.unique as boolean }),\n ...(prop.default !== undefined && { default: prop.default }),\n ...(prop.length !== undefined && { length: prop.length as number }),\n ...(prop.unsigned !== undefined && { unsigned: prop.unsigned as boolean }),\n ...(prop.precision !== undefined && { precision: prop.precision as number }),\n ...(prop.scale !== undefined && { scale: prop.scale as number }),\n ...(prop.enum !== undefined && { enum: prop.enum as readonly string[] }),\n ...(prop.relation !== undefined && { relation: prop.relation as string }),\n ...(prop.target !== undefined && { target: prop.target as string }),\n ...(prop.targets !== undefined && { targets: prop.targets as readonly string[] }),\n ...(prop.morphName !== undefined && { morphName: prop.morphName as string }),\n ...(prop.onDelete !== undefined && { onDelete: prop.onDelete as string }),\n ...(prop.onUpdate !== undefined && { onUpdate: prop.onUpdate as string }),\n ...(prop.mappedBy !== undefined && { mappedBy: prop.mappedBy as string }),\n ...(prop.inversedBy !== undefined && { inversedBy: prop.inversedBy as string }),\n ...(prop.joinTable !== undefined && { joinTable: prop.joinTable as string }),\n ...(prop.owning !== undefined && { owning: prop.owning as boolean }),\n };\n}\n\n/**\n * Convert loaded schemas to version snapshot format.\n */\nfunction schemasToSnapshot(\n schemas: Readonly<Record<string, { name: string; kind?: string; properties?: unknown; options?: unknown; values?: readonly string[] }>>\n): Record<string, VersionSchemaSnapshot> {\n const snapshot: Record<string, VersionSchemaSnapshot> = {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n const properties: Record<string, VersionPropertySnapshot> = {};\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n properties[propName] = propertyToSnapshot(prop as Record<string, unknown>);\n }\n }\n\n const opts = schema.options as Record<string, unknown> | undefined;\n\n // Convert indexes to snapshot format\n const rawIndexes = opts?.indexes as Array<{ columns: string[]; unique?: boolean; name?: string; type?: string }> | undefined;\n const indexSnapshots = rawIndexes?.map((idx) => ({\n columns: idx.columns,\n ...(idx.unique !== undefined && { unique: idx.unique }),\n ...(idx.name !== undefined && { name: idx.name }),\n ...(idx.type !== undefined && { type: idx.type }),\n }));\n\n // Convert unique constraints to indexes with unique=true for tracking\n const rawUnique = opts?.unique as string[][] | undefined;\n const uniqueAsIndexes = rawUnique?.map((cols, i) => ({\n columns: cols,\n unique: true,\n name: `unique_${i}`,\n }));\n\n // Merge indexes and unique constraints\n const allIndexes = [...(indexSnapshots ?? []), ...(uniqueAsIndexes ?? [])];\n\n // Build options - ONLY store non-default values to ensure consistent comparison\n const snapshotOptions: Record<string, unknown> = {};\n if (opts?.id === false) snapshotOptions.id = false; // default is true\n if (opts?.idType && opts.idType !== 'BigInt') snapshotOptions.idType = opts.idType; // default is BigInt\n if (opts?.timestamps === false) snapshotOptions.timestamps = false; // default is true\n if (opts?.softDelete === true) snapshotOptions.softDelete = true; // default is false\n if (opts?.tableName) snapshotOptions.tableName = opts.tableName;\n if (opts?.translations === true) snapshotOptions.translations = true; // default is false\n if (opts?.authenticatable === true) snapshotOptions.authenticatable = true; // default is false\n if (allIndexes.length > 0) snapshotOptions.indexes = allIndexes;\n\n snapshot[name] = {\n name: schema.name,\n kind: (schema.kind ?? 'object') as 'object' | 'enum' | 'partial' | 'pivot',\n ...(Object.keys(properties).length > 0 && { properties }),\n ...(schema.values && { values: schema.values }),\n ...(Object.keys(snapshotOptions).length > 0 && { options: snapshotOptions }),\n };\n }\n\n return snapshot;\n}\n\n/**\n * Result of computing pending changes.\n */\nexport interface PendingChangesResult {\n hasChanges: boolean;\n changes: readonly VersionChange[];\n currentSchemaCount: number;\n previousSchemaCount: number;\n latestVersion: number | null;\n}\n\n/**\n * Result of creating a new version.\n */\nexport interface CreateVersionResult {\n version: number;\n migration: string;\n changes: readonly VersionChange[];\n}\n\n/**\n * Create a new version from the current schemas.\n */\nexport async function createVersion(description?: string): Promise<CreateVersionResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n\n // Load current schemas\n const currentSchemas = await loadSchemas(schemasDir);\n const currentSnapshot = schemasToSnapshot(currentSchemas);\n\n // Get latest version to compute changes\n const latestVersion = await storeInstance.readLatestVersion();\n\n // Compute changes\n let changes: VersionChange[];\n if (!latestVersion) {\n // Initial version - all schemas are new\n changes = Object.keys(currentSnapshot).map((name) => ({\n action: 'schema_added' as const,\n schema: name,\n }));\n } else {\n changes = storeInstance.computeSnapshotDiff(latestVersion.snapshot, currentSnapshot);\n }\n\n if (changes.length === 0) {\n throw new Error('No changes to create version');\n }\n\n // Generate migration name based on timestamp\n const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);\n const migration = `${timestamp}_omnify_migration`;\n\n // Create the version\n const versionFile = await storeInstance.createVersion(currentSnapshot, changes, {\n driver: 'mysql', // TODO: Get from config\n migration,\n description,\n });\n\n return {\n version: versionFile.version,\n migration: versionFile.migration ?? migration,\n changes: versionFile.changes,\n };\n}\n\n/**\n * Get pending changes (current schemas vs latest version).\n */\nexport async function getPendingChanges(): Promise<PendingChangesResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n\n // Load current schemas\n const currentSchemas = await loadSchemas(schemasDir);\n const currentSnapshot = schemasToSnapshot(currentSchemas);\n\n // Get latest version\n const latestVersion = await storeInstance.readLatestVersion();\n\n if (!latestVersion) {\n // No previous version, all schemas are new\n const changes: VersionChange[] = Object.keys(currentSnapshot).map((name) => ({\n action: 'schema_added' as const,\n schema: name,\n }));\n\n return {\n hasChanges: changes.length > 0,\n changes,\n currentSchemaCount: Object.keys(currentSnapshot).length,\n previousSchemaCount: 0,\n latestVersion: null,\n };\n }\n\n // Compute diff from latest version to current\n const changes = storeInstance.computeSnapshotDiff(latestVersion.snapshot, currentSnapshot);\n\n return {\n hasChanges: changes.length > 0,\n changes,\n currentSchemaCount: Object.keys(currentSnapshot).length,\n previousSchemaCount: Object.keys(latestVersion.snapshot).length,\n latestVersion: latestVersion.version,\n };\n}\n\n/**\n * Result of discarding changes.\n */\nexport interface DiscardChangesResult {\n restored: number;\n deleted: number;\n}\n\n/**\n * Convert a property snapshot back to YAML-compatible format.\n * Only includes non-undefined values to match original YAML structure.\n */\nfunction propertySnapshotToYaml(prop: VersionPropertySnapshot): Record<string, unknown> {\n const result: Record<string, unknown> = {\n type: prop.type,\n };\n\n // Only add fields that have values (matching original YAML structure)\n if (prop.displayName !== undefined) result.displayName = prop.displayName;\n if (prop.description !== undefined) result.description = prop.description;\n if (prop.nullable !== undefined) result.nullable = prop.nullable;\n if (prop.unique !== undefined) result.unique = prop.unique;\n if (prop.default !== undefined) result.default = prop.default;\n if (prop.length !== undefined) result.length = prop.length;\n if (prop.unsigned !== undefined) result.unsigned = prop.unsigned;\n if (prop.precision !== undefined) result.precision = prop.precision;\n if (prop.scale !== undefined) result.scale = prop.scale;\n if (prop.enum !== undefined) result.enum = [...prop.enum]; // Convert readonly to mutable\n if (prop.relation !== undefined) result.relation = prop.relation;\n if (prop.target !== undefined) result.target = prop.target;\n if (prop.targets !== undefined) result.targets = [...prop.targets]; // Convert readonly to mutable\n if (prop.morphName !== undefined) result.morphName = prop.morphName;\n if (prop.onDelete !== undefined) result.onDelete = prop.onDelete;\n if (prop.onUpdate !== undefined) result.onUpdate = prop.onUpdate;\n if (prop.mappedBy !== undefined) result.mappedBy = prop.mappedBy;\n if (prop.inversedBy !== undefined) result.inversedBy = prop.inversedBy;\n if (prop.joinTable !== undefined) result.joinTable = prop.joinTable;\n if (prop.owning !== undefined) result.owning = prop.owning;\n\n return result;\n}\n\n/**\n * Convert a version snapshot back to YAML-compatible schema object.\n */\nfunction snapshotToYaml(snapshot: VersionSchemaSnapshot): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n // Only add kind if enum (object is default)\n if (snapshot.kind === 'enum') result.kind = 'enum';\n if (snapshot.displayName) result.displayName = snapshot.displayName;\n if (snapshot.singular) result.singular = snapshot.singular;\n if (snapshot.plural) result.plural = snapshot.plural;\n if (snapshot.titleIndex) result.titleIndex = snapshot.titleIndex;\n if (snapshot.group) result.group = snapshot.group;\n\n // Properties - convert each property to YAML format\n if (snapshot.properties && Object.keys(snapshot.properties).length > 0) {\n const properties: Record<string, Record<string, unknown>> = {};\n for (const [propName, prop] of Object.entries(snapshot.properties)) {\n properties[propName] = propertySnapshotToYaml(prop);\n }\n result.properties = properties;\n }\n\n // Enum values - convert readonly to mutable array\n if (snapshot.values && snapshot.values.length > 0) {\n result.values = [...snapshot.values];\n }\n\n // Options - only include non-default values\n if (snapshot.options) {\n const opts: Record<string, unknown> = {};\n if (snapshot.options.id === false) opts.id = false;\n if (snapshot.options.idType && snapshot.options.idType !== 'BigInt') opts.idType = snapshot.options.idType;\n if (snapshot.options.timestamps === false) opts.timestamps = false;\n if (snapshot.options.softDelete) opts.softDelete = true;\n if (snapshot.options.tableName) opts.tableName = snapshot.options.tableName;\n if (snapshot.options.translations) opts.translations = true;\n if (snapshot.options.authenticatable) opts.authenticatable = true;\n if (snapshot.options.indexes && snapshot.options.indexes.length > 0) {\n // Convert readonly index arrays to mutable\n opts.indexes = snapshot.options.indexes.map((idx) => ({\n columns: [...idx.columns],\n ...(idx.unique !== undefined && { unique: idx.unique }),\n ...(idx.name !== undefined && { name: idx.name }),\n ...(idx.type !== undefined && { type: idx.type }),\n }));\n }\n if (Object.keys(opts).length > 0) {\n result.options = opts;\n }\n }\n\n return result;\n}\n\n/**\n * Discard all pending changes by restoring schemas from the latest version.\n */\nexport async function discardChanges(): Promise<DiscardChangesResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n const latestVersion = await storeInstance.readLatestVersion();\n\n if (!latestVersion) {\n throw new Error('No version to restore from. Cannot discard changes.');\n }\n\n const snapshot = latestVersion.snapshot;\n const snapshotSchemaNames = new Set(Object.keys(snapshot));\n\n // Get current schema files\n const currentFiles = await readdir(schemasDir);\n const yamlFiles = currentFiles.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));\n const currentSchemaNames = new Set(yamlFiles.map((f) => f.replace(/\\.ya?ml$/, '')));\n\n let restored = 0;\n let deleted = 0;\n\n // Restore schemas from snapshot\n for (const [name, schemaSnapshot] of Object.entries(snapshot)) {\n const yamlData = snapshotToYaml(schemaSnapshot);\n const yamlContent = stringify(yamlData, {\n lineWidth: 120,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n });\n\n const filePath = join(schemasDir, `${name}.yaml`);\n await writeFile(filePath, yamlContent, 'utf-8');\n restored++;\n }\n\n // Delete schemas that aren't in the snapshot\n for (const file of yamlFiles) {\n const name = file.replace(/\\.ya?ml$/, '');\n if (!snapshotSchemaNames.has(name)) {\n const filePath = join(schemasDir, file);\n await unlink(filePath);\n deleted++;\n }\n }\n\n return { restored, deleted };\n}\n","/**\n * Plugins API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { readdir, readFile, writeFile } from 'fs/promises';\nimport { writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { createRequire } from 'module';\nimport { pathToFileURL } from 'url';\nimport { spawn } from 'child_process';\nimport type { ApiResponse, PluginInfo, PluginConfigSchema, PluginConfigField } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\n// Store CWD for module resolution\nlet projectCwd: string = process.cwd();\n\n/**\n * Restart the server by spawning a new process after this one exits.\n * Uses a shell wrapper with sleep to ensure port is released.\n */\nfunction restartServer(cwd: string): void {\n console.log('\\n🔄 Restarting server...\\n');\n\n // Create restart marker to prevent auto-opening browser\n try {\n writeFileSync(join(cwd, '.omnify-restart'), '');\n } catch {\n // Ignore\n }\n\n // Get the command that started this process\n const args = process.argv.slice(1);\n const nodeExecutable = process.execPath;\n const fullCommand = [nodeExecutable, ...args].map(a => `\"${a}\"`).join(' ');\n\n // Use shell to wait 1 second before starting new server\n // This ensures the old server has fully released the port\n const child = spawn('sh', ['-c', `sleep 1 && ${fullCommand}`], {\n cwd,\n detached: true,\n stdio: 'ignore',\n env: { ...process.env },\n });\n\n // Unref so parent can exit independently\n child.unref();\n\n // Exit the current process immediately\n process.exit(0);\n}\n\nexport const pluginsRouter: IRouter = Router();\n\n// Known omnify plugins with their metadata and export names\n// Only packages that export a plugin function should be listed here\nconst KNOWN_PLUGINS: Record<string, { description: string; types: string[]; exportName: string; importPath?: string; isFactory?: boolean }> = {\n '@famgia/omnify-japan': {\n description: 'Japan-specific types (JapaneseAddress, JapanesePhone, JapaneseName, etc.)',\n types: ['JapanesePhone', 'JapanesePostalCode', 'JapaneseAddress', 'JapaneseName', 'JapaneseBankAccount'],\n exportName: 'japanTypesPlugin',\n isFactory: false, // Already instantiated\n },\n '@famgia/omnify-laravel': {\n description: 'Laravel migration generator',\n types: [],\n exportName: 'laravelPlugin',\n importPath: '@famgia/omnify-laravel',\n isFactory: true, // Needs to be called with ()\n },\n '@famgia/omnify-typescript': {\n description: 'TypeScript type definitions generator',\n types: [],\n exportName: 'typescriptPlugin',\n importPath: '@famgia/omnify-typescript/plugin',\n isFactory: true, // Needs to be called with ()\n },\n};\n\n// Packages that are NOT plugins (utility libraries)\nconst NON_PLUGIN_PACKAGES = ['@famgia/omnify-sql', '@famgia/omnify-atlas'];\n\n/**\n * Dynamically import a plugin to get its configSchema.\n * Uses createRequire to resolve from the project's CWD instead of this file's location.\n */\nasync function getPluginConfigSchema(packageName: string, cwd: string): Promise<PluginConfigSchema | undefined> {\n try {\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return undefined;\n\n // Create require function from project CWD to resolve packages correctly\n const projectRequire = createRequire(pathToFileURL(join(cwd, 'package.json')).href);\n\n // Resolve the package path from project's node_modules\n const packagePath = projectRequire.resolve(packageName);\n\n // Import the plugin module using file URL\n const pluginModule = await import(pathToFileURL(packagePath).href);\n const pluginFactory = pluginModule[knownPlugin.exportName] || pluginModule.default;\n\n if (typeof pluginFactory !== 'function') return undefined;\n\n // Call the factory to get the plugin instance (with empty options to get defaults)\n const pluginInstance = pluginFactory();\n\n // Return the configSchema if present\n return pluginInstance.configSchema as PluginConfigSchema | undefined;\n } catch (error) {\n console.error(`Failed to load configSchema for ${packageName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Parse plugin configuration from omnify.config.ts\n */\nasync function getPluginConfig(cwd: string, packageName: string): Promise<Record<string, unknown>> {\n const configPath = join(cwd, 'omnify.config.ts');\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return {};\n\n try {\n const content = await readFile(configPath, 'utf-8');\n\n // Look for plugin call with options: laravelPlugin({ ... })\n const pluginVarName = knownPlugin.exportName;\n const pluginCallRegex = new RegExp(`${pluginVarName}\\\\s*\\\\(\\\\s*\\\\{([^}]*)\\\\}\\\\s*\\\\)`, 's');\n const match = content.match(pluginCallRegex);\n\n if (!match) return {};\n\n // Parse the options object (simple parsing for common types)\n const optionsStr = match[1] ?? '';\n const config: Record<string, unknown> = {};\n\n // Parse key: value pairs\n const pairRegex = /(\\w+)\\s*:\\s*(?:'([^']*)'|\"([^\"]*)\"|(\\d+(?:\\.\\d+)?)|(\\btrue\\b|\\bfalse\\b))/g;\n let pairMatch;\n while ((pairMatch = pairRegex.exec(optionsStr)) !== null) {\n const key = pairMatch[1] as string;\n const stringVal = pairMatch[2] ?? pairMatch[3];\n const numVal = pairMatch[4];\n const boolVal = pairMatch[5];\n\n if (stringVal !== undefined) {\n config[key] = stringVal;\n } else if (numVal !== undefined) {\n config[key] = parseFloat(numVal);\n } else if (boolVal !== undefined) {\n config[key] = boolVal === 'true';\n }\n }\n\n return config;\n } catch {\n return {};\n }\n}\n\n/**\n * Update plugin configuration in omnify.config.ts\n */\nasync function savePluginConfig(\n cwd: string,\n packageName: string,\n config: Record<string, unknown>\n): Promise<boolean> {\n const configPath = join(cwd, 'omnify.config.ts');\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return false;\n\n try {\n let content = await readFile(configPath, 'utf-8');\n const pluginVarName = knownPlugin.exportName;\n\n // Convert config object to options string\n const optionsEntries = Object.entries(config)\n .filter(([_, v]) => v !== undefined && v !== '')\n .map(([k, v]) => {\n if (typeof v === 'string') return `${k}: '${v}'`;\n if (typeof v === 'boolean') return `${k}: ${v}`;\n if (typeof v === 'number') return `${k}: ${v}`;\n return null;\n })\n .filter(Boolean);\n\n const optionsStr = optionsEntries.length > 0\n ? `{ ${optionsEntries.join(', ')} }`\n : '';\n\n // Only replace plugin calls within the plugins array, not in import statements\n // Match plugins: [...] and replace the plugin reference inside\n const pluginsArrayRegex = /(plugins:\\s*\\[)([^\\]]*?)(\\])/s;\n const pluginsMatch = content.match(pluginsArrayRegex);\n\n if (pluginsMatch) {\n const [fullMatch, prefix, pluginsContent, suffix] = pluginsMatch;\n\n if (!pluginsContent) {\n return false;\n }\n\n // Replace plugin call within plugins array only\n const pluginCallWithOptionsRegex = new RegExp(`${pluginVarName}\\\\s*\\\\([^)]*\\\\)`, 'g');\n const pluginCallNoOptionsRegex = new RegExp(`\\\\b${pluginVarName}\\\\b(?!\\\\s*\\\\()`, 'g');\n\n let newPluginsContent = pluginsContent;\n const replacement = optionsStr ? `${pluginVarName}(${optionsStr})` : `${pluginVarName}()`;\n\n if (pluginsContent.match(pluginCallWithOptionsRegex)) {\n // Replace existing options\n newPluginsContent = pluginsContent.replace(pluginCallWithOptionsRegex, replacement);\n } else if (pluginsContent.match(pluginCallNoOptionsRegex)) {\n // Add options to plugin call\n newPluginsContent = pluginsContent.replace(pluginCallNoOptionsRegex, replacement);\n }\n\n content = content.replace(fullMatch, `${prefix}${newPluginsContent}${suffix}`);\n }\n\n await writeFile(configPath, content, 'utf-8');\n return true;\n } catch (error) {\n console.error('Failed to save plugin config:', error);\n return false;\n }\n}\n\n/**\n * Scan node_modules for installed omnify plugins\n */\nasync function scanInstalledPlugins(cwd: string): Promise<PluginInfo[]> {\n const plugins: PluginInfo[] = [];\n const nodeModulesPath = join(cwd, 'node_modules', '@famgia');\n\n try {\n const dirs = await readdir(nodeModulesPath);\n\n for (const dir of dirs) {\n // Skip non-plugin packages\n if (!dir.startsWith('omnify-') || dir === 'omnify-cli' || dir === 'omnify-gui' || dir === 'omnify-types' || dir === 'omnify-core') {\n continue;\n }\n\n const packageName = `@famgia/${dir}`;\n\n // Skip utility libraries that don't export plugins\n if (NON_PLUGIN_PACKAGES.includes(packageName)) {\n continue;\n }\n\n // Skip if not a known plugin (we only support known plugins for now)\n if (!KNOWN_PLUGINS[packageName]) {\n continue;\n }\n\n const packageJsonPath = join(nodeModulesPath, dir, 'package.json');\n\n try {\n const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));\n\n // Get types from known plugins or empty array\n const knownPlugin = KNOWN_PLUGINS[packageName];\n const types = knownPlugin?.types || [];\n\n plugins.push({\n name: dir.replace('omnify-', ''),\n packageName,\n version: packageJson.version || '0.0.0',\n description: knownPlugin?.description || packageJson.description || '',\n enabled: false, // Will be updated by checking config\n types,\n });\n } catch {\n // Skip if can't read package.json\n }\n }\n } catch {\n // node_modules/@famgia doesn't exist\n }\n\n return plugins;\n}\n\n/**\n * Check which plugins are enabled in omnify.config.ts\n */\nasync function getEnabledPlugins(cwd: string): Promise<string[]> {\n const configPath = join(cwd, 'omnify.config.ts');\n\n try {\n const content = await readFile(configPath, 'utf-8');\n const enabled: string[] = [];\n\n // Parse imports to find enabled plugins (handles both @famgia/omnify-xxx and @famgia/omnify-xxx/plugin)\n const importRegex = /import\\s+\\{?\\s*(\\w+)\\s*\\}?\\s+from\\s+['\"](@famgia\\/omnify-\\w+)(?:\\/\\w+)?['\"]/g;\n let match;\n while ((match = importRegex.exec(content)) !== null) {\n if (match[2]) enabled.push(match[2]);\n }\n\n return enabled;\n } catch {\n return [];\n }\n}\n\n/**\n * Update omnify.config.ts to enable/disable a plugin\n */\nasync function updatePluginConfig(\n cwd: string,\n packageName: string,\n enable: boolean\n): Promise<boolean> {\n const configPath = join(cwd, 'omnify.config.ts');\n\n try {\n let content = await readFile(configPath, 'utf-8');\n\n // Get the variable name for the plugin from known plugins or generate one\n const knownPlugin = KNOWN_PLUGINS[packageName];\n const pluginVarName = knownPlugin?.exportName ??\n packageName.replace('@famgia/omnify-', '').replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + 'Plugin';\n\n if (enable) {\n // Use custom import path if specified (e.g., @famgia/omnify-typescript/plugin)\n const importFrom = knownPlugin?.importPath ?? packageName;\n const importStatement = `import { ${pluginVarName} } from '${importFrom}';\\n`;\n\n // Check if import already exists (check for package name base, not full path)\n const packageBase = packageName.replace('@famgia/', '');\n if (!content.includes(packageBase)) {\n // Add import after the first import\n const firstImportEnd = content.indexOf('\\n', content.indexOf('import'));\n content = content.slice(0, firstImportEnd + 1) + importStatement + content.slice(firstImportEnd + 1);\n }\n\n // Determine how to add plugin (with or without ())\n const pluginCall = knownPlugin?.isFactory ? `${pluginVarName}()` : pluginVarName;\n\n // Add to plugins array\n if (content.includes('plugins:')) {\n // Add to existing plugins array\n content = content.replace(\n /plugins:\\s*\\[([^\\]]*)\\]/,\n (match, plugins) => {\n if (plugins.includes(pluginVarName)) return match;\n const newPlugins = plugins.trim()\n ? `${plugins.trim()}, ${pluginCall}`\n : pluginCall;\n return `plugins: [${newPlugins}]`;\n }\n );\n } else {\n // Add plugins array before output or at end of config\n content = content.replace(\n /(database:\\s*\\{[^}]+\\},?)/,\n `$1\\n plugins: [${pluginCall}],`\n );\n }\n } else {\n // Remove from plugins array (handle both factory calls \"name()\" and plain \"name\")\n // Handle \", pluginName()\" or \", pluginName\"\n content = content.replace(\n new RegExp(`,\\\\s*${pluginVarName}(?:\\\\([^)]*\\\\))?`, 'g'),\n ''\n );\n // Handle \"pluginName(),\" or \"pluginName,\"\n content = content.replace(\n new RegExp(`${pluginVarName}(?:\\\\([^)]*\\\\))?\\\\s*,`, 'g'),\n ''\n );\n // Handle standalone \"pluginName()\" or \"pluginName\" (last item in array)\n content = content.replace(\n new RegExp(`${pluginVarName}(?:\\\\([^)]*\\\\))?(?=\\\\s*\\\\])`, 'g'),\n ''\n );\n\n // Clean up empty plugins array\n content = content.replace(/plugins:\\s*\\[\\s*\\],?\\n?/, '');\n\n // Remove entire import line for this package (use importPath if available)\n const importFrom = knownPlugin?.importPath ?? packageName;\n const escapedImportFrom = importFrom.replace(/\\//g, '\\\\/');\n content = content.replace(\n new RegExp(`import\\\\s*\\\\{[^}]*\\\\}\\\\s*from\\\\s*['\"]${escapedImportFrom}['\"];?\\\\n?`),\n ''\n );\n }\n\n await writeFile(configPath, content, 'utf-8');\n return true;\n } catch (error) {\n console.error('Failed to update config:', error);\n return false;\n }\n}\n\n// GET /api/plugins - List all installed plugins\npluginsRouter.get('/', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n\n try {\n const plugins = await scanInstalledPlugins(appConfig.cwd);\n const enabledPackages = await getEnabledPlugins(appConfig.cwd);\n\n // Mark enabled plugins and fetch their configSchema + current config\n for (const plugin of plugins) {\n plugin.enabled = enabledPackages.includes(plugin.packageName);\n\n // Get configSchema from plugin (dynamically imported)\n const configSchema = await getPluginConfigSchema(plugin.packageName, appConfig.cwd);\n if (configSchema) {\n plugin.configSchema = configSchema;\n }\n\n // Get current config from omnify.config.ts\n if (plugin.enabled) {\n const config = await getPluginConfig(appConfig.cwd, plugin.packageName);\n plugin.config = config;\n }\n }\n\n const response: ApiResponse<PluginInfo[]> = {\n success: true,\n data: plugins,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PLUGINS_SCAN_ERROR',\n message: error instanceof Error ? error.message : 'Failed to scan plugins',\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/plugins/:name/toggle - Enable/disable a plugin\npluginsRouter.post('/:name/toggle', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const { enabled } = req.body as { enabled: boolean };\n\n const packageName = `@famgia/omnify-${name}`;\n\n try {\n const success = await updatePluginConfig(appConfig.cwd, packageName, enabled);\n\n if (success) {\n const response: ApiResponse<{ enabled: boolean; restarting: boolean }> = {\n success: true,\n data: { enabled, restarting: true },\n };\n\n // Wait for response to be fully sent before restarting\n res.on('finish', () => {\n // Give client time to receive and process the response\n setTimeout(() => {\n restartServer(appConfig.cwd);\n }, 1000);\n });\n\n res.json(response);\n } else {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_UPDATE_ERROR',\n message: 'Failed to update omnify.config.ts',\n },\n };\n res.status(500).json(response);\n }\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'TOGGLE_ERROR',\n message: error instanceof Error ? error.message : 'Failed to toggle plugin',\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/plugins/:name/config - Update plugin configuration\npluginsRouter.post('/:name/config', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const { config } = req.body as { config: Record<string, unknown> };\n\n const packageName = `@famgia/omnify-${name}`;\n\n try {\n const success = await savePluginConfig(appConfig.cwd, packageName, config);\n\n if (success) {\n const response: ApiResponse<{ saved: boolean; restarting: boolean }> = {\n success: true,\n data: { saved: true, restarting: true },\n };\n\n // Wait for response to be fully sent before restarting\n res.on('finish', () => {\n // Give client time to receive and process the response\n setTimeout(() => {\n restartServer(appConfig.cwd);\n }, 1000);\n });\n\n res.json(response);\n } else {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_SAVE_ERROR',\n message: 'Failed to save plugin configuration',\n },\n };\n res.status(500).json(response);\n }\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_SAVE_ERROR',\n message: error instanceof Error ? error.message : 'Failed to save plugin configuration',\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * WebSocket handler for real-time updates\n */\n\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { Server } from 'http';\nimport type { ServerEvent, ClientEvent } from '../../shared/events.js';\n\nexport interface WsHandler {\n broadcast: (event: ServerEvent) => void;\n close: () => void;\n}\n\nexport function createWsHandler(server: Server): WsHandler {\n const wss = new WebSocketServer({ server, path: '/ws' });\n const clients = new Set<WebSocket>();\n\n wss.on('connection', (ws: WebSocket) => {\n clients.add(ws);\n console.log(' WebSocket client connected');\n\n // Send ready event\n const readyEvent: ServerEvent = {\n type: 'connection:ready',\n payload: {\n schemasDir: process.env.SCHEMAS_DIR ?? 'schemas',\n schemaCount: 0,\n },\n };\n ws.send(JSON.stringify(readyEvent));\n\n ws.on('message', (data: Buffer) => {\n try {\n const event = JSON.parse(data.toString()) as ClientEvent;\n handleClientEvent(event, ws);\n } catch {\n console.error('Invalid WebSocket message');\n }\n });\n\n ws.on('close', () => {\n clients.delete(ws);\n console.log(' WebSocket client disconnected');\n });\n\n ws.on('error', (error: Error) => {\n console.error('WebSocket error:', error);\n clients.delete(ws);\n });\n });\n\n function handleClientEvent(_event: ClientEvent, _ws: WebSocket): void {\n // Handle client events (save, validate requests)\n // These are handled by the REST API, but could be used for\n // real-time validation feedback\n }\n\n function broadcast(event: ServerEvent): void {\n const message = JSON.stringify(event);\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message);\n }\n }\n }\n\n function close(): void {\n for (const client of clients) {\n client.close();\n }\n wss.close();\n }\n\n return { broadcast, close };\n}\n","/**\n * File system watcher for schema changes\n */\n\nimport chokidar from 'chokidar';\nimport { basename } from 'path';\nimport { schemaService } from '../services/schemaService.js';\nimport type { WsHandler } from '../ws/handler.js';\nimport type { ServerEvent } from '../../shared/events.js';\n\nexport interface FileWatcher {\n close: () => void;\n}\n\nexport function createFileWatcher(schemasDir: string, wsHandler: WsHandler): FileWatcher {\n const watcher = chokidar.watch(`${schemasDir}/*.yaml`, {\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 200,\n pollInterval: 100,\n },\n });\n\n watcher.on('add', (filePath: string) => {\n console.log(` Schema added: ${basename(filePath)}`);\n void notifySchemaChange(filePath, 'file');\n });\n\n watcher.on('change', (filePath: string) => {\n console.log(` Schema changed: ${basename(filePath)}`);\n void notifySchemaChange(filePath, 'file');\n });\n\n watcher.on('unlink', (filePath: string) => {\n console.log(` Schema deleted: ${basename(filePath)}`);\n void notifyReload();\n });\n\n async function notifySchemaChange(\n filePath: string,\n source: 'file' | 'editor'\n ): Promise<void> {\n try {\n // Clear cache and reload\n schemaService.clearCache(schemasDir);\n const schemas = await schemaService.loadAll(schemasDir);\n\n // Find the changed schema\n const name = basename(filePath, '.yaml');\n const schema = schemas[name];\n\n if (schema) {\n const event: ServerEvent = {\n type: 'schema:changed',\n payload: { name, schema, source },\n };\n wsHandler.broadcast(event);\n }\n } catch (error) {\n console.error('Error notifying schema change:', error);\n }\n }\n\n async function notifyReload(): Promise<void> {\n try {\n schemaService.clearCache(schemasDir);\n const schemas = await schemaService.loadAll(schemasDir);\n\n const event: ServerEvent = {\n type: 'schemas:reloaded',\n payload: { schemas },\n };\n wsHandler.broadcast(event);\n } catch (error) {\n console.error('Error notifying reload:', error);\n }\n }\n\n return {\n close: () => watcher.close(),\n };\n}\n"],"mappings":"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","names":["join","resolve","join","schemasDir","response","Router","loadSchemas","resolveLocalizedString","schemasDir","Router","Router","loadSchemas","schemasDir","Router","response","Router","Router","Router","loadSchemas","writeFile","unlink","join","stringify","loadSchemas","changes","stringify","join","writeFile","unlink","Router","response","Router","readdir","writeFile","join","join","schemasDir","join","schemasDir","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/server/app.ts","../../src/server/api/schemas.ts","../../src/server/services/schemaService.ts","../../src/server/api/validate.ts","../../src/server/services/validationService.ts","../../src/server/api/preview.ts","../../src/server/services/previewService.ts","../../src/server/api/config.ts","../../src/shared/constants.ts","../../src/server/api/versions.ts","../../src/server/services/versionService.ts","../../src/server/api/plugins.ts","../../src/server/ws/handler.ts","../../src/server/watcher/fileWatcher.ts"],"sourcesContent":["/**\n * @famgia/omnify-gui - Server Entry Point\n *\n * Starts the local development server for Omnify GUI.\n */\n\nimport { createServer } from 'http';\nimport { join, resolve } from 'path';\nimport { existsSync, unlinkSync } from 'fs';\nimport open from 'open';\nimport { loadConfig } from '@famgia/omnify-cli';\nimport { createApp } from './app.js';\nimport { createWsHandler } from './ws/handler.js';\nimport { createFileWatcher } from './watcher/fileWatcher.js';\nimport { DEFAULT_PORT, DEFAULT_HOST } from '../shared/constants.js';\n\n// fileURLToPath and dirname imported for potential future use with static files\n// Currently not needed as Vite handles static serving\n\n// Restart marker file path\nconst RESTART_MARKER = join(process.cwd(), '.omnify-restart');\n\nasync function main(): Promise<void> {\n const port = Number(process.env.PORT) || DEFAULT_PORT;\n const host = process.env.HOST ?? DEFAULT_HOST;\n const cwd = process.cwd();\n\n // Check if this is a restart (marker file exists)\n const isRestart = existsSync(RESTART_MARKER);\n console.log(` Restart marker: ${RESTART_MARKER}, exists: ${isRestart}`);\n if (isRestart) {\n console.log(' Detected restart - will not open browser');\n try {\n unlinkSync(RESTART_MARKER);\n } catch {\n // Ignore\n }\n }\n\n // Resolve schemas directory and custom types from omnify config\n let schemasDir: string;\n let customTypes: string[] = [];\n\n if (process.env.SCHEMAS_DIR) {\n schemasDir = process.env.SCHEMAS_DIR;\n } else {\n try {\n const { config } = await loadConfig(cwd);\n schemasDir = resolve(cwd, config.schemasDir);\n // Extract custom type names from plugins\n customTypes = (config.plugins ?? [])\n .flatMap((p) => p.types ?? [])\n .filter((t) => t && typeof t === 'object' && 'name' in t)\n .map((t) => t.name);\n } catch (error) {\n // Fall back to default if no config file found\n console.error(' Failed to load config:', error instanceof Error ? error.message : error);\n schemasDir = join(cwd, 'schemas');\n }\n }\n\n console.log('Starting Omnify GUI...');\n console.log(` Schemas directory: ${schemasDir}`);\n\n // Create Express app\n const app = createApp({ schemasDir, cwd, customTypes });\n\n // Create HTTP server\n const server = createServer(app);\n\n // Create WebSocket handler\n const wsHandler = createWsHandler(server);\n\n // Create file watcher\n const watcher = createFileWatcher(schemasDir, wsHandler);\n\n // Start server\n server.listen(port, host, () => {\n const url = `http://${host}:${port}`;\n console.log(` GUI running at: ${url}`);\n console.log(' Press Ctrl+C to stop\\n');\n\n // Auto-open browser in development (skip if restarting)\n if (process.env.NODE_ENV !== 'production' && !isRestart) {\n open(url).catch(() => {\n // Ignore errors if browser fails to open\n });\n }\n });\n\n // Graceful shutdown\n const shutdown = (): void => {\n console.log('\\nShutting down...');\n watcher.close();\n wsHandler.close();\n server.close(() => {\n console.log('Server closed');\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nmain().catch((error: unknown) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n});\n","/**\n * Express application configuration\n */\n\nimport express, { type Express, type Request, type Response, type NextFunction } from 'express';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { schemasRouter } from './api/schemas.js';\nimport { validateRouter } from './api/validate.js';\nimport { previewRouter } from './api/preview.js';\nimport { configRouter } from './api/config.js';\nimport { versionsRouter } from './api/versions.js';\nimport { pluginsRouter } from './api/plugins.js';\nimport { initVersionStore } from './services/versionService.js';\nimport type { ApiResponse } from '../shared/types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport interface AppConfig {\n schemasDir: string;\n cwd: string;\n customTypes?: string[];\n}\n\nexport function createApp(config: AppConfig): Express {\n const app = express();\n\n // Store config in app locals for access in routes\n app.locals.config = config;\n\n // Initialize version store with project root and schemas directory\n initVersionStore(config.cwd, config.schemasDir);\n\n // Middleware\n app.use(express.json());\n\n // API routes\n app.use('/api/schemas', schemasRouter);\n app.use('/api/validate', validateRouter);\n app.use('/api/preview', previewRouter);\n app.use('/api/config', configRouter);\n app.use('/api/versions', versionsRouter);\n app.use('/api/plugins', pluginsRouter);\n\n // Serve static files (client build)\n const clientDist = join(__dirname, '../client');\n app.use(express.static(clientDist));\n\n // SPA fallback - serve index.html for all non-API routes\n app.get('*', (_req: Request, res: Response) => {\n res.sendFile(join(clientDist, 'index.html'));\n });\n\n // Error handler\n app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {\n console.error('Server error:', err);\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: err.message,\n },\n };\n res.status(500).json(response);\n });\n\n return app;\n}\n","/**\n * Schema CRUD API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { schemaService } from '../services/schemaService.js';\nimport type { ApiResponse, GuiSchema } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const schemasRouter: IRouter = Router();\n\n// GET /api/schemas - List all schemas\nschemasRouter.get('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const schemas = await schemaService.loadAll(config.schemasDir);\n const response: ApiResponse<Record<string, GuiSchema>> = {\n success: true,\n data: schemas,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'LOAD_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// GET /api/schemas/:name - Get single schema\nschemasRouter.get('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const schema = await schemaService.load(config.schemasDir, name!);\n\n if (!schema) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'NOT_FOUND',\n message: `Schema \"${name}\" not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: schema,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'LOAD_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/schemas - Create new schema\nschemasRouter.post('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const schema = req.body as GuiSchema;\n\n if (!schema.name) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VALIDATION_ERROR',\n message: 'Schema name is required',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const saved = await schemaService.save(config.schemasDir, schema);\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: saved,\n };\n res.status(201).json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'SAVE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// PUT /api/schemas/:name - Update schema\nschemasRouter.put('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const schema = req.body as GuiSchema;\n\n // Ensure name matches\n schema.name = name!;\n\n const saved = await schemaService.save(config.schemasDir, schema);\n const response: ApiResponse<GuiSchema> = {\n success: true,\n data: saved,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'SAVE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// DELETE /api/schemas/:name - Delete schema\nschemasRouter.delete('/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { name } = req.params;\n\n await schemaService.delete(config.schemasDir, name!);\n const response: ApiResponse = {\n success: true,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DELETE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Schema CRUD service using omnify-core\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport { writeFile, unlink } from 'fs/promises';\nimport { join } from 'path';\nimport { stringify } from 'yaml';\nimport type { GuiSchema, GuiEnumValue, GuiIndexDefinition } from '../../shared/types.js';\n\n/**\n * Convert indexes from various formats to GuiIndexDefinition[]\n * Indexes can be:\n * - string: \"column_name\" -> { columns: [\"column_name\"] }\n * - string[]: [\"col1\", \"col2\"] -> { columns: [\"col1\", \"col2\"] }\n * - object: { columns: [...], unique: true } -> as-is\n */\nfunction normalizeIndexes(indexes: unknown): GuiIndexDefinition[] | undefined {\n if (!indexes || !Array.isArray(indexes)) return undefined;\n\n return indexes.map((idx) => {\n // Already an object with columns property\n if (typeof idx === 'object' && idx !== null && 'columns' in idx) {\n return idx as GuiIndexDefinition;\n }\n // Array of column names (composite index)\n if (Array.isArray(idx)) {\n return { columns: idx.map(String) };\n }\n // Single column name as string\n return { columns: [String(idx)] };\n });\n}\n\n/**\n * Convert enum values from various formats to GuiEnumValue[]\n */\nfunction normalizeEnumValues(values: unknown): GuiEnumValue[] | undefined {\n if (!values || !Array.isArray(values)) return undefined;\n\n return values.map((v) => {\n // Already an object with value property\n if (typeof v === 'object' && v !== null && 'value' in v) {\n const obj = v as Record<string, unknown>;\n return {\n value: String(obj.value),\n label: obj.label ? String(obj.label) : undefined,\n extra: obj.extra as GuiEnumValue['extra'],\n };\n }\n // Simple string value\n return { value: String(v) };\n });\n}\n\nclass SchemaService {\n private cache: Map<string, Record<string, GuiSchema>> = new Map();\n\n async loadAll(schemasDir: string): Promise<Record<string, GuiSchema>> {\n try {\n const schemas = await loadSchemas(schemasDir);\n const guiSchemas: Record<string, GuiSchema> = {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n // Normalize options with indexes\n const normalizedOptions = schema.options ? {\n ...schema.options,\n indexes: normalizeIndexes(schema.options.indexes),\n } : undefined;\n\n guiSchemas[name] = {\n name: schema.name,\n kind: schema.kind ?? 'object',\n displayName: resolveLocalizedString(schema.displayName),\n filePath: schema.filePath,\n relativePath: schema.relativePath,\n properties: schema.properties as GuiSchema['properties'],\n options: normalizedOptions as GuiSchema['options'],\n values: normalizeEnumValues(schema.values),\n isDirty: false,\n validationErrors: [],\n };\n }\n\n this.cache.set(schemasDir, guiSchemas);\n return guiSchemas;\n } catch (error) {\n // Return empty if no schemas found\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return {};\n }\n throw error;\n }\n }\n\n async load(schemasDir: string, name: string): Promise<GuiSchema | null> {\n const schemas = await this.loadAll(schemasDir);\n return schemas[name] ?? null;\n }\n\n async save(schemasDir: string, schema: GuiSchema): Promise<GuiSchema> {\n // Extract fields that shouldn't be saved to YAML\n const {\n isDirty: _isDirty,\n validationErrors: _validationErrors,\n filePath,\n relativePath,\n name, // Derived from filename, don't save\n kind, // Only save if enum (object is default)\n ...yamlData\n } = schema;\n\n // Build YAML data - only include kind for enums\n const dataToSave = kind === 'enum'\n ? { kind, ...yamlData }\n : yamlData;\n\n // Use existing path if available (update), otherwise create at root (new)\n let targetPath: string;\n let targetRelativePath: string;\n\n if (filePath && relativePath) {\n // Updating existing schema - keep original location\n targetPath = filePath;\n targetRelativePath = relativePath;\n } else {\n // New schema - create at root of schemasDir\n const fileName = `${name}.yaml`;\n targetPath = join(schemasDir, fileName);\n targetRelativePath = fileName;\n }\n\n // Convert to YAML\n const yamlContent = stringify(dataToSave, {\n lineWidth: 120,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n });\n\n await writeFile(targetPath, yamlContent, 'utf-8');\n\n // Return updated schema with file path\n return {\n ...schema,\n filePath: targetPath,\n relativePath: targetRelativePath,\n isDirty: false,\n validationErrors: [],\n };\n }\n\n async delete(schemasDir: string, name: string): Promise<void> {\n // Find the schema to get its actual file path\n const schemas = await this.loadAll(schemasDir);\n const schema = schemas[name];\n\n if (!schema?.filePath) {\n throw new Error(`Schema \"${name}\" not found`);\n }\n\n await unlink(schema.filePath);\n\n // Clear cache\n this.cache.delete(schemasDir);\n }\n\n clearCache(schemasDir?: string): void {\n if (schemasDir) {\n this.cache.delete(schemasDir);\n } else {\n this.cache.clear();\n }\n }\n}\n\nexport const schemaService = new SchemaService();\n","/**\n * Schema validation API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { validationService } from '../services/validationService.js';\nimport type { ApiResponse, GuiSchema, ValidationError } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const validateRouter: IRouter = Router();\n\ninterface ValidateRequest {\n schema?: GuiSchema;\n schemas?: Record<string, GuiSchema>;\n}\n\ninterface ValidateResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n// POST /api/validate - Validate schema(s)\nvalidateRouter.post('/', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const body = req.body as ValidateRequest;\n\n let result: ValidateResult;\n\n if (body.schema) {\n // Validate single schema\n result = await validationService.validateSchema(body.schema, config.schemasDir);\n } else if (body.schemas) {\n // Validate all schemas\n result = await validationService.validateAll(body.schemas);\n } else {\n // Load and validate all from disk\n result = await validationService.validateFromDisk(config.schemasDir);\n }\n\n const response: ApiResponse<ValidateResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VALIDATION_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Schema validation service using omnify-core\n */\n\nimport { loadSchemas, validateSchemas, OmnifyError } from '@famgia/omnify-core';\nimport type { LoadedSchema, SchemaCollection, SchemaOptions } from '@famgia/omnify-types';\nimport { resolveLocalizedString } from '@famgia/omnify-types';\nimport type { GuiSchema, ValidationError } from '../../shared/types.js';\n\ninterface ValidateResult {\n valid: boolean;\n errors: ValidationError[];\n}\n\n/**\n * Convert GuiSchema to LoadedSchema format\n * Handles exactOptionalPropertyTypes by only setting defined properties\n */\nfunction toLoadedSchema(schema: GuiSchema): LoadedSchema {\n // Start with required fields only\n const result = {\n name: schema.name,\n kind: schema.kind,\n filePath: schema.filePath,\n relativePath: schema.relativePath ?? schema.name + '.yaml',\n } as LoadedSchema;\n\n // Only add optional fields if they're defined\n if (schema.displayName !== undefined) {\n (result as { displayName: string }).displayName = schema.displayName;\n }\n if (schema.properties !== undefined) {\n (result as { properties: LoadedSchema['properties'] }).properties = schema.properties as LoadedSchema['properties'];\n }\n if (schema.options !== undefined) {\n (result as { options: SchemaOptions }).options = schema.options as SchemaOptions;\n }\n if (schema.values !== undefined) {\n // Convert GuiEnumValue[] to readonly string[] for validation\n (result as { values: readonly string[] }).values = schema.values.map((v) => v.value);\n }\n\n return result;\n}\n\nclass ValidationService {\n async validateSchema(schema: GuiSchema, schemasDir: string): Promise<ValidateResult> {\n try {\n // Load all schemas to validate references\n const allSchemas = await loadSchemas(schemasDir);\n\n // Convert GuiSchema to LoadedSchema format\n const loadedSchema = toLoadedSchema(schema);\n\n // Create mutable copy and add the schema\n const schemasToValidate: Record<string, LoadedSchema> = { ...allSchemas };\n schemasToValidate[schema.name] = loadedSchema;\n\n // Validate all schemas together\n const result = validateSchemas(schemasToValidate);\n\n // Filter errors for this schema from schema results\n const schemaResult = result.schemas.find((s) => s.schemaName === schema.name);\n const schemaErrors: ValidationError[] = [];\n\n if (schemaResult) {\n for (const e of schemaResult.errors) {\n schemaErrors.push({\n path: this.getErrorPath(e, schema.name),\n message: e.message,\n severity: 'error' as const,\n });\n }\n }\n\n return {\n valid: schemaErrors.length === 0,\n errors: schemaErrors,\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: schema.name,\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n async validateAll(schemas: Record<string, GuiSchema>): Promise<ValidateResult> {\n try {\n // Convert GuiSchemas to LoadedSchemas\n const loadedSchemas: SchemaCollection = {};\n for (const [name, schema] of Object.entries(schemas)) {\n (loadedSchemas as Record<string, LoadedSchema>)[name] = toLoadedSchema(schema);\n }\n\n const result = validateSchemas(loadedSchemas);\n\n const errors: ValidationError[] = [];\n for (const schemaResult of result.schemas) {\n for (const e of schemaResult.errors) {\n errors.push({\n path: this.getErrorPath(e, schemaResult.schemaName),\n message: e.message,\n severity: 'error' as const,\n });\n }\n }\n\n return {\n valid: result.valid,\n errors,\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n async validateFromDisk(schemasDir: string): Promise<ValidateResult> {\n try {\n const schemas = await loadSchemas(schemasDir);\n\n // Convert to GuiSchemas\n const guiSchemas: Record<string, GuiSchema> = {};\n for (const [name, schema] of Object.entries(schemas)) {\n guiSchemas[name] = {\n name: schema.name,\n kind: schema.kind ?? 'object',\n displayName: resolveLocalizedString(schema.displayName),\n filePath: schema.filePath,\n relativePath: schema.relativePath,\n properties: schema.properties as GuiSchema['properties'],\n options: schema.options as GuiSchema['options'],\n // Convert readonly string[] to GuiEnumValue[]\n values: schema.values?.map((v) => ({ value: v })),\n };\n }\n\n return this.validateAll(guiSchemas);\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'root',\n message: (error as Error).message,\n severity: 'error',\n },\n ],\n };\n }\n }\n\n private getErrorPath(error: OmnifyError, schemaName: string): string {\n // Try to extract property name from the error message or details\n const details = error.details;\n if (details && 'propertyName' in details && details.propertyName) {\n return `${schemaName}.${String(details.propertyName)}`;\n }\n return schemaName;\n }\n}\n\nexport const validationService = new ValidationService();\n","/**\n * Code preview API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { previewService } from '../services/previewService.js';\nimport type { ApiResponse, PreviewResult, PreviewType } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\nexport const previewRouter: IRouter = Router();\n\n// GET /api/preview/:type - Get code preview for all schemas\npreviewRouter.get('/:type', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { type } = req.params;\n\n if (!['laravel', 'typescript', 'sql'].includes(type!)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_TYPE',\n message: `Invalid preview type: ${type}. Valid types: laravel, typescript, sql`,\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const previews = await previewService.generateAll(config.schemasDir, type as PreviewType);\n const response: ApiResponse<PreviewResult[]> = {\n success: true,\n data: previews,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PREVIEW_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n// GET /api/preview/:type/:name - Get code preview for single schema\npreviewRouter.get('/:type/:name', async (req: Request, res: Response) => {\n try {\n const config = req.app.locals.config as AppConfig;\n const { type, name } = req.params;\n\n if (!['laravel', 'typescript', 'sql'].includes(type!)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_TYPE',\n message: `Invalid preview type: ${type}. Valid types: laravel, typescript, sql`,\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const preview = await previewService.generateForSchema(\n config.schemasDir,\n name!,\n type as PreviewType\n );\n\n if (!preview) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'NOT_FOUND',\n message: `Schema \"${name}\" not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<PreviewResult> = {\n success: true,\n data: preview,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PREVIEW_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Code preview generation service\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { generateMigrations as generateLaravelMigrations } from '@famgia/omnify-laravel';\nimport { generateMigrations as generateSqlMigrations } from '@famgia/omnify-sql';\nimport type { PreviewResult, PreviewType } from '../../shared/types.js';\n\ninterface EnumSchema {\n kind: 'enum';\n values?: readonly string[];\n}\n\ninterface ObjectSchema {\n kind: 'object';\n properties?: Record<string, { type: string; nullable?: boolean }>;\n}\n\nclass PreviewService {\n async generateAll(schemasDir: string, type: PreviewType): Promise<PreviewResult[]> {\n const schemas = await loadSchemas(schemasDir);\n const previews: PreviewResult[] = [];\n\n switch (type) {\n case 'laravel': {\n const migrations = await generateLaravelMigrations(schemas);\n for (const migration of migrations) {\n previews.push({\n type: 'laravel',\n content: migration.content,\n fileName: migration.fileName,\n });\n }\n break;\n }\n\n case 'sql': {\n const migrations = generateSqlMigrations(schemas, { dialect: 'mysql' });\n for (const migration of migrations) {\n previews.push({\n type: 'sql',\n content: migration.content,\n fileName: migration.fileName,\n });\n }\n break;\n }\n\n case 'typescript': {\n // Generate TypeScript interfaces from schemas\n for (const [name, schema] of Object.entries(schemas)) {\n if (schema.kind === 'enum') {\n previews.push({\n type: 'typescript',\n content: this.generateEnumType(name, schema as EnumSchema),\n fileName: `${name}.ts`,\n });\n } else {\n previews.push({\n type: 'typescript',\n content: this.generateInterfaceType(name, schema as ObjectSchema),\n fileName: `${name}.ts`,\n });\n }\n }\n break;\n }\n }\n\n return previews;\n }\n\n async generateForSchema(\n schemasDir: string,\n schemaName: string,\n type: PreviewType\n ): Promise<PreviewResult | null> {\n const schemas = await loadSchemas(schemasDir);\n const schema = schemas[schemaName];\n\n if (!schema) {\n return null;\n }\n\n switch (type) {\n case 'laravel': {\n const migrations = await generateLaravelMigrations({ [schemaName]: schema });\n const migration = migrations[0];\n return migration\n ? {\n type: 'laravel',\n content: migration.content,\n fileName: migration.fileName,\n }\n : null;\n }\n\n case 'sql': {\n const migrations = generateSqlMigrations({ [schemaName]: schema }, { dialect: 'mysql' });\n const migration = migrations[0];\n return migration\n ? {\n type: 'sql',\n content: migration.content,\n fileName: migration.fileName,\n }\n : null;\n }\n\n case 'typescript': {\n if (schema.kind === 'enum') {\n return {\n type: 'typescript',\n content: this.generateEnumType(schemaName, schema as EnumSchema),\n fileName: `${schemaName}.ts`,\n };\n }\n return {\n type: 'typescript',\n content: this.generateInterfaceType(schemaName, schema as ObjectSchema),\n fileName: `${schemaName}.ts`,\n };\n }\n }\n }\n\n private generateEnumType(name: string, schema: EnumSchema): string {\n const values = schema.values ?? [];\n return `export type ${name} = ${values.map((v) => `'${v}'`).join(' | ') || 'never'};\\n`;\n }\n\n private generateInterfaceType(name: string, schema: ObjectSchema): string {\n const lines: string[] = [`export interface ${name} {`];\n\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n const tsType = this.mapToTsType(prop.type);\n const optional = prop.nullable ? '?' : '';\n lines.push(` ${propName}${optional}: ${tsType};`);\n }\n }\n\n lines.push('}');\n return lines.join('\\n') + '\\n';\n }\n\n private mapToTsType(omnifyType: string): string {\n const typeMap: Record<string, string> = {\n String: 'string',\n Int: 'number',\n BigInt: 'number',\n Float: 'number',\n Decimal: 'number',\n Boolean: 'boolean',\n Text: 'string',\n LongText: 'string',\n Date: 'string',\n Time: 'string',\n Timestamp: 'string',\n Json: 'Record<string, unknown>',\n Email: 'string',\n Password: 'string',\n File: 'string',\n MultiFile: 'string[]',\n Point: '{ lat: number; lng: number }',\n Coordinates: '{ latitude: number; longitude: number }',\n };\n\n return typeMap[omnifyType] ?? 'unknown';\n }\n}\n\nexport const previewService = new PreviewService();\n","/**\n * Config API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport type { ApiResponse, GuiConfig } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\nimport { DEFAULT_PORT, DEFAULT_HOST } from '../../shared/constants.js';\n\nexport const configRouter: IRouter = Router();\n\n// GET /api/config - Get current configuration\nconfigRouter.get('/', (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n\n const config: GuiConfig = {\n schemasDir: appConfig.schemasDir,\n port: Number(process.env.PORT) || DEFAULT_PORT,\n host: process.env.HOST ?? DEFAULT_HOST,\n customTypes: appConfig.customTypes ?? [],\n plugins: [], // Plugins are fetched via /api/plugins\n };\n\n const response: ApiResponse<GuiConfig> = {\n success: true,\n data: config,\n };\n res.json(response);\n});\n","/**\n * Shared constants for @famgia/omnify-gui\n */\n\nexport const DEFAULT_PORT = 3456;\nexport const DEFAULT_HOST = 'localhost';\n\nexport const API_ROUTES = {\n SCHEMAS: '/api/schemas',\n SCHEMA: '/api/schemas/:name',\n VALIDATE: '/api/validate',\n PREVIEW: '/api/preview/:type',\n CONFIG: '/api/config',\n} as const;\n\nexport const WS_EVENTS = {\n // Server → Client\n SCHEMA_CHANGED: 'schema:changed',\n SCHEMA_VALIDATED: 'schema:validated',\n SCHEMAS_RELOADED: 'schemas:reloaded',\n CONNECTION_READY: 'connection:ready',\n\n // Client → Server\n SCHEMA_SAVE: 'schema:save',\n SCHEMA_VALIDATE: 'schema:validate',\n} as const;\n\n// Primary key types - only for ID fields, not shown in regular property dropdown\nexport const PK_TYPES = ['Id', 'Uuid'] as const;\n\n// Regular property types - shown in property dropdown\nexport const PROPERTY_TYPES = [\n 'String',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'Boolean',\n 'Text',\n 'LongText',\n 'Date',\n 'Time',\n 'Timestamp',\n 'Json',\n 'Email',\n 'Password',\n 'File',\n 'Point',\n 'Coordinates',\n 'Enum',\n 'EnumRef',\n] as const;\n\n// All types including PK types - for loading/displaying existing schemas\nexport const ALL_PROPERTY_TYPES = [...PK_TYPES, ...PROPERTY_TYPES] as const;\n\nexport const RELATION_TYPES = [\n 'OneToOne',\n 'OneToMany',\n 'ManyToOne',\n 'ManyToMany',\n] as const;\n\nexport const POLYMORPHIC_RELATION_TYPES = [\n 'MorphTo',\n 'MorphOne',\n 'MorphMany',\n 'MorphToMany',\n 'MorphedByMany',\n] as const;\n\nexport const REFERENTIAL_ACTIONS = [\n 'CASCADE',\n 'SET NULL',\n 'SET DEFAULT',\n 'RESTRICT',\n 'NO ACTION',\n] as const;\n\n// Types allowed for pivot fields (basic types only, no Association)\nexport const PIVOT_FIELD_TYPES = [\n 'String',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'Boolean',\n 'Text',\n 'Date',\n 'Time',\n 'Timestamp',\n 'Json',\n 'Enum',\n] as const;\n","/**\n * Version history API routes\n */\n\nimport { Router, type Request, type Response, type Router as RouterType } from 'express';\nimport type { ApiResponse } from '../../shared/types.js';\nimport {\n listVersions,\n getVersion,\n getLatestVersion,\n diffVersions,\n getPendingChanges,\n createVersion,\n discardChanges,\n type PendingChangesResult,\n type CreateVersionResult,\n type DiscardChangesResult,\n} from '../services/versionService.js';\nimport type { VersionSummary, VersionFile, VersionDiff } from '@famgia/omnify-core';\n\nexport const versionsRouter: RouterType = Router();\n\n/**\n * GET /api/versions - List all versions\n */\nversionsRouter.get('/', async (_req: Request, res: Response) => {\n try {\n const versions = await listVersions();\n const response: ApiResponse<VersionSummary[]> = {\n success: true,\n data: versions,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_LIST_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * POST /api/versions - Create a new version\n */\nversionsRouter.post('/', async (req: Request, res: Response) => {\n try {\n const { description } = req.body as { description?: string };\n const result = await createVersion(description);\n const response: ApiResponse<CreateVersionResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_CREATE_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/pending - Get pending changes (current vs latest)\n */\nversionsRouter.get('/pending', async (_req: Request, res: Response) => {\n try {\n const pending = await getPendingChanges();\n const response: ApiResponse<PendingChangesResult> = {\n success: true,\n data: pending,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PENDING_CHANGES_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * POST /api/versions/discard - Discard pending changes and restore from latest version\n */\nversionsRouter.post('/discard', async (_req: Request, res: Response) => {\n try {\n const result = await discardChanges();\n const response: ApiResponse<DiscardChangesResult> = {\n success: true,\n data: result,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DISCARD_CHANGES_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/latest - Get latest version\n */\nversionsRouter.get('/latest', async (_req: Request, res: Response) => {\n try {\n const version = await getLatestVersion();\n const response: ApiResponse<VersionFile | null> = {\n success: true,\n data: version,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_READ_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/:version - Get specific version\n */\nversionsRouter.get('/:version', async (req: Request, res: Response) => {\n try {\n const versionNum = parseInt(req.params.version ?? '', 10);\n if (isNaN(versionNum)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_VERSION',\n message: 'Version must be a number',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const version = await getVersion(versionNum);\n if (!version) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_NOT_FOUND',\n message: `Version ${versionNum} not found`,\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<VersionFile> = {\n success: true,\n data: version,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'VERSION_READ_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n\n/**\n * GET /api/versions/diff/:from/:to - Get diff between versions\n */\nversionsRouter.get('/diff/:from/:to', async (req: Request, res: Response) => {\n try {\n const fromVersion = parseInt(req.params.from ?? '', 10);\n const toVersion = parseInt(req.params.to ?? '', 10);\n\n if (isNaN(fromVersion) || isNaN(toVersion)) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'INVALID_VERSION',\n message: 'Version numbers must be integers',\n },\n };\n res.status(400).json(response);\n return;\n }\n\n const diff = await diffVersions(fromVersion, toVersion);\n if (!diff) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DIFF_ERROR',\n message: 'Could not compute diff. One or both versions may not exist.',\n },\n };\n res.status(404).json(response);\n return;\n }\n\n const response: ApiResponse<VersionDiff> = {\n success: true,\n data: diff,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'DIFF_ERROR',\n message: (error as Error).message,\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * Version history service for GUI\n */\n\nimport { loadSchemas } from '@famgia/omnify-core';\nimport { writeFile, unlink, readdir } from 'fs/promises';\nimport { join } from 'path';\nimport { stringify } from 'yaml';\nimport {\n createVersionStore,\n type VersionStore,\n type VersionSummary,\n type VersionFile,\n type VersionDiff,\n type VersionChange,\n type VersionSchemaSnapshot,\n type VersionPropertySnapshot,\n} from '@famgia/omnify-core';\n\nlet store: VersionStore | null = null;\nlet schemasDir: string | null = null;\n\n/**\n * Initialize the version store with the project base directory.\n */\nexport function initVersionStore(baseDir: string, schemasDirPath: string): void {\n store = createVersionStore({ baseDir, maxVersions: 100 });\n schemasDir = schemasDirPath;\n}\n\n/**\n * Get the version store instance.\n */\nfunction getStore(): VersionStore {\n if (!store) {\n throw new Error('Version store not initialized. Call initVersionStore first.');\n }\n return store;\n}\n\n/**\n * List all versions.\n */\nexport async function listVersions(): Promise<VersionSummary[]> {\n return getStore().listVersions();\n}\n\n/**\n * Get a specific version.\n */\nexport async function getVersion(version: number): Promise<VersionFile | null> {\n return getStore().readVersion(version);\n}\n\n/**\n * Get the latest version.\n */\nexport async function getLatestVersion(): Promise<VersionFile | null> {\n return getStore().readLatestVersion();\n}\n\n/**\n * Get diff between two versions.\n */\nexport async function diffVersions(fromVersion: number, toVersion: number): Promise<VersionDiff | null> {\n return getStore().diffVersions(fromVersion, toVersion);\n}\n\n/**\n * Get the version store for direct access.\n */\nexport function getVersionStore(): VersionStore {\n return getStore();\n}\n\n/**\n * Convert property to version snapshot format.\n */\nfunction propertyToSnapshot(prop: Record<string, unknown>): VersionPropertySnapshot {\n return {\n type: prop.type as string,\n ...(prop.displayName !== undefined && { displayName: prop.displayName as string }),\n ...(prop.description !== undefined && { description: prop.description as string }),\n ...(prop.nullable !== undefined && { nullable: prop.nullable as boolean }),\n ...(prop.unique !== undefined && { unique: prop.unique as boolean }),\n ...(prop.default !== undefined && { default: prop.default }),\n ...(prop.length !== undefined && { length: prop.length as number }),\n ...(prop.unsigned !== undefined && { unsigned: prop.unsigned as boolean }),\n ...(prop.precision !== undefined && { precision: prop.precision as number }),\n ...(prop.scale !== undefined && { scale: prop.scale as number }),\n ...(prop.enum !== undefined && { enum: prop.enum as readonly string[] }),\n ...(prop.relation !== undefined && { relation: prop.relation as string }),\n ...(prop.target !== undefined && { target: prop.target as string }),\n ...(prop.targets !== undefined && { targets: prop.targets as readonly string[] }),\n ...(prop.morphName !== undefined && { morphName: prop.morphName as string }),\n ...(prop.onDelete !== undefined && { onDelete: prop.onDelete as string }),\n ...(prop.onUpdate !== undefined && { onUpdate: prop.onUpdate as string }),\n ...(prop.mappedBy !== undefined && { mappedBy: prop.mappedBy as string }),\n ...(prop.inversedBy !== undefined && { inversedBy: prop.inversedBy as string }),\n ...(prop.joinTable !== undefined && { joinTable: prop.joinTable as string }),\n ...(prop.owning !== undefined && { owning: prop.owning as boolean }),\n };\n}\n\n/**\n * Convert loaded schemas to version snapshot format.\n */\nfunction schemasToSnapshot(\n schemas: Readonly<Record<string, { name: string; kind?: string; properties?: unknown; options?: unknown; values?: readonly string[] }>>\n): Record<string, VersionSchemaSnapshot> {\n const snapshot: Record<string, VersionSchemaSnapshot> = {};\n\n for (const [name, schema] of Object.entries(schemas)) {\n const properties: Record<string, VersionPropertySnapshot> = {};\n if (schema.properties) {\n for (const [propName, prop] of Object.entries(schema.properties)) {\n properties[propName] = propertyToSnapshot(prop as Record<string, unknown>);\n }\n }\n\n const opts = schema.options as Record<string, unknown> | undefined;\n\n // Convert indexes to snapshot format\n const rawIndexes = opts?.indexes as Array<{ columns: string[]; unique?: boolean; name?: string; type?: string }> | undefined;\n const indexSnapshots = rawIndexes?.map((idx) => ({\n columns: idx.columns,\n ...(idx.unique !== undefined && { unique: idx.unique }),\n ...(idx.name !== undefined && { name: idx.name }),\n ...(idx.type !== undefined && { type: idx.type }),\n }));\n\n // Convert unique constraints to indexes with unique=true for tracking\n const rawUnique = opts?.unique as string[][] | undefined;\n const uniqueAsIndexes = rawUnique?.map((cols, i) => ({\n columns: cols,\n unique: true,\n name: `unique_${i}`,\n }));\n\n // Merge indexes and unique constraints\n const allIndexes = [...(indexSnapshots ?? []), ...(uniqueAsIndexes ?? [])];\n\n // Build options - ONLY store non-default values to ensure consistent comparison\n const snapshotOptions: Record<string, unknown> = {};\n if (opts?.id === false) snapshotOptions.id = false; // default is true\n if (opts?.idType && opts.idType !== 'BigInt') snapshotOptions.idType = opts.idType; // default is BigInt\n if (opts?.timestamps === false) snapshotOptions.timestamps = false; // default is true\n if (opts?.softDelete === true) snapshotOptions.softDelete = true; // default is false\n if (opts?.tableName) snapshotOptions.tableName = opts.tableName;\n if (opts?.translations === true) snapshotOptions.translations = true; // default is false\n if (opts?.authenticatable === true) snapshotOptions.authenticatable = true; // default is false\n if (allIndexes.length > 0) snapshotOptions.indexes = allIndexes;\n\n snapshot[name] = {\n name: schema.name,\n kind: (schema.kind ?? 'object') as 'object' | 'enum' | 'partial' | 'pivot',\n ...(Object.keys(properties).length > 0 && { properties }),\n ...(schema.values && { values: schema.values }),\n ...(Object.keys(snapshotOptions).length > 0 && { options: snapshotOptions }),\n };\n }\n\n return snapshot;\n}\n\n/**\n * Result of computing pending changes.\n */\nexport interface PendingChangesResult {\n hasChanges: boolean;\n changes: readonly VersionChange[];\n currentSchemaCount: number;\n previousSchemaCount: number;\n latestVersion: number | null;\n}\n\n/**\n * Result of creating a new version.\n */\nexport interface CreateVersionResult {\n version: number;\n migration: string;\n changes: readonly VersionChange[];\n}\n\n/**\n * Create a new version from the current schemas.\n */\nexport async function createVersion(description?: string): Promise<CreateVersionResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n\n // Load current schemas\n const currentSchemas = await loadSchemas(schemasDir);\n const currentSnapshot = schemasToSnapshot(currentSchemas);\n\n // Get latest version to compute changes\n const latestVersion = await storeInstance.readLatestVersion();\n\n // Compute changes\n let changes: VersionChange[];\n if (!latestVersion) {\n // Initial version - all schemas are new\n changes = Object.keys(currentSnapshot).map((name) => ({\n action: 'schema_added' as const,\n schema: name,\n }));\n } else {\n changes = storeInstance.computeSnapshotDiff(latestVersion.snapshot, currentSnapshot);\n }\n\n if (changes.length === 0) {\n throw new Error('No changes to create version');\n }\n\n // Generate migration name based on timestamp\n const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14);\n const migration = `${timestamp}_omnify_migration`;\n\n // Create the version\n const versionFile = await storeInstance.createVersion(currentSnapshot, changes, {\n driver: 'mysql', // TODO: Get from config\n migration,\n description,\n });\n\n return {\n version: versionFile.version,\n migration: versionFile.migration ?? migration,\n changes: versionFile.changes,\n };\n}\n\n/**\n * Get pending changes (current schemas vs latest version).\n */\nexport async function getPendingChanges(): Promise<PendingChangesResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n\n // Load current schemas\n const currentSchemas = await loadSchemas(schemasDir);\n const currentSnapshot = schemasToSnapshot(currentSchemas);\n\n // Get latest version\n const latestVersion = await storeInstance.readLatestVersion();\n\n if (!latestVersion) {\n // No previous version, all schemas are new\n const changes: VersionChange[] = Object.keys(currentSnapshot).map((name) => ({\n action: 'schema_added' as const,\n schema: name,\n }));\n\n return {\n hasChanges: changes.length > 0,\n changes,\n currentSchemaCount: Object.keys(currentSnapshot).length,\n previousSchemaCount: 0,\n latestVersion: null,\n };\n }\n\n // Compute diff from latest version to current\n const changes = storeInstance.computeSnapshotDiff(latestVersion.snapshot, currentSnapshot);\n\n return {\n hasChanges: changes.length > 0,\n changes,\n currentSchemaCount: Object.keys(currentSnapshot).length,\n previousSchemaCount: Object.keys(latestVersion.snapshot).length,\n latestVersion: latestVersion.version,\n };\n}\n\n/**\n * Result of discarding changes.\n */\nexport interface DiscardChangesResult {\n restored: number;\n deleted: number;\n}\n\n/**\n * Convert a property snapshot back to YAML-compatible format.\n * Only includes non-undefined values to match original YAML structure.\n */\nfunction propertySnapshotToYaml(prop: VersionPropertySnapshot): Record<string, unknown> {\n const result: Record<string, unknown> = {\n type: prop.type,\n };\n\n // Only add fields that have values (matching original YAML structure)\n if (prop.displayName !== undefined) result.displayName = prop.displayName;\n if (prop.description !== undefined) result.description = prop.description;\n if (prop.nullable !== undefined) result.nullable = prop.nullable;\n if (prop.unique !== undefined) result.unique = prop.unique;\n if (prop.default !== undefined) result.default = prop.default;\n if (prop.length !== undefined) result.length = prop.length;\n if (prop.unsigned !== undefined) result.unsigned = prop.unsigned;\n if (prop.precision !== undefined) result.precision = prop.precision;\n if (prop.scale !== undefined) result.scale = prop.scale;\n if (prop.enum !== undefined) result.enum = [...prop.enum]; // Convert readonly to mutable\n if (prop.relation !== undefined) result.relation = prop.relation;\n if (prop.target !== undefined) result.target = prop.target;\n if (prop.targets !== undefined) result.targets = [...prop.targets]; // Convert readonly to mutable\n if (prop.morphName !== undefined) result.morphName = prop.morphName;\n if (prop.onDelete !== undefined) result.onDelete = prop.onDelete;\n if (prop.onUpdate !== undefined) result.onUpdate = prop.onUpdate;\n if (prop.mappedBy !== undefined) result.mappedBy = prop.mappedBy;\n if (prop.inversedBy !== undefined) result.inversedBy = prop.inversedBy;\n if (prop.joinTable !== undefined) result.joinTable = prop.joinTable;\n if (prop.owning !== undefined) result.owning = prop.owning;\n\n return result;\n}\n\n/**\n * Convert a version snapshot back to YAML-compatible schema object.\n */\nfunction snapshotToYaml(snapshot: VersionSchemaSnapshot): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n // Only add kind if enum (object is default)\n if (snapshot.kind === 'enum') result.kind = 'enum';\n if (snapshot.displayName) result.displayName = snapshot.displayName;\n if (snapshot.singular) result.singular = snapshot.singular;\n if (snapshot.plural) result.plural = snapshot.plural;\n if (snapshot.titleIndex) result.titleIndex = snapshot.titleIndex;\n if (snapshot.group) result.group = snapshot.group;\n\n // Properties - convert each property to YAML format\n if (snapshot.properties && Object.keys(snapshot.properties).length > 0) {\n const properties: Record<string, Record<string, unknown>> = {};\n for (const [propName, prop] of Object.entries(snapshot.properties)) {\n properties[propName] = propertySnapshotToYaml(prop);\n }\n result.properties = properties;\n }\n\n // Enum values - convert readonly to mutable array\n if (snapshot.values && snapshot.values.length > 0) {\n result.values = [...snapshot.values];\n }\n\n // Options - only include non-default values\n if (snapshot.options) {\n const opts: Record<string, unknown> = {};\n if (snapshot.options.id === false) opts.id = false;\n if (snapshot.options.idType && snapshot.options.idType !== 'BigInt') opts.idType = snapshot.options.idType;\n if (snapshot.options.timestamps === false) opts.timestamps = false;\n if (snapshot.options.softDelete) opts.softDelete = true;\n if (snapshot.options.tableName) opts.tableName = snapshot.options.tableName;\n if (snapshot.options.translations) opts.translations = true;\n if (snapshot.options.authenticatable) opts.authenticatable = true;\n if (snapshot.options.indexes && snapshot.options.indexes.length > 0) {\n // Convert readonly index arrays to mutable\n opts.indexes = snapshot.options.indexes.map((idx) => ({\n columns: [...idx.columns],\n ...(idx.unique !== undefined && { unique: idx.unique }),\n ...(idx.name !== undefined && { name: idx.name }),\n ...(idx.type !== undefined && { type: idx.type }),\n }));\n }\n if (Object.keys(opts).length > 0) {\n result.options = opts;\n }\n }\n\n return result;\n}\n\n/**\n * Discard all pending changes by restoring schemas from the latest version.\n */\nexport async function discardChanges(): Promise<DiscardChangesResult> {\n if (!schemasDir) {\n throw new Error('Schemas directory not initialized');\n }\n\n const storeInstance = getStore();\n const latestVersion = await storeInstance.readLatestVersion();\n\n if (!latestVersion) {\n throw new Error('No version to restore from. Cannot discard changes.');\n }\n\n const snapshot = latestVersion.snapshot;\n const snapshotSchemaNames = new Set(Object.keys(snapshot));\n\n // Get current schema files\n const currentFiles = await readdir(schemasDir);\n const yamlFiles = currentFiles.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));\n const currentSchemaNames = new Set(yamlFiles.map((f) => f.replace(/\\.ya?ml$/, '')));\n\n let restored = 0;\n let deleted = 0;\n\n // Restore schemas from snapshot\n for (const [name, schemaSnapshot] of Object.entries(snapshot)) {\n const yamlData = snapshotToYaml(schemaSnapshot);\n const yamlContent = stringify(yamlData, {\n lineWidth: 120,\n defaultKeyType: 'PLAIN',\n defaultStringType: 'PLAIN',\n });\n\n const filePath = join(schemasDir, `${name}.yaml`);\n await writeFile(filePath, yamlContent, 'utf-8');\n restored++;\n }\n\n // Delete schemas that aren't in the snapshot\n for (const file of yamlFiles) {\n const name = file.replace(/\\.ya?ml$/, '');\n if (!snapshotSchemaNames.has(name)) {\n const filePath = join(schemasDir, file);\n await unlink(filePath);\n deleted++;\n }\n }\n\n return { restored, deleted };\n}\n","/**\n * Plugins API routes\n */\n\nimport { Router, type Request, type Response, type IRouter } from 'express';\nimport { readdir, readFile, writeFile } from 'fs/promises';\nimport { writeFileSync } from 'fs';\nimport { join, resolve } from 'path';\nimport { createRequire } from 'module';\nimport { pathToFileURL } from 'url';\nimport { spawn } from 'child_process';\nimport type { ApiResponse, PluginInfo, PluginConfigSchema, PluginConfigField } from '../../shared/types.js';\nimport type { AppConfig } from '../app.js';\n\n// Store CWD for module resolution\nlet projectCwd: string = process.cwd();\n\n/**\n * Restart the server by spawning a new process after this one exits.\n * Uses a shell wrapper with sleep to ensure port is released.\n */\nfunction restartServer(cwd: string): void {\n console.log('\\n🔄 Restarting server...\\n');\n\n // Create restart marker to prevent auto-opening browser\n try {\n writeFileSync(join(cwd, '.omnify-restart'), '');\n } catch {\n // Ignore\n }\n\n // Get the command that started this process\n const args = process.argv.slice(1);\n const nodeExecutable = process.execPath;\n const fullCommand = [nodeExecutable, ...args].map(a => `\"${a}\"`).join(' ');\n\n // Use shell to wait 1 second before starting new server\n // This ensures the old server has fully released the port\n const child = spawn('sh', ['-c', `sleep 1 && ${fullCommand}`], {\n cwd,\n detached: true,\n stdio: 'ignore',\n env: { ...process.env },\n });\n\n // Unref so parent can exit independently\n child.unref();\n\n // Exit the current process immediately\n process.exit(0);\n}\n\nexport const pluginsRouter: IRouter = Router();\n\n// Known omnify plugins with their metadata and export names\n// Only packages that export a plugin function should be listed here\nconst KNOWN_PLUGINS: Record<string, { description: string; types: string[]; exportName: string; importPath?: string; isFactory?: boolean }> = {\n '@famgia/omnify-japan': {\n description: 'Japan-specific types (JapaneseAddress, JapanesePhone, JapaneseName, etc.)',\n types: ['JapanesePhone', 'JapanesePostalCode', 'JapaneseAddress', 'JapaneseName', 'JapaneseBankAccount'],\n exportName: 'japanTypesPlugin',\n isFactory: false, // Already instantiated\n },\n '@famgia/omnify-laravel': {\n description: 'Laravel migration generator',\n types: [],\n exportName: 'laravelPlugin',\n importPath: '@famgia/omnify-laravel',\n isFactory: true, // Needs to be called with ()\n },\n '@famgia/omnify-typescript': {\n description: 'TypeScript type definitions generator',\n types: [],\n exportName: 'typescriptPlugin',\n importPath: '@famgia/omnify-typescript/plugin',\n isFactory: true, // Needs to be called with ()\n },\n};\n\n// Packages that are NOT plugins (utility libraries)\nconst NON_PLUGIN_PACKAGES = ['@famgia/omnify-sql', '@famgia/omnify-atlas'];\n\n/**\n * Dynamically import a plugin to get its configSchema.\n * Uses createRequire to resolve from the project's CWD instead of this file's location.\n */\nasync function getPluginConfigSchema(packageName: string, cwd: string): Promise<PluginConfigSchema | undefined> {\n try {\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return undefined;\n\n // Create require function from project CWD to resolve packages correctly\n const projectRequire = createRequire(pathToFileURL(join(cwd, 'package.json')).href);\n\n // Resolve the package path from project's node_modules\n const packagePath = projectRequire.resolve(packageName);\n\n // Import the plugin module using file URL\n const pluginModule = await import(pathToFileURL(packagePath).href);\n const pluginFactory = pluginModule[knownPlugin.exportName] || pluginModule.default;\n\n if (typeof pluginFactory !== 'function') return undefined;\n\n // Call the factory to get the plugin instance (with empty options to get defaults)\n const pluginInstance = pluginFactory();\n\n // Return the configSchema if present\n return pluginInstance.configSchema as PluginConfigSchema | undefined;\n } catch (error) {\n console.error(`Failed to load configSchema for ${packageName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Parse plugin configuration from omnify.config.ts\n */\nasync function getPluginConfig(cwd: string, packageName: string): Promise<Record<string, unknown>> {\n const configPath = join(cwd, 'omnify.config.ts');\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return {};\n\n try {\n const content = await readFile(configPath, 'utf-8');\n\n // Look for plugin call with options: laravelPlugin({ ... })\n const pluginVarName = knownPlugin.exportName;\n const pluginCallRegex = new RegExp(`${pluginVarName}\\\\s*\\\\(\\\\s*\\\\{([^}]*)\\\\}\\\\s*\\\\)`, 's');\n const match = content.match(pluginCallRegex);\n\n if (!match) return {};\n\n // Parse the options object (simple parsing for common types)\n const optionsStr = match[1] ?? '';\n const config: Record<string, unknown> = {};\n\n // Parse key: value pairs\n const pairRegex = /(\\w+)\\s*:\\s*(?:'([^']*)'|\"([^\"]*)\"|(\\d+(?:\\.\\d+)?)|(\\btrue\\b|\\bfalse\\b))/g;\n let pairMatch;\n while ((pairMatch = pairRegex.exec(optionsStr)) !== null) {\n const key = pairMatch[1] as string;\n const stringVal = pairMatch[2] ?? pairMatch[3];\n const numVal = pairMatch[4];\n const boolVal = pairMatch[5];\n\n if (stringVal !== undefined) {\n config[key] = stringVal;\n } else if (numVal !== undefined) {\n config[key] = parseFloat(numVal);\n } else if (boolVal !== undefined) {\n config[key] = boolVal === 'true';\n }\n }\n\n return config;\n } catch {\n return {};\n }\n}\n\n/**\n * Update plugin configuration in omnify.config.ts\n */\nasync function savePluginConfig(\n cwd: string,\n packageName: string,\n config: Record<string, unknown>\n): Promise<boolean> {\n const configPath = join(cwd, 'omnify.config.ts');\n const knownPlugin = KNOWN_PLUGINS[packageName];\n if (!knownPlugin) return false;\n\n try {\n let content = await readFile(configPath, 'utf-8');\n const pluginVarName = knownPlugin.exportName;\n\n // Convert config object to options string\n const optionsEntries = Object.entries(config)\n .filter(([_, v]) => v !== undefined && v !== '')\n .map(([k, v]) => {\n if (typeof v === 'string') return `${k}: '${v}'`;\n if (typeof v === 'boolean') return `${k}: ${v}`;\n if (typeof v === 'number') return `${k}: ${v}`;\n return null;\n })\n .filter(Boolean);\n\n const optionsStr = optionsEntries.length > 0\n ? `{ ${optionsEntries.join(', ')} }`\n : '';\n\n // Only replace plugin calls within the plugins array, not in import statements\n // Match plugins: [...] and replace the plugin reference inside\n const pluginsArrayRegex = /(plugins:\\s*\\[)([^\\]]*?)(\\])/s;\n const pluginsMatch = content.match(pluginsArrayRegex);\n\n if (pluginsMatch) {\n const [fullMatch, prefix, pluginsContent, suffix] = pluginsMatch;\n\n if (!pluginsContent) {\n return false;\n }\n\n // Replace plugin call within plugins array only\n const pluginCallWithOptionsRegex = new RegExp(`${pluginVarName}\\\\s*\\\\([^)]*\\\\)`, 'g');\n const pluginCallNoOptionsRegex = new RegExp(`\\\\b${pluginVarName}\\\\b(?!\\\\s*\\\\()`, 'g');\n\n let newPluginsContent = pluginsContent;\n const replacement = optionsStr ? `${pluginVarName}(${optionsStr})` : `${pluginVarName}()`;\n\n if (pluginsContent.match(pluginCallWithOptionsRegex)) {\n // Replace existing options\n newPluginsContent = pluginsContent.replace(pluginCallWithOptionsRegex, replacement);\n } else if (pluginsContent.match(pluginCallNoOptionsRegex)) {\n // Add options to plugin call\n newPluginsContent = pluginsContent.replace(pluginCallNoOptionsRegex, replacement);\n }\n\n content = content.replace(fullMatch, `${prefix}${newPluginsContent}${suffix}`);\n }\n\n await writeFile(configPath, content, 'utf-8');\n return true;\n } catch (error) {\n console.error('Failed to save plugin config:', error);\n return false;\n }\n}\n\n/**\n * Scan node_modules for installed omnify plugins\n */\nasync function scanInstalledPlugins(cwd: string): Promise<PluginInfo[]> {\n const plugins: PluginInfo[] = [];\n const nodeModulesPath = join(cwd, 'node_modules', '@famgia');\n\n try {\n const dirs = await readdir(nodeModulesPath);\n\n for (const dir of dirs) {\n // Skip non-plugin packages\n if (!dir.startsWith('omnify-') || dir === 'omnify-cli' || dir === 'omnify-gui' || dir === 'omnify-types' || dir === 'omnify-core') {\n continue;\n }\n\n const packageName = `@famgia/${dir}`;\n\n // Skip utility libraries that don't export plugins\n if (NON_PLUGIN_PACKAGES.includes(packageName)) {\n continue;\n }\n\n // Skip if not a known plugin (we only support known plugins for now)\n if (!KNOWN_PLUGINS[packageName]) {\n continue;\n }\n\n const packageJsonPath = join(nodeModulesPath, dir, 'package.json');\n\n try {\n const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));\n\n // Get types from known plugins or empty array\n const knownPlugin = KNOWN_PLUGINS[packageName];\n const types = knownPlugin?.types || [];\n\n plugins.push({\n name: dir.replace('omnify-', ''),\n packageName,\n version: packageJson.version || '0.0.0',\n description: knownPlugin?.description || packageJson.description || '',\n enabled: false, // Will be updated by checking config\n types,\n });\n } catch {\n // Skip if can't read package.json\n }\n }\n } catch {\n // node_modules/@famgia doesn't exist\n }\n\n return plugins;\n}\n\n/**\n * Check which plugins are enabled in omnify.config.ts\n */\nasync function getEnabledPlugins(cwd: string): Promise<string[]> {\n const configPath = join(cwd, 'omnify.config.ts');\n\n try {\n const content = await readFile(configPath, 'utf-8');\n const enabled: string[] = [];\n\n // Parse imports to find enabled plugins (handles both @famgia/omnify-xxx and @famgia/omnify-xxx/plugin)\n const importRegex = /import\\s+\\{?\\s*(\\w+)\\s*\\}?\\s+from\\s+['\"](@famgia\\/omnify-\\w+)(?:\\/\\w+)?['\"]/g;\n let match;\n while ((match = importRegex.exec(content)) !== null) {\n if (match[2]) enabled.push(match[2]);\n }\n\n return enabled;\n } catch {\n return [];\n }\n}\n\n/**\n * Update omnify.config.ts to enable/disable a plugin\n */\nasync function updatePluginConfig(\n cwd: string,\n packageName: string,\n enable: boolean\n): Promise<boolean> {\n const configPath = join(cwd, 'omnify.config.ts');\n\n try {\n let content = await readFile(configPath, 'utf-8');\n\n // Get the variable name for the plugin from known plugins or generate one\n const knownPlugin = KNOWN_PLUGINS[packageName];\n const pluginVarName = knownPlugin?.exportName ??\n packageName.replace('@famgia/omnify-', '').replace(/-([a-z])/g, (_, c) => c.toUpperCase()) + 'Plugin';\n\n if (enable) {\n // Use custom import path if specified (e.g., @famgia/omnify-typescript/plugin)\n const importFrom = knownPlugin?.importPath ?? packageName;\n const importStatement = `import { ${pluginVarName} } from '${importFrom}';\\n`;\n\n // Check if import already exists (check for package name base, not full path)\n const packageBase = packageName.replace('@famgia/', '');\n if (!content.includes(packageBase)) {\n // Add import after the first import\n const firstImportEnd = content.indexOf('\\n', content.indexOf('import'));\n content = content.slice(0, firstImportEnd + 1) + importStatement + content.slice(firstImportEnd + 1);\n }\n\n // Determine how to add plugin (with or without ())\n const pluginCall = knownPlugin?.isFactory ? `${pluginVarName}()` : pluginVarName;\n\n // Add to plugins array\n if (content.includes('plugins:')) {\n // Add to existing plugins array\n content = content.replace(\n /plugins:\\s*\\[([^\\]]*)\\]/,\n (match, plugins) => {\n if (plugins.includes(pluginVarName)) return match;\n const newPlugins = plugins.trim()\n ? `${plugins.trim()}, ${pluginCall}`\n : pluginCall;\n return `plugins: [${newPlugins}]`;\n }\n );\n } else {\n // Add plugins array before output or at end of config\n content = content.replace(\n /(database:\\s*\\{[^}]+\\},?)/,\n `$1\\n plugins: [${pluginCall}],`\n );\n }\n } else {\n // Remove from plugins array (handle both factory calls \"name()\" and plain \"name\")\n // Handle \", pluginName()\" or \", pluginName\"\n content = content.replace(\n new RegExp(`,\\\\s*${pluginVarName}(?:\\\\([^)]*\\\\))?`, 'g'),\n ''\n );\n // Handle \"pluginName(),\" or \"pluginName,\"\n content = content.replace(\n new RegExp(`${pluginVarName}(?:\\\\([^)]*\\\\))?\\\\s*,`, 'g'),\n ''\n );\n // Handle standalone \"pluginName()\" or \"pluginName\" (last item in array)\n content = content.replace(\n new RegExp(`${pluginVarName}(?:\\\\([^)]*\\\\))?(?=\\\\s*\\\\])`, 'g'),\n ''\n );\n\n // Clean up empty plugins array\n content = content.replace(/plugins:\\s*\\[\\s*\\],?\\n?/, '');\n\n // Remove entire import line for this package (use importPath if available)\n const importFrom = knownPlugin?.importPath ?? packageName;\n const escapedImportFrom = importFrom.replace(/\\//g, '\\\\/');\n content = content.replace(\n new RegExp(`import\\\\s*\\\\{[^}]*\\\\}\\\\s*from\\\\s*['\"]${escapedImportFrom}['\"];?\\\\n?`),\n ''\n );\n }\n\n await writeFile(configPath, content, 'utf-8');\n return true;\n } catch (error) {\n console.error('Failed to update config:', error);\n return false;\n }\n}\n\n// GET /api/plugins - List all installed plugins\npluginsRouter.get('/', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n\n try {\n const plugins = await scanInstalledPlugins(appConfig.cwd);\n const enabledPackages = await getEnabledPlugins(appConfig.cwd);\n\n // Mark enabled plugins and fetch their configSchema + current config\n for (const plugin of plugins) {\n plugin.enabled = enabledPackages.includes(plugin.packageName);\n\n // Get configSchema from plugin (dynamically imported)\n const configSchema = await getPluginConfigSchema(plugin.packageName, appConfig.cwd);\n if (configSchema) {\n plugin.configSchema = configSchema;\n }\n\n // Get current config from omnify.config.ts\n if (plugin.enabled) {\n const config = await getPluginConfig(appConfig.cwd, plugin.packageName);\n plugin.config = config;\n }\n }\n\n const response: ApiResponse<PluginInfo[]> = {\n success: true,\n data: plugins,\n };\n res.json(response);\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'PLUGINS_SCAN_ERROR',\n message: error instanceof Error ? error.message : 'Failed to scan plugins',\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/plugins/:name/toggle - Enable/disable a plugin\npluginsRouter.post('/:name/toggle', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const { enabled } = req.body as { enabled: boolean };\n\n const packageName = `@famgia/omnify-${name}`;\n\n try {\n const success = await updatePluginConfig(appConfig.cwd, packageName, enabled);\n\n if (success) {\n const response: ApiResponse<{ enabled: boolean; restarting: boolean }> = {\n success: true,\n data: { enabled, restarting: true },\n };\n\n // Wait for response to be fully sent before restarting\n res.on('finish', () => {\n // Give client time to receive and process the response\n setTimeout(() => {\n restartServer(appConfig.cwd);\n }, 1000);\n });\n\n res.json(response);\n } else {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_UPDATE_ERROR',\n message: 'Failed to update omnify.config.ts',\n },\n };\n res.status(500).json(response);\n }\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'TOGGLE_ERROR',\n message: error instanceof Error ? error.message : 'Failed to toggle plugin',\n },\n };\n res.status(500).json(response);\n }\n});\n\n// POST /api/plugins/:name/config - Update plugin configuration\npluginsRouter.post('/:name/config', async (req: Request, res: Response) => {\n const appConfig = req.app.locals.config as AppConfig;\n const { name } = req.params;\n const { config } = req.body as { config: Record<string, unknown> };\n\n const packageName = `@famgia/omnify-${name}`;\n\n try {\n const success = await savePluginConfig(appConfig.cwd, packageName, config);\n\n if (success) {\n const response: ApiResponse<{ saved: boolean; restarting: boolean }> = {\n success: true,\n data: { saved: true, restarting: true },\n };\n\n // Wait for response to be fully sent before restarting\n res.on('finish', () => {\n // Give client time to receive and process the response\n setTimeout(() => {\n restartServer(appConfig.cwd);\n }, 1000);\n });\n\n res.json(response);\n } else {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_SAVE_ERROR',\n message: 'Failed to save plugin configuration',\n },\n };\n res.status(500).json(response);\n }\n } catch (error) {\n const response: ApiResponse = {\n success: false,\n error: {\n code: 'CONFIG_SAVE_ERROR',\n message: error instanceof Error ? error.message : 'Failed to save plugin configuration',\n },\n };\n res.status(500).json(response);\n }\n});\n","/**\n * WebSocket handler for real-time updates\n */\n\nimport { WebSocketServer, WebSocket } from 'ws';\nimport type { Server } from 'http';\nimport type { ServerEvent, ClientEvent } from '../../shared/events.js';\n\nexport interface WsHandler {\n broadcast: (event: ServerEvent) => void;\n close: () => void;\n}\n\nexport function createWsHandler(server: Server): WsHandler {\n const wss = new WebSocketServer({ server, path: '/ws' });\n const clients = new Set<WebSocket>();\n\n wss.on('connection', (ws: WebSocket) => {\n clients.add(ws);\n console.log(' WebSocket client connected');\n\n // Send ready event\n const readyEvent: ServerEvent = {\n type: 'connection:ready',\n payload: {\n schemasDir: process.env.SCHEMAS_DIR ?? 'schemas',\n schemaCount: 0,\n },\n };\n ws.send(JSON.stringify(readyEvent));\n\n ws.on('message', (data: Buffer) => {\n try {\n const event = JSON.parse(data.toString()) as ClientEvent;\n handleClientEvent(event, ws);\n } catch {\n console.error('Invalid WebSocket message');\n }\n });\n\n ws.on('close', () => {\n clients.delete(ws);\n console.log(' WebSocket client disconnected');\n });\n\n ws.on('error', (error: Error) => {\n console.error('WebSocket error:', error);\n clients.delete(ws);\n });\n });\n\n function handleClientEvent(_event: ClientEvent, _ws: WebSocket): void {\n // Handle client events (save, validate requests)\n // These are handled by the REST API, but could be used for\n // real-time validation feedback\n }\n\n function broadcast(event: ServerEvent): void {\n const message = JSON.stringify(event);\n for (const client of clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message);\n }\n }\n }\n\n function close(): void {\n for (const client of clients) {\n client.close();\n }\n wss.close();\n }\n\n return { broadcast, close };\n}\n","/**\n * File system watcher for schema changes\n */\n\nimport chokidar from 'chokidar';\nimport { basename } from 'path';\nimport { schemaService } from '../services/schemaService.js';\nimport type { WsHandler } from '../ws/handler.js';\nimport type { ServerEvent } from '../../shared/events.js';\n\nexport interface FileWatcher {\n close: () => void;\n}\n\nexport function createFileWatcher(schemasDir: string, wsHandler: WsHandler): FileWatcher {\n const watcher = chokidar.watch(`${schemasDir}/*.yaml`, {\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 200,\n pollInterval: 100,\n },\n });\n\n watcher.on('add', (filePath: string) => {\n console.log(` Schema added: ${basename(filePath)}`);\n void notifySchemaChange(filePath, 'file');\n });\n\n watcher.on('change', (filePath: string) => {\n console.log(` Schema changed: ${basename(filePath)}`);\n void notifySchemaChange(filePath, 'file');\n });\n\n watcher.on('unlink', (filePath: string) => {\n console.log(` Schema deleted: ${basename(filePath)}`);\n void notifyReload();\n });\n\n async function notifySchemaChange(\n filePath: string,\n source: 'file' | 'editor'\n ): Promise<void> {\n try {\n // Clear cache and reload\n schemaService.clearCache(schemasDir);\n const schemas = await schemaService.loadAll(schemasDir);\n\n // Find the changed schema\n const name = basename(filePath, '.yaml');\n const schema = schemas[name];\n\n if (schema) {\n const event: ServerEvent = {\n type: 'schema:changed',\n payload: { name, schema, source },\n };\n wsHandler.broadcast(event);\n }\n } catch (error) {\n console.error('Error notifying schema change:', error);\n }\n }\n\n async function notifyReload(): Promise<void> {\n try {\n schemaService.clearCache(schemasDir);\n const schemas = await schemaService.loadAll(schemasDir);\n\n const event: ServerEvent = {\n type: 'schemas:reloaded',\n payload: { schemas },\n };\n wsHandler.broadcast(event);\n } catch (error) {\n console.error('Error notifying reload:', error);\n }\n }\n\n return {\n close: () => watcher.close(),\n };\n}\n"],"mappings":"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","names":["join","resolve","join","schemasDir","response","Router","loadSchemas","resolveLocalizedString","schemasDir","Router","Router","loadSchemas","schemasDir","Router","response","Router","Router","Router","loadSchemas","writeFile","unlink","join","stringify","loadSchemas","changes","stringify","join","writeFile","unlink","Router","response","Router","readdir","writeFile","join","join","schemasDir","join","schemasDir","resolve"]}
|