# All files / framework/core ModelRegistry.ts

0% Statements 0/38
0% Branches 0/35
0% Functions 0/14
0% Lines 0/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105

     import { BaseModel } from '../models/BaseModel';
    import { ModelConfig } from '../types/models';
    import { StoreType } from '../types/framework';

    export class ModelRegistry {
      private static models: Map<string, typeof BaseModel> = new Map();
      private static configs: Map<string, ModelConfig> = new Map();

      static register(name: string, modelClass: typeof BaseModel, config: ModelConfig): void {
        this.models.set(name, modelClass);
        this.configs.set(name, config);

        // Validate model configuration
        this.validateModel(modelClass, config);

        console.log(`Registered model: ${name} with scope: ${config.scope || 'global'}`);
      }

      static get(name: string): typeof BaseModel | undefined {
        return this.models.get(name);
      }

      static getConfig(name: string): ModelConfig | undefined {
        return this.configs.get(name);
      }

      static getAllModels(): Map<string, typeof BaseModel> {
        return new Map(this.models);
      }

      static getUserScopedModels(): Array<typeof BaseModel> {
        return Array.from(this.models.values()).filter((model) => model.scope === 'user');
      }

      static getGlobalModels(): Array<typeof BaseModel> {
        return Array.from(this.models.values()).filter((model) => model.scope === 'global');
      }

      static getModelNames(): string[] {
        return Array.from(this.models.keys());
      }

      static clear(): void {
        this.models.clear();
        this.configs.clear();
      }

      private static validateModel(modelClass: typeof BaseModel, config: ModelConfig): void {
        // Validate model name
        if (!modelClass.name) {
          throw new Error('Model class must have a name');
        }

        // Validate database type
        if (config.type && !this.isValidStoreType(config.type)) {
          throw new Error(`Invalid store type: ${config.type}`);
        }

        // Validate scope
        if (config.scope && !['user', 'global'].includes(config.scope)) {
          throw new Error(`Invalid scope: ${config.scope}. Must be 'user' or 'global'`);
        }

        // Validate sharding configuration
        if (config.sharding) {
          this.validateShardingConfig(config.sharding);
        }

        // Validate pinning configuration
        if (config.pinning) {
          this.validatePinningConfig(config.pinning);
        }

        console.log(`✓ Model ${modelClass.name} configuration validated`);
      }

      private static isValidStoreType(type: StoreType): boolean {
        return ['eventlog', 'keyvalue', 'docstore', 'counter', 'feed'].includes(type);
      }

      private static validateShardingConfig(config: any): void {
        if (!config.strategy || !['hash', 'range', 'user'].includes(config.strategy)) {
          throw new Error('Sharding strategy must be one of: hash, range, user');
        }

        if (!config.count || config.count < 1) {
          throw new Error('Sharding count must be a positive number');
        }

        if (!config.key) {
          throw new Error('Sharding key is required');
        }
      }

      private static validatePinningConfig(config: any): void {
        if (config.strategy && !['fixed', 'popularity', 'tiered'].includes(config.strategy)) {
          throw new Error('Pinning strategy must be one of: fixed, popularity, tiered');
        }

        if (config.factor && (typeof config.factor !== 'number' || config.factor < 1)) {
          throw new Error('Pinning factor must be a positive number');
        }
      }
    }