Skip to content

Overhaul ES6 Class Implementations #37

@seansica

Description

@seansica

Problem

The current ES6 class implementations (*Impl classes) in src/classes/[sdo, smo, sro, common]/ are sparse and require several TypeScript linting suppressions. The current approach uses interface declaration merging to extend STIX objects, which is not ideal:

/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */

export class AnalyticImpl extends AttackBaseImpl implements Analytic {
  constructor(readonly analytic: Analytic) {
    super();
    Object.assign(this, analytic);
  }
}

// Suppress the lint error for the empty interface
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface AnalyticImpl extends Analytic {}

/* eslint-enable @typescript-eslint/no-unsafe-declaration-merging */

Issues with current approach:

  • Requires multiple linting error suppressions
  • Uses interface declaration merging as a workaround
  • Lacks comprehensive relationship management
  • Missing domain-specific utility methods

Proposed Solution

Replace the current implementation pattern with a more robust approach using a Validated base class that leverages Zod schemas for type safety:

New Architecture

  1. Schema-based validation: Classes extend Validated(schema) to inherit validated properties from Zod schemas
  2. Private relationship tracking: Use private fields (#property) for mutable relationship state
  3. Comprehensive API: Add domain-specific methods for relationship management and utility operations
  4. Type safety: Eliminate need for linting suppressions and declaration merging

Example Implementation

export class TechniqueImpl extends Validated(techniqueSchema) {
  // Relationship tracking (mutable, not part of JSON data)
  #subTechniques: TechniqueImpl[] = [];
  #tactics: TacticImpl[] = [];
  #mitigations: MitigationImpl[] = [];
  #parentTechnique?: TechniqueImpl;
  // ... other relationships

  // Relationship management
  addSubTechnique(subTechnique: TechniqueImpl): void {
    if (!this.#subTechniques.includes(subTechnique)) {
      this.#subTechniques.push(subTechnique);
    }
  }

  getSubTechniques(): readonly TechniqueImpl[] {
    return [...this.#subTechniques];
  }

  // Domain-specific utilities
  getAttackId(): string | undefined {
    return this.external_references?.[0]?.external_id;
  }

  getDisplayName(): string {
    const attackId = this.getAttackId();
    return attackId ? `${attackId}: ${this.name}` : this.name;
  }

  supportsPlatform(platform: string): boolean {
    return this.x_mitre_platforms?.includes(platform as XMitrePlatform) ?? false;
  }

  // Immutable updates
  with(updates: Partial<TechniqueImpl>): TechniqueImpl {
    const newData = { ...this, ...updates };
    return new TechniqueImpl(newData);
  }
}

Benefits

  • No linting suppressions needed: Clean TypeScript without workarounds
  • Better encapsulation: Private fields for relationship state management
  • Rich API: Domain-specific methods for common operations
  • Type safety: Schema-based validation ensures data integrity
  • Relationship management: Built-in support for navigating object relationships via SROs
  • Immutable patterns: Support for functional updates with with() and touch() methods

Implementation Plan

  1. Create Validated base class that accepts Zod schema parameter
  2. Refactor existing *Impl classes to use new pattern
  3. Add comprehensive relationship management methods
  4. Implement domain-specific utility methods for each object type
  5. Update relationship processing logic to populate private relationship fields
  6. Remove all linting suppressions and declaration merging interfaces

Acceptance Criteria

  • All *Impl classes use Validated base class approach
  • Zero TypeScript linting suppressions in class implementations
  • Comprehensive relationship management APIs
  • Domain-specific utility methods for each object type
  • SRO processing populates relationship fields for easy navigation
  • All existing functionality preserved
  • Type safety maintained throughout

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions