Skip to content

Plugin metadata: let plugins declare name, description, and required config (export const meta) #615

Description

@melvincarvalho

Composability testing across the plugins collection (33 plugins) surfaced a pattern: the loader knows almost nothing about a plugin until activate() is already running, so every mismatch is discovered by crashing.

Observed while trial-composing on one server:

  • 20 of 33 plugins hard-require config (18 need config.baseUrl; terminal correctly refuses to boot an open shell without auth config). The only way to discover this is to boot and read the throw — and boot is fail-closed, so one missing config key = no server. It took four boot attempts to find a 13-plugin set that co-loads (which then ran conflict-free — isolation is in good shape; discoverability is the gap).
  • Identity is inferred, not declaredPlugin id derivation defeats the pod/plugin.js convention — every app derives id "pod" #614: the id comes from path heuristics, which the pod/plugin.js app-repo layout defeats.
  • The roster (api.plugins) carries only { id, prefix, module }, so meta-plugins like admin/dashboard can enumerate siblings but can't describe them.

Proposal: an optional exported meta object that plugins declare and the loader reads before calling activate():

export const meta = {
  name: 'gamestr',                     // stable id — solves #614 explicitly, no path heuristics
  description: 'Points system: bump / day aggregation / stream over hour files',
  version: '0.1.0',
  jss: '>=0.0.219',                    // engine compat range
  config: {                            // declared config surface
    baseUrl: { required: true,  description: 'Public origin for absolute URLs in feeds/JRDs' },
    token:   { required: false, description: 'Shared secret for privileged routes' },
  },
}

Loader behavior, all backwards-compatible (no meta = exactly today's behavior):

  1. Pre-activate validation — required config missing produces one precise boot error naming the plugin, the key, and its description (instead of whatever the plugin's own throw says), or a skip-with-warning if a lenient mode ever exists.
  2. meta.name wins over path derivation for the id — fixes Plugin id derivation defeats the pod/plugin.js convention — every app derives id "pod" #614 without guessing at generic directory names.
  3. Roster enrichmentapi.plugins entries carry description/version, so admin and dashboard can render a real catalog.
  4. Downstream, not now: a declared-metadata convention is the enabler for an install story (jspod install <repo> reading the meta before mounting) and compat checks — WordPress's plugin header (Plugin Name: … Requires at least: …) is the 20-year precedent: that one convention made its directory, installer, and compatibility matrix possible.

Alternatives considered: a WordPress-style comment header (parseable without importing the module — nice for registries, but the loader imports anyway) or a plugin.json sidecar (keeps metadata out of code, but splits the plugin across two files). The exported object is the most natural fit for ESM and is trivially optional.

Deliberately filed as a marker/discussion, not a mandate — plugin conventions are still in an experimentation phase and this should be shaped by more plugin-building experience.

Metadata

Metadata

Assignees

No one assigned

    Labels

    pluginCould be implemented as a plugin (#206); core/plugin line defined in #564

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions