UNPKG

cassandraorm-js

Version:

The most advanced ORM for Apache Cassandra and ScyllaDB with native TypeScript support, AI/ML integration, and enterprise-grade features

105 lines (84 loc) 3.15 kB
import { readdir } from 'fs/promises'; import { join, extname } from 'path'; import type { ModelSchema } from '../types.js'; import type { CassandraClient } from '../client.js'; export interface ModelFile { name: string; path: string; schema: ModelSchema; } export class ModelLoader { constructor(private client: CassandraClient) {} async loadModelsFromDirectory(directory: string): Promise<Map<string, any>> { const models = new Map(); const files = await this.scanDirectory(directory); for (const file of files) { if (this.isModelFile(file.name)) { const modelName = this.extractModelName(file.name); const modelModule = await import(file.path); const schema = modelModule.default || modelModule[`${modelName}Schema`] || modelModule.schema; if (schema) { const ModelClass = this.client.loadSchema(modelName, schema); models.set(modelName, ModelClass); } } } return models; } async syncModelsFromDirectory(directory: string): Promise<void> { const models = await this.loadModelsFromDirectory(directory); // Sync all models to database const syncPromises = Array.from(models.values()).map(Model => new Promise<void>((resolve, reject) => { if (Model.syncDB) { Model.syncDB((err?: Error) => { if (err) reject(err); else resolve(); }); } else { resolve(); } }) ); await Promise.all(syncPromises); } private async scanDirectory(directory: string): Promise<{ name: string; path: string }[]> { const files: { name: string; path: string }[] = []; try { const entries = await readdir(directory, { withFileTypes: true }); for (const entry of entries) { const fullPath = join(directory, entry.name); if (entry.isDirectory()) { const subFiles = await this.scanDirectory(fullPath); files.push(...subFiles); } else if (entry.isFile()) { files.push({ name: entry.name, path: fullPath }); } } } catch (error) { // Directory doesn't exist or can't be read } return files; } private isModelFile(fileName: string): boolean { const validExtensions = ['.js', '.ts', '.mjs', '.cjs']; const hasValidExtension = validExtensions.includes(extname(fileName)); const isModelFile = fileName.toLowerCase().includes('model'); return hasValidExtension && isModelFile; } private extractModelName(fileName: string): string { // Remove extension let name = fileName.replace(/\.[^/.]+$/, ''); // Remove 'Model' suffix if present name = name.replace(/Model$/i, ''); // Convert to lowercase for consistency return name.toLowerCase(); } static async bind(client: CassandraClient, directory: string): Promise<Map<string, any>> { const loader = new ModelLoader(client); await client.connect(); const models = await loader.loadModelsFromDirectory(directory); await loader.syncModelsFromDirectory(directory); return models; } }