Source: scripts/generate-types-from-cia-schemas.js

#!/usr/bin/env node

/**
 * @module Infrastructure/TypeGeneration
 * @category Infrastructure
 * 
 * @title CIA Schema Type Generator - TypeScript Type Safety Infrastructure
 * 
 * @description
 * **INTELLIGENCE OPERATIVE PERSPECTIVE**
 * 
 * This module generates TypeScript type definitions from CIA JSON schemas,
 * providing compile-time type safety for political data processing. While appearing
 * as a technical infrastructure task, type safety serves a critical intelligence
 * function: preventing data corruption bugs that could propagate incorrect
 * information through the analytical pipeline.
 * 
 * **TYPE SAFETY IN INTELLIGENCE SYSTEMS:**
 * Intelligence analysis depends on data accuracy. TypeScript type generation ensures:
 * 1. **Shape Validation**: Data matches expected structure before processing
 * 2. **Property Typos**: Catches misspelled field names at compile time
 * 3. **Type Mismatches**: Prevents treating numbers as strings or vice versa
 * 4. **Null Handling**: Explicit handling of optional vs. required fields
 * 5. **API Contract**: Ensures MCP tool responses match expected types
 * 
 * **CIA SCHEMA CONVERSION PROCESS:**
 * The generator converts JSON Schema → TypeScript types:
 * 1. Load JSON schema from schemas/cia/ directory
 * 2. Parse schema structure (properties, required fields, type constraints)
 * 3. Generate TypeScript interface with all properties
 * 4. Add JSDoc comments from schema descriptions
 * 5. Handle nested objects and arrays recursively
 * 6. Generate Union types for enum fields
 * 7. Write to types/ directory
 * 
 * **SUPPORTED SCHEMA CONVERSIONS:**
 * - **String Types**: Converted to TypeScript string
 * - **Number Types**: integer and number mapped appropriately
 * - **Boolean Types**: Converted to TypeScript boolean
 * - **Array Types**: Generated as T[] arrays
 * - **Nested Objects**: Recursive interface generation
 * - **Enum Types**: Union type generation (type field = 'value1' | 'value2')
 * - **Optional Fields**: Generated as property?: type notation
 * - **Date Fields**: ISO 8601 strings typed as string (runtime validation needed)
 * 
 * **GENERATED TYPE EXAMPLES:**
 * From CIA voting schema generates:
 * ```typescript
 * interface Vote {
 *   id: string;
 *   documentId: string;
 *   date: string; // ISO 8601
 *   topic: string;
 *   memberVotes: MemberVote[];
 *   totalYes: number;
 *   totalNo: number;
 *   totalAbstain: number;
 *   passed: boolean;
 * }
 * ```
 * 
 * **WORKFLOW:**
 * 1. Run during build process: `npm run generate-types-from-cia-schemas`
 * 2. Scans schemas/cia/ for all .schema.json files
 * 3. Generates corresponding TypeScript .d.ts files
 * 4. Reports success/failure for each schema
 * 5. Errors block build (type safety non-negotiable)
 * 
 * **SCHEMA EVOLUTION HANDLING:**
 * When CIA platform adds/removes schema fields:
 * 1. Developer manually updates schema files
 * 2. Type generation runs and creates new .d.ts
 * 3. TypeScript compiler finds references to removed fields
 * 4. Developer updates code to new schema
 * 5. Types are regenerated with updated definitions
 * 
 * **TYPESCRIPT COMPILATION INTEGRATION:**
 * Generated types used in compilation:
 * - `import type { Vote } from '../types/Vote'`
 * - Compiler validates against generated interface
 * - Prevents data shape mismatches at runtime
 * - IDE autocomplete from generated types
 * 
 * **OPTIONAL FEATURE:**
 * Type generation is optional - projects can use without types:
 * - Dynamic typing still works without generated types
 * - Benefits optional, not required
 * - Recommended for production systems
 * - Improves development velocity through IDE support
 * 
 * **PERFORMANCE CONSIDERATIONS:**
 * - Type generation: ~50ms per schema
 * - Compilation: Uses cached types if unchanged
 * - No runtime overhead (types erased during compilation)
 * - Improves IDE responsiveness through type information
 * 
 * **FAILURE MODES:**
 * - Invalid schema JSON: Detailed error identifying issue
 * - Unsupported schema features: Warning with fallback to any
 * - File write errors: Reports permission or disk issues
 * - Circular references: Detected and handled with type aliases
 * 
 * **GDPR COMPLIANCE:**
 * Generated types include personal data fields:
 * - Member names and IDs
 * - Department affiliations
 * - Vote patterns
 * - Committee assignments
 * Types help ensure proper data handling:
 * - Explicit marking of sensitive fields
 * - Runtime validation can check data classifications
 * - Type information supports audit requirements
 * 
 * **INTELLIGENCE APPLICATIONS:**
 * Type safety supports intelligence workflows:
 * - Analysts rely on accurate data shape for reports
 * - Prevents data corruption in analytical pipelines
 * - Enables automated data quality checking
 * - Supports integration testing across data systems
 * 
 * @osint Schema Integrity Monitoring
 * - Detects when CIA platform changes schema unexpectedly
 * - Generation failures alert to schema compatibility issues
 * - Type mismatches reveal integration problems
 * - Enables early detection of API changes
 * 
 * @risk Data Integrity Assurance
 * - Type checking prevents data shape errors
 * - Compile-time validation catches logic errors
 * - IDE support reduces runtime errors
 * - Build fails if types don't match data
 * 
 * @gdpr Data Classification Support
 * - Generated types can include data classification
 * - Sensitive fields explicitly marked
 * - Supports audit trail for data handling
 * - Runtime validation enforces data policies
 * 
 * @security Type-Based Security
 * - Prevents injection attacks through type constraints
 * - String types prevent code injection
 * - Enum types prevent unexpected value injection
 * - Object shape validation prevents prototype pollution
 * 
 * @author Hack23 AB (Data Infrastructure & Type Safety)
 * @license Apache-2.0
 * @version 2.0.0
 * @since 2024-06-15
 * @see https://json-schema-to-typescript.com/ (Type Generation Library)
 * @see schemas/cia/ (JSON Schema Definitions)
 * @see types/ (Generated TypeScript Definitions)
 * @see Issue #76 (Type Safety Enhancement)
 */

import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
import { compile } from 'json-schema-to-typescript';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

class CIATypeGenerator {
  constructor() {
    this.schemasDir = path.join(__dirname, '..', 'schemas', 'cia');
    this.typesDir = path.join(__dirname, '..', 'types');
    this.results = {
      generated: [],
      failed: []
    };
  }

  /**
   * Generate TypeScript types from a single schema
   */
  async generateTypesForSchema(schemaFile) {
    const schemaName = schemaFile.replace('.schema.json', '');
    console.log(`📝 Generating types for: ${schemaName}...`);
    
    try {
      const schemaPath = path.join(this.schemasDir, schemaFile);
      const schemaContent = await fs.readFile(schemaPath, 'utf8');
      const schema = JSON.parse(schemaContent);
      
      // Generate TypeScript types
      const types = await compile(schema, schemaName, {
        bannerComment: `/**
 * Auto-generated TypeScript types from CIA JSON Schema
 * Schema: ${schemaFile}
 * Generated: ${new Date().toISOString()}
 * 
 * DO NOT EDIT MANUALLY - This file is auto-generated
 * Run 'npm run generate-types' to regenerate
 */`,
        style: {
          semi: true,
          singleQuote: true,
          tabWidth: 2
        }
      });
      
      // Save types to file
      const typesPath = path.join(this.typesDir, `${schemaName}.d.ts`);
      await fs.writeFile(typesPath, types, 'utf8');
      
      console.log(`   ✅ Generated: ${schemaName}.d.ts`);
      this.results.generated.push(schemaName);
      
      return true;
    } catch (error) {
      console.error(`   ❌ Failed: ${schemaName} - ${error.message}`);
      this.results.failed.push({
        schema: schemaName,
        error: error.message
      });
      return false;
    }
  }

  /**
   * Generate types for all CIA schemas
   */
  async generateAllTypes() {
    console.log('📝 CIA Type Generation');
    console.log('='.repeat(50));
    console.log(`📁 Schemas directory: ${this.schemasDir}`);
    console.log(`📁 Types directory: ${this.typesDir}`);
    console.log('');

    // Ensure types directory exists
    await fs.mkdir(this.typesDir, { recursive: true });

    // Get all schema files
    let schemaFiles;
    try {
      const files = await fs.readdir(this.schemasDir);
      schemaFiles = files.filter(f => f.endsWith('.schema.json'));
    } catch (error) {
      console.error('❌ Could not read schemas directory');
      console.error('   Run "npm run sync-schemas" first to download schemas');
      return 1;
    }

    if (schemaFiles.length === 0) {
      console.log('⚠️  No schema files found');
      console.log('   Run "npm run sync-schemas" first to download schemas');
      return 1;
    }

    console.log(`📊 Found ${schemaFiles.length} schema file(s)`);
    console.log('');

    // Generate types for each schema
    for (const schemaFile of schemaFiles) {
      await this.generateTypesForSchema(schemaFile);
    }

    // Create index file
    await this.createIndexFile();

    // Print summary
    this.printSummary();

    // Return exit code
    return this.results.failed.length === 0 ? 0 : 1;
  }

  /**
   * Create index.d.ts that exports all types
   */
  async createIndexFile() {
    const imports = this.results.generated
      .map(name => `export * from './${name}';`)
      .join('\n');

    const indexContent = `/**
 * CIA Data Types - Index
 * Auto-generated from CIA JSON Schemas
 * Generated: ${new Date().toISOString()}
 * 
 * DO NOT EDIT MANUALLY
 */

${imports}
`;

    const indexPath = path.join(this.typesDir, 'index.d.ts');
    await fs.writeFile(indexPath, indexContent, 'utf8');
    
    console.log('');
    console.log('📦 Created index.d.ts');
  }

  /**
   * Print generation summary
   */
  printSummary() {
    console.log('');
    console.log('='.repeat(50));
    console.log('📊 Type Generation Summary');
    console.log('='.repeat(50));
    console.log(`✅ Generated: ${this.results.generated.length}`);
    console.log(`❌ Failed: ${this.results.failed.length}`);
    
    if (this.results.failed.length > 0) {
      console.log('');
      console.log('⚠️  Failed generations:');
      for (const failure of this.results.failed) {
        console.log(`   - ${failure.schema}: ${failure.error}`);
      }
    }
    
    console.log('');
    console.log(`📁 Types saved to: ${this.typesDir}`);
    console.log('='.repeat(50));
    console.log('');
    console.log('💡 Usage:');
    console.log('   import type { OverviewDashboard } from "./types/overview-dashboard";');
    console.log('   import type * as CIATypes from "./types";');
  }
}

// Main execution
async function main() {
  try {
    const generator = new CIATypeGenerator();
    const exitCode = await generator.generateAllTypes();
    process.exit(exitCode);
  } catch (error) {
    console.error('💥 Fatal error:', error);
    process.exit(1);
  }
}

// Run if called directly
if (import.meta.url === `file://${process.argv[1]}`) {
  main();
}

export default CIATypeGenerator;