From 6033f686329eb024b30950c5c7499a91ef7b6ffe Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:25:05 +0200 Subject: [PATCH 01/13] feat: DOCX support via existing read_file + edit_block tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add DocxFileHandler (src/utils/files/docx.ts) - read_file default: returns text-bearing outline (paragraphs, tables, images, headers/footers) - read_file with offset/length: returns raw pretty-printed XML with line pagination - edit_block: find/replace on pretty-printed XML, compact + repack into valid DOCX - Also searches headers/footers when edit target not found in document body - Register DocxFileHandler in factory.ts (priority before binary detection) - Route .docx files through DocxFileHandler.editRange in edit.ts - Update read_file and edit_block tool descriptions with DOCX usage - Add isDocx to FileMetadata in base.ts - Add pizzip dependency for DOCX ZIP handling No new tools added — DOCX works through the same read_file/edit_block workflow that already exists for text, Excel, and PDF files. --- package-lock.json | 20 +- package.json | 1 + src/server.ts | 21 ++ src/tools/edit.ts | 32 ++ src/utils/files/base.ts | 3 + src/utils/files/docx.ts | 663 +++++++++++++++++++++++++++++++++++++ src/utils/files/factory.ts | 25 +- 7 files changed, 757 insertions(+), 8 deletions(-) create mode 100644 src/utils/files/docx.ts diff --git a/package-lock.json b/package-lock.json index d53071f0b..27773c107 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wonderwhy-er/desktop-commander", - "version": "0.2.35", + "version": "0.2.36", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wonderwhy-er/desktop-commander", - "version": "0.2.35", + "version": "0.2.36", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -25,6 +25,7 @@ "md-to-pdf": "^5.2.5", "open": "^10.2.0", "pdf-lib": "^1.17.1", + "pizzip": "^3.2.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", @@ -9763,6 +9764,21 @@ "node": ">=0.10.0" } }, + "node_modules/pizzip": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pizzip/-/pizzip-3.2.0.tgz", + "integrity": "sha512-X4NPNICxCfIK8VYhF6wbksn81vTiziyLbvKuORVAmolvnUzl1A1xmz9DAWKxPRq9lZg84pJOOAMq3OE61bD8IQ==", + "license": "(MIT OR GPL-3.0)", + "dependencies": { + "pako": "^2.1.0" + } + }, + "node_modules/pizzip/node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, "node_modules/pkce-challenge": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", diff --git a/package.json b/package.json index 82d0b76b7..b0404212b 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "md-to-pdf": "^5.2.5", "open": "^10.2.0", "pdf-lib": "^1.17.1", + "pizzip": "^3.2.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", diff --git a/src/server.ts b/src/server.ts index 75d70c3b3..833eb830b 100644 --- a/src/server.ts +++ b/src/server.ts @@ -316,6 +316,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { - PDF: Extracts text content as markdown with page structure * offset/length work as page pagination (0-based) * Includes embedded images when available + - DOCX (.docx): Two modes depending on parameters: + * DEFAULT (no offset/length): Returns a text-bearing outline — shows paragraphs with text, + tables with cell content, styles, image refs. Skips shapes/drawings/SVG noise. + Each element shows its body index [0], [1], etc. + * WITH offset/length: Returns raw pretty-printed XML with line pagination. + Use this to drill into specific sections or see the actual XML for editing. + * EDITING WORKFLOW: 1) read_file to get outline, 2) read_file with offset/length + to see raw XML around what you want to edit, 3) edit_block with old_string/new_string + using XML fragments copied from the read output. ${PATH_GUIDANCE} ${CMD_PREFIX_DESCRIPTION}`, @@ -353,6 +362,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { Write or append to file contents. IMPORTANT: DO NOT use this tool to create PDF files. Use 'write_pdf' for all PDF creation tasks. + DO NOT use this tool to edit DOCX files. Use 'edit_block' with old_string/new_string instead. CHUNKING IS STANDARD PRACTICE: Always write files in chunks of 25-30 lines maximum. This is the normal, recommended way to write files - not an emergency measure. @@ -732,6 +742,17 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { - new_string: Replacement text - expected_replacements: Optional number of replacements (default: 1) + DOCX FILES (.docx) - XML Find/Replace mode: + Takes same parameters as text files (old_string, new_string, expected_replacements). + Operates on the pretty-printed XML inside the DOCX — the same XML you see from + read_file with offset/length. Copy XML fragments from read output as old_string. + After editing, the XML is repacked into a valid DOCX. + Also searches headers/footers if not found in document body. + Examples: + - Replace text: old_string="Old Text" new_string="New Text" + - Change style: old_string='' new_string='' + - Add content: include surrounding XML context in old_string, add new elements in new_string + By default, replaces only ONE occurrence of the search text. To replace multiple occurrences, provide expected_replacements with the exact number of matches expected. diff --git a/src/tools/edit.ts b/src/tools/edit.ts index 1e1c599a7..3548c68a6 100644 --- a/src/tools/edit.ts +++ b/src/tools/edit.ts @@ -418,6 +418,38 @@ export async function handleEditBlock(args: unknown): Promise { return createErrorResponse(`Text replacement requires both old_string and new_string parameters`); } + // DOCX files: Route through DocxFileHandler.editRange for XML-aware editing + if (parsed.file_path.toLowerCase().endsWith('.docx')) { + try { + const validatedPath = await validatePath(parsed.file_path); + const { getFileHandler } = await import('../utils/files/factory.js'); + const handler = await getFileHandler(validatedPath); + + if ('editRange' in handler && typeof handler.editRange === 'function') { + const result = await handler.editRange(validatedPath, '', { + old_string: parsed.old_string, + new_string: parsed.new_string, + expected_replacements: parsed.expected_replacements, + }); + + if (result.success) { + return { + content: [{ + type: "text", + text: `Successfully applied ${result.editsApplied} edit(s) to ${parsed.file_path}` + }], + }; + } else { + const errorMsg = result.errors?.map(e => e.error).join('; ') || 'Unknown error'; + return createErrorResponse(errorMsg); + } + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return createErrorResponse(errorMessage); + } + } + const searchReplace = { search: parsed.old_string, replace: parsed.new_string diff --git a/src/utils/files/base.ts b/src/utils/files/base.ts index 775acdb66..9bf2f8c4a 100644 --- a/src/utils/files/base.ts +++ b/src/utils/files/base.ts @@ -130,6 +130,9 @@ export interface FileMetadata { totalPages?: number; pages?: PdfPageItem[]; + /** For DOCX files */ + isDocx?: boolean; + /** Error information if operation failed */ error?: boolean; errorMessage?: string; diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts new file mode 100644 index 000000000..d86b72b59 --- /dev/null +++ b/src/utils/files/docx.ts @@ -0,0 +1,663 @@ +/** + * DOCX File Handler + * + * Approach: expose DOCX as filtered/raw XML through existing read_file + edit_block. + * + * READ (default): Returns a text-bearing outline — skips shapes, drawings, SVG noise. + * Shows paragraphs with text, tables with cell content, style info, and image refs. + * Each element shows its raw XML tag context so Claude can target it for editing. + * + * READ (with offset/length): Returns raw pretty-printed XML with line pagination, + * so Claude can drill into specific sections when the outline isn't enough. + * + * EDIT (old_string/new_string): Find/replace on the pretty-printed XML, then + * compact and repack into valid DOCX. Works exactly like text file editing. + * + * Round-trip: DOCX → unzip → pretty-print → [outline or raw] → edit → compact → repack + */ + +import fs from 'fs/promises'; +import PizZip from 'pizzip'; +import { FileHandler, FileResult, FileInfo, ReadOptions, EditResult } from './base.js'; + +// ════════════════════════════════════════════════════════════════ +// XML Pretty-Print / Compact +// ════════════════════════════════════════════════════════════════ + +/** + * Pretty-print XML: split tags onto separate lines with indentation. + * Preserves text node content exactly. compact→pretty→compact is lossless. + */ +function prettyPrintXml(xml: string): string { + const parts = xml.split(/(?<=>)(?=<)/); + const lines: string[] = []; + let depth = 0; + + for (const part of parts) { + const trimmed = part.trim(); + if (!trimmed) continue; + + const isClosing = trimmed.startsWith(''); + const isProcessingInstruction = trimmed.startsWith(' text nodes. + */ +function compactXml(prettyXml: string): string { + return prettyXml.split('\n').map(l => l.trimStart()).join(''); +} + +// ════════════════════════════════════════════════════════════════ +// DOCX ZIP helpers +// ════════════════════════════════════════════════════════════════ + +interface DocxZipContents { + zip: PizZip; + documentXml: string; + /** All XML parts keyed by path (e.g. "word/header1.xml") */ + xmlParts: Map; +} + +function loadDocxZip(buf: Buffer): DocxZipContents { + const zip = new PizZip(buf); + const docFile = zip.file('word/document.xml'); + if (!docFile) throw new Error('Invalid DOCX: missing word/document.xml'); + + const xmlParts = new Map(); + // Collect all XML parts for potential editing + const zipFiles = zip.files; + for (const relativePath of Object.keys(zipFiles)) { + if (relativePath.endsWith('.xml') || relativePath.endsWith('.rels')) { + try { + xmlParts.set(relativePath, zipFiles[relativePath].asText()); + } catch { /* skip binary entries */ } + } + } + + return { + zip, + documentXml: docFile.asText(), + xmlParts, + }; +} + +// ════════════════════════════════════════════════════════════════ +// Outline extraction — the key feature +// ════════════════════════════════════════════════════════════════ + +interface OutlineItem { + index: number; + tag: string; + style?: string; + text?: string; + textLength?: number; + tableInfo?: string; + imageInfo?: string; + skippedReason?: string; + /** Raw XML of this element (for small items) or truncated preview */ + xml?: string; +} + +/** + * Extract a text-bearing outline from document.xml. + * + * Walks direct children of and for each: + * - w:p (paragraph): extracts text from elements, shows style + * - w:tbl (table): extracts cell text for each row + * - mc:AlternateContent / shapes / drawings: shows size, skips content + * - w:sdt: looks inside for text/tables + * + * Returns a human-readable outline with enough context for editing. + */ +function extractOutline(xml: string): string { + const lines: string[] = []; + + // Parse body children using regex — faster and more reliable than DOM for outline + // Find ... + const bodyMatch = xml.match(/]*>([\s\S]*)<\/w:body>/); + if (!bodyMatch) return '[No w:body found in document.xml]'; + + const bodyContent = bodyMatch[1]; + + // Split into top-level children of w:body + // We need to find top-level elements, respecting nesting + const children = splitTopLevelElements(bodyContent); + + let paragraphCount = 0; + let tableCount = 0; + let imageCount = 0; + + for (let i = 0; i < children.length; i++) { + const child = children[i]; + const tagMatch = child.match(/^<(\S+?)[\s>\/]/); + if (!tagMatch) continue; + const tag = tagMatch[1]; + + if (tag === 'w:p') { + const text = extractAllText(child); + const style = extractParagraphStyle(child); + const hasDrawing = child.includes(' 200) { + line += `\n "${text.substring(0, 200)}..."`; + } else { + line += `\n "${text}"`; + } + } else if (!hasDrawing) { + line += ' (empty)'; + } + + lines.push(line); + paragraphCount++; + } else if (tag === 'w:tbl') { + const rows = extractTableRows(child); + let line = `[${i}] w:tbl (${rows.length} rows)`; + const style = extractTableStyle(child); + if (style) line += ` style="${style}"`; + // Show first few rows as preview + for (let r = 0; r < Math.min(rows.length, 4); r++) { + const cells = rows[r].map(c => { + if (!c || c.trim() === '') return ''; + return c.length > 30 ? c.substring(0, 30) + '…' : c; + }); + line += `\n row${r}: [${cells.join(' | ')}]`; + } + if (rows.length > 4) line += `\n ... (${rows.length - 4} more rows)`; + lines.push(line); + tableCount++; + } else if (tag === 'w:sdt') { + // Structured document tag — look inside for content + const sdtText = extractAllText(child); + const innerTables = (child.match(/]/g) || []).length; + let line = `[${i}] w:sdt`; + if (innerTables > 0) { + line += ` (contains ${innerTables} table${innerTables > 1 ? 's' : ''})`; + tableCount += innerTables; + } + if (sdtText) { + if (sdtText.length > 150) { + line += `\n "${sdtText.substring(0, 150)}..."`; + } else { + line += `\n "${sdtText}"`; + } + } + lines.push(line); + } else if (tag === 'w:sectPr') { + lines.push(`[${i}] w:sectPr (section properties)`); + } else if (tag === 'mc:AlternateContent') { + lines.push(`[${i}] mc:AlternateContent [drawing, ${(child.length / 1024).toFixed(1)}KB — skipped]`); + imageCount++; + } else { + lines.push(`[${i}] ${tag} (${(child.length / 1024).toFixed(1)}KB)`); + } + } + + // Summary header + const header = `DOCX Outline: ${children.length} body children, ${paragraphCount} paragraphs, ${tableCount} tables, ${imageCount} images\n` + + `Use read_file with offset/length to see raw XML of specific sections.\n` + + `Use edit_block with old_string/new_string to edit the XML directly.\n` + + '─'.repeat(70); + + return header + '\n' + lines.join('\n'); +} + +// ════════════════════════════════════════════════════════════════ +// XML text extraction helpers (regex-based, no DOM needed) +// ════════════════════════════════════════════════════════════════ + +/** Extract all ... text content from an XML fragment */ +function extractAllText(xml: string): string { + const texts: string[] = []; + const re = /]*>([\s\S]*?)<\/w:t>/g; + let m; + while ((m = re.exec(xml)) !== null) { + if (m[1]) texts.push(m[1]); + } + return texts.join('').trim(); +} + +/** Extract paragraph style id from w:pPr/w:pStyle */ +function extractParagraphStyle(xml: string): string | null { + const m = xml.match(/... using nesting-aware extraction + const rowElements = extractNestedElements(tableXml, 'w:tr'); + for (const rowXml of rowElements) { + const cells: string[] = []; + const cellElements = extractNestedElements(rowXml, 'w:tc'); + for (const cellXml of cellElements) { + cells.push(extractAllText(cellXml)); + } + if (cells.length > 0) rows.push(cells); + } + return rows; +} + +/** + * Extract all occurrences of a named element from XML, respecting nesting. + * Returns array of full element strings including open/close tags. + */ +function extractNestedElements(xml: string, tagName: string): string[] { + const results: string[] = []; + const openTag = `<${tagName}`; + const closeTag = ``; + let searchFrom = 0; + + while (searchFrom < xml.length) { + const openPos = xml.indexOf(openTag, searchFrom); + if (openPos === -1) break; + + // Check it's actually a tag start (followed by space, >, or /) + const charAfter = xml[openPos + openTag.length]; + if (charAfter !== ' ' && charAfter !== '>' && charAfter !== '/') { + searchFrom = openPos + 1; + continue; + } + + // Check for self-closing + const nextClose = xml.indexOf('>', openPos); + if (nextClose !== -1 && xml[nextClose - 1] === '/') { + results.push(xml.substring(openPos, nextClose + 1)); + searchFrom = nextClose + 1; + continue; + } + + // Find matching close tag respecting nesting + let depth = 1; + let pos = nextClose + 1; + while (depth > 0 && pos < xml.length) { + const nextOpen = xml.indexOf(openTag, pos); + const nextCloseTag = xml.indexOf(closeTag, pos); + + if (nextCloseTag === -1) break; // malformed XML + + if (nextOpen !== -1 && nextOpen < nextCloseTag) { + // Check it's actually an open tag + const ca = xml[nextOpen + openTag.length]; + if (ca === ' ' || ca === '>' || ca === '/') { + depth++; + } + pos = nextOpen + openTag.length; + } else { + depth--; + if (depth === 0) { + results.push(xml.substring(openPos, nextCloseTag + closeTag.length)); + } + pos = nextCloseTag + closeTag.length; + } + } + searchFrom = pos; + } + return results; +} + +/** + * Split XML into top-level elements respecting nesting depth. + * E.g. for body content, returns each direct child element as a string. + */ +function splitTopLevelElements(xml: string): string[] { + const elements: string[] = []; + let depth = 0; + let currentStart = -1; + + // Simple state machine: track < > and nesting + let i = 0; + while (i < xml.length) { + if (xml[i] === '<') { + // Check what kind of tag + if (xml[i + 1] === '/') { + // Closing tag + depth--; + if (depth === 0) { + // Find end of this closing tag + const closeEnd = xml.indexOf('>', i); + if (closeEnd !== -1 && currentStart !== -1) { + elements.push(xml.substring(currentStart, closeEnd + 1).trim()); + currentStart = -1; + } + i = closeEnd + 1; + continue; + } + } else if (xml[i + 1] === '?' || xml[i + 1] === '!') { + // Processing instruction or comment — skip + const end = xml.indexOf('>', i); + i = end + 1; + continue; + } else { + // Opening tag + if (depth === 0) currentStart = i; + // Check for self-closing + const tagEnd = xml.indexOf('>', i); + if (tagEnd !== -1 && xml[tagEnd - 1] === '/') { + // Self-closing + if (depth === 0) { + elements.push(xml.substring(currentStart, tagEnd + 1).trim()); + currentStart = -1; + i = tagEnd + 1; + continue; + } + } else { + depth++; + } + i = tagEnd + 1; + continue; + } + } + i++; + } + + return elements.filter(e => e.length > 0); +} + +/** + * Extract outline info for headers and footers from the DOCX zip. + */ +function extractHeaderFooterOutline(zip: PizZip): string { + const parts: string[] = []; + const zipFiles = zip.files; + + for (const relativePath of Object.keys(zipFiles)) { + if ((relativePath.startsWith('word/header') || relativePath.startsWith('word/footer')) + && relativePath.endsWith('.xml')) { + try { + const xml = zipFiles[relativePath].asText(); + const text = extractAllText(xml); + const name = relativePath.replace('word/', ''); + if (text) { + parts.push(`${name}: "${text.length > 100 ? text.substring(0, 100) + '...' : text}"`); + } else { + parts.push(`${name}: (no text content)`); + } + } catch { /* skip */ } + } + } + + return parts.length > 0 ? '\n\nHeaders/Footers:\n' + parts.join('\n') : ''; +} + +// ════════════════════════════════════════════════════════════════ +// Count occurrences helper +// ════════════════════════════════════════════════════════════════ + +function countOccurrences(haystack: string, needle: string): number { + let count = 0; + let pos = haystack.indexOf(needle); + while (pos !== -1) { + count++; + pos = haystack.indexOf(needle, pos + 1); + } + return count; +} + +// ════════════════════════════════════════════════════════════════ +// DocxFileHandler — implements FileHandler +// ════════════════════════════════════════════════════════════════ + +export class DocxFileHandler implements FileHandler { + private readonly extensions = ['.docx']; + + canHandle(path: string): boolean { + return this.extensions.some(e => path.toLowerCase().endsWith(e)); + } + + /** + * Read DOCX content. + * + * Default (offset=0, no explicit length or default length): returns outline + * With offset/length: returns raw pretty-printed XML with line pagination + */ + async read(path: string, options?: ReadOptions): Promise { + const buf = await fs.readFile(path); + const { zip, documentXml } = loadDocxZip(buf); + const pretty = prettyPrintXml(documentXml); + const allLines = pretty.split('\n'); + const totalLines = allLines.length; + const offset = options?.offset ?? 0; + const length = options?.length; + + // If user explicitly requests offset or a non-default length, give raw XML + const wantsRaw = offset !== 0 || (length !== undefined && length < totalLines); + + if (wantsRaw) { + let startLine: number; + let sliceLength: number; + + if (offset < 0) { + startLine = Math.max(0, totalLines + offset); + sliceLength = totalLines - startLine; + } else { + startLine = offset; + sliceLength = length ?? totalLines; + } + + const sliced = allLines.slice(startLine, startLine + sliceLength); + const remaining = totalLines - (startLine + sliced.length); + const status = `[DOCX XML: lines ${startLine}-${startLine + sliced.length - 1} of ${totalLines} (${remaining} remaining)]`; + + return { + content: status + '\n' + sliced.join('\n'), + mimeType: 'application/xml', + metadata: { isDocx: true, lineCount: totalLines }, + }; + } + + // Default: return outline + const outline = extractOutline(documentXml); + const headerFooterInfo = extractHeaderFooterOutline(zip); + const rawSizeKB = (documentXml.length / 1024).toFixed(1); + + return { + content: outline + headerFooterInfo + + `\n\nRaw XML: ${totalLines} lines, ${rawSizeKB}KB. Use offset/length to read raw XML sections.`, + mimeType: 'text/plain', + metadata: { isDocx: true, lineCount: totalLines }, + }; + } + + /** + * Write DOCX — not directly supported. + * Use edit_block for modifications. + */ + async write(_path: string, _content: any, _mode?: 'rewrite' | 'append'): Promise { + throw new Error( + 'DOCX files cannot be created using write_file. ' + + 'Use edit_block with old_string/new_string to edit existing DOCX files.' + ); + } + + /** + * Edit DOCX via find/replace on pretty-printed XML. + * + * Works on the same representation that read() returns when using offset/length, + * so XML fragments copied from read output work as search strings. + * After editing, XML is compacted and repacked into the DOCX. + */ + async editRange( + path: string, + _range: string, + content: any, + options?: Record, + ): Promise { + try { + let oldStr: string; + let newStr: string; + let expectedReplacements = 1; + + if (typeof content === 'object' && content !== null) { + oldStr = content.oldStr || content.old_string || content.search || ''; + newStr = content.newStr || content.new_string || content.replace || ''; + expectedReplacements = content.expectedReplacements || content.expected_replacements || 1; + } else { + return { + success: false, editsApplied: 0, + errors: [{ location: 'docx', error: 'DOCX editing requires old_string and new_string' }], + }; + } + + if (!oldStr) { + return { + success: false, editsApplied: 0, + errors: [{ location: 'docx', error: 'old_string cannot be empty' }], + }; + } + + // Load and pretty-print + const buf = await fs.readFile(path); + const zip = new PizZip(buf); + const docFile = zip.file('word/document.xml'); + if (!docFile) throw new Error('Invalid DOCX: missing word/document.xml'); + + const rawXml = docFile.asText(); + const pretty = prettyPrintXml(rawXml); + + // Also check headers/footers for the search string + let targetPretty = pretty; + let targetFile = 'word/document.xml'; + let matchCount = countOccurrences(pretty, oldStr); + + // If not found in document.xml, search through headers/footers + if (matchCount === 0) { + const xmlFiles = ['word/header1.xml', 'word/header2.xml', 'word/header3.xml', + 'word/footer1.xml', 'word/footer2.xml', 'word/footer3.xml']; + for (const xmlPath of xmlFiles) { + const f = zip.file(xmlPath); + if (!f) continue; + const partPretty = prettyPrintXml(f.asText()); + const c = countOccurrences(partPretty, oldStr); + if (c > 0) { + targetPretty = partPretty; + targetFile = xmlPath; + matchCount = c; + break; + } + } + } + + if (matchCount === 0) { + return { + success: false, editsApplied: 0, + errors: [{ location: targetFile, error: `Search string not found in DOCX` }], + }; + } + + if (matchCount !== expectedReplacements) { + return { + success: false, editsApplied: 0, + errors: [{ + location: targetFile, + error: `Expected ${expectedReplacements} occurrence(s) but found ${matchCount}. ` + + `Set expected_replacements to ${matchCount} to replace all, ` + + `or add more context to make the search unique.`, + }], + }; + } + + // Apply replacement + let edited = targetPretty; + if (expectedReplacements === 1) { + const idx = edited.indexOf(oldStr); + edited = edited.substring(0, idx) + newStr + edited.substring(idx + oldStr.length); + } else { + edited = edited.split(oldStr).join(newStr); + } + + // Compact and repack + const compacted = compactXml(edited); + zip.file(targetFile, compacted); + + const outBuf = zip.generate({ + type: 'nodebuffer', + compression: 'DEFLATE', + compressionOptions: { level: 6 }, + }); + await fs.writeFile(path, outBuf); + + return { success: true, editsApplied: matchCount }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + success: false, editsApplied: 0, + errors: [{ location: 'docx', error: errorMessage }], + }; + } + } + + /** + * Get DOCX file info + */ + async getInfo(path: string): Promise { + const stats = await fs.stat(path); + + let metadata: any = { isDocx: true }; + try { + const buf = await fs.readFile(path); + const { documentXml } = loadDocxZip(buf); + const text = extractAllText(documentXml); + const wordCount = text.split(/\s+/).filter(w => w.length > 0).length; + const paragraphCount = (documentXml.match(/]/g) || []).length; + const tableCount = (documentXml.match(/]/g) || []).length; + const imageCount = (documentXml.match(/]/g) || []).length; + + metadata = { + isDocx: true, + paragraphCount, + tableCount, + imageCount, + wordCount, + }; + } catch { /* return basic info */ } + + return { + size: stats.size, + created: stats.birthtime, + modified: stats.mtime, + accessed: stats.atime, + isDirectory: false, + isFile: true, + permissions: (stats.mode & 0o777).toString(8), + fileType: 'docx' as any, + metadata, + }; + } +} diff --git a/src/utils/files/factory.ts b/src/utils/files/factory.ts index 34a2e1f43..054107cbc 100644 --- a/src/utils/files/factory.ts +++ b/src/utils/files/factory.ts @@ -12,6 +12,7 @@ import { ImageFileHandler } from './image.js'; import { BinaryFileHandler } from './binary.js'; import { ExcelFileHandler } from './excel.js'; import { PdfFileHandler } from './pdf.js'; +import { DocxFileHandler } from './docx.js'; // Singleton instances of each handler let excelHandler: ExcelFileHandler | null = null; @@ -19,6 +20,7 @@ let imageHandler: ImageFileHandler | null = null; let textHandler: TextFileHandler | null = null; let binaryHandler: BinaryFileHandler | null = null; let pdfHandler: PdfFileHandler | null = null; +let docxHandler: DocxFileHandler | null = null; /** * Initialize handlers (lazy initialization) @@ -48,6 +50,11 @@ function getPdfHandler(): PdfFileHandler { return pdfHandler; } +function getDocxHandler(): DocxFileHandler { + if (!docxHandler) docxHandler = new DocxFileHandler(); + return docxHandler; +} + /** * Get the appropriate file handler for a given file path * @@ -56,17 +63,23 @@ function getPdfHandler(): PdfFileHandler { * BinaryFileHandler uses async isBinaryFile for content-based detection. * * Priority order: - * 1. PDF files (extension based) - * 2. Excel files (xlsx, xls, xlsm) - extension based - * 3. Image files (png, jpg, gif, webp) - extension based - * 4. Binary files - content-based detection via isBinaryFile - * 5. Text files (default) + * 1. DOCX files (extension based) + * 2. PDF files (extension based) + * 3. Excel files (xlsx, xls, xlsm) - extension based + * 4. Image files (png, jpg, gif, webp) - extension based + * 5. Binary files - content-based detection via isBinaryFile + * 6. Text files (default) * * @param filePath File path to get handler for * @returns FileHandler instance that can handle this file */ export async function getFileHandler(filePath: string): Promise { - // Check PDF first (extension-based, sync) + // Check DOCX first (extension-based, sync) + if (getDocxHandler().canHandle(filePath)) { + return getDocxHandler(); + } + + // Check PDF (extension-based, sync) if (getPdfHandler().canHandle(filePath)) { return getPdfHandler(); } From aa9cf50a9c704076adad8928313ece6a586eddb8 Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:29:50 +0200 Subject: [PATCH 02/13] fix: regenerate package-lock.json with devDependencies --- package-lock.json | 1860 ++++++++++++++------------------------------- 1 file changed, 556 insertions(+), 1304 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27773c107..a441e9663 100644 --- a/package-lock.json +++ b/package-lock.json @@ -81,12 +81,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -104,9 +104,9 @@ } }, "node_modules/@borewit/text-codec": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz", - "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.1.tgz", + "integrity": "sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==", "license": "MIT", "funding": { "type": "github", @@ -133,17 +133,6 @@ "node": ">=12" } }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@discoveryjs/json-ext": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", @@ -155,9 +144,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "license": "MIT", "optional": true, "dependencies": { @@ -165,9 +154,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ "ppc64" ], @@ -182,9 +171,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "cpu": [ "arm" ], @@ -199,9 +188,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "cpu": [ "arm64" ], @@ -216,9 +205,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "cpu": [ "x64" ], @@ -233,9 +222,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "cpu": [ "arm64" ], @@ -250,9 +239,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "cpu": [ "x64" ], @@ -267,9 +256,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "cpu": [ "arm64" ], @@ -284,9 +273,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "cpu": [ "x64" ], @@ -301,9 +290,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "cpu": [ "arm" ], @@ -318,9 +307,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ "arm64" ], @@ -335,9 +324,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "cpu": [ "ia32" ], @@ -352,9 +341,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "cpu": [ "loong64" ], @@ -369,9 +358,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "cpu": [ "mips64el" ], @@ -386,9 +375,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "cpu": [ "ppc64" ], @@ -403,9 +392,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "cpu": [ "riscv64" ], @@ -420,9 +409,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "cpu": [ "s390x" ], @@ -437,9 +426,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "cpu": [ "x64" ], @@ -454,9 +443,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "cpu": [ "arm64" ], @@ -471,9 +460,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "cpu": [ "x64" ], @@ -488,9 +477,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "cpu": [ "arm64" ], @@ -505,9 +494,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "cpu": [ "x64" ], @@ -522,9 +511,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "cpu": [ "arm64" ], @@ -539,9 +528,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "cpu": [ "x64" ], @@ -556,9 +545,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "cpu": [ "arm64" ], @@ -573,9 +562,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "cpu": [ "ia32" ], @@ -590,9 +579,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "cpu": [ "x64" ], @@ -648,9 +637,9 @@ "license": "MIT" }, "node_modules/@hono/node-server": { - "version": "1.19.7", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.7.tgz", - "integrity": "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==", + "version": "1.19.9", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", + "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", "license": "MIT", "engines": { "node": ">=18.14.1" @@ -1180,9 +1169,9 @@ } }, "node_modules/@inquirer/core/node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "22.19.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.11.tgz", + "integrity": "sha512-BH7YwL6rA93ReqeQS1c4bsPpcfOmJasG+Fkr6Y59q83f9M1WcBRHR2vM+P9eOisYRcN3ujQoiZY8uk5W+1WL8w==", "dev": true, "license": "MIT", "dependencies": { @@ -1439,6 +1428,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1460,14 +1460,7 @@ "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", @@ -1478,87 +1471,31 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.1.tgz", - "integrity": "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", + "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.7", + "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -1566,14 +1503,15 @@ "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "jose": "^6.1.1", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.0" + "zod-to-json-schema": "^3.25.1" }, "engines": { "node": ">=18" @@ -1591,243 +1529,6 @@ } } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1867,28 +1568,19 @@ } }, "node_modules/@opendocsg/pdf2md": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@opendocsg/pdf2md/-/pdf2md-0.2.2.tgz", - "integrity": "sha512-l6mcjcbL+eboX8ddUgu29R6aFOcDxkadVJvPG+1QcUhUrJt+q3+n0TxmKmYheaXeL17Eq9ZGUtyS2EnPs5a2vw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@opendocsg/pdf2md/-/pdf2md-0.2.3.tgz", + "integrity": "sha512-3LwYnqKa1KEIFE+54FbdPtCgr84To0IqhkFAQP95wG0WGOUc1WS3T+z+rWRkJWNz4fIXcq+Jk+tusLOLQ1XfCg==", "license": "MIT", "dependencies": { "enumify": "^1.0.4", "minimist": "^1.2.5", - "unpdf": "^0.12.1" + "unpdf": "^1.4.0" }, "bin": { "pdf2md": "lib/pdf2md-cli.js" } }, - "node_modules/@opendocsg/pdf2md/node_modules/unpdf": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/unpdf/-/unpdf-0.12.2.tgz", - "integrity": "sha512-3eyDFfayk+Sf5+inJ4OyhecR2BtRFEeZqUfGPdq2O8aBLau9MYL9lAP+GEcSAaVd2JWqde8Dnz38z0x7KRglaA==", - "license": "MIT", - "optionalDependencies": { - "canvas": "^2.11.2" - } - }, "node_modules/@pdf-lib/standard-fonts": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", @@ -1918,16 +1610,16 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.0.tgz", - "integrity": "sha512-n6oQX6mYkG8TRPuPXmbPidkUbsSRalhmaaVAQxvH1IkQy63cwsH+kOjB3e4cpCDHg0aSvsiX9bQ4s2VB6mGWUQ==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.12.1.tgz", + "integrity": "sha512-fXa6uXLxfslBlus3MEpW8S6S9fe5RwmAE5Gd8u3krqOwnkZJV3/lQJiY3LaFdTctLLqJtyMgEUGkbDnRNf6vbQ==", "license": "Apache-2.0", "dependencies": { "debug": "^4.4.3", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.7.3", + "semver": "^7.7.4", "tar-fs": "^3.1.1", "yargs": "^17.7.2" }, @@ -1972,9 +1664,9 @@ } }, "node_modules/@supabase/auth-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.90.0.tgz", - "integrity": "sha512-J5Jgr1XE86NpK0LX8yLdjv3NzzsUnGky72QIGR1AcdVXHQIhwjb3JFEjNutODNKyOrknx00lyClOvqooHFHIiw==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.95.3.tgz", + "integrity": "sha512-vD2YoS8E2iKIX0F7EwXTmqhUpaNsmbU6X2R0/NdFcs02oEfnHyNP/3M716f3wVJ2E5XHGiTFXki6lRckhJ0Thg==", "license": "MIT", "dependencies": { "tslib": "2.8.1" @@ -1984,9 +1676,9 @@ } }, "node_modules/@supabase/functions-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.90.0.tgz", - "integrity": "sha512-YEk4AVtdaUzjxhil2GemOjq0VQVQfg8LmPyooJt80lNscQHfDyCGmHeQ6pDI48dkICTE87V7KVrlXaVGCZa1Rw==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.95.3.tgz", + "integrity": "sha512-uTuOAKzs9R/IovW1krO0ZbUHSJnsnyJElTXIRhjJTqymIVGcHzkAYnBCJqd7468Fs/Foz1BQ7Dv6DCl05lr7ig==", "license": "MIT", "dependencies": { "tslib": "2.8.1" @@ -1996,9 +1688,9 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.90.0.tgz", - "integrity": "sha512-XCgrXuGtBPgxQWKfS8tZ4/deK5+cgUW+XLl4zq4v7JRUfCHlc3ZewZid5hjcpAIDYwGWq9ihrfPUNDAfl5jDdg==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.95.3.tgz", + "integrity": "sha512-LTrRBqU1gOovxRm1vRXPItSMPBmEFqrfTqdPTRtzOILV4jPSueFz6pES5hpb4LRlkFwCPRmv3nQJ5N625V2Xrg==", "license": "MIT", "dependencies": { "tslib": "2.8.1" @@ -2008,9 +1700,9 @@ } }, "node_modules/@supabase/realtime-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.90.0.tgz", - "integrity": "sha512-Hncs2Obk2Wd4Mcj51XDtLqOuiDT6onSmpHkwjsaLDZylgLi4uN81W4LYhj+rdPm3A9nQIRB4/5SZ3Hab2Adlsg==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.95.3.tgz", + "integrity": "sha512-D7EAtfU3w6BEUxDACjowWNJo/ZRo7sDIuhuOGKHIm9FHieGeoJV5R6GKTLtga/5l/6fDr2u+WcW/m8I9SYmaIw==", "license": "MIT", "dependencies": { "@types/phoenix": "^1.6.6", @@ -2023,9 +1715,9 @@ } }, "node_modules/@supabase/storage-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.90.0.tgz", - "integrity": "sha512-50XiDACfHXhibm20J94TEdOYMLXm4fZCHTdAAs9xBDJTBA4RXVN52Bx1MVW34pu3S72rAgObQxVyAFaZ+7+7Tg==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.95.3.tgz", + "integrity": "sha512-4GxkJiXI3HHWjxpC3sDx1BVrV87O0hfX+wvJdqGv67KeCu+g44SPnII8y0LL/Wr677jB7tpjAxKdtVWf+xhc9A==", "license": "MIT", "dependencies": { "iceberg-js": "^0.8.1", @@ -2036,16 +1728,16 @@ } }, "node_modules/@supabase/supabase-js": { - "version": "2.90.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.90.0.tgz", - "integrity": "sha512-foWQl5x1+LuqT7qdnAoCDcKHTNBSaED+eSEOEmmpqXiQuCfJU2K0lDkfGm7PUBx/BDaw3tFObzuJyZtHDbrehA==", + "version": "2.95.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.95.3.tgz", + "integrity": "sha512-Fukw1cUTQ6xdLiHDJhKKPu6svEPaCEDvThqCne3OaQyZvuq2qjhJAd91kJu3PXLG18aooCgYBaB6qQz35hhABg==", "license": "MIT", "dependencies": { - "@supabase/auth-js": "2.90.0", - "@supabase/functions-js": "2.90.0", - "@supabase/postgrest-js": "2.90.0", - "@supabase/realtime-js": "2.90.0", - "@supabase/storage-js": "2.90.0" + "@supabase/auth-js": "2.95.3", + "@supabase/functions-js": "2.95.3", + "@supabase/postgrest-js": "2.95.3", + "@supabase/realtime-js": "2.95.3", + "@supabase/storage-js": "2.95.3" }, "engines": { "node": ">=20.0.0" @@ -2167,9 +1859,9 @@ "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "dev": true, "license": "MIT" }, @@ -2206,9 +1898,9 @@ } }, "node_modules/@types/node": { - "version": "20.19.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz", - "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", + "version": "20.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz", + "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", "license": "MIT", "peer": true, "dependencies": { @@ -2579,21 +2271,14 @@ "@yarnpkg/fslib": "^3.1.3" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC", - "optional": true - }, "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" @@ -2649,9 +2334,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "peer": true, "dependencies": { @@ -2764,13 +2449,6 @@ "dev": true, "license": "MIT" }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "license": "ISC", - "optional": true - }, "node_modules/archive-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", @@ -2847,7 +2525,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -2906,21 +2584,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -2928,19 +2591,10 @@ "license": "MIT" }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-union": { "version": "2.1.0", @@ -2987,9 +2641,9 @@ } }, "node_modules/b4a": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", - "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.4.tgz", + "integrity": "sha512-u20zJLDaSWpxaZ+zaAkEIB2dZZ1o+DF4T/MRbmsvGp9nletHOyiai19OzX1fF8xUBYsO1bPXxODvcd0978pnug==", "license": "Apache-2.0", "peerDependencies": { "react-native-b4a": "*" @@ -3031,9 +2685,9 @@ } }, "node_modules/bare-fs": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.2.tgz", - "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.4.tgz", + "integrity": "sha512-POK4oplfA7P7gqvetNmCs4CNtm9fNsx+IAh7jH7GgU0OJdge2rso0R20TNWVq6VoWcCvsTdlNDaleLHGaKx8CA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -3128,9 +2782,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.11", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", - "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", + "version": "2.9.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3198,69 +2852,27 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/body-parser/node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" + "node": ">=18" }, - "engines": { - "node": ">= 0.8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/brace-expansion": { @@ -3535,9 +3147,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001761", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", - "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", + "version": "1.0.30001770", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", + "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", "dev": true, "funding": [ { @@ -3555,22 +3167,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", - "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.17.0", - "simple-get": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/caw": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", @@ -3666,16 +3262,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -3687,9 +3273,9 @@ } }, "node_modules/chromium-bidi": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-12.0.1.tgz", - "integrity": "sha512-fGg+6jr0xjQhzpy5N4ErZxQ4wF7KLEvhGZXD6EgvZKDhu7iOhZXnZhcDxPJDcwTcrD48NPzOCo84RP2lv3Z+Cg==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz", + "integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==", "license": "Apache-2.0", "dependencies": { "mitt": "^3.0.1", @@ -3917,16 +3503,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "license": "ISC", - "optional": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -3976,23 +3552,17 @@ "proto-list": "~1.2.1" } }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "license": "ISC", - "optional": true - }, "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/content-type": { @@ -4014,10 +3584,13 @@ } }, "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } }, "node_modules/core-util-is": { "version": "1.0.3", @@ -4026,9 +3599,9 @@ "license": "MIT" }, "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -4036,6 +3609,10 @@ }, "engines": { "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cosmiconfig": { @@ -4064,12 +3641,6 @@ } } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, "node_modules/cosmiconfig/node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", @@ -4176,9 +3747,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -4471,9 +4042,9 @@ } }, "node_modules/default-browser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", - "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -4565,13 +4136,6 @@ "node": ">= 14" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "license": "MIT", - "optional": true - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -4590,16 +4154,6 @@ "node": ">=6" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -4623,16 +4177,16 @@ } }, "node_modules/devtools-protocol": { - "version": "0.0.1534754", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1534754.tgz", - "integrity": "sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==", + "version": "0.0.1566079", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1566079.tgz", + "integrity": "sha512-MJfAEA1UfVhSs7fbSQOG4czavUp1ajfg6prlAN0+cmfa2zNjaIbvq8VneP7do1WAQQIvgNJWSMeP6UyI90gIlQ==", "license": "BSD-3-Clause", "peer": true }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -4721,6 +4275,19 @@ "node": ">=0.10.0" } }, + "node_modules/download/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/download/node_modules/decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -4958,9 +4525,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, "license": "ISC" }, @@ -4998,14 +4565,14 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.4", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", - "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -5098,9 +4665,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5111,32 +4678,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, "node_modules/escalade": { @@ -5322,45 +4889,43 @@ } }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "peer": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" }, "funding": { "type": "opencollective", @@ -5368,10 +4933,13 @@ } }, "node_modules/express-rate-limit": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", - "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", + "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", "license": "MIT", + "dependencies": { + "ip-address": "10.0.1" + }, "engines": { "node": ">= 16" }, @@ -5382,21 +4950,6 @@ "express": ">= 4.11" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -5625,9 +5178,9 @@ } }, "node_modules/file-type": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.2.0.tgz", - "integrity": "sha512-vCYBgFOrJQLoTzDyAXAL/RFfKnXXpUYt4+tipVy26nJJhT7ftgGETf2tAQF59EEL61i3MrorV/PG6tf7LJK7eg==", + "version": "21.3.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.0.tgz", + "integrity": "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==", "license": "MIT", "dependencies": { "@tokenizer/inflate": "^0.4.1", @@ -5680,38 +5233,26 @@ } }, "node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -5802,12 +5343,12 @@ } }, "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/from2": { @@ -5875,32 +5416,6 @@ "node": ">=12" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "optional": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5951,7 +5466,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -6029,57 +5544,6 @@ "node": ">= 12" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "optional": true - }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC", - "optional": true - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -6177,9 +5641,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -6207,6 +5671,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -6439,13 +5904,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "license": "ISC", - "optional": true - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -6468,9 +5926,9 @@ } }, "node_modules/hono": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.3.tgz", - "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==", + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz", + "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", "license": "MIT", "peer": true, "engines": { @@ -6554,9 +6012,9 @@ } }, "node_modules/iconv-lite": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", - "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -6706,9 +6164,9 @@ } }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", "engines": { "node": ">= 12" @@ -6945,9 +6403,9 @@ } }, "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -7081,6 +6539,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -7476,9 +6943,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, "license": "MIT" }, @@ -7768,9 +7235,9 @@ "license": "ISC" }, "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -7784,12 +7251,6 @@ "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -8069,19 +7530,22 @@ "license": "MIT" }, "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -8113,15 +7577,6 @@ "node": ">=10.4.0" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromark": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", @@ -8699,18 +8154,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -8721,24 +8164,19 @@ } }, "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/mimic-fn": { @@ -8796,33 +8234,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "license": "MIT", - "optional": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -8833,7 +8244,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -8883,17 +8294,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/nan": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.24.0.tgz", - "integrity": "sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==", - "license": "MIT", - "optional": true - }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -9130,22 +8534,6 @@ "node": ">=4" } }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9156,9 +8544,9 @@ } }, "node_modules/normalize-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", - "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.1.tgz", + "integrity": "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==", "dev": true, "license": "MIT", "engines": { @@ -9192,20 +8580,6 @@ "node": ">=4" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "license": "ISC", - "optional": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -9674,10 +9048,14 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, "node_modules/path-type": { "version": "4.0.0", @@ -9937,17 +9315,17 @@ } }, "node_modules/puppeteer": { - "version": "24.34.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.34.0.tgz", - "integrity": "sha512-Sdpl/zsYOsagZ4ICoZJPGZw8d9gZmK5DcxVal11dXi/1/t2eIXHjCf5NfmhDg5XnG9Nye+yo/LqMzIxie2rHTw==", + "version": "24.37.3", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.37.3.tgz", + "integrity": "sha512-AUGGWq0BhPM+IOS2U9A+ZREH3HDFkV1Y5HERYGDg5cbGXjoGsTCT7/A6VZRfNU0UJJdCclyEimZICkZW6pqJyw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.11.0", - "chromium-bidi": "12.0.1", + "@puppeteer/browsers": "2.12.1", + "chromium-bidi": "14.0.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1534754", - "puppeteer-core": "24.34.0", + "devtools-protocol": "0.0.1566079", + "puppeteer-core": "24.37.3", "typed-query-selector": "^2.12.0" }, "bin": { @@ -9958,27 +9336,27 @@ } }, "node_modules/puppeteer-core": { - "version": "24.34.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.34.0.tgz", - "integrity": "sha512-24evawO+mUGW4mvS2a2ivwLdX3gk8zRLZr9HP+7+VT2vBQnm0oh9jJEZmUE3ePJhRkYlZ93i7OMpdcoi2qNCLg==", + "version": "24.37.3", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.37.3.tgz", + "integrity": "sha512-fokQ8gv+hNgsRWqVuP5rUjGp+wzV5aMTP3fcm8ekNabmLGlJdFHas1OdMscAH9Gzq4Qcf7cfI/Pe6wEcAqQhqg==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.11.0", - "chromium-bidi": "12.0.1", + "@puppeteer/browsers": "2.12.1", + "chromium-bidi": "14.0.0", "debug": "^4.4.3", - "devtools-protocol": "0.0.1534754", + "devtools-protocol": "0.0.1566079", "typed-query-selector": "^2.12.0", - "webdriver-bidi-protocol": "0.3.10", - "ws": "^8.18.3" + "webdriver-bidi-protocol": "0.4.1", + "ws": "^8.19.0" }, "engines": { "node": ">=18" } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -10348,7 +9726,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -10364,7 +9742,7 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -10375,8 +9753,8 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "devOptional": true, + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -10397,7 +9775,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -10428,16 +9806,6 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -10614,9 +9982,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10626,44 +9994,31 @@ } }, "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -10766,27 +10121,24 @@ } }, "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC", - "optional": true - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -10928,7 +10280,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -11060,65 +10412,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true - }, - "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "license": "MIT", - "optional": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "license": "MIT", - "optional": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -11527,24 +10820,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "license": "ISC", - "optional": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/tar-fs": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", @@ -11586,20 +10861,10 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "license": "ISC", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11650,6 +10915,17 @@ } } }, + "node_modules/terser-webpack-plugin/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -11658,9 +10934,9 @@ "license": "MIT" }, "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" @@ -11736,12 +11012,12 @@ } }, "node_modules/token-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", - "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", "license": "MIT", "dependencies": { - "@borewit/text-codec": "^0.1.0", + "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" }, @@ -11936,13 +11212,14 @@ } }, "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" @@ -12084,9 +11361,9 @@ } }, "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -12253,15 +11530,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -12316,9 +11584,9 @@ } }, "node_modules/watchpack": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.0.tgz", - "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -12340,9 +11608,9 @@ } }, "node_modules/webdriver-bidi-protocol": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.3.10.tgz", - "integrity": "sha512-5LAE43jAVLOhB/QqX4bwSiv0Hg1HBfMmOuwBSXHdvg4GMGu9Y0lIq7p4R/yySu6w74WmaR4GM4H9t2IwLW7hgw==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", + "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", "license": "Apache-2.0" }, "node_modules/webidl-conversions": { @@ -12352,9 +11620,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.104.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.104.1.tgz", - "integrity": "sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==", + "version": "5.105.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz", + "integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==", "dev": true, "license": "MIT", "peer": true, @@ -12369,7 +11637,7 @@ "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.4", + "enhanced-resolve": "^5.19.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -12382,7 +11650,7 @@ "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.4.4", + "watchpack": "^2.5.1", "webpack-sources": "^3.3.3" }, "bin": { @@ -12513,15 +11781,38 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", + "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -12548,9 +11839,9 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -12569,38 +11860,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "optional": true - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -12690,9 +11949,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -12750,13 +12009,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": true - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -12886,7 +12138,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", From 5acc6f7f3875e1596497aa9608287a2f8f2f1dac Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:44:20 +0200 Subject: [PATCH 03/13] fix: DOCX outline mode should not trigger on default length param Only switch to raw XML mode when offset is explicitly non-zero. Previously, the default fileReadLineLimit (1000) passed as length would incorrectly trigger raw XML mode for large documents. --- src/utils/files/docx.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index d86b72b59..c9ef0341f 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -456,8 +456,8 @@ export class DocxFileHandler implements FileHandler { const offset = options?.offset ?? 0; const length = options?.length; - // If user explicitly requests offset or a non-default length, give raw XML - const wantsRaw = offset !== 0 || (length !== undefined && length < totalLines); + // If user explicitly requests non-zero offset, give raw XML with pagination + const wantsRaw = offset !== 0; if (wantsRaw) { let startLine: number; From b680d66caaeb85c40ca55de0bda998e28d6bff58 Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:48:13 +0200 Subject: [PATCH 04/13] fix: extractAllText regex was matching w:tbl/w:tc/w:tr instead of only w:t The regex ]*> matched any tag starting with 'w:t' including w:tbl, w:tc, w:tr etc. Fixed to ]*)?> which requires the tag name to end at > or whitespace. Also added full-document text preview at top of outline so content is always visible regardless of XML nesting depth (text boxes, etc). --- src/utils/files/docx.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index c9ef0341f..e262c51af 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -223,9 +223,16 @@ function extractOutline(xml: string): string { } // Summary header + const allText = extractAllText(xml); + const textPreview = allText.length > 500 + ? allText.substring(0, 500) + '...' + : allText; + const header = `DOCX Outline: ${children.length} body children, ${paragraphCount} paragraphs, ${tableCount} tables, ${imageCount} images\n` + `Use read_file with offset/length to see raw XML of specific sections.\n` + `Use edit_block with old_string/new_string to edit the XML directly.\n` + + '─'.repeat(70) + '\n' + + `Full text preview:\n"${textPreview}"\n` + '─'.repeat(70); return header + '\n' + lines.join('\n'); @@ -238,7 +245,8 @@ function extractOutline(xml: string): string { /** Extract all ... text content from an XML fragment */ function extractAllText(xml: string): string { const texts: string[] = []; - const re = /]*>([\s\S]*?)<\/w:t>/g; + // Match or but NOT , , , etc. + const re = /]*)?>([^<]*)<\/w:t>/g; let m; while ((m = re.exec(xml)) !== null) { if (m[1]) texts.push(m[1]); From 5d025796f44fe8b8499fd2975df324bcae45ae43 Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:49:25 +0200 Subject: [PATCH 05/13] refactor: remove flat text preview, structural outline is sufficient The regex fix made the outline show text correctly in all elements including table cells with text boxes. A flat text dump loses the structural awareness that makes the outline useful for editing. --- src/utils/files/docx.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index e262c51af..05634d7fc 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -223,16 +223,9 @@ function extractOutline(xml: string): string { } // Summary header - const allText = extractAllText(xml); - const textPreview = allText.length > 500 - ? allText.substring(0, 500) + '...' - : allText; - const header = `DOCX Outline: ${children.length} body children, ${paragraphCount} paragraphs, ${tableCount} tables, ${imageCount} images\n` + `Use read_file with offset/length to see raw XML of specific sections.\n` + `Use edit_block with old_string/new_string to edit the XML directly.\n` + - '─'.repeat(70) + '\n' + - `Full text preview:\n"${textPreview}"\n` + '─'.repeat(70); return header + '\n' + lines.join('\n'); From 6ca8bd87b9d91b419d6c561d2a3508a4aed7c62e Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 22:54:56 +0200 Subject: [PATCH 06/13] improve: outline shows XML fragments for direct use in edit_block - Paragraphs and SDTs now show text fragments instead of plain text, so Claude can copy them directly into edit_block calls - Table cells still show plain text for readability - Updated tool description: offset must be non-zero for raw XML mode - Added extractTextFragments() helper --- src/server.ts | 2 ++ src/utils/files/docx.ts | 34 ++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/server.ts b/src/server.ts index 833eb830b..4a066dca3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -325,6 +325,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { * EDITING WORKFLOW: 1) read_file to get outline, 2) read_file with offset/length to see raw XML around what you want to edit, 3) edit_block with old_string/new_string using XML fragments copied from the read output. + * IMPORTANT: offset MUST be non-zero to get raw XML (use offset=1 to start from line 1). + offset=0 always returns the outline regardless of length. ${PATH_GUIDANCE} ${CMD_PREFIX_DESCRIPTION}`, diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index 05634d7fc..bae3197c6 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -148,6 +148,7 @@ function extractOutline(xml: string): string { if (tag === 'w:p') { const text = extractAllText(child); + const textFragments = extractTextFragments(child); const style = extractParagraphStyle(child); const hasDrawing = child.includes(' 200) { - line += `\n "${text.substring(0, 200)}..."`; + if (textFragments.length > 0) { + const joined = textFragments.join(''); + if (joined.length > 200) { + line += `\n ${textFragments.slice(0, 5).join('')}...`; } else { - line += `\n "${text}"`; + line += `\n ${joined}`; } } else if (!hasDrawing) { line += ' (empty)'; @@ -188,7 +190,7 @@ function extractOutline(xml: string): string { for (let r = 0; r < Math.min(rows.length, 4); r++) { const cells = rows[r].map(c => { if (!c || c.trim() === '') return ''; - return c.length > 30 ? c.substring(0, 30) + '…' : c; + return c.length > 40 ? c.substring(0, 40) + '…' : c; }); line += `\n row${r}: [${cells.join(' | ')}]`; } @@ -197,18 +199,19 @@ function extractOutline(xml: string): string { tableCount++; } else if (tag === 'w:sdt') { // Structured document tag — look inside for content - const sdtText = extractAllText(child); + const sdtFragments = extractTextFragments(child); const innerTables = (child.match(/]/g) || []).length; let line = `[${i}] w:sdt`; if (innerTables > 0) { line += ` (contains ${innerTables} table${innerTables > 1 ? 's' : ''})`; tableCount += innerTables; } - if (sdtText) { - if (sdtText.length > 150) { - line += `\n "${sdtText.substring(0, 150)}..."`; + if (sdtFragments.length > 0) { + const joined = sdtFragments.join(''); + if (joined.length > 150) { + line += `\n ${sdtFragments.slice(0, 3).join('')}...`; } else { - line += `\n "${sdtText}"`; + line += `\n ${joined}`; } } lines.push(line); @@ -247,6 +250,17 @@ function extractAllText(xml: string): string { return texts.join('').trim(); } +/** Extract ... elements as XML fragments for use in edit_block */ +function extractTextFragments(xml: string): string[] { + const fragments: string[] = []; + const re = /]*)?>([^<]*)<\/w:t>/g; + let m; + while ((m = re.exec(xml)) !== null) { + if (m[1] && m[1].trim()) fragments.push(m[0]); + } + return fragments; +} + /** Extract paragraph style id from w:pPr/w:pStyle */ function extractParagraphStyle(xml: string): string | null { const m = xml.match(/ Date: Mon, 16 Feb 2026 22:59:17 +0200 Subject: [PATCH 07/13] feat: content search inside DOCX files (parallel to Excel search) Extracts text from document.xml, headers, and footers, then searches with regex matching. Runs async alongside ripgrep, same pattern as searchExcelFiles. Triggered when filePattern includes *.docx or rootPath is a .docx file. --- src/search-manager.ts | 173 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/src/search-manager.ts b/src/search-manager.ts index 8ebacb96c..3bbe861d2 100644 --- a/src/search-manager.ts +++ b/src/search-manager.ts @@ -5,6 +5,7 @@ import { validatePath } from './tools/filesystem.js'; import { capture } from './utils/capture.js'; import { getRipgrepPath } from './utils/ripgrep-resolver.js'; import { isExcelFile } from './utils/files/index.js'; +import PizZip from 'pizzip'; export interface SearchResult { file: string; @@ -171,6 +172,27 @@ export interface SearchSessionOptions { }); } + // For content searches, also search DOCX files + const shouldSearchDocx = options.searchType === 'content' && + this.shouldIncludeDocxSearch(options.filePattern, validPath); + + if (shouldSearchDocx) { + this.searchDocxFiles( + validPath, + options.pattern, + options.ignoreCase !== false, + options.maxResults, + options.filePattern + ).then(docxResults => { + for (const result of docxResults) { + session.results.push(result); + session.totalMatches++; + } + }).catch((err) => { + capture('docx_search_error', { error: err instanceof Error ? err.message : String(err) }); + }); + } + // Wait for first chunk of data or early completion instead of fixed delay // Excel search runs in background and results are merged via readSearchResults const firstChunk = new Promise(resolve => { @@ -469,6 +491,157 @@ export interface SearchSessionOptions { return excelFiles; } + /** + * Determine if DOCX search should be included based on context + */ + private shouldIncludeDocxSearch(filePattern?: string, rootPath?: string): boolean { + const docxExtensions = ['.docx']; + + if (rootPath) { + const lowerPath = rootPath.toLowerCase(); + if (docxExtensions.some(ext => lowerPath.endsWith(ext))) { + return true; + } + } + + if (filePattern) { + const lowerPattern = filePattern.toLowerCase(); + if (docxExtensions.some(ext => + lowerPattern.includes(`*${ext}`) || lowerPattern.endsWith(ext) + )) { + return true; + } + } + + return false; + } + + /** + * Search DOCX files for content matches + * Extracts text from document.xml and searches it + */ + private async searchDocxFiles( + rootPath: string, + pattern: string, + ignoreCase: boolean, + maxResults?: number, + filePattern?: string + ): Promise { + const results: SearchResult[] = []; + + const flags = ignoreCase ? 'i' : ''; + let regex: RegExp; + try { + regex = new RegExp(pattern, flags); + } catch { + const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + regex = new RegExp(escaped, flags); + } + + let docxFiles = await this.findDocxFiles(rootPath); + + if (filePattern) { + const patterns = filePattern.split('|').map(p => p.trim()).filter(Boolean); + docxFiles = docxFiles.filter(filePath => { + const fileName = path.basename(filePath); + return patterns.some(pat => { + if (pat.includes('*')) { + const regexPat = pat.replace(/\./g, '\\.').replace(/\*/g, '.*'); + return new RegExp(`^${regexPat}$`, 'i').test(fileName); + } + return fileName.toLowerCase() === pat.toLowerCase(); + }); + }); + } + + for (const filePath of docxFiles) { + if (maxResults && results.length >= maxResults) break; + + try { + const buf = await fs.readFile(filePath); + const zip = new PizZip(buf); + + // Search all XML parts that can contain text + const xmlParts = ['word/document.xml', 'word/header1.xml', 'word/header2.xml', + 'word/header3.xml', 'word/footer1.xml', 'word/footer2.xml', 'word/footer3.xml']; + + for (const xmlPath of xmlParts) { + if (maxResults && results.length >= maxResults) break; + + const file = zip.file(xmlPath); + if (!file) continue; + + const xml = file.asText(); + // Extract all text with position tracking + const wtRe = /]*)?>([^<]*)<\/w:t>/g; + let m; + let lineNum = 0; + + while ((m = wtRe.exec(xml)) !== null) { + if (maxResults && results.length >= maxResults) break; + const text = m[1]; + if (!text || !text.trim()) continue; + lineNum++; + + if (regex.test(text)) { + const match = text.match(regex); + const matchContext = match + ? this.getMatchContext(text, match.index || 0, match[0].length) + : text.substring(0, 150); + + const partName = xmlPath === 'word/document.xml' ? '' : `:${xmlPath.replace('word/', '')}`; + results.push({ + file: `${filePath}${partName}`, + line: lineNum, + match: matchContext, + type: 'content' + }); + } + } + } + } catch { + continue; + } + } + + return results; + } + + /** + * Find all DOCX files in a directory recursively + */ + private async findDocxFiles(rootPath: string): Promise { + const docxFiles: string[] = []; + const isDocx = (name: string) => name.toLowerCase().endsWith('.docx'); + + async function walk(dir: string): Promise { + try { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (!entry.name.startsWith('.') && entry.name !== 'node_modules') { + await walk(fullPath); + } + } else if (entry.isFile() && isDocx(entry.name)) { + docxFiles.push(fullPath); + } + } + } catch { /* skip */ } + } + + try { + const stats = await fs.stat(rootPath); + if (stats.isFile() && isDocx(rootPath)) { + return [rootPath]; + } else if (stats.isDirectory()) { + await walk(rootPath); + } + } catch { /* skip */ } + + return docxFiles; + } + /** * Extract context around a match for display (show surrounding text) */ From 55bee4e5036fee68327f616a1680813ae13975e4 Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 23:05:31 +0200 Subject: [PATCH 08/13] improve: show all table rows in outline, better editing guidance - Show all table rows instead of truncating at 4 (tables contain real content) - Increase cell text preview to 60 chars, paragraph text to 500 chars - Update outline header: show edit_block example with syntax - Add guidance for bulk operations (translation): use Python script - Clarify raw XML access requires offset=1 --- src/utils/files/docx.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index bae3197c6..c6c650de9 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -170,8 +170,8 @@ function extractOutline(xml: string): string { if (textFragments.length > 0) { const joined = textFragments.join(''); - if (joined.length > 200) { - line += `\n ${textFragments.slice(0, 5).join('')}...`; + if (joined.length > 500) { + line += `\n ${textFragments.slice(0, 8).join('')}...`; } else { line += `\n ${joined}`; } @@ -186,15 +186,14 @@ function extractOutline(xml: string): string { let line = `[${i}] w:tbl (${rows.length} rows)`; const style = extractTableStyle(child); if (style) line += ` style="${style}"`; - // Show first few rows as preview - for (let r = 0; r < Math.min(rows.length, 4); r++) { + // Show all rows (tables usually contain the real content) + for (let r = 0; r < rows.length; r++) { const cells = rows[r].map(c => { if (!c || c.trim() === '') return ''; - return c.length > 40 ? c.substring(0, 40) + '…' : c; + return c.length > 60 ? c.substring(0, 60) + '…' : c; }); line += `\n row${r}: [${cells.join(' | ')}]`; } - if (rows.length > 4) line += `\n ... (${rows.length - 4} more rows)`; lines.push(line); tableCount++; } else if (tag === 'w:sdt') { @@ -227,8 +226,8 @@ function extractOutline(xml: string): string { // Summary header const header = `DOCX Outline: ${children.length} body children, ${paragraphCount} paragraphs, ${tableCount} tables, ${imageCount} images\n` + - `Use read_file with offset/length to see raw XML of specific sections.\n` + - `Use edit_block with old_string/new_string to edit the XML directly.\n` + + `Edit with: edit_block(file, old_string="old text", new_string="new text")\n` + + `Raw XML: use read_file with offset=1 to see pretty-printed XML for advanced edits.\n` + '─'.repeat(70); return header + '\n' + lines.join('\n'); @@ -504,7 +503,8 @@ export class DocxFileHandler implements FileHandler { return { content: outline + headerFooterInfo + - `\n\nRaw XML: ${totalLines} lines, ${rawSizeKB}KB. Use offset/length to read raw XML sections.`, + `\n\nRaw XML: ${totalLines} lines, ${rawSizeKB}KB.` + + `\nFor bulk changes (translation, mass find/replace): use start_process with a Python script using zipfile to edit elements.`, mimeType: 'text/plain', metadata: { isDocx: true, lineCount: totalLines }, }; From ed773a737ed5c98436d571610ca701e2575d0553 Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 23:06:09 +0200 Subject: [PATCH 09/13] docs: add bulk operations guidance to read_file tool description --- src/server.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server.ts b/src/server.ts index 4a066dca3..5a15c2f2e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -327,6 +327,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { using XML fragments copied from the read output. * IMPORTANT: offset MUST be non-zero to get raw XML (use offset=1 to start from line 1). offset=0 always returns the outline regardless of length. + * For BULK changes (translation, mass replacements): use start_process with Python + zipfile module to find/replace all elements at once. ${PATH_GUIDANCE} ${CMD_PREFIX_DESCRIPTION}`, From 5e327d43461a6afa270e1e0dd99c7ec7c2cbc54a Mon Sep 17 00:00:00 2001 From: Eduard Ruzga Date: Mon, 16 Feb 2026 23:20:12 +0200 Subject: [PATCH 10/13] feat: DOCX creation via write_file write_file('doc.docx', content) creates a valid DOCX file with: - Markdown headings (#, ##, ###) converted to Word heading styles - Plain text lines as Normal paragraphs - Empty lines as empty paragraphs - Proper Calibri font defaults and page margins - Complete ZIP structure with styles.xml, content types, relationships Updated write_file tool description to reflect DOCX creation support. --- src/server.ts | 1 + src/utils/files/docx.ts | 98 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/server.ts b/src/server.ts index 5a15c2f2e..2d48a90bc 100644 --- a/src/server.ts +++ b/src/server.ts @@ -367,6 +367,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { IMPORTANT: DO NOT use this tool to create PDF files. Use 'write_pdf' for all PDF creation tasks. DO NOT use this tool to edit DOCX files. Use 'edit_block' with old_string/new_string instead. + To CREATE a new DOCX, use write_file with .docx extension — text content with markdown headings (#, ##, ###) is converted to styled DOCX paragraphs. CHUNKING IS STANDARD PRACTICE: Always write files in chunks of 25-30 lines maximum. This is the normal, recommended way to write files - not an emergency measure. diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index c6c650de9..ef19af537 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -430,6 +430,57 @@ function extractHeaderFooterOutline(zip: PizZip): string { return parts.length > 0 ? '\n\nHeaders/Footers:\n' + parts.join('\n') : ''; } +// ════════════════════════════════════════════════════════════════ +// DOCX creation helpers +// ════════════════════════════════════════════════════════════════ + +function escapeXml(text: string): string { + return text.replace(/&/g, '&').replace(//g, '>') + .replace(/"/g, '"').replace(/'/g, '''); +} + +function createMinimalDocxZip(documentXml: string): PizZip { + const zip = new PizZip(); + + zip.file('[Content_Types].xml', + `` + + `` + + `` + + `` + + `` + + `` + + ``); + + zip.file('_rels/.rels', + `` + + `` + + `` + + ``); + + zip.file('word/_rels/document.xml.rels', + `` + + `` + + `` + + ``); + + zip.file('word/styles.xml', + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + `` + + ``); + + zip.file('word/document.xml', documentXml); + + return zip; +} + // ════════════════════════════════════════════════════════════════ // Count occurrences helper // ════════════════════════════════════════════════════════════════ @@ -511,14 +562,47 @@ export class DocxFileHandler implements FileHandler { } /** - * Write DOCX — not directly supported. - * Use edit_block for modifications. + * Write/create a DOCX file. + * Content is plain text — each line becomes a paragraph. + * Lines starting with # become headings (# = Heading1, ## = Heading2, etc.) */ - async write(_path: string, _content: any, _mode?: 'rewrite' | 'append'): Promise { - throw new Error( - 'DOCX files cannot be created using write_file. ' + - 'Use edit_block with old_string/new_string to edit existing DOCX files.' - ); + async write(path: string, content: any, mode?: 'rewrite' | 'append'): Promise { + if (mode === 'append') { + throw new Error('DOCX append not supported. Use edit_block to modify existing DOCX files.'); + } + + const text = typeof content === 'string' ? content : String(content); + const lines = text.split('\n'); + + // Build paragraph XML from lines + const paragraphs: string[] = []; + for (const line of lines) { + const headingMatch = line.match(/^(#{1,6})\s+(.+)/); + if (headingMatch) { + const level = headingMatch[1].length; + const headingText = headingMatch[2]; + paragraphs.push( + `` + + `${escapeXml(headingText)}` + ); + } else if (line.trim() === '') { + paragraphs.push(``); + } else { + paragraphs.push( + `${escapeXml(line)}` + ); + } + } + + const docXml = `` + + `` + + `${paragraphs.join('')}` + + `` + + ``; + + const zip = createMinimalDocxZip(docXml); + const buf = zip.generate({ type: 'nodebuffer', compression: 'DEFLATE', compressionOptions: { level: 6 } }); + await fs.writeFile(path, buf); } /** From 685d108b272b3f1da30e053eba5b4742f15167a0 Mon Sep 17 00:00:00 2001 From: edgarssskore Date: Thu, 19 Feb 2026 16:15:27 +0200 Subject: [PATCH 11/13] fix: DOCX type safety and malformed-XML infinite loop - Add 'docx' to FileInfo.fileType union in base.ts; remove `as any` cast in DocxFileHandler.getInfo - Fix splitTopLevelElements infinite loop: indexOf returning -1 would set i=0 and restart the loop; now bails out with break on malformed XML in all three tag branches (closing, processing-instruction, opening/self-closing) Co-Authored-By: Claude Sonnet 4.6 --- src/utils/files/base.ts | 2 +- src/utils/files/docx.ts | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/utils/files/base.ts b/src/utils/files/base.ts index 9bf2f8c4a..852e0b21f 100644 --- a/src/utils/files/base.ts +++ b/src/utils/files/base.ts @@ -215,7 +215,7 @@ export interface FileInfo { permissions: string; /** File type classification */ - fileType: 'text' | 'excel' | 'image' | 'binary'; + fileType: 'text' | 'excel' | 'image' | 'binary' | 'docx'; /** Type-specific metadata */ metadata?: FileMetadata; diff --git a/src/utils/files/docx.ts b/src/utils/files/docx.ts index ef19af537..407d59f3d 100644 --- a/src/utils/files/docx.ts +++ b/src/utils/files/docx.ts @@ -366,7 +366,8 @@ function splitTopLevelElements(xml: string): string[] { if (depth === 0) { // Find end of this closing tag const closeEnd = xml.indexOf('>', i); - if (closeEnd !== -1 && currentStart !== -1) { + if (closeEnd === -1) break; // malformed XML — bail out + if (currentStart !== -1) { elements.push(xml.substring(currentStart, closeEnd + 1).trim()); currentStart = -1; } @@ -376,6 +377,7 @@ function splitTopLevelElements(xml: string): string[] { } else if (xml[i + 1] === '?' || xml[i + 1] === '!') { // Processing instruction or comment — skip const end = xml.indexOf('>', i); + if (end === -1) break; // malformed XML — bail out i = end + 1; continue; } else { @@ -383,7 +385,8 @@ function splitTopLevelElements(xml: string): string[] { if (depth === 0) currentStart = i; // Check for self-closing const tagEnd = xml.indexOf('>', i); - if (tagEnd !== -1 && xml[tagEnd - 1] === '/') { + if (tagEnd === -1) break; // malformed XML — bail out + if (xml[tagEnd - 1] === '/') { // Self-closing if (depth === 0) { elements.push(xml.substring(currentStart, tagEnd + 1).trim()); @@ -755,7 +758,7 @@ export class DocxFileHandler implements FileHandler { isDirectory: false, isFile: true, permissions: (stats.mode & 0o777).toString(8), - fileType: 'docx' as any, + fileType: 'docx', metadata, }; } From ffb234a1d22c2e289698b6f69d64accb3552910a Mon Sep 17 00:00:00 2001 From: edgarssskore Date: Thu, 19 Feb 2026 16:48:42 +0200 Subject: [PATCH 12/13] fix: allow empty new_string in edit_block for deletion use case Relax validation so new_string can be an empty string (delete the matched text), while old_string must still be non-empty. Co-Authored-By: Claude Sonnet 4.6 --- src/tools/schemas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/schemas.ts b/src/tools/schemas.ts index 67959c650..a2cdb39eb 100644 --- a/src/tools/schemas.ts +++ b/src/tools/schemas.ts @@ -140,7 +140,7 @@ export const EditBlockArgsSchema = z.object({ data => { // Helper to check if value is actually provided (not undefined, not empty string) const hasValue = (v: unknown) => v !== undefined && v !== ''; - return (hasValue(data.old_string) && hasValue(data.new_string)) || + return (hasValue(data.old_string) && data.new_string !== undefined) || (hasValue(data.range) && hasValue(data.content)); }, { message: "Must provide either (old_string + new_string) or (range + content)" } From 28b161c60e7f81237ff944761c7520003ac62903 Mon Sep 17 00:00:00 2001 From: edgarssskore Date: Thu, 19 Feb 2026 16:48:57 +0200 Subject: [PATCH 13/13] =?UTF-8?q?refactor:=20handleEditBlock=20=E2=80=94?= =?UTF-8?q?=20single=20handler=20lookup,=20handler-agnostic=20dispatch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Validate path and resolve file handler once at the top instead of duplicating validatePath + getFileHandler in each branch - Compute hasEditRange once and reuse across both dispatch paths - Remove hardcoded .endsWith('.docx') extension check — DocxFileHandler is picked up automatically via hasEditRange like any other handler - Path 1 (range + content): Excel and any future range-based handlers - Path 2 (old_string + new_string): handlers with editRange own their own text-replacement (DOCX); plain text falls through to performSearchReplace Co-Authored-By: Claude Sonnet 4.6 --- src/tools/edit.ts | 105 +++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/src/tools/edit.ts b/src/tools/edit.ts index 3548c68a6..5933b9cc1 100644 --- a/src/tools/edit.ts +++ b/src/tools/edit.ts @@ -371,89 +371,90 @@ function highlightDifferences(expected: string, actual: string): string { export async function handleEditBlock(args: unknown): Promise { const parsed = EditBlockArgsSchema.parse(args); - // Structured files: Range rewrite // Note: Check for truthy range to handle empty strings from AI clients that send all optional params const hasRange = parsed.range !== undefined && parsed.range !== ''; const hasContent = parsed.content !== undefined && parsed.content !== ''; - if (hasRange && hasContent) { - try { - // Validate path before any filesystem operations - const validatedPath = await validatePath(parsed.file_path); - const { getFileHandler } = await import('../utils/files/factory.js'); - const handler = await getFileHandler(validatedPath); + // Validate path and resolve handler once — used by both dispatch paths below + let validatedPath: string; + let handler: Awaited>; + try { + validatedPath = await validatePath(parsed.file_path); + const { getFileHandler } = await import('../utils/files/factory.js'); + handler = await getFileHandler(validatedPath); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return createErrorResponse(errorMessage); + } - // Parse content if it's a JSON string (AI often sends arrays as JSON strings) - let content = parsed.content; - if (typeof content === 'string') { - try { - content = JSON.parse(content); - } catch { - // Leave as-is if not valid JSON - let handler decide - } + const hasEditRange = 'editRange' in handler && typeof handler.editRange === 'function'; + + // Path 1: Range rewrite (Excel, etc.) — range + content + if (hasRange && hasContent) { + // Parse content if it's a JSON string (AI often sends arrays as JSON strings) + let content = parsed.content; + if (typeof content === 'string') { + try { + content = JSON.parse(content); + } catch { + // Leave as-is if not valid JSON - let handler decide } + } - // Check if handler supports range editing - if ('editRange' in handler && typeof handler.editRange === 'function') { + if (hasEditRange) { + try { // parsed.range is guaranteed non-empty string by hasRange check above - await handler.editRange(validatedPath, parsed.range!, content, parsed.options); + await handler.editRange!(validatedPath!, parsed.range!, content, parsed.options); return { content: [{ type: "text", text: `Successfully updated range ${parsed.range} in ${parsed.file_path}` }], }; - } else { - return createErrorResponse(`Range-based editing not supported for ${parsed.file_path}. For text files, use old_string and new_string parameters instead. If your client requires range/content parameters, set them to empty strings ("").`); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return createErrorResponse(errorMessage); } - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - return createErrorResponse(errorMessage); } + + return createErrorResponse(`Range-based editing not supported for ${parsed.file_path}. For text files, use old_string and new_string parameters instead. If your client requires range/content parameters, set them to empty strings ("").`); } - // Text files: String replacement - // Validate required parameters for text replacement + // Path 2: Text replacement — old_string + new_string if (parsed.old_string === undefined || parsed.new_string === undefined) { return createErrorResponse(`Text replacement requires both old_string and new_string parameters`); } - // DOCX files: Route through DocxFileHandler.editRange for XML-aware editing - if (parsed.file_path.toLowerCase().endsWith('.docx')) { + // If the handler implements editRange it owns text-replacement for its file type + // (e.g. DocxFileHandler does find/replace on pretty-printed XML rather than raw bytes). + // Plain text files fall through to performSearchReplace. + if (hasEditRange) { try { - const validatedPath = await validatePath(parsed.file_path); - const { getFileHandler } = await import('../utils/files/factory.js'); - const handler = await getFileHandler(validatedPath); - - if ('editRange' in handler && typeof handler.editRange === 'function') { - const result = await handler.editRange(validatedPath, '', { - old_string: parsed.old_string, - new_string: parsed.new_string, - expected_replacements: parsed.expected_replacements, - }); + const result = await handler.editRange!(validatedPath!, '', { + old_string: parsed.old_string, + new_string: parsed.new_string, + expected_replacements: parsed.expected_replacements, + }); - if (result.success) { - return { - content: [{ - type: "text", - text: `Successfully applied ${result.editsApplied} edit(s) to ${parsed.file_path}` - }], - }; - } else { - const errorMsg = result.errors?.map(e => e.error).join('; ') || 'Unknown error'; - return createErrorResponse(errorMsg); - } + if (result.success) { + return { + content: [{ + type: "text", + text: `Successfully applied ${result.editsApplied} edit(s) to ${parsed.file_path}` + }], + }; } + + const errorMsg = result.errors?.map(e => e.error).join('; ') || 'Unknown error'; + return createErrorResponse(errorMsg); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return createErrorResponse(errorMessage); } } - const searchReplace = { + return performSearchReplace(parsed.file_path, { search: parsed.old_string, replace: parsed.new_string - }; - - return performSearchReplace(parsed.file_path, searchReplace, parsed.expected_replacements); + }, parsed.expected_replacements); } \ No newline at end of file