Overview
Every plugin must ship module.metadata.json at the plugin root. Folder name, metadata.name, and package identity must match. The same file is copied into available-plugins and installed-plugins builds.
- Path — plugins/<plugin-name>/module.metadata.json
- Used by @Module({ name: metadata.name }), DI scopes, and install UI
- pluginDependencies control boot / register order
1. Fields
| Field | Type | Purpose |
|---|---|---|
| name | string | Unique plugin id — must match folder name |
| type | string | Reserved (often "") |
| pluginVersion | string | This plugin’s semver |
| description | string | Short summary for module / install UI |
| moduleEntryObject | string | Backend entry export name (usually "Module") |
| requiredBasedVersion | string | Minimum compatible core / @quan-erp/* base line |
| pluginDependencies | object | Map of other plugin names → semver ranges that must load first |
2. Example
JSONplugins/inventory/module.metadata.json
1{
2 "name": "inventory",
3 "type": "",
4 "pluginVersion": "1.0.0",
5 "description": "Inventory management system",
6 "moduleEntryObject": "Module",
7 "requiredBasedVersion": "1.0.0",
8 "pluginDependencies": {
9 "products": "^1.0.0",
10 "accounting": "^1.0.0"
11 }
12}3. pluginDependencies
Keys are provider metadata.name values (not npm package names). Values are semver ranges for the provider’s pluginVersion. The core loads providers before dependents and refuses to start if a required dependency is missing or incompatible.
- Declare a dependency when you @Inject(Service, "other-plugin") or reuse exported APIs
- Empty {} means no plugin deps — core builtins remain available
- Keep ranges in sync when you bump a provider’s pluginVersion
- See How it works → Module dependencies and Export services
Rules
- name === folder name under plugins/
- Align requiredBasedVersion with the running core line
- Import metadata with { type: "json" } in backend / frontend entry files
- After rename or version bump, rebuild and re-install so installed-plugins picks up the new file