演示

导出服务

如何从插件导出后端服务 / 实体,供其他插件安装 @quan-erp-plugins/<name>-backend,并用 @Inject(Service, "plugin-name") 注入。

概述

跨插件后端复用依赖「已发布包 + DI 作用域」。在 export.ts 导出稳定类,构建并发布 @quan-erp-plugins/<name>-backend,消费方安装后用 provider 的 metadata.name 注入。

  • 禁止直接导入其他插件的 backend/src/
  • 包名:@quan-erp-plugins/<name>-backend
  • @Inject(Service, "provider-name") — 第二参数必须等于 module.metadata.json 的 name
  • 在 pluginDependencies 中声明,确保 provider 先加载

1. 定义公开面(export.ts)

在 backend/src/export.ts 中只 re-export 稳定的服务、实体与类型。

  • Use .js extensions in relative re-exports (ESM build)
  • Prefer exporting @Service classes consumers will inject
  • Entity exports are optional — only when another plugin must type against them
  • Keep export.ts small; deep paths stay private
TSXbackend/src/export.ts
1// plugins/fleet-management/backend/src/export.ts 2 3export * from "./feature/driver/driver.service.js"; 4export * from "./feature/driver/driver.controller.js"; 5export * from "./schema/driver/driver.entity.js";

2. 构建与发布

运行 npm run build:export,再 npm run release:beta(或你们的 registry 发布流程)。

  • build:export — compile export.ts + dependencies into dist/
  • release:beta — publish to the internal / self-hosted npm registry with the beta tag
  • Align @quan-erp/* versions with the base stack before publishing
  • Consumers need a valid ~/.npmrc for the same registry
SHTerminal (provider plugin backend/)
cd plugins/fleet-management/backend npm run build:export npm run release:beta

3. 消费方 — 安装包

在消费方 backend 中安装 @quan-erp-plugins/<name>-backend。

  • Add the dependency to plugins/<consumer>/backend/package.json
  • Pin a compatible version range that matches what you tested
  • Do not copy service source files into the consumer plugin
SHTerminal (consumer plugin backend/)
cd plugins/my-plugin/backend npm install @quan-erp-plugins/fleet-management-backend

4. 消费方 — 注入

用 @Inject,并将 provider 的 metadata.name 作为第二参数。

  • Second argument MUST equal the provider’s module.metadata.json "name" (e.g. "fleet-management")
  • Omit the second argument only for services registered in the same plugin
  • Builtin platform services use ContainerRegistryManager.BUILTIN_PLUGIN instead of a plugin name
  • Call cross-plugin work from @OnAllModuleLoaded when you need every dependency module finished @OnInit
TSXconsumer service
1import { Service, Inject } from "@quan-erp/shared-backend-core"; 2import { FleetDriverManagementService } from "@quan-erp-plugins/fleet-management-backend"; 3 4@Service() 5export class MyService { 6 @Inject(FleetDriverManagementService, "fleet-management") 7 driverService: FleetDriverManagementService; 8 9 async doSomething() { 10 const drivers = await this.driverService.list(); 11 return drivers; 12 } 13}

5. 声明 pluginDependencies

在消费方 module.metadata.json 中写入 provider 名称与 semver 范围。

  • Keys are provider plugin names (folder / metadata.name), not npm package names
  • Values are semver ranges for the provider’s pluginVersion
  • Without this entry, DI may fail or load order may be wrong
JSONplugins/my-plugin/module.metadata.json
1{ 2 "name": "my-plugin", 3 "type": "", 4 "pluginVersion": "1.0.0", 5 "description": "Depends on fleet-management backend APIs", 6 "moduleEntryObject": "Module", 7 "requiredBasedVersion": "1.0.0", 8 "pluginDependencies": { 9 "fleet-management": "^1.0.0" 10 } 11}

清单

export.ts → build:export → publish → install → pluginDependencies → @Inject。

  • Provider: backend/src/export.ts re-exports public services / types
  • Provider: npm run build:export && npm run release:beta (or your registry publish flow)
  • Consumer: npm install @quan-erp-plugins/<name>-backend
  • Consumer: pluginDependencies includes the provider name + version range
  • Consumer: @Inject(Service, "<provider-metadata-name>")
  • Both plugins installed in the ERP and on a matching @quan-erp/* version line

常见失败

  • 直接导入其他插件 src
  • @Inject 的插件名错误
  • 缺少 pluginDependencies
  • 未发布或版本不一致