Module: Esp::Plugins

Defined in:
lib/esp/plugins.rb

Overview

The game-plugin registry. Each plugin (Esp::Mw today; future Esp::Ob, Esp::Sr) registers itself here at load time with a short ‘id` (the value that lands in a project’s ‘.espresso/project.json` `game:` field) and the modules the frontends need to reach into — its Operations façade today.

The shell composes its routes/tools against this registry, so the only thing tying the shell to a specific game is the project the user opens. Add a plugin: drop ‘lib/esp/<id>/`, call `Esp::Plugins.register` from its entry file, and add it to the load manifest.

Lookups are by id string; ‘default_id` names the plugin used when no project is open (today: the first registered, which is `mw` because the load manifest loads it first). Slice 2 wires Esp::Operations.dispatch through `Esp::Plugins.active_for(input)` so an op like `build` reaches the plugin matching the active project’s ‘game:` field rather than always Esp::Mw::Operations.

Defined Under Namespace

Classes: Entry

Class Method Summary collapse

Class Method Details

.active_for(input = {}) ⇒ Object

The plugin handling the current request. Order of precedence:

1. explicit `game:` in the input hash (lets the diff panel etc.
   target a specific plugin even when a project is open),
2. the active project's game (Esp::ActiveProject.game),
3. the default plugin (the only one for now; the fallback for
   ops invoked before any project is open — version, providers).

Unknown id raises so frontends surface a clear error.



48
49
50
51
# File 'lib/esp/plugins.rb', line 48

def active_for(input = {})
  id = (input.is_a?(Hash) && input['game']) || Esp::ActiveProject.game || default_id
  fetch(id)
end

.default_idObject



64
65
66
# File 'lib/esp/plugins.rb', line 64

def default_id
  registry.keys.first
end

.fetch(id) ⇒ Object



53
54
55
56
57
58
# File 'lib/esp/plugins.rb', line 53

def fetch(id)
  registry.fetch(id.to_s) do
    raise Esp::Operations::InputError,
          Esp.t('errors.plugins.unknown_game', game: id, known: ids.join(', '))
  end
end

.idsObject



60
61
62
# File 'lib/esp/plugins.rb', line 60

def ids
  registry.keys
end

.known?(id) ⇒ Boolean

True when ‘id` names a registered plugin. Cheap predicate for open_project to validate before storing on ActiveProject.

Returns:

  • (Boolean)


70
71
72
# File 'lib/esp/plugins.rb', line 70

def known?(id)
  registry.key?(id.to_s)
end

.register(id, label:, operations:) ⇒ Object

A plugin announces itself. ‘operations` is its Esp::*::Operations module (the game half of the service layer); `label` is the human-friendly name shown in error messages. Idempotent — a re-load in tests just rebinds the same entry.



35
36
37
38
39
# File 'lib/esp/plugins.rb', line 35

def register(id, label:, operations:)
  @mutex.synchronize do
    registry[id.to_s] = Entry.new(id: id.to_s, label: label, operations: operations)
  end
end

.registryObject

The id → Entry map, lazily initialized and populated by plugins at load time. Mutable hash (like Esp::Providers.registry) because the plugin set isn’t known until every require finishes.



27
28
29
# File 'lib/esp/plugins.rb', line 27

def registry
  @registry ||= {}
end