From 65d23eab4ac79f379677c88dcf6492019bb3b1bc Mon Sep 17 00:00:00 2001 From: g1307092382 <1307092382@qq.com> Date: Thu, 13 Aug 2026 17:17:33 +0800 Subject: [PATCH] feat(finance): add financial disclosure publishing --- apps/admin-web/package.json | 2 + apps/admin-web/src/App.vue | 11 + .../src/api/financial-disclosures.ts | 43 ++ apps/admin-web/src/financial-document.spec.ts | 10 + apps/admin-web/src/financial-document.ts | 17 + apps/admin-web/src/mammoth-browser.d.ts | 11 + apps/admin-web/src/styles.css | 151 +++++++ .../src/views/FinancialDisclosuresView.vue | 380 ++++++++++++++++++ apps/api/package.json | 4 +- .../migration.sql | 53 +++ apps/api/prisma/schema.prisma | 53 +++ apps/api/src/app.module.ts | 2 + .../dto/financial-disclosure.dto.ts | 38 ++ .../financial-disclosures.controller.ts | 91 +++++ .../financial-disclosures.module.ts | 13 + .../financial-disclosures.service.ts | 341 ++++++++++++++++ apps/api/test/auth.integration-spec.ts | 2 + .../test/case-management.integration-spec.ts | 2 + .../content-notifications.integration-spec.ts | 2 + .../financial-disclosures.integration-spec.ts | 156 +++++++ apps/api/test/follow-ups.integration-spec.ts | 2 + .../test/participation.integration-spec.ts | 2 + .../service-applications.integration-spec.ts | 2 + apps/miniprogram/miniprogram/app.json | 4 +- .../financial-disclosure-detail.json | 1 + .../financial-disclosure-detail.ts | 24 ++ .../financial-disclosure-detail.wxml | 1 + .../financial-disclosure-detail.wxss | 55 +++ .../financial-disclosures.json | 1 + .../financial-disclosures.ts | 26 ++ .../financial-disclosures.wxml | 1 + .../financial-disclosures.wxss | 74 ++++ .../pages/public-welfare/public-welfare.ts | 3 + .../pages/public-welfare/public-welfare.wxml | 2 +- .../services/financial-disclosures.ts | 13 + apps/miniprogram/scripts/check-pages.mjs | 2 + docs/02_PRODUCT_PRD_V1.md | 8 + docs/04_DATA_MODEL.md | 15 + docs/05_API_AND_WORKFLOW.md | 19 + docs/06_SECURITY_PRIVACY.md | 7 + docs/07_UI_UX.md | 8 + docs/09_TEST_ACCEPTANCE.md | 10 + docs/10_TASK_STATE.md | 14 + docs/11_DECISIONS.md | 14 + packages/contracts/src/auth.ts | 3 + .../contracts/src/financial-disclosures.ts | 55 +++ packages/contracts/src/index.ts | 14 + pnpm-lock.yaml | 336 ++++++++++++++++ pnpm-workspace.yaml | 1 + 49 files changed, 2096 insertions(+), 3 deletions(-) create mode 100644 apps/admin-web/src/api/financial-disclosures.ts create mode 100644 apps/admin-web/src/financial-document.spec.ts create mode 100644 apps/admin-web/src/financial-document.ts create mode 100644 apps/admin-web/src/mammoth-browser.d.ts create mode 100644 apps/admin-web/src/views/FinancialDisclosuresView.vue create mode 100644 apps/api/prisma/migrations/20260813150000_financial_disclosures/migration.sql create mode 100644 apps/api/src/financial-disclosures/dto/financial-disclosure.dto.ts create mode 100644 apps/api/src/financial-disclosures/financial-disclosures.controller.ts create mode 100644 apps/api/src/financial-disclosures/financial-disclosures.module.ts create mode 100644 apps/api/src/financial-disclosures/financial-disclosures.service.ts create mode 100644 apps/api/test/financial-disclosures.integration-spec.ts create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosure-detail/financial-disclosure-detail.json create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosure-detail/financial-disclosure-detail.ts create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosure-detail/financial-disclosure-detail.wxml create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosure-detail/financial-disclosure-detail.wxss create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.json create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.ts create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.wxml create mode 100644 apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.wxss create mode 100644 apps/miniprogram/miniprogram/services/financial-disclosures.ts create mode 100644 packages/contracts/src/financial-disclosures.ts diff --git a/apps/admin-web/package.json b/apps/admin-web/package.json index 39715b8..01cdb99 100644 --- a/apps/admin-web/package.json +++ b/apps/admin-web/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@lehuo/contracts": "workspace:*", + "dompurify": "^3.4.13", + "mammoth": "^1.12.1", "pinia": "^3.0.3", "vue": "^3.5.20", "vue-router": "^4.5.1" diff --git a/apps/admin-web/src/App.vue b/apps/admin-web/src/App.vue index 2b107d3..f0af4f8 100644 --- a/apps/admin-web/src/App.vue +++ b/apps/admin-web/src/App.vue @@ -17,6 +17,7 @@ import NotificationDeliveriesView from './views/NotificationDeliveriesView.vue'; import StatisticsView from './views/StatisticsView.vue'; import DashboardView from './views/DashboardView.vue'; import AdminIcon from './components/AdminIcon.vue'; +import FinancialDisclosuresView from './views/FinancialDisclosuresView.vue'; const auth = useAuthStore(); const form = reactive({ username: '', password: '' }); @@ -36,6 +37,7 @@ const activeView = ref< | 'content' | 'notifications' | 'statistics' + | 'financial-disclosures' >('dashboard'); onMounted(() => auth.restore()); @@ -171,6 +173,14 @@ async function logout(): Promise { > 内容发布 + 暂无公开文档财务公开文档发布后会展示在这里。 diff --git a/apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.wxss b/apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.wxss new file mode 100644 index 0000000..bb0ecb6 --- /dev/null +++ b/apps/miniprogram/miniprogram/pages/financial-disclosures/financial-disclosures.wxss @@ -0,0 +1,74 @@ +@import '../../app.wxss'; +.financial-hero { + padding: 40rpx 34rpx; + border-radius: 28rpx; + background: linear-gradient(135deg, #ff6b35, #ff9b5f); + color: #fff; + box-shadow: 0 18rpx 40rpx rgba(240, 90, 40, 0.18); +} +.financial-hero text, +.financial-card text { + display: block; +} +.financial-hero__eyebrow { + font-size: 24rpx; + opacity: 0.86; +} +.financial-hero__title { + margin-top: 8rpx; + font-size: 46rpx; + font-weight: 700; +} +.financial-hero__copy { + margin-top: 14rpx; + line-height: 1.65; +} +.financial-card { + width: 100%; + margin-top: 24rpx; + padding: 30rpx; + border: 0; + border-radius: 24rpx; + background: #fff; + text-align: left; + box-shadow: 0 8rpx 28rpx rgba(38, 42, 48, 0.07); +} +.financial-card::after { + border: 0; +} +.financial-card__top { + display: flex; + align-items: center; + justify-content: space-between; + min-height: 38rpx; +} +.pin-tag { + padding: 4rpx 14rpx; + border-radius: 999rpx; + background: #fff0e8; + color: #ee5b27; + font-size: 22rpx; +} +.financial-card__date { + margin-left: auto; + color: #969ba3; + font-size: 22rpx; +} +.financial-card__title { + margin-top: 16rpx; + color: #262a30; + font-size: 34rpx; + font-weight: 700; +} +.financial-card__summary { + margin-top: 14rpx; + color: #676d76; + font-size: 27rpx; + line-height: 1.65; +} +.financial-card__link { + margin-top: 20rpx; + color: #f05a28; + font-size: 26rpx; + font-weight: 600; +} diff --git a/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.ts b/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.ts index 66e1fe9..f1a7cee 100644 --- a/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.ts +++ b/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.ts @@ -43,6 +43,9 @@ Page({ organization() { void wx.navigateTo({ url: '/pages/content/content?type=ORGANIZATION_INTRO' }); }, + financialDisclosures() { + void wx.navigateTo({ url: '/pages/financial-disclosures/financial-disclosures' }); + }, openProject(event: WechatMiniprogram.BaseEvent) { void wx.navigateTo({ url: `/pages/project-detail/project-detail?publicId=${event.currentTarget.dataset['id'] as string}`, diff --git a/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.wxml b/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.wxml index 077a87f..40fa8c5 100644 --- a/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.wxml +++ b/apps/miniprogram/miniprogram/pages/public-welfare/public-welfare.wxml @@ -10,6 +10,6 @@ 暂无可查看活动 了解乐活所有内容均经审核发布 - + diff --git a/apps/miniprogram/miniprogram/services/financial-disclosures.ts b/apps/miniprogram/miniprogram/services/financial-disclosures.ts new file mode 100644 index 0000000..6d9891a --- /dev/null +++ b/apps/miniprogram/miniprogram/services/financial-disclosures.ts @@ -0,0 +1,13 @@ +import type { + FinancialDisclosureDetailResponse, + PaginatedFinancialDisclosuresResponse, +} from '@lehuo/contracts'; +import { apiRequest } from './api-client'; +export const fetchFinancialDisclosures = () => + apiRequest( + '/api/v1/financial-disclosures?page=1&pageSize=50', + ); +export const fetchFinancialDisclosure = (id: string) => + apiRequest( + `/api/v1/financial-disclosures/${encodeURIComponent(id)}`, + ); diff --git a/apps/miniprogram/scripts/check-pages.mjs b/apps/miniprogram/scripts/check-pages.mjs index aa8d00e..297b48b 100644 --- a/apps/miniprogram/scripts/check-pages.mjs +++ b/apps/miniprogram/scripts/check-pages.mjs @@ -13,6 +13,8 @@ const allowedTags = new Set([ 'input', 'label', 'picker', + 'rich-text', + 'scroll-view', 'switch', 'text', 'textarea', diff --git a/docs/02_PRODUCT_PRD_V1.md b/docs/02_PRODUCT_PRD_V1.md index 61538e5..e8b550c 100644 --- a/docs/02_PRODUCT_PRD_V1.md +++ b/docs/02_PRODUCT_PRD_V1.md @@ -452,3 +452,11 @@ V1: - 志愿服务时长 不得用手工填写数字覆盖真实统计结果。 + +--- + +## 17. 财务公开文档 + +经用户批准,财务公开采用文档发布方式,不建设财务核算或在线募捐系统。工作人员在本地完成文档后,可在管理后台导入 `.docx`、继续编辑基础富文本排版、预览并发布;公众在小程序“公益”页查看已发布文档列表和详情。 + +最小字段为标题、可选摘要、富文本正文、草稿/已发布/已归档状态、置顶、排序、revision、发布时间和创建/更新人员。首版不包含支付、捐赠订单、银行流水同步、结构化收支录入、金额统计或复杂审批。 diff --git a/docs/04_DATA_MODEL.md b/docs/04_DATA_MODEL.md index 3a36dd1..0424acf 100644 --- a/docs/04_DATA_MODEL.md +++ b/docs/04_DATA_MODEL.md @@ -470,3 +470,18 @@ Phase 7 不建立可人工修改的统计快照;九项 V1 指标直接从申 6. 所有枚举在 contracts 中有单一事实来源。 7. migration 不允许 destructive change 直接上线。 8. 删除列采用“停用 → 迁移 → 验证 → 后续版本删除”。 + +--- + +## 23. financial_disclosures + +- id / public_id(随机 UUID) +- client_request_id / request_fingerprint(创建幂等) +- title / summary nullable +- rich_text(后端白名单清洗后的富文本) +- status:DRAFT / PUBLISHED / ARCHIVED +- is_pinned / sort_order / revision +- published_at nullable +- created_by / updated_by / timestamps + +`financial_disclosure_status_history` 只追加保存创建、发布和归档事实,请求 UUID 全局唯一。已发布文档禁止覆盖编辑,只能归档;草稿编辑使用 revision 乐观锁。 diff --git a/docs/05_API_AND_WORKFLOW.md b/docs/05_API_AND_WORKFLOW.md index a8d7064..317ab00 100644 --- a/docs/05_API_AND_WORKFLOW.md +++ b/docs/05_API_AND_WORKFLOW.md @@ -287,3 +287,22 @@ Phase 0 提供: ``` 健康检查不得返回配置值、数据库连接串、密钥或其他敏感信息。业务 API 仍统一使用 `/api/v1` 前缀;基础设施健康检查不属于业务 API。 + +--- + +## 12. 财务公开文档 API + +公众接口: + +- `GET /api/v1/financial-disclosures` +- `GET /api/v1/financial-disclosures/:publicId` + +只返回 `PUBLISHED` 文档,草稿和归档文档按不存在处理。 + +管理端接口: + +- `GET/POST /api/v1/admin/financial-disclosures` +- `GET/PATCH /api/v1/admin/financial-disclosures/:publicId` +- `POST /api/v1/admin/financial-disclosures/:publicId/transition` + +创建、发布和归档使用客户端 UUID 幂等;编辑只允许草稿且要求 expectedRevision。状态为 `DRAFT → PUBLISHED → ARCHIVED`,状态变化与历史、审计事务一致。DOCX 在管理端浏览器转换为富文本,API 只接受并白名单清洗富文本,不执行 Office 文件。 diff --git a/docs/06_SECURITY_PRIVACY.md b/docs/06_SECURITY_PRIVACY.md index 95feb36..16ac2ee 100644 --- a/docs/06_SECURITY_PRIVACY.md +++ b/docs/06_SECURITY_PRIVACY.md @@ -283,3 +283,10 @@ - 只有 `APPROVED` 志愿者可报名;活动行锁、有效报名计数和数据库唯一约束共同防止并发超额与重复报名。 - 报名审核、取消、签到、缺席和服务分钟均写不可变历史与审计。服务分钟只允许对已通过、已签到且活动已完成的记录核定,且不得超过活动持续时间。 - 公益项目和活动公开接口只返回公开状态内容,不返回志愿者名单或服务对象资料。封面未配置对象存储时不生成假地址或假成功。 + +## 财务公开富文本安全(2026-08-13) + +- DOCX 仅在管理端浏览器转换,不由 API 执行或解析 Office 宏;首版不持久化原 Word 文件。 +- 管理端导入和预览先经 DOMPurify 清洗,API 保存前再次使用独立白名单清洗;禁止脚本、事件属性、iframe、非 HTTPS 链接和非 HTTPS 图片。 +- 只有管理员与超级管理员默认获得财务公开查看、编辑和发布权限;公众只能访问已发布文档。 +- 已发布文档禁止原地覆盖编辑,归档后不可公开;发布和归档写入不可变历史与审计。 diff --git a/docs/07_UI_UX.md b/docs/07_UI_UX.md index 6fedeea..3d112f8 100644 --- a/docs/07_UI_UX.md +++ b/docs/07_UI_UX.md @@ -167,3 +167,11 @@ P2:5. 公益项目 6. 公益活动 7. 我要做公益 - 生成的人物图片均为虚构品牌场景素材,仅作服务类别与项目视觉,不作为真实服务对象、服务现场或项目成果证据;素材已压缩进入小程序本地包。 - 捐赠支付、自动捐赠、捐赠记录/金额、物资订单、志愿者培训/证书/团队不展示入口;代码只保留禁用的集中能力登记和组件/导航扩展边界。 - 图片中的金额、满意度、捐赠人数等示例值不得复制;所有运行时数字必须来自已批准接口,缺少事实时使用明确空状态。 + +--- + +## 13. 财务公开文档体验(2026-08-13) + +- 管理端新增独立“财务公开”导航,支持空白新建、10MB 以内 DOCX 导入、标题/摘要、基础标题与段落、加粗、下划线、列表、对齐、撤销/重做和接近小程序宽度的预览。 +- Word 的复杂浮动对象、页眉页脚、分页和高级样式允许在导入时简化,发布前必须人工预览确认;首版重点保障段落、标题、列表和表格。 +- 小程序“公益 → 了解乐活”新增财务公开入口;列表展示置顶、标题、摘要和发布时间,详情使用 rich-text 展示,宽表可横向滚动,加载失败可重试。 diff --git a/docs/09_TEST_ACCEPTANCE.md b/docs/09_TEST_ACCEPTANCE.md index f0f0a08..d63c464 100644 --- a/docs/09_TEST_ACCEPTANCE.md +++ b/docs/09_TEST_ACCEPTANCE.md @@ -155,3 +155,13 @@ UAT 不只让开发人员自测。 - 微信小程序审核所需材料就绪; - 监控和告警正常; - 可回滚上一版本。 + +--- + +## 8. 财务公开验收 + +- DOCX 可在管理端本地导入,基础标题、段落、列表和表格可继续编辑并预览。 +- 危险 HTML、脚本、事件属性、iframe 和非 HTTPS 外链不能进入公开正文。 +- 未登录或无权限人员不能访问管理接口;草稿和归档文档不能从公众接口获取。 +- 草稿可编辑并使用 revision 防并发覆盖;已发布文档不能覆盖编辑,只能归档。 +- 创建、发布和归档幂等,状态历史和审计完整;小程序列表、详情、空状态和失败状态可用。 diff --git a/docs/10_TASK_STATE.md b/docs/10_TASK_STATE.md index d190ef7..dd14b95 100644 --- a/docs/10_TASK_STATE.md +++ b/docs/10_TASK_STATE.md @@ -6,6 +6,20 @@ 2026-08-13 +任务:财务公开文档发布模块。 + +完成:按用户确认的简化范围新增独立财务公开模块。管理后台支持新建空白文档、导入 10MB 内 `.docx`、编辑标题/摘要/置顶/排序、基础富文本排版、小程序宽度预览、保存草稿、直接发布和归档;小程序“公益”页增加财务公开入口,完成公开列表、详情、宽表横向阅读、空状态和错误状态。新增共享契约、`financial_disclosures` 与只追加状态历史、三项独立权限、随机公开 ID、创建/状态幂等、revision 乐观锁、发布/归档事务审计,以及管理端 DOMPurify + API sanitize-html 双层富文本白名单清洗。已发布内容禁止原地覆盖编辑。 + +范围:这是用户明确批准的新增模块,但不改变 D-017 对支付和公开募捐的排除。首版不保存原 DOCX、不提供结构化收支字段、财务核算、复杂审批、支付、捐赠订单、银行流水同步或金额统计。Word 复杂浮动对象、页眉页脚和高级分页样式可能简化,发布前必须人工预览。 + +验证:格式化、Lint、全仓类型检查和 28 个单元测试通过;新增 migration 已部署到专用 `lehuo_test`,共 9 个 migration;36 个真实 MySQL 集成测试全部通过,覆盖草稿隔离、危险富文本清洗、发布可见、发布后禁止覆盖、归档隐藏、状态历史和审计;小程序页面门禁通过 20 个页面,运行时 workspace 导入门禁通过;全仓生产构建通过。新增 D-018。 + +遗留:仍需在微信开发者工具清缓存重新编译并进行真机财务公开列表/详情视觉验收;需用机构实际 DOCX 样本确认复杂表格和排版还原度。真实微信 AppID/AppSecret、合法 HTTPS 域名和生产环境配置仍按既有计划后期提供。 + +--- + +2026-08-13 + 任务:微信真机二级页面白屏修复。 根因:服务申请和协作任务详情/服务记录页面在运行时从 workspace 包 `@lehuo/contracts` 导入业务常量。现有小程序工程没有生成 `miniprogram_npm`,常规 TypeScript 检查会擦除类型导入并通过,但真机无法解析运行时 workspace 模块,导致页面脚本在 `Page()` 注册前终止并显示空白。另发现内容详情使用非小程序原生 `article` 标签、项目详情使用 `strong` 标签,以及详情页缺少路由参数时可能持续处于加载状态。 diff --git a/docs/11_DECISIONS.md b/docs/11_DECISIONS.md index 1f56600..aeb86aa 100644 --- a/docs/11_DECISIONS.md +++ b/docs/11_DECISIONS.md @@ -209,6 +209,20 @@ V1 统计直接从业务事实表计算,不建立可人工覆盖的统计表 --- +## D-018 财务公开采用受限富文本文档发布 + +状态:ACCEPTED + +决定: +财务公开作为独立文档发布模块,由管理人员在本地完成文档后导入管理后台、调整基础富文本排版、预览并直接发布,小程序只读查看。状态采用 `DRAFT → PUBLISHED → ARCHIVED`;已发布正文禁止覆盖编辑,创建、发布和归档必须幂等并写不可变状态历史及审计。 + +DOCX 仅在管理端浏览器转换,API 保存前对富文本执行服务端白名单清洗。首版不保存原 Word 文件,不建设结构化财务核算、复杂审核、在线募捐、支付、捐赠订单、银行流水同步或金额统计。 + +原因: +满足机构以现有本地文档进行公开的真实工作方式,降低录入成本,并通过双层富文本清洗、后端权限和发布状态隔离保证公众展示安全;同时避免把轻量公开需求扩大成财务或支付系统。 + +--- + ## 待确认建议 Codex 若有会改变已批准架构的建议,只能写在这里,不得直接实施: diff --git a/packages/contracts/src/auth.ts b/packages/contracts/src/auth.ts index 3a40d9b..a01b650 100644 --- a/packages/contracts/src/auth.ts +++ b/packages/contracts/src/auth.ts @@ -48,6 +48,9 @@ export const PERMISSION_CODES = { CONTENT_READ: 'content:read', CONTENT_MANAGE: 'content:manage', CONTENT_REVIEW: 'content:review', + FINANCIAL_DISCLOSURES_READ: 'financial_disclosures:read', + FINANCIAL_DISCLOSURES_MANAGE: 'financial_disclosures:manage', + FINANCIAL_DISCLOSURES_PUBLISH: 'financial_disclosures:publish', NOTIFICATIONS_MANAGE: 'notifications:manage', STATISTICS_READ: 'statistics:read', EXPORTS_CREATE: 'exports:create', diff --git a/packages/contracts/src/financial-disclosures.ts b/packages/contracts/src/financial-disclosures.ts new file mode 100644 index 0000000..81f77a0 --- /dev/null +++ b/packages/contracts/src/financial-disclosures.ts @@ -0,0 +1,55 @@ +export const FINANCIAL_DISCLOSURE_STATUSES = ['DRAFT', 'PUBLISHED', 'ARCHIVED'] as const; +export type FinancialDisclosureStatus = (typeof FINANCIAL_DISCLOSURE_STATUSES)[number]; + +export const FINANCIAL_DISCLOSURE_STATUS_LABELS: Record = { + DRAFT: '草稿', + PUBLISHED: '已发布', + ARCHIVED: '已归档', +}; + +export interface FinancialDisclosureListItem { + publicId: string; + title: string; + summary: string | null; + status: FinancialDisclosureStatus; + isPinned: boolean; + sortOrder: number; + revision: number; + publishedAt: string | null; + updatedAt: string; +} + +export interface FinancialDisclosureDetail extends FinancialDisclosureListItem { + richText: string; +} + +export interface PaginatedFinancialDisclosuresResponse { + items: FinancialDisclosureListItem[]; + page: number; + pageSize: number; + total: number; +} + +export interface FinancialDisclosureDetailResponse { + disclosure: FinancialDisclosureDetail; +} +export interface CreateFinancialDisclosureRequest { + clientRequestId: string; + title: string; + summary?: string; + richText: string; + isPinned?: boolean; + sortOrder?: number; +} +export interface UpdateFinancialDisclosureRequest { + expectedRevision: number; + title: string; + summary?: string; + richText: string; + isPinned?: boolean; + sortOrder?: number; +} +export interface TransitionFinancialDisclosureRequest { + clientRequestId: string; + targetStatus: 'PUBLISHED' | 'ARCHIVED'; +} diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index 3d2d9ab..a3560ab 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -27,6 +27,20 @@ export { SERVICE_CATEGORY_LABELS, } from './service-applications.js'; export type { StatisticsOverview } from './statistics.js'; +export { + FINANCIAL_DISCLOSURE_STATUSES, + FINANCIAL_DISCLOSURE_STATUS_LABELS, +} from './financial-disclosures.js'; +export type { + FinancialDisclosureStatus, + FinancialDisclosureListItem, + FinancialDisclosureDetail, + PaginatedFinancialDisclosuresResponse, + FinancialDisclosureDetailResponse, + CreateFinancialDisclosureRequest, + UpdateFinancialDisclosureRequest, + TransitionFinancialDisclosureRequest, +} from './financial-disclosures.js'; export { CONTENT_POST_STATUSES, CONTENT_POST_STATUS_LABELS, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3ea909..fcee622 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ settings: overrides: js-yaml: 5.2.2 + lodash: 4.18.1 importers: @@ -35,6 +36,12 @@ importers: '@lehuo/contracts': specifier: workspace:* version: link:../../packages/contracts + dompurify: + specifier: ^3.4.13 + version: 3.4.13 + mammoth: + specifier: ^1.12.1 + version: 1.12.1 pinia: specifier: ^3.0.3 version: 3.0.3(typescript@5.9.2)(vue@3.5.41(typescript@5.9.2)) @@ -114,6 +121,9 @@ importers: rxjs: specifier: ^7.8.2 version: 7.8.2 + sanitize-html: + specifier: ^2.17.6 + version: 2.17.6 devDependencies: '@nestjs/testing': specifier: ^11.1.6 @@ -127,6 +137,9 @@ importers: '@types/node': specifier: ^24.3.0 version: 24.13.3 + '@types/sanitize-html': + specifier: ^2.16.1 + version: 2.16.1 '@types/supertest': specifier: ^6.0.3 version: 6.0.3 @@ -1032,6 +1045,9 @@ packages: '@types/react@19.2.18': resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} + '@types/sanitize-html@2.16.1': + resolution: {integrity: sha512-n9wjs8bCOTyN/ynwD8s/nTcTreIHB1vf31vhLMGqUPNHaweKC4/fAl4Dj+hUlCTKYgm4P3k83fmiFfzkZ6sgMA==} + '@types/send@1.2.1': resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} @@ -1044,6 +1060,9 @@ packages: '@types/supertest@6.0.3': resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/validator@13.15.10': resolution: {integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==} @@ -1231,6 +1250,10 @@ packages: '@vue/shared@3.5.41': resolution: {integrity: sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==} + '@xmldom/xmldom@0.8.13': + resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} + engines: {node: '>=10.0.0'} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -1281,6 +1304,9 @@ packages: resolution: {integrity: sha512-skm+/WCjkGqCQxF7FG1LuZXM5yvbFjgbfiCGsud2oLgaDhh6b6dbH0b1EkghbM+xx4Bj8Ape+KKgixoIlWZicQ==} engines: {node: '>=16.17.0'} + argparse@1.0.3: + resolution: {integrity: sha512-W3ljhM0j9lduyssD8+dPR0P0HWCSCGrflhsgIVFzNQpx8TDQGN/dcqcb0hOuOWsf0TNZ8OIVgKXC7Rb2vpUp+Q==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1305,12 +1331,18 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + better-result@2.10.0: resolution: {integrity: sha512-oQhh0y1qo2/ZKdAAEvHZAqKKiHOFU5k/bW96fE2ScgQOVkJRiHwB+nOS1SgFsYqRlxMDWvefXi9Q3px7QvgNDw==} birpc@2.3.0: resolution: {integrity: sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g==} + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + body-parser@2.3.0: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} @@ -1450,6 +1482,9 @@ packages: resolution: {integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==} engines: {node: '>=18'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} engines: {node: '>= 0.10'} @@ -1518,6 +1553,9 @@ packages: resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} engines: {node: '>=12'} + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1538,6 +1576,10 @@ packages: resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} engines: {node: '>=16.0.0'} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} @@ -1562,10 +1604,48 @@ packages: dezalgo@1.0.4: resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + dingbat-to-unicode@1.0.1: + resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + dom-serializer@3.1.1: + resolution: {integrity: sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==} + engines: {node: '>=20.19.0'} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domelementtype@3.0.0: + resolution: {integrity: sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==} + engines: {node: '>=20.19.0'} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domhandler@6.0.1: + resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==} + engines: {node: '>=20.19.0'} + + dompurify@3.4.13: + resolution: {integrity: sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + domutils@4.0.2: + resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==} + engines: {node: '>=20.19.0'} + dotenv@17.4.2: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} + duck@0.1.12: + resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1596,10 +1676,18 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + entities@4.2.0: + resolution: {integrity: sha512-wEJa03bJgqEwPnkUqYdgmcfUXfm6+4hePQhntIvRy/1/+C4dFuhYHsgKBRjbQ6OWBh42P+VhAoCDO77DUh0e/Q==} + engines: {node: '>=0.12'} + entities@7.0.1: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1862,6 +1950,13 @@ packages: hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + + htmlparser2@12.0.0: + resolution: {integrity: sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==} + engines: {node: '>=20.19.0'} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -1885,6 +1980,9 @@ packages: resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} engines: {node: '>= 4'} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + import-fresh@3.2.1: resolution: {integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==} engines: {node: '>=6'} @@ -1916,6 +2014,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -1926,6 +2028,9 @@ packages: resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} engines: {node: '>=18'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1960,9 +2065,15 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + launder@1.7.1: + resolution: {integrity: sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1970,6 +2081,9 @@ packages: libphonenumber-js@1.13.10: resolution: {integrity: sha512-xJxrdqvbl2rtn2MaUJrUejz8J7/uZNC0V77oks2LxYrO/+ZtVpRmz+fEQMuu6VusnEB1fmpByiLS1WXecOnAnw==} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + load-esm@1.0.3: resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} engines: {node: '>=13.2.0'} @@ -1987,6 +2101,9 @@ packages: long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + lop@0.4.2: + resolution: {integrity: sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==} + loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} @@ -2011,6 +2128,11 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + mammoth@1.12.1: + resolution: {integrity: sha512-nCH9KKjWi3jQ+i8bUKs7k1yrXtSEGpWgF8IYkzsFMcbn+5S6l4bZEBbyx2hOQErFiXPuAs9RPa6qjXVxhyx/8g==} + engines: {node: '>=12.0.0'} + hasBin: true + mariadb@3.4.5: resolution: {integrity: sha512-gThTYkhIS5rRqkVr+Y0cIdzr+GRqJ9sA2Q34e0yzmyhMCwyApf3OKAC1jnF23aSlIOqJuyaUFUcj7O1qZslmmQ==} engines: {node: '>= 14'} @@ -2142,6 +2264,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + option@0.2.4: + resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2161,10 +2286,16 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.2: + resolution: {integrity: sha512-qCaDHl8pk5JSbz5k1Bi5zTZf430DUuV13pmcFEHHan4fW++WIwm2HXUirpzfciBRyFUN+eeZW11bfIM/Y4Zeog==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-srcset@1.0.2: + resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -2176,6 +2307,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2249,6 +2384,9 @@ packages: typescript: optional: true + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} @@ -2287,6 +2425,9 @@ packages: resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} engines: {node: '>=0.10.0'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2340,6 +2481,9 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -2350,6 +2494,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sanitize-html@2.17.6: + resolution: {integrity: sha512-M4bo9tfv1yfhQZZKkc6dL07ALrGJtfvNOuhX3hU9AVPR/uPQ+nKOJBqTYc7LfMQblTW04mtSWDJWEyLvygJsLA==} + engines: {node: '>=22.12.0'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -2369,6 +2517,9 @@ packages: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -2414,6 +2565,9 @@ packages: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sqlstring@2.3.3: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} @@ -2443,6 +2597,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2563,6 +2720,9 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} + underscore@1.13.8: + resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} + undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} @@ -2712,6 +2872,10 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + xmlbuilder@10.1.1: + resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==} + engines: {node: '>=4.0'} + zeptomatch@2.1.0: resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==} @@ -3534,6 +3698,10 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/sanitize-html@2.16.1': + dependencies: + htmlparser2: 10.1.0 + '@types/send@1.2.1': dependencies: '@types/node': 24.13.3 @@ -3555,6 +3723,9 @@ snapshots: '@types/methods': 1.1.4 '@types/superagent': 8.1.11 + '@types/trusted-types@2.0.7': + optional: true + '@types/validator@13.15.10': {} '@types/wechat-miniprogram@3.4.10': {} @@ -3871,6 +4042,8 @@ snapshots: '@vue/shared@3.5.41': {} + '@xmldom/xmldom@0.8.13': {} + accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -3921,6 +4094,11 @@ snapshots: node-addon-api: 8.9.1 node-gyp-build: 4.8.4 + argparse@1.0.3: + dependencies: + lodash: 4.18.1 + sprintf-js: 1.0.3 + argparse@2.0.1: {} asap@2.0.6: {} @@ -3935,10 +4113,14 @@ snapshots: balanced-match@4.0.4: {} + base64-js@1.5.1: {} + better-result@2.10.0: {} birpc@2.3.0: {} + bluebird@3.4.7: {} + body-parser@2.3.0: dependencies: bytes: 3.1.2 @@ -4082,6 +4264,8 @@ snapshots: dependencies: is-what: 5.5.0 + core-util-is@1.0.3: {} + cors@2.8.6: dependencies: object-assign: 4.1.1 @@ -4148,6 +4332,8 @@ snapshots: dependencies: d3-array: 3.2.4 + dayjs@1.11.21: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -4158,6 +4344,8 @@ snapshots: deepmerge-ts@7.1.5: {} + deepmerge@4.3.1: {} + defu@6.1.7: {} delaunator@5.1.0: @@ -4177,8 +4365,54 @@ snapshots: asap: 2.0.6 wrappy: 1.0.2 + dingbat-to-unicode@1.0.1: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.2.0 + + dom-serializer@3.1.1: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + entities: 8.0.0 + + domelementtype@2.3.0: {} + + domelementtype@3.0.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domhandler@6.0.1: + dependencies: + domelementtype: 3.0.0 + + dompurify@3.4.13: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + domutils@4.0.2: + dependencies: + dom-serializer: 3.1.1 + domelementtype: 3.0.0 + domhandler: 6.0.1 + dotenv@17.4.2: {} + duck@0.1.12: + dependencies: + underscore: 1.13.8 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4204,8 +4438,12 @@ snapshots: encodeurl@2.0.0: {} + entities@4.2.0: {} + entities@7.0.1: {} + entities@8.0.0: {} + env-paths@3.0.0: {} es-define-property@1.0.1: {} @@ -4538,6 +4776,20 @@ snapshots: hookable@5.5.3: {} + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + + htmlparser2@12.0.0: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + domutils: 4.0.2 + entities: 8.0.0 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -4560,6 +4812,8 @@ snapshots: ignore@7.0.6: {} + immediate@3.0.6: {} + import-fresh@3.2.1: dependencies: parent-module: 1.0.1 @@ -4581,12 +4835,16 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-plain-object@5.0.0: {} + is-promise@4.0.0: {} is-property@1.0.2: {} is-what@5.5.0: {} + isarray@1.0.0: {} + isexe@2.0.0: {} iterare@1.2.1: {} @@ -4613,10 +4871,21 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.2 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + launder@1.7.1: + dependencies: + dayjs: 1.11.21 + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4624,6 +4893,10 @@ snapshots: libphonenumber-js@1.13.10: {} + lie@3.3.0: + dependencies: + immediate: 3.0.6 + load-esm@1.0.3: {} locate-path@6.0.0: @@ -4636,6 +4909,12 @@ snapshots: long@5.3.2: {} + lop@0.4.2: + dependencies: + duck: 0.1.12 + option: 0.2.4 + underscore: 1.13.8 + loupe@3.2.1: {} lru-cache@10.2.0: {} @@ -4654,6 +4933,19 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + mammoth@1.12.1: + dependencies: + '@xmldom/xmldom': 0.8.13 + argparse: 1.0.3 + base64-js: 1.5.1 + bluebird: 3.4.7 + dingbat-to-unicode: 1.0.1 + jszip: 3.10.1 + lop: 0.4.2 + path-is-absolute: 1.0.1 + underscore: 1.13.8 + xmlbuilder: 10.1.1 + mariadb@3.4.5: dependencies: '@types/geojson': 7946.0.16 @@ -4767,6 +5059,8 @@ snapshots: dependencies: wrappy: 1.0.2 + option@0.2.4: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4788,16 +5082,22 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@1.0.2: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 + parse-srcset@1.0.2: {} + parseurl@1.3.3: {} path-browserify@1.0.1: {} path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-scurry@1.11.1: @@ -4861,6 +5161,8 @@ snapshots: - react - react-dom + process-nextick-args@2.0.1: {} + proper-lockfile@4.1.2: dependencies: graceful-fs: 4.2.11 @@ -4902,6 +5204,16 @@ snapshots: react@19.2.8: {} + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -4976,6 +5288,8 @@ snapshots: dependencies: tslib: 2.8.1 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-regex2@5.1.1: @@ -4984,6 +5298,16 @@ snapshots: safer-buffer@2.1.2: {} + sanitize-html@2.17.6: + dependencies: + deepmerge: 4.3.1 + escape-string-regexp: 4.0.0 + htmlparser2: 12.0.0 + is-plain-object: 5.0.0 + launder: 1.7.1 + parse-srcset: 1.0.2 + postcss: 8.5.26 + scheduler@0.27.0: {} semver@7.8.5: {} @@ -5015,6 +5339,8 @@ snapshots: transitivePeerDependencies: - supports-color + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -5061,6 +5387,8 @@ snapshots: speakingurl@14.0.1: {} + sprintf-js@1.0.3: {} + sqlstring@2.3.3: {} stackback@0.0.2: {} @@ -5085,6 +5413,10 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.2.0 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -5212,6 +5544,8 @@ snapshots: uint8array-extras@1.5.0: {} + underscore@1.13.8: {} + undici-types@7.18.2: {} unpipe@1.0.0: {} @@ -5354,6 +5688,8 @@ snapshots: wrappy@1.0.2: {} + xmlbuilder@10.1.1: {} + zeptomatch@2.1.0: dependencies: grammex: 3.1.13 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 81d755c..482ac6e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,7 @@ packages: overrides: js-yaml: 5.2.2 + lodash: 4.18.1 allowBuilds: '@nestjs/core': true