Ever Gauzy 职位搜索插件(@gauzy/plugin-job-search)实战指南:构建、测试、发布与集成原理
Ever Gauzy 职位搜索插件(@gauzy/plugin-job-search)实战指南:构建、测试、发布与集成原理
导读
@gauzy/plugin-job-search 是 Ever Gauzy 开放业务管理平台(ERP/CRM/HRM/ATS/PM)中的职位搜索(Job Search)插件,为求职者与雇主双方提供职位检索、匹配与申请能力。本文以插件官方 README(packages/plugins/job-search/README.md)为核心骨架,结合仓库源码深入讲解其安装、构建、单元测试、发布流程,以及背后基于 NestJS、CQRS 与 Gauzy AI 的匹配实现原理,帮助你将该插件正确集成到自己的 Gauzy 部署中。
插件定位与功能概览
面向双方的一站式职位工具
根据 README 概述,该插件被定位为"增强职位搜索体验的强大工具",无论使用者是求职者还是雇主,都能借助它简化流程、提升效率。它对外公开的两大核心特性包括:
- 高级搜索(Advanced Search):利用高级筛选条件查找符合个人偏好的职位列表;
- 职位提醒(Job Alerts):设置职位提醒,当出现符合条件的新职位时接收通知。
在 package.json 的 keywords 中,插件被标注为 job-search、recruitment、employment、NestJS、microservices 等,可见其定位是一个部署在服务端、面向招聘与求职场景的 NestJS 微服务模块。
插件在整个平台中的角色
从 project.json 可以确认,它是一个 type:plugin 类型的 Nx 库,且声明了隐式依赖:common、config、contracts、core、plugin、plugin-integration-ai、utils。这意味着插件深度复用了 Gauzy 核心包、契约类型定义,以及 Gauzy AI 集成插件——职位匹配的核心逻辑正是交由 Gauzy AI 服务完成的(下文详述)。
环境要求与依赖
在安装和构建前,请先确认运行环境满足 package.json 中声明的引擎要求:
| 项目 | 要求 |
|---|---|
| Node.js | >=22 |
| Yarn | >=1.22 |
| 运行时 peer 依赖 | @nestjs/common ^11.1.26、@nestjs/core ^11.1.26 |
主要运行时依赖还包括:@gauzy/common、@gauzy/config、@gauzy/contracts、@gauzy/core、@gauzy/plugin、@gauzy/plugin-integration-ai、@mikro-orm/nestjs、@nestjs/cqrs、@nestjs/swagger、@nestjs/typeorm、html-to-text、class-validator 等。其中 @nestjs/cqrs 用于命令/查询总线,html-to-text 用于将职位申请提案的 HTML 内容转为纯文本(见 employee-job.service.ts)。
安装插件
根据 README 安装章节,在终端中执行以下任一命令即可安装:
npm install @gauzy/plugin-job-search
# 或
yarn add @gauzy/plugin-job-search
注:当前仓库内该包标记为
"private": true(见 package.json),因此其发布版@gauzy/plugin-job-search面向 npm 上的公开发行版本。在仓库内本地联调时,也可通过工作区直接引用源码库。
构建插件库
使用 Nx 构建
README 构建章节 给出的构建命令是:
yarn nx build plugin-job-search
该命令由 project.json 中的 build target 驱动,采用 @nx/js:tsc 执行器,关键配置如下:
- 输出目录:
dist/packages/plugins/job-search; - TypeScript 配置:tsconfig.lib.json;
- 入口文件:
packages/plugins/job-search/src/index.ts; - 资源拷贝:将
packages/plugins/job-search/*.md(即 README、CHANGELOG 等文档)一并复制到产物目录; - 依赖顺序:
dependsOn: ["^build"],会先构建其依赖库(common、core、plugin-integration-ai 等)。
仓库内 package.json 还提供了三个便捷脚本,与 Nx 命令等价:
"scripts": {
"lib:build": "yarn nx build plugin-job-search",
"lib:build:prod": "yarn nx build plugin-job-search",
"lib:watch": "yarn nx build plugin-job-search --watch"
}
lib:build/lib:build:prod:普通构建与生产构建;lib:watch:开启 watch 模式,源码变更时增量编译,适合开发调试。
构建产物的清单入口(main)指向 ./src/index.js,类型声明为 ./src/index.d.ts(见 package.json)。
插件的公开 API 面
插件的唯一公开导出在 src/index.ts:
export * from './lib/job-search.plugin';
也就是说,使用方只需引入 JobSearchPlugin 类并将其注册进 Gauzy 应用即可。其内部结构(employee-job、employee-job-preset 两个子模块)均为实现细节,不对外暴露。
运行单元测试
README 测试章节 给出的测试命令为:
yarn nx test plugin-job-search
测试通过 Jest:
module.exports = {
displayName: 'plugin-job-search',
preset: '../../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }]
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../../coverage/packages/plugins/job-search'
};
要点说明:
testEnvironment: 'node':该插件是纯服务端库,测试运行在 Node 环境而非 jsdom;- 使用
ts-jest配合 tsconfig.spec.json 编译 TypeScript; - 覆盖率报告输出至
coverage/packages/plugins/job-search。
在 project.json 中,test target 使用 @nx/jest:jest 执行器,并同样输出覆盖率到 coverage/{projectRoot}。
发布到 npm
README 发布章节 给出了发布步骤:
- 先执行构建:
yarn nx build plugin-job-search; - 进入产物目录:
dist/packages/plugins/job-search; - 执行发布:
npm publish。
由于构建 target 配置了 assets: <a href="https://link.gitcode.com/i/ece6d9cc203199efe185c5ab7d8a5047" target="_blank">"packages/plugins/job-search/*.md"],发布包中会携带 README 与 CHANGELOG 文档。仓库侧还通过 [project.json 的 nx-release-publish target 支持 Nx 的发布流程,发布根目录同样指向 dist/{projectRoot},版本号通过 git tag 解析(currentVersionResolver: "git-tag")。发布前请按需修改 package.json 中的 version 字段(当前为 0.1.0)。
源码级原理:插件如何工作
插件生命周期与种子数据
JobSearchPlugin(见 job-search.plugin.ts)实现了 IOnPluginBootstrap、IOnPluginDestroy、IOnPluginSeedable 三个生命周期接口,通过 @Plugin() 装饰器声明其构成:
@Plugin({
imports: [EmployeeJobPostModule, EmployeeJobPresetModule, SeederModule],
entities: [...entities],
configuration: (config: ApplicationPluginConfig) => {
config.customFields.Employee.push({
name: 'jobPresets',
type: 'relation',
relationType: 'many-to-many',
pivotTable: 'employee_job_preset',
joinColumn: 'jobPresetId',
inverseJoinColumn: 'employeeId',
entity: JobPreset,
inverseSide: (it: JobPreset) => it.employees
});
return config;
},
providers: [JobSeederService]
})
export class JobSearchPlugin implements IOnPluginBootstrap, IOnPluginDestroy, IOnPluginSeedable
- 生命周期钩子:
onPluginBootstrap/onPluginDestroy分别在插件启动、销毁时通过 chalk 输出绿色/红色日志; - 自定义字段:插件启动时向
Employee实体注入jobPresets多对多关系字段,中间表为employee_job_preset,关联JobPreset实体——这是职位预设(Preset)与员工关联的底层机制; - 种子数据:
onPluginDefaultSeed调用JobSeederService.seedDefaultJobsData(),写入默认职位搜索类别与职业类别(详见 job-seeder.service.ts);onPluginRandomSeed则预留随机数据填充逻辑。
entities 数组(来自 employee-job-preset.module.ts)包含五个实体:JobPreset、JobPresetUpworkJobSearchCriterion、EmployeeUpworkJobsSearchCriterion、JobSearchOccupation、JobSearchCategory,它们构成职位预设、筛选条件、职业类别与搜索类别的数据模型。
两个子模块:职位发布与职位预设
插件内部拆分为两个 NestJS 模块:
1. EmployeeJobPostModule(employee-job.module.ts)
负责"员工—职位"匹配业务,导入 EmployeeModule、IntegrationTenantModule、TenantModule、RolePermissionModule、GauzyAIModule.forRoot() 与 CqrsModule,注册了 EmployeeJobPostController、EmployeeJobPostService 以及一组命令/查询处理器。
2. EmployeeJobPresetModule(employee-job-preset.module.ts)
负责职位搜索预设(Preset)体系,同时注册 TypeORM 与 MikroORM 两套实体特性(TypeOrmModule.forFeature 与 MikroOrmModule.forFeature),暴露四个控制器:JobSearchOccupationController、JobSearchCategoryController、EmployeePresetController、JobSearchPresetController,并向外部导出 JobPresetService、JobSearchCategoryService、JobSearchOccupationService。
职位 API 端点一览
EmployeeJobPostController 挂载于 /employee-job 路径,全部端点受 TenantPermissionGuard 与 PermissionGuard 保护,并按权限细分:
| HTTP 方法与路径 | 权限 | 用途 |
|---|---|---|
GET /employee-job/ |
ORG_JOB_SEARCH |
分页查询员工职位列表 |
GET /employee-job/statistics |
ORG_JOB_EMPLOYEE_VIEW |
员工职位统计 |
PUT /employee-job/:id/job-search-status |
ORG_EMPLOYEES_EDIT、PROFILE_EDIT |
更新员工职位搜索状态 |
POST /employee-job/apply |
ORG_JOB_APPLY |
申请职位 |
POST /employee-job/updateApplied |
ORG_JOB_APPLY |
更新申请状态 |
POST /employee-job/hide |
ORG_JOB_EDIT |
隐藏/恢复职位可见性 |
POST /employee-job/pre-process |
ORG_JOB_APPLY |
创建职位申请预记录 |
GET /employee-job/application/:employeeJobApplicationId |
ORG_JOB_APPLY |
获取 AI 生成的申请提案 |
POST /employee-job/generate-proposal/:employeeJobApplicationId |
ORG_JOB_APPLY |
生成 AI 申请提案 |
代码风格上,命令类操作(如更新搜索状态)通过 CommandBus 派发 CQRS 命令,查询类操作(如统计)通过 QueryBus 派发查询,服务层则承担与 Gauzy AI 的实际交互。
与 Gauzy AI 的协作:高级搜索与职位提醒的底层支撑
高级搜索与职位提醒是 README 宣传的两大特性,它们在源码中主要由 EmployeeJobPostService 与 Gauzy AI 集成插件协同实现:
- 职位匹配:
findAll方法首先通过EmployeeService.findAllActive()获取活跃员工,再检测配置项env.gauzyAIGraphQLEndpoint(来自@gauzy/config)是否可用;若可用,则校验GAUZY_AI集成与JOB_MATCHING实体同步状态,最终调用GauzyAIService.getEmployeesJobPosts(data)获取匹配职位。若用户缺少CHANGE_SELECTED_EMPLOYEE权限,则自动将筛选范围限定为当前员工 ID——从源码结构看,这是权限控制与数据隔离的默认策略。 - 职位申请:
apply方法先将proposal字段中的 HTML 通过html-to-text转为无换行纯文本,再交给 Gauzy AI 服务执行申请。 - 可见性与申请状态:
updateVisibility、updateApplied均直接委托GauzyAIService,对应"隐藏职位"与"标记已申请"两个动作,其中是否针对单个员工生效取决于请求中是否携带employeeId。
可见,该插件的定位是一个"厚集成层":对外提供 REST API 与数据模型,对内将职位匹配、申请等重活委托给 Gauzy AI 服务,这与 project.json 中声明的 plugin-integration-ai 隐式依赖完全吻合。
预设(Preset)体系与种子数据
职位预设体系让雇主可批量定义搜索偏好:JobPreset 与 JobPresetUpworkJobSearchCriterion、EmployeeUpworkJobsSearchCriterion 实体用于存储预设及其 Upwork 搜索条件,JobSearchCategory、JobSearchOccupation 提供类别与职业维度。配套的命令处理器(见 commands/handlers)包括 CreateJobPresetHandler、SaveEmployeePresetHandler、SaveEmployeeCriterionHandler、SavePresetCriterionHandler,覆盖预设创建、员工预设保存、员工条件保存、预设条件保存等场景。
默认数据方面,JobSeederService.seedDefaultJobsData()(job-seeder.service.ts)在插件默认种子阶段执行,通过 createDefaultJobSearchCategories 与 createDefaultJobSearchOccupations(定义于 job-search-category.seed.ts 与 job-search-occupation.seed.ts)写入默认类别与职业数据,并区分生产与非生产环境的日志输出。
常见问题与注意事项
- 构建失败先查依赖:由于
buildtarget 带有dependsOn: ["^build"],一次构建会级联编译 common、core、plugin-integration-ai 等上游库,耗时较长属正常现象; - 测试环境为 Node:插件不含任何浏览器相关代码,测试必须运行在
testEnvironment: 'node'下; - 职位匹配依赖 Gauzy AI:若未配置
gauzyAIGraphQLEndpoint或未建立GAUZY_AI集成与JOB_MATCHING实体同步,findAll将退化为仅返回本地员工列表(见 employee-job.service.ts),无法获得 AI 匹配职位; - 发布前版本管理:仓库内该包为
private,正式对外发布需先在 npm 上具备@gauzy/plugin-job-search的发布权限,并按 project.json 的 release 配置管理版本号。
参考文件索引
- 官方说明:packages/plugins/job-search/README.md
- 包元数据:packages/plugins/job-search/package.json
- Nx 工程配置:packages/plugins/job-search/project.json
- 插件入口与生命周期:src/index.ts、job-search.plugin.ts
- 职位匹配模块:employee-job.module.ts、employee-job.controller.ts、employee-job.service.ts
- 职位预设模块:employee-job-preset.module.ts、job-seeder.service.ts
- 测试配置:jest.config.ts