Class Architecture - Incomplete-Infinity/eve-companion GitHub Wiki

🧠 Class Architecture

The EVE Companion App follows a modular class-based design, where each major data structure (e.g., a character, type, or system) is represented by a single class in its own file. This approach ensures clarity, separation of concerns, and scalability.


🗂️ Directory Structure

All core logic classes are stored in:

src/js/main/

Each file contains one class that corresponds to a game object or logical entity.

Examples:

  • InventoryType.js → Represents an item type from ESI
  • Character.js → Represents a pilot
  • System.js → Represents a solar system
  • Corporation.js → Represents a player corp

📚 Class Pattern

Each class:

  • Accepts a minimal identifier in the constructor (e.g., typeId, characterId)
  • Retrieves data from the ESI Swagger client
  • Enriches or reformats the data
  • Exposes it via instance properties
  • Optionally saves to local cache (Dexie)
export default class InventoryType {
  constructor(typeId, token) {
    this.typeId = typeId;
    this.token = token;
    this.name = null;
    this.description = null;
    this.groupId = null;
    this.loaded = false;
  }

  async load() {
    if (this.loaded) return;

    const api = new UniverseApi(new Configuration({
      accessToken: this.token,
      basePath: 'https://esi.evetech.net/latest'
    }));

    const { data } = await api.getUniverseTypesTypeId({ typeId: this.typeId });
    Object.assign(this, data);
    this.loaded = true;
  }
}

💡 Lazy Loading Strategy

To reduce API load and startup time:

  • Instances are created with IDs only
  • .load() or similar must be called to fetch details
  • Zustand and p-queue manage global request state and throttling

🔗 Connecting Classes

Many classes relate to each other. Example:

const type = new InventoryType(34, token);
await type.load();

const group = new InventoryGroup(type.groupId);
await group.load();

Future improvements will allow auto-linking via shared cache or context.


🌐 Frontend Integration

  • These classes live in the main/worker context (Node/Electron)
  • The renderer UI accesses data via messaging or shared IndexedDB
  • Zustand stores track current selection (e.g., activeCharacter, selectedFit)

🔍 Naming Conventions

  • Class names are PascalCase
  • Files are named to match the class
  • Methods like .load(), .toJSON(), .save() are standardized
  • Internal-only methods are prefixed with _ (e.g., _fetch())

⚡ Advanced Extensions (Planned)

  • Auto-cache with Dexie
  • Shared instance registry (Universe pattern)
  • Class inheritance for shared logic (e.g., CharacterContact)
  • Relationship mapping (e.g., Character.corporation as a Corporation instance)

🔄 Summary

This class-based architecture is central to the app. It provides:

  • Clean abstraction over ESI
  • Consistent lazy-loading and caching
  • A scalable structure for future features

Continue to: