BREAKING CHANGE: Generated plugin indexes now export `plugins` as an array
of `[app_name, module_namespace]` tuples instead of re-exporting individual
classes directly.
This enables a new deployment model:
1. The transpiler discovers JavaScript in `static/js/plugins/<type>/` from
ALL Python packages on `sys.path` — not only `INSTALLED_APPS`.
2. Every plugin is compiled into the bundle, but core pages filter at runtime
via `this.app.settings.APPS.includes(app)` before instantiating anything.
3. A single bundle can be built during packaging (CI, Debian, Docker) and
shipped to production. End users enable/disable bundled plugins by editing
`INSTALLED_APPS` without ever running the transpiler on the server.
Migration for consumer code:
- Old: `import * as plugins from "../../plugins/type"` + `Object.keys(plugins).forEach(...)`
- New: `import {plugins} from "../../plugins/type"` + `plugins.forEach(([app, plugin]) => { if (!this.app.settings.APPS.includes(app)) return; ... })`
Other changes:
- `InstalledAppDirectoriesFinder` walks all discoverable Python packages.
- `AllAppsFinder` merges Django static finders with the new finder.
- Plugin deduplication prevents the same module from being registered twice.
- Legacy `init.js` placeholders are still ignored but no longer required.
Documentation:
- README.md now has a dedicated "Plugins" section explaining discovery,
index generation, runtime filtering, and the packaging workflow.