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
No fields configured for Feature.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions