feat(knowledge): add file upload with text extraction for knowledge base

支持在管理后台知识库页面上传文件(PDF、Word、TXT、Markdown),
自动提取文本内容,管理员预览编辑后保存为知识库文章。

## 后端 (knowledge-service)

- 新增 TextExtractionService:文件文本提取服务
  - PDF 提取:使用 pdf-parse v2 (PDFParse class API)
  - Word (.docx) 提取:使用 mammoth.extractRawText()
  - TXT/Markdown:直接 UTF-8 解码
  - 支持中英文混合字数统计
  - 文件大小限制 200MB,类型校验(MIME 白名单)
  - 空文本 PDF(扫描件/图片)返回友好错误提示

- 新增上传接口:POST /knowledge/articles/upload
  - 使用 NestJS FileInterceptor 处理 multipart/form-data
  - 仅提取文本并返回,不直接创建文章(两步流程)
  - 返回:extractedText, suggestedTitle, wordCount, pageCount

- 新增 ExtractedTextResponse DTO
- KnowledgeModule 注册 TextExtractionService

## 前端 (admin-client)

- knowledge.api.ts:新增 uploadFile() 方法(FormData + 120s 超时)
- useKnowledge.ts:新增 useUploadKnowledgeFile hook
- KnowledgePage.tsx:
  - 新增 Segmented 切换器(手动输入 / 文件上传),仅新建时显示
  - 文件上传模式显示 Upload.Dragger 拖拽上传区域
  - 上传后自动提取文本,填入标题+内容字段
  - 提取完成自动切回手动模式,管理员可预览编辑后保存
  - 显示提取结果(字数、页数)

## 用户流程

新建文章 → 切换"文件上传" → 拖入/选择文件 → 系统提取文本
→ 自动填入标题+内容 → 管理员编辑确认 → 点击保存

## 依赖

- pdf-parse@^2.4.5(PDF 文本提取)
- mammoth@^1.8.0(Word 文档文本提取)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-06 22:58:19 -08:00
parent 897b86db26
commit e16ec7930d
11 changed files with 506 additions and 15 deletions

View File

@ -5,5 +5,6 @@ export {
useDeleteArticle, useDeleteArticle,
usePublishArticle, usePublishArticle,
useUnpublishArticle, useUnpublishArticle,
useUploadKnowledgeFile,
KNOWLEDGE_QUERY_KEY, KNOWLEDGE_QUERY_KEY,
} from './useKnowledge'; } from './useKnowledge';

View File

@ -59,6 +59,15 @@ export function usePublishArticle() {
}); });
} }
export function useUploadKnowledgeFile() {
return useMutation({
mutationFn: (file: File) => knowledgeApi.uploadFile(file),
onError: () => {
message.error('文件上传失败');
},
});
}
export function useUnpublishArticle() { export function useUnpublishArticle() {
const queryClient = useQueryClient(); const queryClient = useQueryClient();

View File

@ -1,2 +1,2 @@
export { knowledgeApi } from './knowledge.api'; export { knowledgeApi } from './knowledge.api';
export type { Article, ArticleListResponse, CreateArticleParams, UpdateArticleParams } from './knowledge.api'; export type { Article, ArticleListResponse, CreateArticleParams, UpdateArticleParams, ExtractedTextResponse } from './knowledge.api';

View File

@ -26,6 +26,13 @@ export interface CreateArticleParams {
tags?: string[]; tags?: string[];
} }
export interface ExtractedTextResponse {
extractedText: string;
suggestedTitle: string;
wordCount: number;
pageCount?: number;
}
export interface UpdateArticleParams extends Partial<CreateArticleParams> { export interface UpdateArticleParams extends Partial<CreateArticleParams> {
id: string; id: string;
} }
@ -59,4 +66,14 @@ export const knowledgeApi = {
unpublishArticle: async (id: string): Promise<void> => { unpublishArticle: async (id: string): Promise<void> => {
await api.post(`/knowledge/articles/${id}/unpublish`); await api.post(`/knowledge/articles/${id}/unpublish`);
}, },
uploadFile: async (file: File): Promise<ExtractedTextResponse> => {
const formData = new FormData();
formData.append('file', file);
const response = await api.post('/knowledge/articles/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
timeout: 120000,
});
return response.data.data;
},
}; };

View File

@ -12,6 +12,9 @@ import {
Popconfirm, Popconfirm,
Typography, Typography,
Drawer, Drawer,
Upload,
Segmented,
message,
} from 'antd'; } from 'antd';
import { import {
PlusOutlined, PlusOutlined,
@ -21,6 +24,8 @@ import {
EyeOutlined, EyeOutlined,
CheckOutlined, CheckOutlined,
StopOutlined, StopOutlined,
InboxOutlined,
UploadOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { import {
useKnowledgeArticles, useKnowledgeArticles,
@ -29,6 +34,7 @@ import {
useDeleteArticle, useDeleteArticle,
usePublishArticle, usePublishArticle,
useUnpublishArticle, useUnpublishArticle,
useUploadKnowledgeFile,
} from '../../application'; } from '../../application';
import type { Article, CreateArticleParams } from '../../infrastructure'; import type { Article, CreateArticleParams } from '../../infrastructure';
@ -51,6 +57,8 @@ export function KnowledgePage() {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isDrawerOpen, setIsDrawerOpen] = useState(false); const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const [selectedArticle, setSelectedArticle] = useState<Article | null>(null); const [selectedArticle, setSelectedArticle] = useState<Article | null>(null);
const [inputMode, setInputMode] = useState<'manual' | 'upload'>('manual');
const [isExtracting, setIsExtracting] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
const { data, isLoading } = useKnowledgeArticles(categoryFilter); const { data, isLoading } = useKnowledgeArticles(categoryFilter);
@ -59,6 +67,7 @@ export function KnowledgePage() {
const deleteMutation = useDeleteArticle(); const deleteMutation = useDeleteArticle();
const publishMutation = usePublishArticle(); const publishMutation = usePublishArticle();
const unpublishMutation = useUnpublishArticle(); const unpublishMutation = useUnpublishArticle();
const uploadMutation = useUploadKnowledgeFile();
const handleEdit = (article: Article) => { const handleEdit = (article: Article) => {
setSelectedArticle(article); setSelectedArticle(article);
@ -98,6 +107,25 @@ export function KnowledgePage() {
} }
}; };
const handleFileUpload = (file: File) => {
setIsExtracting(true);
uploadMutation.mutate(file, {
onSuccess: (result) => {
form.setFieldsValue({
title: result.suggestedTitle,
content: result.extractedText,
});
const info = result.pageCount
? `已提取 ${result.wordCount} 字(${result.pageCount} 页)`
: `已提取 ${result.wordCount}`;
message.success(info);
setInputMode('manual');
},
onSettled: () => setIsExtracting(false),
});
return false; // prevent default upload
};
const columns = [ const columns = [
{ {
title: '标题', title: '标题',
@ -234,6 +262,7 @@ export function KnowledgePage() {
onClick={() => { onClick={() => {
setSelectedArticle(null); setSelectedArticle(null);
form.resetFields(); form.resetFields();
setInputMode('manual');
setIsModalOpen(true); setIsModalOpen(true);
}} }}
> >
@ -287,13 +316,47 @@ export function KnowledgePage() {
<Select mode="tags" placeholder="输入标签后回车" /> <Select mode="tags" placeholder="输入标签后回车" />
</Form.Item> </Form.Item>
<Form.Item {!selectedArticle && (
name="content" <Form.Item label="内容来源">
label="内容" <Segmented
rules={[{ required: true, message: '请输入内容' }]} value={inputMode}
> onChange={(val) => setInputMode(val as 'manual' | 'upload')}
<TextArea rows={12} placeholder="支持Markdown格式" /> options={[
</Form.Item> { label: '手动输入', value: 'manual', icon: <EditOutlined /> },
{ label: '文件上传', value: 'upload', icon: <UploadOutlined /> },
]}
/>
</Form.Item>
)}
{inputMode === 'upload' && !selectedArticle ? (
<Form.Item label="上传文件">
<Upload.Dragger
accept=".pdf,.docx,.txt,.md"
showUploadList={false}
beforeUpload={handleFileUpload}
disabled={isExtracting}
>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">
{isExtracting ? '正在提取文本...' : '点击或拖拽文件到此区域'}
</p>
<p className="ant-upload-hint">
PDFWord(.docx)TXTMarkdown 200MB
</p>
</Upload.Dragger>
</Form.Item>
) : (
<Form.Item
name="content"
label="内容"
rules={[{ required: true, message: '请输入内容' }]}
>
<TextArea rows={12} placeholder="支持Markdown格式" />
</Form.Item>
)}
<Form.Item className="mb-0 text-right"> <Form.Item className="mb-0 text-right">
<Space> <Space>

View File

@ -15,15 +15,17 @@
"test:cov": "jest --coverage" "test:cov": "jest --coverage"
}, },
"dependencies": { "dependencies": {
"@iconsulting/shared": "workspace:*",
"@anthropic-ai/sdk": "^0.52.0", "@anthropic-ai/sdk": "^0.52.0",
"@iconsulting/shared": "workspace:*",
"@nestjs/common": "^10.0.0", "@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.0", "@nestjs/config": "^3.2.0",
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^10.0.0", "@nestjs/typeorm": "^10.0.0",
"mammoth": "^1.11.0",
"neo4j-driver": "^5.17.0", "neo4j-driver": "^5.17.0",
"openai": "^4.28.0", "openai": "^4.28.0",
"pdf-parse": "^2.4.5",
"pg": "^8.11.3", "pg": "^8.11.3",
"pgvector": "^0.1.8", "pgvector": "^0.1.8",
"reflect-metadata": "^0.2.1", "reflect-metadata": "^0.2.1",
@ -37,6 +39,7 @@
"@nestjs/testing": "^10.0.0", "@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.21", "@types/express": "^4.17.21",
"@types/jest": "^29.5.11", "@types/jest": "^29.5.11",
"@types/multer": "^1.4.11",
"@types/node": "^20.10.6", "@types/node": "^20.10.6",
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"jest": "^29.7.0", "jest": "^29.7.0",

View File

@ -9,9 +9,14 @@ import {
Query, Query,
HttpCode, HttpCode,
HttpStatus, HttpStatus,
UploadedFile,
UseInterceptors,
BadRequestException,
} from '@nestjs/common'; } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { KnowledgeService } from '../../application/services/knowledge.service'; import { KnowledgeService } from '../../application/services/knowledge.service';
import { RAGService } from '../../application/services/rag.service'; import { RAGService } from '../../application/services/rag.service';
import { TextExtractionService } from '../../application/services/text-extraction.service';
import { KnowledgeSource } from '../../domain/entities/knowledge-article.entity'; import { KnowledgeSource } from '../../domain/entities/knowledge-article.entity';
import { import {
CreateArticleDto, CreateArticleDto,
@ -20,6 +25,7 @@ import {
RetrieveKnowledgeDto, RetrieveKnowledgeDto,
ImportArticlesDto, ImportArticlesDto,
FeedbackDto, FeedbackDto,
ExtractedTextResponse,
} from '../../application/dtos/knowledge.dto'; } from '../../application/dtos/knowledge.dto';
@Controller('knowledge') @Controller('knowledge')
@ -27,6 +33,7 @@ export class KnowledgeController {
constructor( constructor(
private knowledgeService: KnowledgeService, private knowledgeService: KnowledgeService,
private ragService: RAGService, private ragService: RAGService,
private textExtractionService: TextExtractionService,
) {} ) {}
/** /**
@ -45,6 +52,36 @@ export class KnowledgeController {
}; };
} }
/**
*
* createArticle
*/
@Post('articles/upload')
@UseInterceptors(
FileInterceptor('file', {
limits: { fileSize: 200 * 1024 * 1024 },
}),
)
async uploadAndExtract(
@UploadedFile() file: Express.Multer.File,
): Promise<{ success: boolean; data: ExtractedTextResponse }> {
if (!file) {
throw new BadRequestException('未上传文件');
}
const extracted = await this.textExtractionService.extractText(file);
return {
success: true,
data: {
extractedText: extracted.text,
suggestedTitle: extracted.title,
wordCount: extracted.wordCount,
pageCount: extracted.pageCount,
},
};
}
/** /**
* *
*/ */

View File

@ -42,3 +42,10 @@ export class ImportArticlesDto {
export class FeedbackDto { export class FeedbackDto {
helpful: boolean; helpful: boolean;
} }
export class ExtractedTextResponse {
extractedText: string;
suggestedTitle: string;
wordCount: number;
pageCount?: number;
}

View File

@ -0,0 +1,135 @@
/**
* Text Extraction Service
* PDFWordTXTMarkdown
*/
import { Injectable, BadRequestException, Logger } from '@nestjs/common';
import { PDFParse } from 'pdf-parse';
import * as mammoth from 'mammoth';
export interface ExtractedContent {
text: string;
title: string;
pageCount?: number;
wordCount: number;
}
const ALLOWED_MIME_TYPES = [
'application/pdf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain',
'text/markdown',
];
const MAX_FILE_SIZE = 200 * 1024 * 1024; // 200MB
@Injectable()
export class TextExtractionService {
private readonly logger = new Logger(TextExtractionService.name);
validateFile(file: Express.Multer.File): void {
if (!ALLOWED_MIME_TYPES.includes(file.mimetype)) {
throw new BadRequestException(
`不支持的文件类型: ${file.mimetype}。支持: PDF, DOCX, TXT, MD`,
);
}
if (file.size > MAX_FILE_SIZE) {
throw new BadRequestException(
`文件过大: ${(file.size / 1024 / 1024).toFixed(1)}MB最大支持 200MB`,
);
}
}
async extractText(file: Express.Multer.File): Promise<ExtractedContent> {
this.validateFile(file);
const title = this.deriveTitleFromFilename(file.originalname);
this.logger.log(
`Extracting text from "${file.originalname}" (${file.mimetype}, ${(file.size / 1024).toFixed(0)}KB)`,
);
switch (file.mimetype) {
case 'application/pdf':
return this.extractFromPdf(file.buffer, title);
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
return this.extractFromDocx(file.buffer, title);
case 'text/plain':
case 'text/markdown':
return this.extractFromText(file.buffer, title);
default:
throw new BadRequestException(`不支持的文件类型: ${file.mimetype}`);
}
}
private async extractFromPdf(
buffer: Buffer,
title: string,
): Promise<ExtractedContent> {
const parser = new PDFParse({ data: new Uint8Array(buffer), verbosity: 0 });
const result = await parser.getText();
if (!result.text || result.text.trim().length === 0) {
await parser.destroy();
throw new BadRequestException(
'无法从 PDF 中提取文本。该文件可能是扫描件或纯图片 PDF。',
);
}
const text = result.text.trim();
const pageCount = result.total;
await parser.destroy();
return {
text,
title,
pageCount,
wordCount: this.countWords(text),
};
}
private async extractFromDocx(
buffer: Buffer,
title: string,
): Promise<ExtractedContent> {
const result = await mammoth.extractRawText({ buffer });
if (!result.value || result.value.trim().length === 0) {
throw new BadRequestException('无法从 Word 文档中提取文本。');
}
return {
text: result.value.trim(),
title,
wordCount: this.countWords(result.value),
};
}
private extractFromText(
buffer: Buffer,
title: string,
): ExtractedContent {
const text = buffer.toString('utf-8');
return {
text: text.trim(),
title,
wordCount: this.countWords(text),
};
}
private deriveTitleFromFilename(filename: string): string {
return filename
.replace(/\.[^.]+$/, '')
.replace(/[-_]/g, ' ')
.replace(/\s+/g, ' ')
.trim();
}
private countWords(text: string): number {
const chineseChars = (text.match(/[\u4e00-\u9fff]/g) || []).length;
const englishWords = text
.replace(/[\u4e00-\u9fff]/g, '')
.split(/\s+/)
.filter((w) => w.length > 0).length;
return chineseChars + englishWords;
}
}

View File

@ -5,6 +5,7 @@ import { KnowledgeService } from '../application/services/knowledge.service';
import { RAGService } from '../application/services/rag.service'; import { RAGService } from '../application/services/rag.service';
import { ChunkingService } from '../application/services/chunking.service'; import { ChunkingService } from '../application/services/chunking.service';
import { EmbeddingService } from '../infrastructure/embedding/embedding.service'; import { EmbeddingService } from '../infrastructure/embedding/embedding.service';
import { TextExtractionService } from '../application/services/text-extraction.service';
import { KnowledgePostgresRepository } from '../adapters/outbound/persistence/knowledge-postgres.repository'; import { KnowledgePostgresRepository } from '../adapters/outbound/persistence/knowledge-postgres.repository';
import { import {
UserMemoryPostgresRepository, UserMemoryPostgresRepository,
@ -35,6 +36,7 @@ import {
RAGService, RAGService,
ChunkingService, ChunkingService,
EmbeddingService, EmbeddingService,
TextExtractionService,
{ {
provide: KNOWLEDGE_REPOSITORY, provide: KNOWLEDGE_REPOSITORY,
useClass: KnowledgePostgresRepository, useClass: KnowledgePostgresRepository,

View File

@ -405,12 +405,18 @@ importers:
'@nestjs/typeorm': '@nestjs/typeorm':
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.2(@nestjs/common@10.4.21)(@nestjs/core@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.28) version: 10.0.2(@nestjs/common@10.4.21)(@nestjs/core@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.28)
mammoth:
specifier: ^1.11.0
version: 1.11.0
neo4j-driver: neo4j-driver:
specifier: ^5.17.0 specifier: ^5.17.0
version: 5.28.2 version: 5.28.2
openai: openai:
specifier: ^4.28.0 specifier: ^4.28.0
version: 4.104.0 version: 4.104.0
pdf-parse:
specifier: ^2.4.5
version: 2.4.5
pg: pg:
specifier: ^8.11.3 specifier: ^8.11.3
version: 8.16.3 version: 8.16.3
@ -445,6 +451,9 @@ importers:
'@types/jest': '@types/jest':
specifier: ^29.5.11 specifier: ^29.5.11
version: 29.5.14 version: 29.5.14
'@types/multer':
specifier: ^1.4.11
version: 1.4.13
'@types/node': '@types/node':
specifier: ^20.10.6 specifier: ^20.10.6
version: 20.19.27 version: 20.19.27
@ -2072,6 +2081,112 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@napi-rs/canvas-android-arm64@0.1.80:
resolution: {integrity: sha512-sk7xhN/MoXeuExlggf91pNziBxLPVUqF2CAVnB57KLG/pz7+U5TKG8eXdc3pm0d7Od0WreB6ZKLj37sX9muGOQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-darwin-arm64@0.1.80:
resolution: {integrity: sha512-O64APRTXRUiAz0P8gErkfEr3lipLJgM6pjATwavZ22ebhjYl/SUbpgM0xcWPQBNMP1n29afAC/Us5PX1vg+JNQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-darwin-x64@0.1.80:
resolution: {integrity: sha512-FqqSU7qFce0Cp3pwnTjVkKjjOtxMqRe6lmINxpIZYaZNnVI0H5FtsaraZJ36SiTHNjZlUB69/HhxNDT1Aaa9vA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-arm-gnueabihf@0.1.80:
resolution: {integrity: sha512-eyWz0ddBDQc7/JbAtY4OtZ5SpK8tR4JsCYEZjCE3dI8pqoWUC8oMwYSBGCYfsx2w47cQgQCgMVRVTFiiO38hHQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-arm64-gnu@0.1.80:
resolution: {integrity: sha512-qwA63t8A86bnxhuA/GwOkK3jvb+XTQaTiVML0vAWoHyoZYTjNs7BzoOONDgTnNtr8/yHrq64XXzUoLqDzU+Uuw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-arm64-musl@0.1.80:
resolution: {integrity: sha512-1XbCOz/ymhj24lFaIXtWnwv/6eFHXDrjP0jYkc6iHQ9q8oXKzUX1Lc6bu+wuGiLhGh2GS/2JlfORC5ZcXimRcg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-riscv64-gnu@0.1.80:
resolution: {integrity: sha512-XTzR125w5ZMs0lJcxRlS1K3P5RaZ9RmUsPtd1uGt+EfDyYMu4c6SEROYsxyatbbu/2+lPe7MPHOO/0a0x7L/gw==}
engines: {node: '>= 10'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-x64-gnu@0.1.80:
resolution: {integrity: sha512-BeXAmhKg1kX3UCrJsYbdQd3hIMDH/K6HnP/pG2LuITaXhXBiNdh//TVVVVCBbJzVQaV5gK/4ZOCMrQW9mvuTqA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-linux-x64-musl@0.1.80:
resolution: {integrity: sha512-x0XvZWdHbkgdgucJsRxprX/4o4sEed7qo9rCQA9ugiS9qE2QvP0RIiEugtZhfLH3cyI+jIRFJHV4Fuz+1BHHMg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas-win32-x64-msvc@0.1.80:
resolution: {integrity: sha512-Z8jPsM6df5V8B1HrCHB05+bDiCxjE9QA//3YrkKIdVDEwn5RKaqOxCJDRJkl48cJbylcrJbW4HxZbTte8juuPg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@napi-rs/canvas@0.1.80:
resolution: {integrity: sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==}
engines: {node: '>= 10'}
optionalDependencies:
'@napi-rs/canvas-android-arm64': 0.1.80
'@napi-rs/canvas-darwin-arm64': 0.1.80
'@napi-rs/canvas-darwin-x64': 0.1.80
'@napi-rs/canvas-linux-arm-gnueabihf': 0.1.80
'@napi-rs/canvas-linux-arm64-gnu': 0.1.80
'@napi-rs/canvas-linux-arm64-musl': 0.1.80
'@napi-rs/canvas-linux-riscv64-gnu': 0.1.80
'@napi-rs/canvas-linux-x64-gnu': 0.1.80
'@napi-rs/canvas-linux-x64-musl': 0.1.80
'@napi-rs/canvas-win32-x64-msvc': 0.1.80
dev: false
/@nestjs/cli@10.4.9: /@nestjs/cli@10.4.9:
resolution: {integrity: sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==} resolution: {integrity: sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==}
engines: {node: '>= 16.14'} engines: {node: '>= 16.14'}
@ -2178,6 +2293,7 @@ packages:
uid: 2.0.2 uid: 2.0.2
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
dev: false
/@nestjs/core@10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2): /@nestjs/core@10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2):
resolution: {integrity: sha512-MhiSGplB4TkadceA7opn/NaZmJhwYYNdB8nS8I29nLNx3vU+8aGHBiueZgcphEVDETZJSfc2VA5Mn/FC3JcsrA==} resolution: {integrity: sha512-MhiSGplB4TkadceA7opn/NaZmJhwYYNdB8nS8I29nLNx3vU+8aGHBiueZgcphEVDETZJSfc2VA5Mn/FC3JcsrA==}
@ -2209,7 +2325,6 @@ packages:
uid: 2.0.2 uid: 2.0.2
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
dev: false
/@nestjs/jwt@10.2.0(@nestjs/common@10.4.21): /@nestjs/jwt@10.2.0(@nestjs/common@10.4.21):
resolution: {integrity: sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==} resolution: {integrity: sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==}
@ -2228,7 +2343,7 @@ packages:
'@nestjs/core': ^10.0.0 '@nestjs/core': ^10.0.0
dependencies: dependencies:
'@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
'@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(@nestjs/websockets@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2)
body-parser: 1.20.3 body-parser: 1.20.3
cors: 2.8.5 cors: 2.8.5
express: 4.22.1 express: 4.22.1
@ -2253,6 +2368,7 @@ packages:
- bufferutil - bufferutil
- supports-color - supports-color
- utf-8-validate - utf-8-validate
dev: false
/@nestjs/schedule@4.1.2(@nestjs/common@10.4.21)(@nestjs/core@10.4.21): /@nestjs/schedule@4.1.2(@nestjs/common@10.4.21)(@nestjs/core@10.4.21):
resolution: {integrity: sha512-hCTQ1lNjIA5EHxeu8VvQu2Ed2DBLS1GSC6uKPYlBiQe6LL9a7zfE9iVSK+zuK8E2odsApteEBmfAQchc8Hx0Gg==} resolution: {integrity: sha512-hCTQ1lNjIA5EHxeu8VvQu2Ed2DBLS1GSC6uKPYlBiQe6LL9a7zfE9iVSK+zuK8E2odsApteEBmfAQchc8Hx0Gg==}
@ -2310,7 +2426,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
'@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(@nestjs/websockets@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2)
'@nestjs/platform-express': 10.4.21(@nestjs/common@10.4.21)(@nestjs/core@10.4.21) '@nestjs/platform-express': 10.4.21(@nestjs/common@10.4.21)(@nestjs/core@10.4.21)
tslib: 2.8.1 tslib: 2.8.1
dev: true dev: true
@ -2325,7 +2441,7 @@ packages:
typeorm: ^0.3.0 typeorm: ^0.3.0
dependencies: dependencies:
'@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/common': 10.4.21(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2)
'@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(@nestjs/websockets@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 10.4.21(@nestjs/common@10.4.21)(@nestjs/platform-express@10.4.21)(reflect-metadata@0.2.2)(rxjs@7.8.2)
reflect-metadata: 0.2.2 reflect-metadata: 0.2.2
rxjs: 7.8.2 rxjs: 7.8.2
typeorm: 0.3.28(ioredis@5.9.1)(pg@8.16.3)(ts-node@10.9.2) typeorm: 0.3.28(ioredis@5.9.1)(pg@8.16.3)(ts-node@10.9.2)
@ -2352,6 +2468,7 @@ packages:
reflect-metadata: 0.2.2 reflect-metadata: 0.2.2
rxjs: 7.8.2 rxjs: 7.8.2
tslib: 2.8.1 tslib: 2.8.1
dev: false
/@nodelib/fs.scandir@2.1.5: /@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
@ -3942,6 +4059,11 @@ packages:
'@xtuc/long': 4.2.2 '@xtuc/long': 4.2.2
dev: true dev: true
/@xmldom/xmldom@0.8.11:
resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==}
engines: {node: '>=10.0.0'}
dev: false
/@xtuc/ieee754@1.2.0: /@xtuc/ieee754@1.2.0:
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
dev: true dev: true
@ -4268,7 +4390,6 @@ packages:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies: dependencies:
sprintf-js: 1.0.3 sprintf-js: 1.0.3
dev: true
/argparse@2.0.1: /argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@ -4462,6 +4583,10 @@ packages:
readable-stream: 3.6.2 readable-stream: 3.6.2
dev: false dev: false
/bluebird@3.4.7:
resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==}
dev: false
/body-parser@1.20.3: /body-parser@1.20.3:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@ -5106,6 +5231,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
ms: 2.1.3 ms: 2.1.3
dev: false
/debug@4.4.3: /debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
@ -5252,6 +5378,10 @@ packages:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
dev: false dev: false
/dingbat-to-unicode@1.0.1:
resolution: {integrity: sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==}
dev: false
/dir-glob@3.0.1: /dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -5292,6 +5422,12 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
dev: false dev: false
/duck@0.1.12:
resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==}
dependencies:
underscore: 1.13.7
dev: false
/dunder-proto@1.0.1: /dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -6374,6 +6510,10 @@ packages:
engines: {node: '>= 4'} engines: {node: '>= 4'}
dev: true dev: true
/immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
dev: false
/import-fresh@3.3.1: /import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -7256,6 +7396,15 @@ packages:
semver: 7.7.3 semver: 7.7.3
dev: false dev: false
/jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
dependencies:
lie: 3.3.0
pako: 1.0.11
readable-stream: 2.3.8
setimmediate: 1.0.5
dev: false
/jwa@1.4.2: /jwa@1.4.2:
resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==}
dependencies: dependencies:
@ -7318,6 +7467,12 @@ packages:
/libphonenumber-js@1.12.33: /libphonenumber-js@1.12.33:
resolution: {integrity: sha512-r9kw4OA6oDO4dPXkOrXTkArQAafIKAU71hChInV4FxZ69dxCfbwQGDPzqR5/vea94wU705/3AZroEbSoeVWrQw==} resolution: {integrity: sha512-r9kw4OA6oDO4dPXkOrXTkArQAafIKAU71hChInV4FxZ69dxCfbwQGDPzqR5/vea94wU705/3AZroEbSoeVWrQw==}
/lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
dependencies:
immediate: 3.0.6
dev: false
/lilconfig@3.1.3: /lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -7411,6 +7566,14 @@ packages:
js-tokens: 4.0.0 js-tokens: 4.0.0
dev: false dev: false
/lop@0.4.2:
resolution: {integrity: sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==}
dependencies:
duck: 0.1.12
option: 0.2.4
underscore: 1.13.7
dev: false
/lru-cache@10.4.3: /lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@ -7463,6 +7626,23 @@ packages:
tmpl: 1.0.5 tmpl: 1.0.5
dev: true dev: true
/mammoth@1.11.0:
resolution: {integrity: sha512-BcEqqY/BOwIcI1iR5tqyVlqc3KIaMRa4egSoK83YAVrBf6+yqdAAbtUcFDCWX8Zef8/fgNZ6rl4VUv+vVX8ddQ==}
engines: {node: '>=12.0.0'}
hasBin: true
dependencies:
'@xmldom/xmldom': 0.8.11
argparse: 1.0.10
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.7
xmlbuilder: 10.1.1
dev: false
/map-obj@2.0.0: /map-obj@2.0.0:
resolution: {integrity: sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ==} resolution: {integrity: sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -8134,6 +8314,10 @@ packages:
- encoding - encoding
dev: false dev: false
/option@0.2.4:
resolution: {integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==}
dev: false
/optionator@0.9.4: /optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -8216,6 +8400,10 @@ packages:
/package-json-from-dist@1.0.1: /package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
/pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
dev: false
/parent-module@1.0.1: /parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -8293,6 +8481,22 @@ packages:
through: 2.3.8 through: 2.3.8
dev: false dev: false
/pdf-parse@2.4.5:
resolution: {integrity: sha512-mHU89HGh7v+4u2ubfnevJ03lmPgQ5WU4CxAVmTSh/sxVTEDYd1er/dKS/A6vg77NX47KTEoihq8jZBLr8Cxuwg==}
engines: {node: '>=20.16.0 <21 || >=22.3.0'}
hasBin: true
dependencies:
'@napi-rs/canvas': 0.1.80
pdfjs-dist: 5.4.296
dev: false
/pdfjs-dist@5.4.296:
resolution: {integrity: sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==}
engines: {node: '>=20.16.0 || >=22.3.0'}
optionalDependencies:
'@napi-rs/canvas': 0.1.80
dev: false
/pg-cloudflare@1.2.7: /pg-cloudflare@1.2.7:
resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
requiresBuild: true requiresBuild: true
@ -9714,6 +9918,10 @@ packages:
gopd: 1.2.0 gopd: 1.2.0
has-property-descriptors: 1.0.2 has-property-descriptors: 1.0.2
/setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
dev: false
/setprototypeof@1.2.0: /setprototypeof@1.2.0:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
@ -9880,6 +10088,7 @@ packages:
- bufferutil - bufferutil
- supports-color - supports-color
- utf-8-validate - utf-8-validate
dev: false
/socket.io@4.8.3: /socket.io@4.8.3:
resolution: {integrity: sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==} resolution: {integrity: sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==}
@ -9947,7 +10156,6 @@ packages:
/sprintf-js@1.0.3: /sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
dev: true
/sql-highlight@6.1.0: /sql-highlight@6.1.0:
resolution: {integrity: sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==} resolution: {integrity: sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==}
@ -10731,6 +10939,10 @@ packages:
resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==}
engines: {node: '>=18'} engines: {node: '>=18'}
/underscore@1.13.7:
resolution: {integrity: sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==}
dev: false
/undici-types@5.26.5: /undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
dev: false dev: false
@ -11246,6 +11458,11 @@ packages:
xmlbuilder: 11.0.1 xmlbuilder: 11.0.1
dev: false dev: false
/xmlbuilder@10.1.1:
resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==}
engines: {node: '>=4.0'}
dev: false
/xmlbuilder@11.0.1: /xmlbuilder@11.0.1:
resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}