From 7f2bec8c0efe1aa46b7dc52d9dac0b66bd6ad63a Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Wed, 23 Sep 2026 22:14:12 +0530 Subject: [PATCH 1/7] In between --- electron/diagram-handlers.cjs | 149 ++++ electron/preload.cjs | 6 + package-lock.json | 100 +++ package.json | 1 + src/components/MarkdownPreview.jsx | 28 +- src/components/MarkdownToolbar.jsx | 25 +- src/components/WebViewPreview.jsx | 20 +- src/components/WireframeBlock.jsx | 186 +++++ src/components/WireframeEditor.jsx | 708 ++++++++++++++++++ src/services/wireframeService.js | 97 +++ src/styles/WireframeEditor.css | 267 +++++++ .../WireframeBlock.integration.test.jsx | 91 +++ src/utils/diagramFileUtils.js | 2 +- src/utils/renderUtils.js | 22 + 14 files changed, 1696 insertions(+), 6 deletions(-) create mode 100644 src/components/WireframeBlock.jsx create mode 100644 src/components/WireframeEditor.jsx create mode 100644 src/services/wireframeService.js create mode 100644 src/styles/WireframeEditor.css create mode 100644 src/tests/components/WireframeBlock.integration.test.jsx diff --git a/electron/diagram-handlers.cjs b/electron/diagram-handlers.cjs index b07d2999..07584a0c 100644 --- a/electron/diagram-handlers.cjs +++ b/electron/diagram-handlers.cjs @@ -547,6 +547,155 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { }; } }); + + // ── Wireframe handlers ──────────────────────────────────────────────────── + + function getWireframeSourceFile(diagramId, documentPath) { + const root = resolveWorkspaceRoot(documentPath); + const mediaFile = path.join(root, 'media', 'wireframe', `${diagramId}.wireframe.json`); + return mediaFile; + } + + function getWireframeImageFile(diagramId, documentPath) { + const root = resolveWorkspaceRoot(documentPath); + return path.join(root, 'media', 'wireframe', `${diagramId}.png`); + } + + /** + * Read wireframe source file + */ + ipcMain.handle('wireframe:read-source', async (event, { diagramId, documentPath }) => { + try { + const sourceFile = getWireframeSourceFile(diagramId, documentPath); + const data = await fs.readFile(sourceFile, 'utf-8'); + return { success: true, data }; + } catch (err) { + if (isNotFoundError(err)) { + return { success: false, notFound: true }; + } + console.error('Failed to read wireframe source:', err); + return { success: false, error: err.message }; + } + }); + + /** + * Write wireframe source file + */ + ipcMain.handle('wireframe:write-source', async (event, { diagramId, data, documentPath }) => { + try { + const root = resolveWorkspaceRoot(documentPath); + const wireframeDir = path.join(root, 'media', 'wireframe'); + const sourceFile = path.join(wireframeDir, `${diagramId}.wireframe.json`); + const existed = fsSync.existsSync(sourceFile); + const previousBase64 = existed ? fsSync.readFileSync(sourceFile).toString('base64') : null; + const previousHash = previousBase64 && typeof hashContent === 'function' ? hashContent(previousBase64) : null; + + await mkdirRecursive(wireframeDir); + await fs.writeFile(sourceFile, data, 'utf-8'); + emitDiagramSync(sourceFile, { op: existed ? 'update' : 'create', baseHash: previousHash }); + + return { success: true }; + } catch (err) { + console.error('Failed to write wireframe source:', err); + return { success: false, error: err.message }; + } + }); + + /** + * Write wireframe image file + */ + ipcMain.handle('wireframe:write-image', async (event, { diagramId, imageData, documentPath }) => { + try { + const root = resolveWorkspaceRoot(documentPath); + const wireframeDir = path.join(root, 'media', 'wireframe'); + const imageFile = path.join(wireframeDir, `${diagramId}.png`); + const existed = fsSync.existsSync(imageFile); + const previousBase64 = existed ? fsSync.readFileSync(imageFile).toString('base64') : null; + const previousHash = previousBase64 && typeof hashContent === 'function' ? hashContent(previousBase64) : null; + + await mkdirRecursive(wireframeDir); + + let buffer; + if (typeof imageData === 'string') { + const base64Data = imageData.replace(/^data:image\/png;base64,/, ''); + buffer = Buffer.from(base64Data, 'base64'); + } else { + buffer = imageData; + } + + await fs.writeFile(imageFile, buffer); + emitDiagramSync(imageFile, { op: existed ? 'update' : 'create', baseHash: previousHash }); + + return { success: true }; + } catch (err) { + console.error('Failed to write wireframe image:', err); + return { success: false, error: err.message }; + } + }); + + /** + * Read wireframe image file as base64 + */ + ipcMain.handle('wireframe:read-image', async (event, { diagramId, documentPath }) => { + try { + const imageFile = getWireframeImageFile(diagramId, documentPath); + const imageData = await fs.readFile(imageFile); + const base64 = imageData.toString('base64'); + return { success: true, data: `data:image/png;base64,${base64}` }; + } catch (err) { + if (isNotFoundError(err)) { + return { success: false, notFound: true }; + } + console.error('Failed to read wireframe image:', err); + return { success: false, error: err.message }; + } + }); + + /** + * Delete wireframe files + */ + ipcMain.handle('wireframe:delete', async (event, { diagramId, documentPath }) => { + try { + const root = resolveWorkspaceRoot(documentPath); + const filesToDelete = [ + path.join(root, 'media', 'wireframe', `${diagramId}.wireframe.json`), + path.join(root, 'media', 'wireframe', `${diagramId}.png`), + ]; + + for (const file of filesToDelete) { + if (fsSync.existsSync(file)) { + const hash = (typeof hashContent === 'function') + ? hashContent(fsSync.readFileSync(file).toString('base64')) + : null; + await fs.unlink(file); + emitDiagramSync(file, { op: 'delete', baseHash: hash }); + } + } + + return { success: true }; + } catch (err) { + console.error('Failed to delete wireframe diagram:', err); + return { success: false, error: err.message }; + } + }); + + /** + * Check if wireframe diagram exists + */ + ipcMain.handle('wireframe:exists', async (event, { diagramId, documentPath }) => { + try { + const sourceFile = getWireframeSourceFile(diagramId, documentPath); + try { + await fs.access(sourceFile); + return { exists: true }; + } catch { + return { exists: false }; + } + } catch (err) { + console.error('Failed to check wireframe existence:', err); + return { exists: false, error: err.message }; + } + }); } /** diff --git a/electron/preload.cjs b/electron/preload.cjs index 048b465f..5e785ae0 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -240,6 +240,12 @@ contextBridge.exposeInMainWorld("notesApi", { drawioReadImage: (payload) => ipcRenderer.invoke("drawio:read-image", payload), drawioDelete: (payload) => ipcRenderer.invoke("drawio:delete", payload), drawioExists: (payload) => ipcRenderer.invoke("drawio:exists", payload), + wireframeReadSource: (payload) => ipcRenderer.invoke("wireframe:read-source", payload), + wireframeWriteSource: (payload) => ipcRenderer.invoke("wireframe:write-source", payload), + wireframeWriteImage: (payload) => ipcRenderer.invoke("wireframe:write-image", payload), + wireframeReadImage: (payload) => ipcRenderer.invoke("wireframe:read-image", payload), + wireframeDelete: (payload) => ipcRenderer.invoke("wireframe:delete", payload), + wireframeExists: (payload) => ipcRenderer.invoke("wireframe:exists", payload), openInEditor: (filePath) => ipcRenderer.invoke("documents:open-in-editor", filePath), openWebView: (payload) => ipcRenderer.invoke("documents:open-web-view", payload), downloadPdf: (payload) => ipcRenderer.invoke("documents:download-pdf", payload), diff --git a/package-lock.json b/package-lock.json index 78f905f7..e3cf5e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.1.0", "globals": "^15.14.0", + "grapesjs": "^0.23.6", "jsdom": "^29.1.1", "lucide-react": "^0.405.0", "markdown-table": "^3.0.4", @@ -5621,6 +5622,17 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/backbone": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@types/backbone/-/backbone-1.4.15.tgz", + "integrity": "sha512-WWeKtYlsIMtDyLbbhkb96taJMEbfQBnuz7yw1u0pkphCOtksemoWhIXhK74VRCY9hbjnsH3rsJu2uUiFtnsEYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jquery": "*", + "@types/underscore": "*" + } + }, "node_modules/@types/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -5979,6 +5991,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jquery": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-4.0.1.tgz", + "integrity": "sha512-9a59A/tycXgYuPABcp6/3spSShn0NT2UOM4EfHvMumjYi4lJWTsK5SZWjhx3yRm9IHGCeWXdV2YfNsrWrft/CA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -6094,6 +6113,13 @@ "license": "MIT", "optional": true }, + "node_modules/@types/underscore": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.13.0.tgz", + "integrity": "sha512-L6LBgy1f0EFQZ+7uSA57+n2g/s4Qs5r06Vwrwn0/nuK1de+adz00NWaztRQ30aEqw5qOaWbPI8u2cGQ52lj6VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -7357,6 +7383,28 @@ "proxy-from-env": "^2.1.0" } }, + "node_modules/backbone": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.1.tgz", + "integrity": "sha512-ADy1ztN074YkWbHi8ojJVFe3vAanO/lrzMGZWUClIP7oDD/Pjy2vrASraUP+2EVCfIiTtCW4FChVow01XneivA==", + "dev": true, + "license": "MIT", + "dependencies": { + "underscore": ">=1.8.3" + } + }, + "node_modules/backbone-undo": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/backbone-undo/-/backbone-undo-0.2.6.tgz", + "integrity": "sha512-AsfpNiljLXlk7TcffDUu3EAUq7CxWbyTNwARWrql5XTzN4vh6WzEEBZYaKK4kTTz+iW1tSzqUooaGRIwO83kWA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "backbone": ">=1.0.0", + "underscore": ">=1.4.4" + } + }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -8160,6 +8208,13 @@ "@codemirror/view": "^6.0.0" } }, + "node_modules/codemirror-formatting": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/codemirror-formatting/-/codemirror-formatting-1.0.0.tgz", + "integrity": "sha512-br9yM6eJI3pJHekEnoyHaBEb1B7XxxDjju+vRyBe8QGLp5saTIXXkZ+eFCTqXSAtI8QEZDFVEX2/SOjH2sVWRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/codemirror-lang-mermaid": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/codemirror-lang-mermaid/-/codemirror-lang-mermaid-0.5.0.tgz", @@ -11331,6 +11386,30 @@ "dev": true, "license": "ISC" }, + "node_modules/grapesjs": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/grapesjs/-/grapesjs-0.23.6.tgz", + "integrity": "sha512-I8M/sPWjHm6MLIdUtRFNOKsQ3PtDgIDsc2S8ANkJsfHj3ZoH98oNMMWr64Kx22XgjHCQ4xpUx7nvXyQSKV1mrQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@types/backbone": "1.4.15", + "backbone": "1.4.1", + "backbone-undo": "0.2.6", + "codemirror": "5.63.0", + "codemirror-formatting": "1.0.0", + "html-entities": "~1.4.0", + "promise-polyfill": "8.3.0", + "underscore": "1.13.8" + } + }, + "node_modules/grapesjs/node_modules/codemirror": { + "version": "5.63.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.63.0.tgz", + "integrity": "sha512-KlLWRPggDg2rBD1Mx7/EqEhaBdy+ybBCVh/efgjBDsPpMeEu6MbTAJzIT4TuCzvmbTEgvKOGzVT6wdBTNusqrg==", + "dev": true, + "license": "MIT" + }, "node_modules/graphlib": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", @@ -11563,6 +11642,13 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true, + "license": "MIT" + }, "node_modules/html-void-elements": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", @@ -15373,6 +15459,13 @@ "node": ">=0.4.0" } }, + "node_modules/promise-polyfill": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", + "dev": true, + "license": "MIT" + }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", @@ -18026,6 +18119,13 @@ "react": ">=15.0.0" } }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", diff --git a/package.json b/package.json index 7427a4e8..926bcf78 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.1.0", "globals": "^15.14.0", + "grapesjs": "^0.23.6", "jsdom": "^29.1.1", "lucide-react": "^0.405.0", "markdown-table": "^3.0.4", diff --git a/src/components/MarkdownPreview.jsx b/src/components/MarkdownPreview.jsx index 1bf1c428..7a12c24d 100644 --- a/src/components/MarkdownPreview.jsx +++ b/src/components/MarkdownPreview.jsx @@ -20,6 +20,7 @@ import useConfirm from "../hooks/useConfirm"; import { MermaidBlock } from "./MermaidBlock"; import { ExcalidrawBlock } from "./ExcalidrawBlock"; import { DrawioBlock } from "./DrawioBlock"; +import { WireframeBlock } from "./WireframeBlock"; import { PreviewModalsContainer } from "./preview/PreviewModalsContainer"; import { VideoPlayerModal } from "./VideoPlayerModal"; @@ -2166,12 +2167,14 @@ export const MarkdownPreview = memo(function MarkdownPreviewContent({ {parts.map((part, index) => { const blockKey = part.type === "mermaid" - ? `mermaid-${part.startLine}-${part.value.slice(0, 35)}` + ? `mermaid-${part.startLine}-${(part.value || "").slice(0, 35)}` : part.type === "excalidraw" ? part.diagramId ? `excalidraw-${part.diagramId}` : `excalidraw-${part.startLine}-${part.imagePath}` : part.type === "drawio" ? part.diagramId ? `drawio-${part.diagramId}` : `drawio-${part.startLine}-${part.imagePath}` - : `md-${part.startLine}-${part.value.slice(0, 30)}`; + : part.type === "wireframe" + ? part.diagramId ? `wireframe-${part.diagramId}` : `wireframe-${part.startLine}-${part.imagePath}` + : `md-${part.startLine}-${(part.value || "").slice(0, 30)}`; return part.type === "mermaid" ? ( ) + ) : part.type === "wireframe" ? ( + readOnly ? ( +
+ {part.imagePath ? ( + Wireframe diagram + ) : ( +
+ Wireframe diagram +
+ )} +
+ ) : ( + + ) ) : (
{ + const diagramId = generateDiagramId(); + const rawPath = basePath ? toRelativeDocPath(basePath, `media/wireframes/${diagramId}.png`, workspacePath) : `media/wireframes/${diagramId}.png`; + const rawMarkdown = `![Wireframe Diagram](${rawPath}){data-diagram-id="${diagramId}"}`; + const normalizedMarkdown = rawMarkdown.replace(/\(([^)]+)\)/, (_match, pathValue) => { + return `(${normalizeImagePathForMarkdown(pathValue)})`; + }); + + insertTextAtCursor(value, onChange, `\n\n${normalizedMarkdown}\n`, textareaRef); + setShowMermaidBuilder(false); + if (!basePath) { + onNotify?.("Wireframe reference inserted. Save this note to resolve diagram files.", "info"); + return; + } + onNotify?.("Wireframe reference inserted.", "success"); + }; + const createScreenshotFileName = () => { const now = new Date(); const pad = (value) => String(value).padStart(2, "0"); @@ -1590,7 +1608,7 @@ export function MarkdownToolbar({ {diagramMode === "picker" ? ( <> -
+
+
Tool Selection Guide:
@@ -1610,6 +1632,7 @@ export function MarkdownToolbar({
  • Mermaid: Quick code-based diagrams (flows, sequences, trees). Saved as inline text.
  • Excalidraw: Hand-drawn style wireframes, sketches, and collaborative brainstorm boards.
  • Draw.io: Structured professional schemas, network charts, and architecture models.
  • +
  • Wireframe: Responsive UI mockups, screen layouts, and web components (GrapesJS).
  • diff --git a/src/components/WebViewPreview.jsx b/src/components/WebViewPreview.jsx index ac77925b..fe6028c7 100644 --- a/src/components/WebViewPreview.jsx +++ b/src/components/WebViewPreview.jsx @@ -6,6 +6,8 @@ import { } from "../utils/renderUtils"; import { MermaidBlock } from "./MermaidBlock"; import { ExcalidrawBlock } from "./ExcalidrawBlock"; +import { DrawioBlock } from "./DrawioBlock"; +import { WireframeBlock } from "./WireframeBlock"; export function WebViewPreview({ content, basePath }) { const parts = useMemo(() => parseDiagramBlocks(content), [content]); @@ -55,11 +57,25 @@ export function WebViewPreview({ content, basePath }) { + ) : part.type === "drawio" ? ( + + ) : part.type === "wireframe" ? ( + ) : (
    { + if (!diagramId) return; + + let cancelled = false; + const loadWireframe = async () => { + try { + setLoading(true); + + const source = await readWireframeSource(diagramId, documentPath); + if (!cancelled && source) { + setDiagramData(source); + } + + const imageDataUrl = await readWireframeImage(diagramId, documentPath); + if (!cancelled) { + if (imageDataUrl) { + setThumbnail(imageDataUrl); + } else if (imagePath) { + setThumbnail(imagePath); + } + setError(""); + } + } catch (err) { + if (!cancelled) { + console.error("Failed to load Wireframe:", err); + setError("Failed to load wireframe"); + } + } finally { + if (!cancelled) { + setLoading(false); + } + } + }; + + void loadWireframe(); + return () => { + cancelled = true; + }; + }, [diagramId, documentPath, imagePath]); + + const handleDownload = async () => { + if (!thumbnail) return; + try { + const filename = `${diagramId || "wireframe-diagram"}.png`; + const result = await runExport("diagram_image", { + dataUrl: thumbnail, + filename, + customExportType: "diagram_wireframe", + category: "diagram", + }); + if (result?.success) { + onNotify?.(`Wireframe exported to ${result.filename}`, "success"); + } else { + onNotify?.(result?.error || "Failed to export wireframe.", "error"); + } + } catch (err) { + console.error("Failed to download wireframe:", err); + onNotify?.("Failed to export wireframe.", "error"); + } + }; + + const handleSave = async (newDiagramData, previewImageData) => { + try { + setLoading(true); + + const sourceSaved = await writeWireframeSource(diagramId, newDiagramData, documentPath); + if (!sourceSaved) { + throw new Error("Failed to persist wireframe source"); + } + + if (previewImageData) { + setThumbnail(previewImageData); + } + + setDiagramData(newDiagramData); + onUpdate?.({ + diagramId, + imagePath, + data: newDiagramData, + }); + + setError(""); + onNotify?.("Wireframe saved successfully.", "success"); + onForceSaveNote?.(); + } catch (err) { + console.error("Failed to save wireframe:", err); + setError("Failed to save wireframe"); + onNotify?.("Failed to save wireframe.", "error"); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    !loading && setIsModalOpen(true)} + role="button" + tabIndex={0} + onKeyPress={(e) => { + if (e.key === "Enter" && !loading) setIsModalOpen(true); + }} + > + {loading &&
    Loading...
    } + + {thumbnail && !loading ? ( +
    +
    + + + +
    + Wireframe preview setThumbnail(null)} + /> +
    + ) : !loading ? ( +
    +
    📐
    + Click to create a Wireframe +
    + ) : null} +
    + + {error &&
    {error}
    } + + {isModalOpen && ( + setIsModalOpen(false)} + onSave={handleSave} + /> + )} +
    + ); +} + +export default WireframeBlock; diff --git a/src/components/WireframeEditor.jsx b/src/components/WireframeEditor.jsx new file mode 100644 index 00000000..39f117dd --- /dev/null +++ b/src/components/WireframeEditor.jsx @@ -0,0 +1,708 @@ +import { useEffect, useRef, useState, useCallback } from "react"; +import { Save, X, Download } from "lucide-react"; +import AppButton from "./AppButton"; +import OverlayDialog from "./OverlayDialog"; +import useConfirm from "../hooks/useConfirm"; +import { writeWireframeSource, writeWireframeImage } from "../services/wireframeService"; +import { runExport } from "../services/electronService"; +import "../styles/ExcalidrawEditor.css"; +import "../styles/WireframeEditor.css"; + +// ── Wireframe component definitions ───────────────────────────────────────── + +const WIREFRAME_COMPONENTS = [ + { + id: "wf-frame", + label: "Frame", + icon: "🖼️", + content: `
    +
    Screen / Frame
    +
    `, + category: "Layout", + }, + { + id: "wf-container", + label: "Container", + icon: "📦", + content: `
    Container
    `, + category: "Layout", + }, + { + id: "wf-header", + label: "Header", + icon: "🔝", + content: `
    +
    App Name
    +
    + Nav 1Nav 2Nav 3 +
    +
    `, + category: "Layout", + }, + { + id: "wf-footer", + label: "Footer", + icon: "🔻", + content: `
    Footer content · Links · Copyright
    `, + category: "Layout", + }, + { + id: "wf-navbar", + label: "Navbar", + icon: "🧭", + content: ``, + category: "Layout", + }, + { + id: "wf-sidebar", + label: "Sidebar", + icon: "📋", + content: ``, + category: "Layout", + }, + { + id: "wf-text", + label: "Text", + icon: "📝", + content: `

    Text content goes here. Click to edit this placeholder text.

    `, + category: "Elements", + }, + { + id: "wf-heading", + label: "Heading", + icon: "H", + content: `

    Page Heading

    `, + category: "Elements", + }, + { + id: "wf-button", + label: "Button", + icon: "🔘", + content: ``, + category: "Elements", + }, + { + id: "wf-input", + label: "Input", + icon: "✏️", + content: ``, + category: "Elements", + }, + { + id: "wf-select", + label: "Select", + icon: "🔽", + content: ``, + category: "Elements", + }, + { + id: "wf-checkbox", + label: "Checkbox", + icon: "☑️", + content: ``, + category: "Elements", + }, + { + id: "wf-radio", + label: "Radio", + icon: "🔵", + content: `
    + + +
    `, + category: "Elements", + }, + { + id: "wf-image", + label: "Image", + icon: "🖼", + content: `
    [ Image ]
    `, + category: "Elements", + }, + { + id: "wf-divider", + label: "Divider", + icon: "➖", + content: `
    `, + category: "Elements", + }, + { + id: "wf-card", + label: "Card", + icon: "🃏", + content: `
    +
    [ Image Area ]
    +
    +
    Card Title
    +
    Card description text goes here.
    + +
    +
    `, + category: "Patterns", + }, + { + id: "wf-list", + label: "List", + icon: "📄", + content: `
      +
    • List item 1
    • List item 2
    • List item 3
    • +
    `, + category: "Elements", + }, + { + id: "wf-table", + label: "Table", + icon: "📊", + content: ` + + + + + + + + + + + +
    Col 1Col 2Col 3
    DataDataData
    DataDataData
    `, + category: "Patterns", + }, + { + id: "wf-tabs", + label: "Tabs", + icon: "🗂️", + content: `
    +
    +
    Tab 1
    +
    Tab 2
    +
    Tab 3
    +
    +
    Tab content area
    +
    `, + category: "Patterns", + }, + { + id: "wf-modal", + label: "Modal", + icon: "🪟", + content: `
    +
    +
    +
    +
    Modal Title
    +
    ✕
    +
    +
    Modal content and description text goes here.
    +
    + + +
    +
    +
    `, + category: "Patterns", + }, + { + id: "wf-form", + label: "Form", + icon: "📋", + content: `
    +
    Form Title
    + + + +
    `, + category: "Patterns", + }, +]; + +// ── PNG export helper ──────────────────────────────────────────────────────── + +async function exportWireframeToPng(editor) { + return new Promise((resolve) => { + try { + if (!editor) { + resolve(createFallbackPng(editor)); + return; + } + + const html = editor.getHtml?.() || ""; + const css = editor.getCss?.() || ""; + + const width = 1200; + const height = 800; + + const svgDoc = ` + + +
    + +
    + ${html} +
    +
    +
    +
    + `; + + const blob = new Blob([svgDoc], { type: "image/svg+xml;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const img = new Image(); + + img.onload = () => { + try { + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, width, height); + ctx.drawImage(img, 0, 0); + URL.revokeObjectURL(url); + resolve(canvas.toDataURL("image/png")); + } catch { + URL.revokeObjectURL(url); + resolve(createFallbackPng(editor)); + } + }; + + img.onerror = () => { + URL.revokeObjectURL(url); + resolve(createFallbackPng(editor)); + }; + + img.src = url; + } catch { + resolve(createFallbackPng(editor)); + } + }); +} + +function createFallbackPng(editor) { + const canvas = document.createElement('canvas'); + canvas.width = 1200; + canvas.height = 800; + const ctx = canvas.getContext('2d'); + + // Background + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, 1200, 800); + + // Border + ctx.strokeStyle = '#cccccc'; + ctx.lineWidth = 2; + ctx.strokeRect(10, 10, 1180, 780); + + // Label + ctx.fillStyle = '#888888'; + ctx.font = '16px system-ui, sans-serif'; + ctx.textAlign = 'center'; + + const html = editor?.getHtml?.() || ''; + const hasContent = html.replace(/<[^>]+>/g, '').trim().length > 10; + ctx.fillText(hasContent ? 'Wireframe Preview' : 'Empty Wireframe', 600, 410); + + return canvas.toDataURL('image/png'); +} + +// ── WireframeEditor component ──────────────────────────────────────────────── + +export function WireframeEditor({ + initialData, // JSON string of GrapesJS project data + diagramId, + documentPath, + onClose, + onSave, + onNotify, +}) { + const editorRef = useRef(null); + const editorContainerRef = useRef(null); + const saveButtonRef = useRef(null); + const { confirm } = useConfirm(); + const [isSaving, setIsSaving] = useState(false); + const [isExporting, setIsExporting] = useState(false); + const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + const [isLoading, setIsLoading] = useState(true); + + const handleClose = useCallback(async () => { + if (hasUnsavedChanges) { + const confirmed = await confirm({ + title: "Discard Changes?", + message: "You have unsaved changes. Are you sure you want to discard them?", + confirmLabel: "Discard", + cancelLabel: "Cancel", + variant: "danger", + }); + if (!confirmed) return; + } + onClose?.(); + }, [hasUnsavedChanges, onClose, confirm]); + + // Initialize GrapesJS + useEffect(() => { + if (!editorContainerRef.current || editorRef.current) return; + + let destroyed = false; + + async function initGrapesJS() { + try { + const grapesjs = (await import('grapesjs')).default; + + if (destroyed || !editorContainerRef.current) return; + + const editor = grapesjs.init({ + container: editorContainerRef.current, + height: '100%', + width: '100%', + storageManager: false, // We manage persistence manually + undoManager: true, + deviceManager: { + devices: [ + { name: 'Desktop', width: '' }, + { name: 'Tablet', width: '768px' }, + { name: 'Mobile', width: '375px' }, + ], + }, + // Minimal panel set — strip website builder UI + panels: { + defaults: [ + { + id: 'panel-top', + el: '.panel__top', + buttons: [], + }, + { + id: 'commands', + buttons: [], + }, + { + id: 'options', + buttons: [ + { + active: true, + id: 'sw-visibility', + command: 'sw-visibility', + label: '⬜', + }, + { + id: 'preview', + command: 'preview', + label: '👁', + }, + { + id: 'fullscreen', + command: 'fullscreen', + label: '⛶', + }, + { + id: 'undo', + command: 'core:undo', + label: '↩', + }, + { + id: 'redo', + command: 'core:redo', + label: '↪', + }, + { + id: 'clear-canvas', + command: 'core:canvas-clear', + label: '🗑', + }, + ], + }, + { + id: 'views', + buttons: [ + { + id: 'open-blocks', + active: true, + command: 'open-blocks', + label: '⊞', + }, + { + id: 'open-sm', + command: 'open-sm', + label: '🎨', + }, + { + id: 'open-layers', + command: 'open-layers', + label: '≡', + }, + ], + }, + ], + }, + blockManager: { + appendTo: '.wireframe-blocks-panel', + }, + styleManager: { + appendTo: '.wireframe-sm-panel', + sectors: [ + { + name: 'Layout', + open: true, + properties: ['display', 'flex-direction', 'align-items', 'justify-content', 'gap', 'padding', 'margin', 'width', 'height', 'min-height'], + }, + { + name: 'Typography', + open: false, + properties: ['font-family', 'font-size', 'font-weight', 'color', 'text-align', 'line-height'], + }, + { + name: 'Appearance', + open: false, + properties: ['background-color', 'border', 'border-radius', 'opacity'], + }, + ], + }, + layerManager: { + appendTo: '.wireframe-layers-panel', + }, + traitManager: { + appendTo: '.wireframe-traits-panel', + }, + // Wireframe-optimised CSS defaults + protectedCss: ` + * { box-sizing: border-box; } + body { margin: 0; padding: 16px; font-family: system-ui, sans-serif; background: #fff; } + `, + canvas: { + styles: [` + * { box-sizing: border-box; } + body { margin: 0; font-family: system-ui, sans-serif; } + `], + }, + }); + + editorRef.current = editor; + + // Register wireframe component blocks + const blockManager = editor.BlockManager; + WIREFRAME_COMPONENTS.forEach((comp) => { + blockManager.add(comp.id, { + label: `
    ${comp.icon}
    ${comp.label}
    `, + category: comp.category, + content: comp.content, + attributes: { class: 'fa fa-th' }, + }); + }); + + // Load existing project data + if (initialData) { + try { + const parsed = typeof initialData === 'string' ? JSON.parse(initialData) : initialData; + if (parsed && typeof parsed === 'object') { + editor.loadProjectData(parsed); + } else if (typeof initialData === 'string' && initialData.trim().startsWith('<')) { + // Legacy: raw HTML + editor.setComponents(initialData); + } + } catch { + // Ignore parse errors for corrupted data + } + } + + // Mark dirty on change + editor.on('component:add component:remove component:update style:change', () => { + setHasUnsavedChanges(true); + }); + + setIsLoading(false); + } catch (err) { + console.error('Failed to initialize GrapesJS:', err); + setIsLoading(false); + } + } + + void initGrapesJS(); + + return () => { + destroyed = true; + if (editorRef.current) { + try { + editorRef.current.destroy(); + } catch { + // ignore + } + editorRef.current = null; + } + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // Escape key handler + useEffect(() => { + const handleEscape = (event) => { + if (event.key === 'Escape') handleClose(); + }; + document.addEventListener('keydown', handleEscape); + return () => document.removeEventListener('keydown', handleEscape); + }, [handleClose]); + + // Ctrl+S handler + const handleSaveRef = useRef(null); + useEffect(() => { handleSaveRef.current = handleSave; }); + useEffect(() => { + const handleKeyDown = (event) => { + if ((event.ctrlKey || event.metaKey) && event.key?.toLowerCase() === 's') { + event.preventDefault(); + event.stopPropagation(); + handleSaveRef.current?.(); + } + }; + window.addEventListener('keydown', handleKeyDown, true); + return () => window.removeEventListener('keydown', handleKeyDown, true); + }, []); + + const handleSave = async () => { + const editor = editorRef.current; + if (!editor || isSaving) return; + + setIsSaving(true); + try { + const projectData = editor.getProjectData(); + const projectJson = JSON.stringify(projectData); + + // Render preview PNG + const pngDataUrl = await exportWireframeToPng(editor); + + // Persist source + if (diagramId) { + await writeWireframeSource(diagramId, projectJson, documentPath); + if (pngDataUrl) { + await writeWireframeImage(diagramId, pngDataUrl, documentPath); + } + } + + setHasUnsavedChanges(false); + onSave?.(projectJson, pngDataUrl); + onNotify?.('Wireframe saved successfully.', 'success'); + } catch (err) { + console.error('Failed to save wireframe:', err); + onNotify?.(err?.message || 'Failed to save wireframe.', 'error'); + } finally { + setIsSaving(false); + } + }; + + const handleDownload = async () => { + const editor = editorRef.current; + if (!editor || isExporting) return; + + setIsExporting(true); + try { + const pngDataUrl = await exportWireframeToPng(editor); + if (!pngDataUrl) { + onNotify?.('Failed to generate wireframe image.', 'error'); + return; + } + + const filename = `${diagramId || 'wireframe'}.png`; + const result = await runExport('diagram_image', { + dataUrl: pngDataUrl, + filename, + customExportType: 'diagram_wireframe', + category: 'diagram', + }); + + if (result?.success) { + onNotify?.(`Wireframe exported to ${result.filename}`, 'success'); + } else { + onNotify?.(result?.error || 'Failed to export wireframe.', 'error'); + } + } catch (err) { + console.error('Failed to download wireframe:', err); + onNotify?.('Failed to export wireframe.', 'error'); + } finally { + setIsExporting(false); + } + }; + + return ( + +
    +

    Wireframe Editor

    +
    + + + + + + +
    +
    + +
    + {isLoading && ( +
    + Loading Wireframe Editor... +
    + )} +
    +
    +
    +
    +
    +
    +
    +
    + + ); +} + +export default WireframeEditor; diff --git a/src/services/wireframeService.js b/src/services/wireframeService.js new file mode 100644 index 00000000..13032010 --- /dev/null +++ b/src/services/wireframeService.js @@ -0,0 +1,97 @@ +/** + * Electron service for Wireframe diagram file operations + * Handles reading, writing, and managing wireframe diagram files. + * Follows the same pattern as drawioService.js. + */ + +function invokeWireframe(method, payload) { + const apiMethod = window.notesApi?.[method]; + if (typeof apiMethod === 'function') { + return apiMethod(payload); + } + throw new Error(`Wireframe API method unavailable: ${method}`); +} + +/** + * Read wireframe source file (.wireframe.json) + */ +export async function readWireframeSource(diagramId, documentPath) { + try { + const response = await invokeWireframe('wireframeReadSource', { diagramId, documentPath }); + if (response && response.success) { + return response.data; + } + return null; + } catch (err) { + console.error('Failed to read wireframe source:', err); + return null; + } +} + +/** + * Write wireframe source file (.wireframe.json) + */ +export async function writeWireframeSource(diagramId, data, documentPath) { + try { + const response = await invokeWireframe('wireframeWriteSource', { diagramId, data, documentPath }); + return response?.success ?? false; + } catch (err) { + console.error('Failed to write wireframe source:', err); + return false; + } +} + +/** + * Write wireframe image file (.png) + */ +export async function writeWireframeImage(diagramId, imageData, documentPath) { + try { + const response = await invokeWireframe('wireframeWriteImage', { diagramId, imageData, documentPath }); + return response?.success ?? false; + } catch (err) { + console.error('Failed to write wireframe image:', err); + return false; + } +} + +/** + * Read wireframe image file (.png) as a data URL + */ +export async function readWireframeImage(diagramId, documentPath) { + try { + const response = await invokeWireframe('wireframeReadImage', { diagramId, documentPath }); + if (response?.success && response?.data) { + return response.data; + } + return null; + } catch (err) { + console.error('Failed to read wireframe image:', err); + return null; + } +} + +/** + * Delete wireframe diagram files + */ +export async function deleteWireframe(diagramId, documentPath) { + try { + const response = await invokeWireframe('wireframeDelete', { diagramId, documentPath }); + return response?.success ?? false; + } catch (err) { + console.error('Failed to delete wireframe:', err); + return false; + } +} + +/** + * Check if wireframe diagram exists + */ +export async function wireframeExists(diagramId, documentPath) { + try { + const response = await invokeWireframe('wireframeExists', { diagramId, documentPath }); + return response?.exists ?? false; + } catch (err) { + console.error('Failed to check wireframe existence:', err); + return false; + } +} diff --git a/src/styles/WireframeEditor.css b/src/styles/WireframeEditor.css new file mode 100644 index 00000000..28c5426c --- /dev/null +++ b/src/styles/WireframeEditor.css @@ -0,0 +1,267 @@ +/* ══════════════════════════════════════════════════════════════════ + WireframeEditor — GrapesJS theme overrides + Inherits .excalidraw-modal-overlay / .excalidraw-modal-container + from ExcalidrawEditor.css + ══════════════════════════════════════════════════════════════════ */ + +.wireframe-modal-container { + background: var(--surface-bg); +} + +.wireframe-editor-wrapper { + flex: 1; + min-height: 0; + display: flex; + overflow: hidden; + position: relative; +} + +.wireframe-sidebar { + width: 260px; + background: var(--surface-bg); + border-right: 1px solid var(--border-soft); + display: flex; + flex-direction: column; + overflow-y: auto; + flex-shrink: 0; +} + +/* ── GrapesJS canvas area ─────────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-editor { + flex: 1; + border: none; + font-family: var(--font-ui, system-ui, sans-serif); +} + +.wireframe-editor-wrapper .gjs-cv-canvas { + background: #f4f4f4; + width: 100%; + height: 100%; +} + +:root[data-theme="dark"] .wireframe-editor-wrapper .gjs-cv-canvas { + background: #1e2228; +} + +/* ── GrapesJS toolbar / panels ────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-pn-panels { + background: var(--surface-bg); + border-right: 1px solid var(--border-soft); +} + +.wireframe-editor-wrapper .gjs-pn-panel { + background: transparent; +} + +.wireframe-editor-wrapper .gjs-pn-btn { + color: var(--text-muted); + border: none; + background: transparent; + padding: 6px 8px; + border-radius: var(--radius-sm, 4px); + cursor: pointer; + transition: background var(--motion-fast), color var(--motion-fast); +} + +.wireframe-editor-wrapper .gjs-pn-btn:hover, +.wireframe-editor-wrapper .gjs-pn-btn.gjs-pn-active { + background: var(--surface-hover); + color: var(--text-strong); +} + +/* ── Blocks panel ─────────────────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-blocks-c { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + padding: 8px; + overflow-y: auto; + background: var(--surface-bg); +} + +.wireframe-editor-wrapper .gjs-block { + background: var(--surface-elevated); + border: 1px solid var(--border-soft); + border-radius: var(--radius-md, 6px); + color: var(--text-strong); + font-size: 11px; + font-weight: 500; + padding: 8px 6px 6px; + text-align: center; + cursor: grab; + transition: background var(--motion-fast), border-color var(--motion-fast), box-shadow var(--motion-fast); + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + min-width: 0; + word-break: break-word; +} + +.wireframe-editor-wrapper .gjs-block:hover { + background: var(--surface-hover); + border-color: var(--border-default); + box-shadow: 0 2px 8px rgba(0,0,0,0.08); +} + +.wireframe-editor-wrapper .gjs-block__media { + font-size: 18px; + line-height: 1; +} + +/* ── Style manager ────────────────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-sm-sector { + border-bottom: 1px solid var(--border-subtle); + padding: 6px 8px; +} + +.wireframe-editor-wrapper .gjs-sm-sector-title { + background: transparent; + color: var(--text-muted); + font-size: 10px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + padding: 4px 0 4px; + border: none; + cursor: pointer; +} + +.wireframe-editor-wrapper .gjs-field { + background: var(--surface-bg); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm, 4px); + color: var(--app-text); +} + +.wireframe-editor-wrapper .gjs-field input, +.wireframe-editor-wrapper .gjs-field select { + background: transparent; + color: var(--app-text); + border: none; + font-size: 11px; +} + +/* ── Selected component highlight ─────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-selected { + outline: 2px solid var(--accent-solid) !important; + outline-offset: 1px !important; +} + +/* ── Toolbar (floating component toolbar) ─────────────────────────── */ +.wireframe-editor-wrapper .gjs-toolbar { + background: var(--surface-elevated); + border: 1px solid var(--border-soft); + border-radius: var(--radius-md, 6px); + box-shadow: var(--shadow-sm); +} + +.wireframe-editor-wrapper .gjs-toolbar-item { + color: var(--text-muted); + padding: 4px 6px; + cursor: pointer; + border-radius: var(--radius-sm, 4px); + transition: background var(--motion-fast), color var(--motion-fast); +} + +.wireframe-editor-wrapper .gjs-toolbar-item:hover { + background: var(--surface-hover); + color: var(--text-strong); +} + +/* ── Trait manager ────────────────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-trt-trait { + padding: 4px 8px; + display: flex; + align-items: center; + gap: 6px; +} + +.wireframe-editor-wrapper .gjs-trt-trait label { + font-size: 11px; + color: var(--text-muted); + min-width: 60px; + flex-shrink: 0; +} + +/* ── Layer manager ────────────────────────────────────────────────── */ +.wireframe-editor-wrapper .gjs-layer { + color: var(--text-strong); + font-size: 11px; + background: transparent; +} + +.wireframe-editor-wrapper .gjs-layer:hover { + background: var(--surface-hover); +} + +/* ── Right panel (style/traits/layers) ───────────────────────────── */ +.wireframe-right-panel { + width: 220px; + min-width: 220px; + border-left: 1px solid var(--border-soft); + display: flex; + flex-direction: column; + background: var(--surface-bg); + overflow: hidden; +} + +.wireframe-right-panel-tabs { + display: flex; + border-bottom: 1px solid var(--border-soft); + background: color-mix(in srgb, var(--surface-bg) 94%, var(--surface-elevated)); +} + +.wireframe-right-panel-tab { + flex: 1; + padding: 6px 4px; + border: none; + background: transparent; + color: var(--text-muted); + font-size: 10px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + cursor: pointer; + transition: color var(--motion-fast), border-bottom var(--motion-fast); + border-bottom: 2px solid transparent; +} + +.wireframe-right-panel-tab.active { + color: var(--accent-solid); + border-bottom-color: var(--accent-solid); +} + +.wireframe-right-panel-body { + flex: 1; + overflow-y: auto; + min-height: 0; +} + +/* ── Wireframe-specific component styles (inside iframe) ──────────── */ +.wireframe-placeholder { + background: #e8e8e8; + border: 2px dashed #b0b0b0; + display: flex; + align-items: center; + justify-content: center; + color: #888; + font-family: system-ui, sans-serif; + font-size: 12px; + font-weight: 500; + box-sizing: border-box; +} + +/* ── Loading state ────────────────────────────────────────────────── */ +.wireframe-editor-loading { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + background: var(--surface-bg); + color: var(--text-muted); + font-size: 0.9rem; + z-index: 5; + gap: 10px; +} diff --git a/src/tests/components/WireframeBlock.integration.test.jsx b/src/tests/components/WireframeBlock.integration.test.jsx new file mode 100644 index 00000000..99429eb0 --- /dev/null +++ b/src/tests/components/WireframeBlock.integration.test.jsx @@ -0,0 +1,91 @@ +// @vitest-environment jsdom +import { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { WireframeBlock } from "../../components/WireframeBlock"; + +const wireframeExistsMock = vi.fn(); +const wireframeReadSourceMock = vi.fn(); +const wireframeReadImageMock = vi.fn(); + +beforeEach(() => { + wireframeExistsMock.mockReset(); + wireframeReadSourceMock.mockReset(); + wireframeReadImageMock.mockReset(); + + globalThis.notesApi = { + wireframeExists: (...args) => wireframeExistsMock(...args), + wireframeReadSource: (...args) => wireframeReadSourceMock(...args), + wireframeReadImage: (...args) => wireframeReadImageMock(...args), + }; +}); + +afterEach(() => { + delete globalThis.notesApi; + document.body.innerHTML = ""; +}); + +function renderBlock(props) { + const host = document.createElement("div"); + document.body.appendChild(host); + const root = createRoot(host); + + act(() => { + root.render(); + }); + + return { + host, + unmount() { + act(() => { + root.unmount(); + }); + host.remove(); + }, + }; +} + +function waitFor(ms) { + return new Promise((resolve) => { + window.setTimeout(resolve, ms); + }); +} + +describe("WireframeBlock", () => { + it("renders placeholder state when wireframe diagram image does not exist", async () => { + wireframeExistsMock.mockResolvedValue({ success: true, exists: false }); + wireframeReadImageMock.mockResolvedValue({ success: false, data: null }); + + const view = renderBlock({ + diagramId: "test-wireframe-id", + }); + + await act(async () => { + await waitFor(50); + }); + + expect(view.host.textContent).toContain("Click to create a Wireframe"); + view.unmount(); + }); + + it("renders preview image and action buttons when wireframe exists", async () => { + wireframeExistsMock.mockResolvedValue({ success: true, exists: true }); + wireframeReadImageMock.mockResolvedValue({ success: true, data: "data:image/png;base64,WIREFRAMETEST" }); + + const view = renderBlock({ + diagramId: "test-wireframe-id", + }); + + await act(async () => { + await waitFor(50); + }); + + const img = view.host.querySelector("img"); + expect(img).toBeTruthy(); + expect(img.getAttribute("src")).toBe("data:image/png;base64,WIREFRAMETEST"); + + const buttons = view.host.querySelectorAll("button"); + expect(buttons.length).toBeGreaterThan(0); + view.unmount(); + }); +}); diff --git a/src/utils/diagramFileUtils.js b/src/utils/diagramFileUtils.js index 60fc123b..eabb00dc 100644 --- a/src/utils/diagramFileUtils.js +++ b/src/utils/diagramFileUtils.js @@ -101,7 +101,7 @@ export function parseDiagramReference(markdownRef) { export function isDiagramReference(imagePath) { return ( Boolean(imagePath) && - (imagePath.includes('excali-diagrams') || imagePath.includes('excalidraw') || imagePath.includes('media/diagrams') || imagePath.includes('media/draw.io') || imagePath.includes('drawio-diagrams')) && + (imagePath.includes('excali-diagrams') || imagePath.includes('excalidraw') || imagePath.includes('media/diagrams') || imagePath.includes('media/draw.io') || imagePath.includes('drawio-diagrams') || imagePath.includes('media/wireframes') || imagePath.includes('wireframes')) && (imagePath.includes('diagram.png') || imagePath.endsWith('.png')) ); } diff --git a/src/utils/renderUtils.js b/src/utils/renderUtils.js index 0d53856f..e672be06 100644 --- a/src/utils/renderUtils.js +++ b/src/utils/renderUtils.js @@ -370,6 +370,7 @@ export function parseDiagramBlocks(content) { const mermaidRegex = /```mermaid\s*([\s\S]*?)```/gi; const excalidrawRegex = /!\[Excalidraw Diagram\]\(((?:\.\.\/|\.\/)*(?:\.notes-app\/)?excali-diagrams\/(?:(?:[^/]+\/)?([^/]+))\/diagram\.png|(?:\.\.\/|\.\/)*media\/(?:excalidraw|diagrams)\/(?:(?:[^/]+\/)?([^/]+))\/diagram\.png|(?:\.\.\/|\.\/)*media\/diagrams\/([^/.]+)\.png)\)\s*(\{[^}]*\})?/gi; const drawioRegex = /!\[(?:Drawio|Draw\.io|draw\.io) Diagram\]\(((?:\.\.\/|\.\/)*(?:\.notes-app\/drawio-diagrams\/|media\/draw\.io\/|media\/drawio\/)([^/.]+)\.png)\)\s*(\{[^}]*\})?/gi; + const wireframeRegex = /!\[(?:Wireframe|wireframe) Diagram\]\(((?:\.\.\/|\.\/)*(?:\.notes-app\/wireframes\/|media\/wireframes\/)([^/.]+)\.png)\)\s*(\{[^}]*\})?/gi; const positions = []; let match; @@ -426,6 +427,20 @@ export function parseDiagramBlocks(content) { }); } + // Find all wireframe image references + while ((match = wireframeRegex.exec(content || ""))) { + const attributeBlock = match[3] || ""; + const explicitDiagramId = readAttribute(attributeBlock, "data-diagram-id"); + positions.push({ + index: match.index, + endIndex: wireframeRegex.lastIndex, + type: "wireframe", + imagePath: match[1], + diagramId: explicitDiagramId || match[2], + fullMatch: match[0], + }); + } + // Sort by position positions.sort((a, b) => a.index - b.index); @@ -457,6 +472,13 @@ export function parseDiagramBlocks(content) { diagramId: pos.diagramId, startLine: currentLine, }); + } else if (pos.type === "wireframe") { + chunks.push({ + type: "wireframe", + imagePath: pos.imagePath, + diagramId: pos.diagramId, + startLine: currentLine, + }); } currentLine += countLines(pos.fullMatch); From bb7a8f94792cda2086e2636550df7ddd45d731a7 Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Wed, 23 Sep 2026 22:30:30 +0530 Subject: [PATCH 2/7] baasic --- src/components/WireframeEditor.jsx | 1191 +++++++++++++++++++--------- src/styles/WireframeEditor.css | 833 +++++++++++++++---- 2 files changed, 1485 insertions(+), 539 deletions(-) diff --git a/src/components/WireframeEditor.jsx b/src/components/WireframeEditor.jsx index 39f117dd..33acced3 100644 --- a/src/components/WireframeEditor.jsx +++ b/src/components/WireframeEditor.jsx @@ -1,6 +1,28 @@ -import { useEffect, useRef, useState, useCallback } from "react"; -import { Save, X, Download } from "lucide-react"; -import AppButton from "./AppButton"; +import { useEffect, useRef, useState, useCallback, useMemo } from "react"; +import { + Save, + X, + Download, + Search, + Monitor, + Tablet, + Smartphone, + Undo2, + Redo2, + Trash2, + Eye, + EyeOff, + Grid3X3, + Layers, + Palette, + Layout, + Square, + Box, + Sliders, + Sparkles, + MousePointer, + Plus, +} from "lucide-react"; import OverlayDialog from "./OverlayDialog"; import useConfirm from "../hooks/useConfirm"; import { writeWireframeSource, writeWireframeImage } from "../services/wireframeService"; @@ -8,236 +30,412 @@ import { runExport } from "../services/electronService"; import "../styles/ExcalidrawEditor.css"; import "../styles/WireframeEditor.css"; -// ── Wireframe component definitions ───────────────────────────────────────── -const WIREFRAME_COMPONENTS = [ +// ── Figma-inspired Component Categories ────────────────────────────────────── + +const CATEGORIES = [ + { id: "all", label: "All Stencils" }, + { id: "frames", label: "Artboards & Frames", icon: Layout }, + { id: "headers", label: "Headers & Nav", icon: Box }, + { id: "hero", label: "Hero Sections", icon: Sparkles }, + { id: "content", label: "Content & Grids", icon: Grid3X3 }, + { id: "components", label: "UI Components", icon: Square }, + { id: "forms", label: "Forms & Inputs", icon: Sliders }, + { id: "tables", label: "Data & Tables", icon: Layers }, + { id: "feedback", label: "Modals & Feedback", icon: MousePointer }, +]; + +const FIGMA_STENCILS = [ + // ── Artboards & Frames ─────────────────────────────────────────────────────── { - id: "wf-frame", - label: "Frame", - icon: "🖼️", - content: `
    -
    Screen / Frame
    + id: "wf-desktop-canvas", + label: "Desktop Canvas", + category: "frames", + desc: "1200px responsive frame with padding", + icon: "🖥️", + content: `
    +
    Desktop Screen Artboard
    `, - category: "Layout", - }, - { - id: "wf-container", - label: "Container", - icon: "📦", - content: `
    Container
    `, - category: "Layout", }, { - id: "wf-header", - label: "Header", - icon: "🔝", - content: `
    -
    App Name
    -
    - Nav 1Nav 2Nav 3 + id: "wf-mobile-device", + label: "Mobile iPhone Frame", + category: "frames", + desc: "375x812px mobile frame with notch", + icon: "📱", + content: `
    +
    +
    -
    `, - category: "Layout", - }, - { - id: "wf-footer", - label: "Footer", - icon: "🔻", - content: `
    Footer content · Links · Copyright
    `, - category: "Layout", - }, - { - id: "wf-navbar", - label: "Navbar", - icon: "🧭", - content: ``, - category: "Layout", +
    Mobile Viewport
    +
    `, }, { - id: "wf-sidebar", - label: "Sidebar", - icon: "📋", - content: ``, - category: "Layout", +
    +
    + Overview +
    +
    +
    +
    Drop dashboard widgets and cards here
    +
    +
    +
    `, }, + + // ── Headers & Nav ─────────────────────────────────────────────────────────── { - id: "wf-text", - label: "Text", - icon: "📝", - content: `

    Text content goes here. Click to edit this placeholder text.

    `, - category: "Elements", + id: "wf-nav-modern", + label: "Modern SaaS Navbar", + category: "headers", + desc: "Logo, pill links, search & CTA buttons", + icon: "🧭", + content: `
    +
    +
    + Brand +
    + +
    +
    + + +
    +
    `, }, { - id: "wf-heading", - label: "Heading", - icon: "H", - content: `

    Page Heading

    `, - category: "Elements", + id: "wf-segmented-tabs", + label: "Figma Segmented Control", + category: "headers", + desc: "iOS/Figma style pill segmented tabs", + icon: "🗂️", + content: `
    + + + +
    `, }, { - id: "wf-button", - label: "Button", - icon: "🔘", - content: ``, - category: "Elements", + id: "wf-page-header", + label: "Page Header with Actions", + category: "headers", + desc: "Title, breadcrumb, badge & action buttons", + icon: "🔝", + content: `
    +
    +
    + Workspace/Settings +
    +
    +

    Project Configuration

    + Live +
    +
    +
    + + +
    +
    `, }, + + // ── Hero Sections ─────────────────────────────────────────────────────────── { - id: "wf-input", - label: "Input", - icon: "✏️", - content: ``, - category: "Elements", + id: "wf-hero-centered", + label: "Hero Centered Section", + category: "hero", + desc: "Headline, badge, CTA buttons & mockup frame", + icon: "🌟", + content: `
    +
    + ✨ Just Released v2.0 +
    +

    Design systems that scale with ease

    +

    Create beautiful wireframes, mockups, and interface flows directly inside your documentation.

    +
    + + +
    +
    + [ App Preview Screen Mockup ] +
    +
    `, }, { - id: "wf-select", - label: "Select", - icon: "🔽", - content: ``, - category: "Elements", + id: "wf-cta-banner", + label: "Call to Action Banner", + category: "hero", + desc: "Dark accent conversion box with buttons", + icon: "📣", + content: `
    +
    +

    Ready to upgrade your workflow?

    +

    Collaborate in real time with high-velocity interface components.

    +
    +
    + +
    +
    `, }, + + // ── Content & Grids ───────────────────────────────────────────────────────── { - id: "wf-checkbox", - label: "Checkbox", - icon: "☑️", - content: ``, - category: "Elements", + id: "wf-feature-grid-3", + label: "3-Column Feature Cards", + category: "content", + desc: "Feature icons with title and descriptions", + icon: "🗃️", + content: `
    +
    +
    âš¡
    +

    Lightning Fast

    +

    Instant drag-and-drop elements designed for rapid wireframing.

    +
    +
    +
    🎨
    +

    Figma Precision

    +

    Pixel-calibrated spacing, modern typography, and clean tokens.

    +
    +
    +
    🔒
    +

    Offline Native

    +

    100% saved locally alongside notes with instant export capabilities.

    +
    +
    `, }, { - id: "wf-radio", - label: "Radio", - icon: "🔵", - content: `
    - - + id: "wf-pricing-card-group", + label: "Pricing Tier Cards", + category: "content", + desc: "Basic vs Pro pricing comparison tier", + icon: "🏷️", + content: `
    +
    +
    Starter
    +
    $0/mo
    +
      +
    • ✓ Up to 10 wireframes
    • +
    • ✓ Standard export (PNG)
    • +
    • ✓ Core component library
    • +
    + +
    +
    + Popular +
    Professional
    +
    $19/mo
    +
      +
    • ✓ Unlimited wireframes
    • +
    • ✓ Vector & SVG export
    • +
    • ✓ Full UI stencil packs
    • +
    + +
    `, - category: "Elements", }, { - id: "wf-image", - label: "Image", - icon: "🖼", - content: `
    [ Image ]
    `, - category: "Elements", + id: "wf-kpi-row", + label: "Metric KPI Stats Row", + category: "content", + desc: "3 metric numbers with trends", + icon: "📈", + content: `
    +
    +
    Active Users
    +
    24,520
    +
    ↑ 14.8% this week
    +
    +
    +
    Conversion Rate
    +
    3.84%
    +
    ↑ 2.1% average
    +
    +
    +
    Total Notes
    +
    1,420
    +
    ● Syncing live
    +
    +
    `, }, + + // ── UI Components ─────────────────────────────────────────────────────────── { - id: "wf-divider", - label: "Divider", - icon: "➖", - content: `
    `, - category: "Elements", + id: "wf-card-media", + label: "Article / Media Card", + category: "components", + desc: "Post card with tag, author, title & image", + icon: "🃏", + content: `
    +
    [ Cover Photo ]
    +
    + Engineering +

    Designing resilient distributed architectures

    +

    Key architectural patterns for high-throughput node applications.

    +
    +
    + David Kim · 5m read +
    +
    +
    `, }, { - id: "wf-card", - label: "Card", - icon: "🃏", - content: `
    -
    [ Image Area ]
    -
    -
    Card Title
    -
    Card description text goes here.
    - + id: "wf-user-profile-widget", + label: "User Profile Card", + category: "components", + desc: "Avatar, follower count, and follow button", + icon: "👤", + content: `
    +
    OK
    +

    Sarah Jenkins

    +

    Senior Product Designer

    +
    +
    128
    Projects
    +
    4.9k
    Followers
    +
    `, - category: "Patterns", }, + + // ── Forms & Inputs ─────────────────────────────────────────────────────────── { - id: "wf-list", - label: "List", - icon: "📄", - content: `
      -
    • List item 1
    • List item 2
    • List item 3
    • -
    `, - category: "Elements", + id: "wf-modern-login-form", + label: "Modern Auth Form", + category: "forms", + desc: "Clean login form with social sign-in", + icon: "🔒", + content: `
    +

    Welcome back

    +

    Enter your details to access your account

    +
    +
    + + +
    +
    +
    + + Forgot? +
    + +
    + +
    +
    `, }, { - id: "wf-table", - label: "Table", - icon: "📊", - content: ` - - - - - - - - - - - -
    Col 1Col 2Col 3
    DataDataData
    DataDataData
    `, - category: "Patterns", + id: "wf-filter-panel", + label: "Filter & Search Bar", + category: "forms", + desc: "Search bar, select dropdowns & view toggle", + icon: "🔍", + content: `
    + +
    + + +
    +
    `, }, + + // ── Data & Tables ─────────────────────────────────────────────────────────── { - id: "wf-tabs", - label: "Tabs", - icon: "🗂️", - content: `
    -
    -
    Tab 1
    -
    Tab 2
    -
    Tab 3
    -
    -
    Tab content area
    + id: "wf-rich-table", + label: "Figma Interactive Table", + category: "tables", + desc: "Zebra table with avatars, badges & checkboxes", + icon: "📊", + content: `
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    UserRoleStatusAction
    +
    EM
    +
    Elena Morales
    elena@company.com
    +
    AdminActiveEdit
    +
    TH
    +
    Thomas Hayes
    thomas@company.com
    +
    EditorPendingEdit
    `, - category: "Patterns", }, + + // ── Modals & Feedback ─────────────────────────────────────────────────────── { - id: "wf-modal", - label: "Modal", - icon: "🪟", - content: `
    -
    -
    -
    -
    Modal Title
    -
    ✕
    -
    -
    Modal content and description text goes here.
    -
    - - -
    + id: "wf-modal-figma", + label: "Figma Clean Dialog", + category: "feedback", + desc: "Centered popup with cancel/confirm buttons", + icon: "🪟", + content: `
    +
    +

    Publish Project Changes

    + ✕ +
    +

    Your changes will immediately become visible to all team members collaborating in this workspace.

    +
    + +
    `, - category: "Patterns", }, { - id: "wf-form", - label: "Form", - icon: "📋", - content: `
    -
    Form Title
    - - - -
    `, - category: "Patterns", + id: "wf-toast-notification", + label: "Toast Notification", + category: "feedback", + desc: "Floating success/info message pill", + icon: "🔔", + content: `
    + ✓ + Document exported successfully to PNG. + ✕ +
    `, }, ]; -// ── PNG export helper ──────────────────────────────────────────────────────── +// ── Export SVG rasterizer ─────────────────────────────────────────────────── async function exportWireframeToPng(editor) { return new Promise((resolve) => { @@ -256,13 +454,13 @@ async function exportWireframeToPng(editor) { const svgDoc = ` -
    +
    -
    +
    ${html}
    @@ -304,36 +502,32 @@ async function exportWireframeToPng(editor) { } function createFallbackPng(editor) { - const canvas = document.createElement('canvas'); + const canvas = document.createElement("canvas"); canvas.width = 1200; canvas.height = 800; - const ctx = canvas.getContext('2d'); + const ctx = canvas.getContext("2d"); - // Background - ctx.fillStyle = '#ffffff'; + ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, 1200, 800); - - // Border - ctx.strokeStyle = '#cccccc'; + ctx.strokeStyle = "#e2e8f0"; ctx.lineWidth = 2; - ctx.strokeRect(10, 10, 1180, 780); + ctx.strokeRect(16, 16, 1168, 768); - // Label - ctx.fillStyle = '#888888'; - ctx.font = '16px system-ui, sans-serif'; - ctx.textAlign = 'center'; + ctx.fillStyle = "#64748b"; + ctx.font = "bold 18px system-ui, sans-serif"; + ctx.textAlign = "center"; - const html = editor?.getHtml?.() || ''; - const hasContent = html.replace(/<[^>]+>/g, '').trim().length > 10; - ctx.fillText(hasContent ? 'Wireframe Preview' : 'Empty Wireframe', 600, 410); + const html = editor?.getHtml?.() || ""; + const hasContent = html.replace(/<[^>]+>/g, "").trim().length > 10; + ctx.fillText(hasContent ? "Wireframe Mockup" : "Empty Wireframe", 600, 400); - return canvas.toDataURL('image/png'); + return canvas.toDataURL("image/png"); } -// ── WireframeEditor component ──────────────────────────────────────────────── +// ── WireframeEditor Component ────────────────────────────────────────────── export function WireframeEditor({ - initialData, // JSON string of GrapesJS project data + initialData, diagramId, documentPath, onClose, @@ -344,16 +538,35 @@ export function WireframeEditor({ const editorContainerRef = useRef(null); const saveButtonRef = useRef(null); const { confirm } = useConfirm(); + const [isSaving, setIsSaving] = useState(false); const [isExporting, setIsExporting] = useState(false); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); const [isLoading, setIsLoading] = useState(true); + // Editor controls state + const [activeCategory, setActiveCategory] = useState("all"); + const [searchQuery, setSearchQuery] = useState(""); + const [activeDevice, setActiveDevice] = useState("Desktop"); + const [gridVisible, setGridVisible] = useState(true); + const [activeRightTab, setActiveRightTab] = useState("styles"); + + const filteredStencils = useMemo(() => { + return FIGMA_STENCILS.filter((item) => { + const matchCat = activeCategory === "all" || item.category === activeCategory; + const matchSearch = + !searchQuery || + item.label.toLowerCase().includes(searchQuery.toLowerCase()) || + item.desc.toLowerCase().includes(searchQuery.toLowerCase()); + return matchCat && matchSearch; + }); + }, [activeCategory, searchQuery]); + const handleClose = useCallback(async () => { if (hasUnsavedChanges) { const confirmed = await confirm({ title: "Discard Changes?", - message: "You have unsaved changes. Are you sure you want to discard them?", + message: "You have unsaved wireframe changes. Are you sure you want to discard them?", confirmLabel: "Discard", cancelLabel: "Cancel", variant: "danger", @@ -371,172 +584,132 @@ export function WireframeEditor({ async function initGrapesJS() { try { - const grapesjs = (await import('grapesjs')).default; - + const grapesjs = (await import("grapesjs")).default; if (destroyed || !editorContainerRef.current) return; const editor = grapesjs.init({ container: editorContainerRef.current, - height: '100%', - width: '100%', - storageManager: false, // We manage persistence manually + height: "100%", + width: "100%", + storageManager: false, undoManager: true, deviceManager: { devices: [ - { name: 'Desktop', width: '' }, - { name: 'Tablet', width: '768px' }, - { name: 'Mobile', width: '375px' }, + { name: "Desktop", width: "" }, + { name: "Tablet", width: "768px" }, + { name: "Mobile", width: "375px" }, ], }, - // Minimal panel set — strip website builder UI - panels: { - defaults: [ - { - id: 'panel-top', - el: '.panel__top', - buttons: [], - }, - { - id: 'commands', - buttons: [], - }, - { - id: 'options', - buttons: [ - { - active: true, - id: 'sw-visibility', - command: 'sw-visibility', - label: '⬜', - }, - { - id: 'preview', - command: 'preview', - label: '👁', - }, - { - id: 'fullscreen', - command: 'fullscreen', - label: '⛶', - }, - { - id: 'undo', - command: 'core:undo', - label: '↩', - }, - { - id: 'redo', - command: 'core:redo', - label: '↪', - }, - { - id: 'clear-canvas', - command: 'core:canvas-clear', - label: '🗑', - }, - ], - }, - { - id: 'views', - buttons: [ - { - id: 'open-blocks', - active: true, - command: 'open-blocks', - label: '⊞', - }, - { - id: 'open-sm', - command: 'open-sm', - label: '🎨', - }, - { - id: 'open-layers', - command: 'open-layers', - label: '≡', - }, - ], - }, - ], - }, - blockManager: { - appendTo: '.wireframe-blocks-panel', - }, + panels: { defaults: [] }, styleManager: { - appendTo: '.wireframe-sm-panel', + appendTo: ".wireframe-sm-container", sectors: [ { - name: 'Layout', + name: "Layout & Auto-Layout", open: true, - properties: ['display', 'flex-direction', 'align-items', 'justify-content', 'gap', 'padding', 'margin', 'width', 'height', 'min-height'], + properties: [ + "display", + "flex-direction", + "justify-content", + "align-items", + "gap", + "padding", + "margin", + "width", + "max-width", + "min-height", + ], }, { - name: 'Typography', - open: false, - properties: ['font-family', 'font-size', 'font-weight', 'color', 'text-align', 'line-height'], + name: "Typography", + open: true, + properties: [ + "font-size", + "font-weight", + "color", + "text-align", + "line-height", + ], }, { - name: 'Appearance', - open: false, - properties: ['background-color', 'border', 'border-radius', 'opacity'], + name: "Fill & Stroke", + open: true, + properties: [ + "background-color", + "border", + "border-radius", + "box-shadow", + "opacity", + ], }, ], }, layerManager: { - appendTo: '.wireframe-layers-panel', + appendTo: ".wireframe-layers-container", }, traitManager: { - appendTo: '.wireframe-traits-panel', + appendTo: ".wireframe-traits-container", }, - // Wireframe-optimised CSS defaults - protectedCss: ` - * { box-sizing: border-box; } - body { margin: 0; padding: 16px; font-family: system-ui, sans-serif; background: #fff; } - `, canvas: { - styles: [` - * { box-sizing: border-box; } - body { margin: 0; font-family: system-ui, sans-serif; } - `], + styles: [ + ` + *, *::before, *::after { box-sizing: border-box; } + body { + margin: 0; + padding: 40px; + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + background: #f8fafc; + min-height: 100vh; + } + .gjs-selected { + outline: 2px solid #7c6af7 !important; + outline-offset: 2px !important; + box-shadow: 0 0 0 4px rgba(124,106,247,0.18) !important; + } + .gjs-hovered { + outline: 1px dashed #a78bfa !important; + outline-offset: 1px !important; + } + `, + ], }, + }); editorRef.current = editor; - // Register wireframe component blocks - const blockManager = editor.BlockManager; - WIREFRAME_COMPONENTS.forEach((comp) => { - blockManager.add(comp.id, { - label: `
    ${comp.icon}
    ${comp.label}
    `, - category: comp.category, - content: comp.content, - attributes: { class: 'fa fa-th' }, + // Register components into BlockManager + const bm = editor.BlockManager; + FIGMA_STENCILS.forEach((stencil) => { + bm.add(stencil.id, { + label: stencil.label, + category: stencil.category, + content: stencil.content, }); }); - // Load existing project data + // Load project data if (initialData) { try { - const parsed = typeof initialData === 'string' ? JSON.parse(initialData) : initialData; - if (parsed && typeof parsed === 'object') { + const parsed = typeof initialData === "string" ? JSON.parse(initialData) : initialData; + if (parsed && typeof parsed === "object") { editor.loadProjectData(parsed); - } else if (typeof initialData === 'string' && initialData.trim().startsWith('<')) { - // Legacy: raw HTML + } else if (typeof initialData === "string" && initialData.trim().startsWith("<")) { editor.setComponents(initialData); } } catch { - // Ignore parse errors for corrupted data + // ignore malformed JSON } } - // Mark dirty on change - editor.on('component:add component:remove component:update style:change', () => { + // Track dirty state + editor.on("component:add component:remove component:update style:change", () => { setHasUnsavedChanges(true); }); setIsLoading(false); } catch (err) { - console.error('Failed to initialize GrapesJS:', err); + console.error("Failed to initialize GrapesJS:", err); setIsLoading(false); } } @@ -554,33 +727,69 @@ export function WireframeEditor({ editorRef.current = null; } }; - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Escape key handler useEffect(() => { - const handleEscape = (event) => { - if (event.key === 'Escape') handleClose(); + const handleEscape = (e) => { + if (e.key === "Escape") handleClose(); }; - document.addEventListener('keydown', handleEscape); - return () => document.removeEventListener('keydown', handleEscape); + document.addEventListener("keydown", handleEscape); + return () => document.removeEventListener("keydown", handleEscape); }, [handleClose]); - // Ctrl+S handler + // Keyboard shortcut Ctrl+S const handleSaveRef = useRef(null); - useEffect(() => { handleSaveRef.current = handleSave; }); useEffect(() => { - const handleKeyDown = (event) => { - if ((event.ctrlKey || event.metaKey) && event.key?.toLowerCase() === 's') { - event.preventDefault(); - event.stopPropagation(); + handleSaveRef.current = handleSave; + }); + useEffect(() => { + const handleKeyDown = (e) => { + if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "s") { + e.preventDefault(); + e.stopPropagation(); handleSaveRef.current?.(); } }; - window.addEventListener('keydown', handleKeyDown, true); - return () => window.removeEventListener('keydown', handleKeyDown, true); + window.addEventListener("keydown", handleKeyDown, true); + return () => window.removeEventListener("keydown", handleKeyDown, true); }, []); + // Device switcher + const handleSetDevice = (device) => { + setActiveDevice(device); + editorRef.current?.setDevice(device); + }; + + // Canvas Actions + const handleUndo = () => editorRef.current?.UndoManager?.undo(); + const handleRedo = () => editorRef.current?.UndoManager?.redo(); + const handleClear = () => { + if (window.confirm("Clear the current wireframe canvas?")) { + editorRef.current?.runCommand("core:canvas-clear"); + setHasUnsavedChanges(true); + } + }; + + const handleToggleBorders = () => { + setGridVisible(!gridVisible); + editorRef.current?.runCommand("sw-visibility"); + }; + + // Direct component insertion onto canvas + const handleInsertStencil = (stencil) => { + const editor = editorRef.current; + if (!editor) return; + const selected = editor.getSelected(); + if (selected) { + selected.append(stencil.content); + } else { + editor.addComponents(stencil.content); + } + setHasUnsavedChanges(true); + }; + + // Save handler const handleSave = async () => { const editor = editorRef.current; if (!editor || isSaving) return; @@ -590,10 +799,8 @@ export function WireframeEditor({ const projectData = editor.getProjectData(); const projectJson = JSON.stringify(projectData); - // Render preview PNG const pngDataUrl = await exportWireframeToPng(editor); - // Persist source if (diagramId) { await writeWireframeSource(diagramId, projectJson, documentPath); if (pngDataUrl) { @@ -603,15 +810,16 @@ export function WireframeEditor({ setHasUnsavedChanges(false); onSave?.(projectJson, pngDataUrl); - onNotify?.('Wireframe saved successfully.', 'success'); + onNotify?.("Wireframe saved successfully.", "success"); } catch (err) { - console.error('Failed to save wireframe:', err); - onNotify?.(err?.message || 'Failed to save wireframe.', 'error'); + console.error("Failed to save wireframe:", err); + onNotify?.(err?.message || "Failed to save wireframe.", "error"); } finally { setIsSaving(false); } }; + // Download handler const handleDownload = async () => { const editor = editorRef.current; if (!editor || isExporting) return; @@ -620,26 +828,26 @@ export function WireframeEditor({ try { const pngDataUrl = await exportWireframeToPng(editor); if (!pngDataUrl) { - onNotify?.('Failed to generate wireframe image.', 'error'); + onNotify?.("Failed to generate wireframe image.", "error"); return; } - const filename = `${diagramId || 'wireframe'}.png`; - const result = await runExport('diagram_image', { + const filename = `${diagramId || "wireframe"}.png`; + const result = await runExport("diagram_image", { dataUrl: pngDataUrl, filename, - customExportType: 'diagram_wireframe', - category: 'diagram', + customExportType: "diagram_wireframe", + category: "diagram", }); if (result?.success) { - onNotify?.(`Wireframe exported to ${result.filename}`, 'success'); + onNotify?.(`Wireframe exported to ${result.filename}`, "success"); } else { - onNotify?.(result?.error || 'Failed to export wireframe.', 'error'); + onNotify?.(result?.error || "Failed to export wireframe.", "error"); } } catch (err) { - console.error('Failed to download wireframe:', err); - onNotify?.('Failed to export wireframe.', 'error'); + console.error("Failed to download wireframe:", err); + onNotify?.("Failed to export wireframe.", "error"); } finally { setIsExporting(false); } @@ -649,57 +857,274 @@ export function WireframeEditor({ -
    -

    Wireframe Editor

    -
    - + {/* Brand */} +
    +
    ✦
    +
    +

    Wireframe Studio

    +
    Visual UI Builder
    +
    +
    + +
    + + {/* Viewport switchers */} +
    + + + +
    + +
    + + {/* Canvas tool icons */} +
    + + + + + +
    + + {/* Action buttons */} +
    + {hasUnsavedChanges && } + + +
    -
    + {/* ── Studio Body ─────────────────────────────────────────────────── */} +
    {isLoading && (
    - Loading Wireframe Editor... +
    + Loading Wireframe Studio…
    )} -
    -
    -
    -
    -
    -
    -
    + + {/* ── Left Sidebar ──────────────────────────────────────────── */} + + + {/* ── Center Canvas ─────────────────────────────────────────── */} +
    +
    +
    +
    + {/* Status bar */} +
    + + Canvas ready · {activeDevice} +
    + Click stencil to insert  Â·  Ctrl+S to save +
    +
    +
    + + {/* ── Right Inspector Panel ──────────────────────────────── */} +
    ); diff --git a/src/styles/WireframeEditor.css b/src/styles/WireframeEditor.css index 28c5426c..4f413144 100644 --- a/src/styles/WireframeEditor.css +++ b/src/styles/WireframeEditor.css @@ -1,267 +1,788 @@ -/* ══════════════════════════════════════════════════════════════════ - WireframeEditor — GrapesJS theme overrides - Inherits .excalidraw-modal-overlay / .excalidraw-modal-container - from ExcalidrawEditor.css - ══════════════════════════════════════════════════════════════════ */ +/* ══════════════════════════════════════════════════════════════════ + Wireframe Studio — Figma-Quality Dark Design System + ══════════════════════════════════════════════════════════════════ */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); + +/* ── Root Tokens ──────────────────────────────────────────────────── */ .wireframe-modal-container { - background: var(--surface-bg); + --wf-bg: #1e1e2e; + --wf-surface: #252535; + --wf-surface2: #2d2d42; + --wf-surface3: #323248; + --wf-border: rgba(255,255,255,0.07); + --wf-border2: rgba(255,255,255,0.12); + --wf-text: #e2e4f0; + --wf-text-muted: #8b8eab; + --wf-text-dim: #5c5f7a; + --wf-accent: #7c6af7; + --wf-accent-glow: rgba(124,106,247,0.3); + --wf-green: #4ade80; + --wf-radius: 10px; + --wf-radius-sm: 6px; + --wf-radius-lg: 14px; + font-family: 'Inter', system-ui, -apple-system, sans-serif; + + background: var(--wf-bg) !important; + width: 96vw !important; + max-width: 1600px !important; + height: 93vh !important; + display: flex; + flex-direction: column; + overflow: hidden; + border-radius: 16px; + border: 1px solid var(--wf-border2); + box-shadow: + 0 0 0 1px rgba(255,255,255,0.04), + 0 32px 80px rgba(0,0,0,0.6), + 0 8px 24px rgba(0,0,0,0.4); } -.wireframe-editor-wrapper { - flex: 1; - min-height: 0; +/* ── Top Bar / Studio Header ──────────────────────────────────────── */ +.wireframe-studio-header { display: flex; - overflow: hidden; + align-items: center; + gap: 12px; + padding: 0 16px; + height: 48px; + background: var(--wf-surface); + border-bottom: 1px solid var(--wf-border); + flex-shrink: 0; position: relative; + z-index: 10; } -.wireframe-sidebar { - width: 260px; - background: var(--surface-bg); - border-right: 1px solid var(--border-soft); +/* thin rainbow accent line at the very top */ +.wireframe-studio-header::before { + content: ''; + position: absolute; + top: 0; left: 0; right: 0; + height: 2px; + background: linear-gradient(90deg, #7c6af7, #a78bfa, #60a5fa, #34d399, #fbbf24); + border-radius: 16px 16px 0 0; +} + +.wireframe-studio-title-group { display: flex; - flex-direction: column; - overflow-y: auto; + align-items: center; + gap: 10px; flex-shrink: 0; } -/* ── GrapesJS canvas area ─────────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-editor { - flex: 1; - border: none; - font-family: var(--font-ui, system-ui, sans-serif); +.wireframe-studio-logo { + width: 28px; + height: 28px; + background: linear-gradient(135deg, #7c6af7 0%, #60a5fa 100%); + border-radius: 7px; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + box-shadow: 0 2px 8px rgba(124,106,247,0.35); + flex-shrink: 0; } -.wireframe-editor-wrapper .gjs-cv-canvas { - background: #f4f4f4; - width: 100%; - height: 100%; +.wireframe-studio-title { + font-size: 13px; + font-weight: 700; + color: var(--wf-text); + margin: 0; + letter-spacing: -0.01em; } -:root[data-theme="dark"] .wireframe-editor-wrapper .gjs-cv-canvas { - background: #1e2228; +.wireframe-studio-subtitle { + font-size: 10px; + color: var(--wf-text-dim); + letter-spacing: 0.01em; } -/* ── GrapesJS toolbar / panels ────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-pn-panels { - background: var(--surface-bg); - border-right: 1px solid var(--border-soft); +.wireframe-header-divider { + width: 1px; + height: 20px; + background: var(--wf-border2); + flex-shrink: 0; } -.wireframe-editor-wrapper .gjs-pn-panel { +/* ── Viewport Device Switcher ─────────────────────────────────────── */ +.wireframe-viewport-controls { + display: flex; + align-items: center; + background: var(--wf-bg); + padding: 3px; + border-radius: var(--wf-radius-sm); + border: 1px solid var(--wf-border2); + gap: 1px; + flex-shrink: 0; +} + +.wireframe-vp-btn { + display: flex; + align-items: center; + gap: 5px; + padding: 4px 10px; + border: none; background: transparent; + color: var(--wf-text-muted); + font-size: 11px; + font-weight: 500; + font-family: inherit; + border-radius: 4px; + cursor: pointer; + transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); + white-space: nowrap; +} + +.wireframe-vp-btn:hover { + color: var(--wf-text); + background: var(--wf-surface2); } -.wireframe-editor-wrapper .gjs-pn-btn { - color: var(--text-muted); +.wireframe-vp-btn.active { + background: var(--wf-accent); + color: #fff; + font-weight: 600; + box-shadow: 0 2px 8px var(--wf-accent-glow); +} + +/* ── Canvas Toolbar (Undo/Redo/Grid/etc) ──────────────────────────── */ +.wireframe-canvas-tools { + display: flex; + align-items: center; + gap: 1px; + background: var(--wf-bg); + padding: 3px; + border-radius: var(--wf-radius-sm); + border: 1px solid var(--wf-border2); + flex-shrink: 0; +} + +.wireframe-tool-icon-btn { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; border: none; background: transparent; - padding: 6px 8px; - border-radius: var(--radius-sm, 4px); + color: var(--wf-text-muted); + border-radius: 4px; cursor: pointer; - transition: background var(--motion-fast), color var(--motion-fast); + transition: all 0.15s ease; + font-family: inherit; } -.wireframe-editor-wrapper .gjs-pn-btn:hover, -.wireframe-editor-wrapper .gjs-pn-btn.gjs-pn-active { - background: var(--surface-hover); - color: var(--text-strong); +.wireframe-tool-icon-btn:hover { + background: var(--wf-surface2); + color: var(--wf-text); } -/* ── Blocks panel ─────────────────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-blocks-c { - display: grid; - grid-template-columns: 1fr 1fr; +.wireframe-tool-icon-btn.active { + background: color-mix(in srgb, var(--wf-accent) 20%, transparent); + color: var(--wf-accent); +} + +.wireframe-tool-icon-btn.danger:hover { + background: rgba(239, 68, 68, 0.15); + color: #f87171; +} + +.wireframe-tool-sep { + width: 1px; + height: 14px; + background: var(--wf-border2); + margin: 0 2px; + flex-shrink: 0; +} + +/* ── Action Buttons Row ───────────────────────────────────────────── */ +.wireframe-action-buttons { + display: flex; + align-items: center; gap: 6px; - padding: 8px; - overflow-y: auto; - background: var(--surface-bg); + margin-left: auto; + flex-shrink: 0; } -.wireframe-editor-wrapper .gjs-block { - background: var(--surface-elevated); - border: 1px solid var(--border-soft); - border-radius: var(--radius-md, 6px); - color: var(--text-strong); - font-size: 11px; - font-weight: 500; - padding: 8px 6px 6px; - text-align: center; - cursor: grab; - transition: background var(--motion-fast), border-color var(--motion-fast), box-shadow var(--motion-fast); +.wf-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 5px 12px; + border-radius: var(--wf-radius-sm); + font-size: 12px; + font-weight: 600; + font-family: inherit; + cursor: pointer; + transition: all 0.15s ease; + border: 1px solid transparent; + white-space: nowrap; + flex-shrink: 0; + line-height: 1; +} + +.wf-btn-ghost { + background: transparent; + color: var(--wf-text-muted); + border-color: var(--wf-border2); +} + +.wf-btn-ghost:hover { + background: var(--wf-surface2); + color: var(--wf-text); +} + +.wf-btn-primary { + background: var(--wf-accent); + color: #fff; + box-shadow: 0 2px 8px var(--wf-accent-glow); +} + +.wf-btn-primary:hover:not(:disabled) { + background: #6d5ce7; + box-shadow: 0 4px 14px var(--wf-accent-glow); + transform: translateY(-1px); +} + +.wf-btn:disabled { + opacity: 0.4; + cursor: not-allowed; + transform: none !important; +} + +/* ── Studio Body Layout ───────────────────────────────────────────── */ +.wireframe-studio-body { + display: flex; + flex: 1; + min-height: 0; + overflow: hidden; + position: relative; +} + +/* ── Left Sidebar: Stencil Library ────────────────────────────────── */ +.wireframe-stencil-sidebar { + width: 252px; + background: var(--wf-surface); + border-right: 1px solid var(--wf-border); display: flex; flex-direction: column; + flex-shrink: 0; + overflow: hidden; +} + +.wireframe-sidebar-header { + padding: 10px 12px 6px; + flex-shrink: 0; +} + +.wireframe-sidebar-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--wf-text-dim); + margin-bottom: 7px; + padding-left: 2px; +} + +/* Search */ +.wireframe-sidebar-search { + position: relative; + display: flex; align-items: center; - gap: 4px; - min-width: 0; - word-break: break-word; + margin-bottom: 8px; } -.wireframe-editor-wrapper .gjs-block:hover { - background: var(--surface-hover); - border-color: var(--border-default); - box-shadow: 0 2px 8px rgba(0,0,0,0.08); +.wireframe-search-icon { + position: absolute; + left: 9px; + color: var(--wf-text-dim); + pointer-events: none; + z-index: 1; } -.wireframe-editor-wrapper .gjs-block__media { - font-size: 18px; +.wireframe-search-input { + width: 100%; + padding: 6px 28px 6px 28px; + border: 1px solid var(--wf-border2); + border-radius: var(--wf-radius-sm); + font-size: 11px; + font-family: inherit; + background: var(--wf-bg); + color: var(--wf-text); + outline: none; + transition: border-color 0.15s, box-shadow 0.15s; +} + +.wireframe-search-input::placeholder { color: var(--wf-text-dim); } + +.wireframe-search-input:focus { + border-color: var(--wf-accent); + box-shadow: 0 0 0 2px var(--wf-accent-glow); +} + +.wireframe-search-clear { + position: absolute; + right: 8px; + background: transparent; + border: none; + font-size: 12px; + color: var(--wf-text-muted); + cursor: pointer; + padding: 2px 4px; + border-radius: 3px; line-height: 1; + transition: color 0.1s; } -/* ── Style manager ────────────────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-sm-sector { - border-bottom: 1px solid var(--border-subtle); - padding: 6px 8px; +.wireframe-search-clear:hover { color: var(--wf-text); } + +/* Category chips */ +.wireframe-category-chips { + display: flex; + flex-wrap: wrap; + gap: 4px; + padding: 0 12px 10px; + border-bottom: 1px solid var(--wf-border); } -.wireframe-editor-wrapper .gjs-sm-sector-title { +.wireframe-category-chip { + padding: 3px 9px; + border: 1px solid var(--wf-border2); background: transparent; - color: var(--text-muted); + color: var(--wf-text-muted); + border-radius: 999px; font-size: 10px; + font-weight: 500; + font-family: inherit; + white-space: nowrap; + cursor: pointer; + transition: all 0.14s ease; +} + +.wireframe-category-chip:hover { + background: var(--wf-surface2); + color: var(--wf-text); +} + +.wireframe-category-chip.active { + background: var(--wf-accent); + color: #fff; + border-color: transparent; + font-weight: 600; + box-shadow: 0 1px 6px var(--wf-accent-glow); +} + +/* Stencil list */ +.wireframe-stencil-grid { + flex: 1; + overflow-y: auto; + padding: 8px 10px 16px; + display: flex; + flex-direction: column; + gap: 2px; + scrollbar-width: thin; + scrollbar-color: var(--wf-border2) transparent; +} + +.wireframe-stencil-grid::-webkit-scrollbar { width: 4px; } +.wireframe-stencil-grid::-webkit-scrollbar-track { background: transparent; } +.wireframe-stencil-grid::-webkit-scrollbar-thumb { + background: var(--wf-border2); + border-radius: 4px; +} + +/* Section headers */ +.wireframe-stencil-section { + font-size: 9px; font-weight: 700; text-transform: uppercase; - letter-spacing: 0.06em; - padding: 4px 0 4px; - border: none; + letter-spacing: 0.08em; + color: var(--wf-text-dim); + padding: 10px 4px 4px; +} + +.wireframe-stencil-card { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 8px; + background: transparent; + border: 1px solid transparent; + border-radius: var(--wf-radius-sm); cursor: pointer; + user-select: none; + transition: all 0.14s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; } -.wireframe-editor-wrapper .gjs-field { - background: var(--surface-bg); - border: 1px solid var(--border-default); - border-radius: var(--radius-sm, 4px); - color: var(--app-text); +.wireframe-stencil-card:hover { + background: var(--wf-surface2); + border-color: var(--wf-border2); } -.wireframe-editor-wrapper .gjs-field input, -.wireframe-editor-wrapper .gjs-field select { - background: transparent; - color: var(--app-text); - border: none; - font-size: 11px; +.wireframe-stencil-card:hover .wireframe-stencil-add { + opacity: 1; + transform: scale(1); } -/* ── Selected component highlight ─────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-selected { - outline: 2px solid var(--accent-solid) !important; - outline-offset: 1px !important; +.wireframe-stencil-card:active { transform: scale(0.98); } + +.wireframe-stencil-icon { + width: 32px; + height: 32px; + border-radius: var(--wf-radius-sm); + background: var(--wf-surface3); + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + flex-shrink: 0; + border: 1px solid var(--wf-border); } -/* ── Toolbar (floating component toolbar) ─────────────────────────── */ -.wireframe-editor-wrapper .gjs-toolbar { - background: var(--surface-elevated); - border: 1px solid var(--border-soft); - border-radius: var(--radius-md, 6px); - box-shadow: var(--shadow-sm); +.wireframe-stencil-info { + flex: 1; + min-width: 0; } -.wireframe-editor-wrapper .gjs-toolbar-item { - color: var(--text-muted); - padding: 4px 6px; - cursor: pointer; - border-radius: var(--radius-sm, 4px); - transition: background var(--motion-fast), color var(--motion-fast); +.wireframe-stencil-name { + font-size: 11.5px; + font-weight: 600; + color: var(--wf-text); + margin-bottom: 1px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } -.wireframe-editor-wrapper .gjs-toolbar-item:hover { - background: var(--surface-hover); - color: var(--text-strong); +.wireframe-stencil-desc { + font-size: 10px; + color: var(--wf-text-dim); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } -/* ── Trait manager ────────────────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-trt-trait { - padding: 4px 8px; +.wireframe-stencil-add { + width: 18px; + height: 18px; + background: var(--wf-accent); + color: #fff; + border-radius: 4px; display: flex; align-items: center; - gap: 6px; + justify-content: center; + flex-shrink: 0; + opacity: 0; + transform: scale(0.6); + transition: all 0.15s ease; } -.wireframe-editor-wrapper .gjs-trt-trait label { +.wireframe-empty-stencils { + padding: 32px 16px; + text-align: center; + color: var(--wf-text-dim); font-size: 11px; - color: var(--text-muted); - min-width: 60px; + line-height: 1.6; +} + +/* ── Center Canvas ────────────────────────────────────────────────── */ +.wireframe-canvas-container { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + min-width: 0; + position: relative; + background-color: #131320; + background-image: + linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px), + linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px); + background-size: 24px 24px; +} + +.wireframe-canvas-statusbar { + display: flex; + align-items: center; + gap: 10px; + padding: 4px 14px; + background: var(--wf-surface); + border-top: 1px solid var(--wf-border); flex-shrink: 0; + font-size: 10px; + color: var(--wf-text-dim); +} + +.wireframe-canvas-statusbar-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--wf-green); + box-shadow: 0 0 4px var(--wf-green); + flex-shrink: 0; +} + +.wireframe-canvas-tip { + margin-left: auto; + display: flex; + align-items: center; + gap: 5px; +} + +.wireframe-canvas-tip kbd { + background: var(--wf-surface2); + border: 1px solid var(--wf-border2); + border-radius: 3px; + padding: 1px 4px; + font-size: 9px; + font-family: inherit; + color: var(--wf-text-muted); +} + +.wireframe-gjs-host { + flex: 1; + min-height: 0; + overflow: hidden; + position: relative; +} + +/* empty state overlay */ +.wireframe-canvas-empty-hint { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + pointer-events: none; + user-select: none; } -/* ── Layer manager ────────────────────────────────────────────────── */ -.wireframe-editor-wrapper .gjs-layer { - color: var(--text-strong); +.wf-empty-icon { + font-size: 40px; + opacity: 0.15; +} + +.wf-empty-label { + font-size: 13px; + font-weight: 600; + color: rgba(255,255,255,0.1); + letter-spacing: 0.02em; +} + +.wf-empty-sub { font-size: 11px; - background: transparent; + color: rgba(255,255,255,0.06); +} + +/* GrapesJS canvas overrides */ +.wireframe-gjs-host .gjs-editor { + background: transparent !important; + border: none !important; } -.wireframe-editor-wrapper .gjs-layer:hover { - background: var(--surface-hover); +.wireframe-gjs-host .gjs-cv-canvas { + background: transparent !important; + width: 100% !important; + height: 100% !important; } -/* ── Right panel (style/traits/layers) ───────────────────────────── */ -.wireframe-right-panel { - width: 220px; - min-width: 220px; - border-left: 1px solid var(--border-soft); +/* ── Right Inspector Panel ────────────────────────────────────────── */ +.wireframe-inspector-panel { + width: 248px; + background: var(--wf-surface); + border-left: 1px solid var(--wf-border); display: flex; flex-direction: column; - background: var(--surface-bg); + flex-shrink: 0; overflow: hidden; } -.wireframe-right-panel-tabs { +.wireframe-inspector-tabs { display: flex; - border-bottom: 1px solid var(--border-soft); - background: color-mix(in srgb, var(--surface-bg) 94%, var(--surface-elevated)); + border-bottom: 1px solid var(--wf-border); + background: var(--wf-bg); + padding: 4px 8px 0; + gap: 2px; + flex-shrink: 0; } -.wireframe-right-panel-tab { +.wireframe-inspector-tab { flex: 1; - padding: 6px 4px; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + padding: 7px 4px; border: none; background: transparent; - color: var(--text-muted); - font-size: 10px; + color: var(--wf-text-dim); + font-size: 11px; font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; + font-family: inherit; cursor: pointer; - transition: color var(--motion-fast), border-bottom var(--motion-fast); border-bottom: 2px solid transparent; + transition: all 0.15s ease; + border-radius: 4px 4px 0 0; + margin-bottom: -1px; } -.wireframe-right-panel-tab.active { - color: var(--accent-solid); - border-bottom-color: var(--accent-solid); +.wireframe-inspector-tab:hover { + color: var(--wf-text-muted); + background: var(--wf-surface2); } -.wireframe-right-panel-body { +.wireframe-inspector-tab.active { + color: var(--wf-accent); + border-bottom-color: var(--wf-accent); + background: var(--wf-surface); +} + +.wireframe-inspector-content { flex: 1; overflow-y: auto; - min-height: 0; + padding: 10px; + scrollbar-width: thin; + scrollbar-color: var(--wf-border2) transparent; +} + +.wireframe-inspector-content::-webkit-scrollbar { width: 4px; } +.wireframe-inspector-content::-webkit-scrollbar-track { background: transparent; } +.wireframe-inspector-content::-webkit-scrollbar-thumb { + background: var(--wf-border2); + border-radius: 4px; } -/* ── Wireframe-specific component styles (inside iframe) ──────────── */ -.wireframe-placeholder { - background: #e8e8e8; - border: 2px dashed #b0b0b0; +.wireframe-inspector-empty { display: flex; + flex-direction: column; align-items: center; justify-content: center; - color: #888; - font-family: system-ui, sans-serif; - font-size: 12px; - font-weight: 500; - box-sizing: border-box; + gap: 8px; + padding: 40px 16px; + color: var(--wf-text-dim); + font-size: 11px; + text-align: center; + line-height: 1.5; +} + +.wireframe-inspector-empty-icon { font-size: 26px; opacity: 0.4; } + +/* GrapesJS Style Manager inside inspector */ +.wireframe-sm-container .gjs-sm-sector, +.wireframe-inspector-panel .gjs-sm-sector { + border-bottom: 1px solid var(--wf-border); + padding: 6px 0; } -/* ── Loading state ────────────────────────────────────────────────── */ +.wireframe-sm-container .gjs-sm-sector-title, +.wireframe-inspector-panel .gjs-sm-sector-title { + color: var(--wf-text-muted) !important; + background: transparent !important; + font-size: 10px !important; + font-weight: 700 !important; + text-transform: uppercase; + letter-spacing: 0.06em; + padding: 5px 0 !important; + border: none !important; + cursor: pointer; +} + +.wireframe-sm-container .gjs-sm-sector-title:hover, +.wireframe-inspector-panel .gjs-sm-sector-title:hover { + color: var(--wf-text) !important; +} + +.wireframe-inspector-panel .gjs-field, +.wireframe-sm-container .gjs-field { + background: var(--wf-bg) !important; + border: 1px solid var(--wf-border2) !important; + border-radius: var(--wf-radius-sm) !important; + color: var(--wf-text) !important; + font-size: 11px !important; +} + +.wireframe-inspector-panel .gjs-field input, +.wireframe-inspector-panel .gjs-field select, +.wireframe-sm-container .gjs-field input, +.wireframe-sm-container .gjs-field select { + background: transparent !important; + color: var(--wf-text) !important; + border: none !important; + font-size: 11px !important; + font-family: inherit !important; +} + +.wireframe-inspector-panel .gjs-sm-label, +.wireframe-sm-container .gjs-sm-label { + color: var(--wf-text-muted) !important; + font-size: 10px !important; +} + +/* Layers */ +.wireframe-inspector-panel .gjs-layer, +.wireframe-layers-container .gjs-layer { + color: var(--wf-text) !important; + background: transparent !important; + border-bottom: 1px solid var(--wf-border) !important; + font-size: 11px !important; +} + +.wireframe-inspector-panel .gjs-layer:hover, +.wireframe-layers-container .gjs-layer:hover { + background: var(--wf-surface2) !important; +} + +.wireframe-inspector-panel .gjs-layer.gjs-selected, +.wireframe-layers-container .gjs-layer.gjs-selected { + background: color-mix(in srgb, var(--wf-accent) 15%, transparent) !important; + color: var(--wf-accent) !important; +} + +/* ── Loading overlay ──────────────────────────────────────────────── */ .wireframe-editor-loading { position: absolute; inset: 0; + background: rgba(19, 19, 32, 0.9); + backdrop-filter: blur(6px); display: flex; + flex-direction: column; align-items: center; justify-content: center; - background: var(--surface-bg); - color: var(--text-muted); - font-size: 0.9rem; - z-index: 5; - gap: 10px; + gap: 14px; + z-index: 50; + font-size: 12px; + font-weight: 500; + color: var(--wf-text-muted); + letter-spacing: 0.02em; +} + +.wireframe-spinner { + width: 30px; + height: 30px; + border: 2.5px solid var(--wf-border2); + border-top-color: var(--wf-accent); + border-radius: 50%; + animation: wf-spin 0.75s linear infinite; +} + +@keyframes wf-spin { to { transform: rotate(360deg); } } + +/* Unsaved dot */ +.wf-unsaved-dot { + display: inline-block; + width: 7px; + height: 7px; + background: #f59e0b; + border-radius: 50%; + box-shadow: 0 0 6px rgba(245,158,11,0.6); + flex-shrink: 0; + animation: wf-pulse 2s ease-in-out infinite; +} + +@keyframes wf-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } } + From 9e55910d98ebfa9f3356f87b4a07e07b7ef91d9b Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Wed, 23 Sep 2026 23:57:21 +0530 Subject: [PATCH 3/7] Wireframed Studio Intital revisio complete --- electron/diagram-handlers.cjs | 39 +- src/components/WireframeBlock.jsx | 17 +- src/components/WireframeEditor.jsx | 877 +++++++++++++++++------------ src/styles/WireframeEditor.css | 853 ++++++++++++++-------------- 4 files changed, 1002 insertions(+), 784 deletions(-) diff --git a/electron/diagram-handlers.cjs b/electron/diagram-handlers.cjs index 07584a0c..c69ec3d3 100644 --- a/electron/diagram-handlers.cjs +++ b/electron/diagram-handlers.cjs @@ -34,13 +34,23 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { } if (documentPath) { let curr = path.resolve(documentPath); - while (curr && curr !== path.dirname(curr)) { - if (fsSync.existsSync(path.join(curr, '.notes-app'))) { - return curr; + try { + if (fsSync.existsSync(curr) && fsSync.statSync(curr).isFile()) { + curr = path.dirname(curr); + } else if (curr.endsWith('.md') || curr.endsWith('.markdown')) { + curr = path.dirname(curr); } - curr = path.dirname(curr); + } catch { + // fallback if unreadable } - return path.resolve(documentPath); + let check = curr; + while (check && check !== path.dirname(check)) { + if (fsSync.existsSync(path.join(check, '.notes-app'))) { + return check; + } + check = path.dirname(check); + } + return curr; } return ""; } @@ -552,13 +562,20 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { function getWireframeSourceFile(diagramId, documentPath) { const root = resolveWorkspaceRoot(documentPath); - const mediaFile = path.join(root, 'media', 'wireframe', `${diagramId}.wireframe.json`); - return mediaFile; + const pluralFile = path.join(root, 'media', 'wireframes', `${diagramId}.wireframe.json`); + if (fsSync.existsSync(pluralFile)) return pluralFile; + const singularFile = path.join(root, 'media', 'wireframe', `${diagramId}.wireframe.json`); + if (fsSync.existsSync(singularFile)) return singularFile; + return pluralFile; } function getWireframeImageFile(diagramId, documentPath) { const root = resolveWorkspaceRoot(documentPath); - return path.join(root, 'media', 'wireframe', `${diagramId}.png`); + const pluralFile = path.join(root, 'media', 'wireframes', `${diagramId}.png`); + if (fsSync.existsSync(pluralFile)) return pluralFile; + const singularFile = path.join(root, 'media', 'wireframe', `${diagramId}.png`); + if (fsSync.existsSync(singularFile)) return singularFile; + return pluralFile; } /** @@ -584,7 +601,7 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { ipcMain.handle('wireframe:write-source', async (event, { diagramId, data, documentPath }) => { try { const root = resolveWorkspaceRoot(documentPath); - const wireframeDir = path.join(root, 'media', 'wireframe'); + const wireframeDir = path.join(root, 'media', 'wireframes'); const sourceFile = path.join(wireframeDir, `${diagramId}.wireframe.json`); const existed = fsSync.existsSync(sourceFile); const previousBase64 = existed ? fsSync.readFileSync(sourceFile).toString('base64') : null; @@ -607,7 +624,7 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { ipcMain.handle('wireframe:write-image', async (event, { diagramId, imageData, documentPath }) => { try { const root = resolveWorkspaceRoot(documentPath); - const wireframeDir = path.join(root, 'media', 'wireframe'); + const wireframeDir = path.join(root, 'media', 'wireframes'); const imageFile = path.join(wireframeDir, `${diagramId}.png`); const existed = fsSync.existsSync(imageFile); const previousBase64 = existed ? fsSync.readFileSync(imageFile).toString('base64') : null; @@ -658,6 +675,8 @@ function setupDiagramHandlers(ipcMain, appDataPath, deps = {}) { try { const root = resolveWorkspaceRoot(documentPath); const filesToDelete = [ + path.join(root, 'media', 'wireframes', `${diagramId}.wireframe.json`), + path.join(root, 'media', 'wireframes', `${diagramId}.png`), path.join(root, 'media', 'wireframe', `${diagramId}.wireframe.json`), path.join(root, 'media', 'wireframe', `${diagramId}.png`), ]; diff --git a/src/components/WireframeBlock.jsx b/src/components/WireframeBlock.jsx index b2be0855..d666ab92 100644 --- a/src/components/WireframeBlock.jsx +++ b/src/components/WireframeBlock.jsx @@ -1,6 +1,11 @@ import { useEffect, useState } from "react"; import { Download, Pencil } from "lucide-react"; -import { readWireframeImage, readWireframeSource, writeWireframeSource } from "../services/wireframeService"; +import { + readWireframeImage, + readWireframeSource, + writeWireframeImage, + writeWireframeSource, +} from "../services/wireframeService"; import { runExport } from "../services/electronService"; import WireframeEditor from "./WireframeEditor"; import "../styles/ExcalidrawBlock.css"; // Reuse block styles @@ -29,8 +34,10 @@ export function WireframeBlock({ imagePath, diagramId, documentPath, onUpdate, o if (!cancelled) { if (imageDataUrl) { setThumbnail(imageDataUrl); - } else if (imagePath) { + } else if (imagePath && (imagePath.startsWith("data:") || imagePath.startsWith("blob:"))) { setThumbnail(imagePath); + } else { + setThumbnail(null); } setError(""); } @@ -83,6 +90,11 @@ export function WireframeBlock({ imagePath, diagramId, documentPath, onUpdate, o } if (previewImageData) { + try { + await writeWireframeImage(diagramId, previewImageData, documentPath); + } catch (imgErr) { + console.warn("Failed to write wireframe preview image:", imgErr); + } setThumbnail(previewImageData); } @@ -177,6 +189,7 @@ export function WireframeBlock({ imagePath, diagramId, documentPath, onUpdate, o documentPath={documentPath} onClose={() => setIsModalOpen(false)} onSave={handleSave} + onNotify={onNotify} /> )}
    diff --git a/src/components/WireframeEditor.jsx b/src/components/WireframeEditor.jsx index 33acced3..3a65491e 100644 --- a/src/components/WireframeEditor.jsx +++ b/src/components/WireframeEditor.jsx @@ -21,96 +21,111 @@ import { Sliders, Sparkles, MousePointer, - Plus, + ZoomIn, + ZoomOut, + BarChart3, + FormInput, + Shield, + Zap, + CreditCard, + User, + AlignLeft, + Columns, + MessageSquare, } from "lucide-react"; +import AppButton from "./AppButton"; +import AppSelect from "./AppSelect"; import OverlayDialog from "./OverlayDialog"; import useConfirm from "../hooks/useConfirm"; import { writeWireframeSource, writeWireframeImage } from "../services/wireframeService"; import { runExport } from "../services/electronService"; +import "grapesjs/dist/css/grapes.min.css"; import "../styles/ExcalidrawEditor.css"; import "../styles/WireframeEditor.css"; - -// ── Figma-inspired Component Categories ────────────────────────────────────── +// --- Stencil Categories --- const CATEGORIES = [ - { id: "all", label: "All Stencils" }, - { id: "frames", label: "Artboards & Frames", icon: Layout }, - { id: "headers", label: "Headers & Nav", icon: Box }, - { id: "hero", label: "Hero Sections", icon: Sparkles }, - { id: "content", label: "Content & Grids", icon: Grid3X3 }, - { id: "components", label: "UI Components", icon: Square }, - { id: "forms", label: "Forms & Inputs", icon: Sliders }, - { id: "tables", label: "Data & Tables", icon: Layers }, - { id: "feedback", label: "Modals & Feedback", icon: MousePointer }, + { id: "all", label: "All" }, + { id: "frames", label: "Frames" }, + { id: "headers", label: "Nav" }, + { id: "hero", label: "Hero" }, + { id: "content", label: "Content" }, + { id: "metrics", label: "Stats" }, + { id: "components", label: "UI" }, + { id: "forms", label: "Forms" }, + { id: "tables", label: "Tables" }, + { id: "feedback", label: "Modals" }, ]; -const FIGMA_STENCILS = [ - // ── Artboards & Frames ─────────────────────────────────────────────────────── +// --- Curated Modern Lo-Fi / Mid-Fi Stencil Library --- + +const WIREFRAME_STENCILS = [ + // --- Artboards & Frames --- { id: "wf-desktop-canvas", - label: "Desktop Canvas", + label: "Desktop Canvas (1200px)", category: "frames", - desc: "1200px responsive frame with padding", - icon: "🖥️", - content: `
    -
    Desktop Screen Artboard
    + desc: "Clean desktop artboard frame with header boundary", + icon: Monitor, + content: `
    +
    Desktop Artboard Boundary (1200px)
    `, }, { id: "wf-mobile-device", label: "Mobile iPhone Frame", category: "frames", - desc: "375x812px mobile frame with notch", - icon: "📱", - content: `
    -
    - + desc: "375x720px mobile viewport with speaker notch", + icon: Smartphone, + content: `
    +
    +
    -
    Mobile Viewport
    +
    Mobile Viewport (375px)
    `, }, { id: "wf-app-shell", label: "SaaS Dashboard Shell", category: "frames", - desc: "Left sidebar + topbar + main content", - icon: "🔲", - content: `
    -
    + desc: "Sidebar navigation + topbar + main canvas container", + icon: Columns, + content: `
    +
    - Notely App + Notely App
    -
    📊 Dashboard
    -
    📁 Projects
    -
    👥 Team
    -
    ⚙️ Settings
    +
    Dashboard
    +
    Projects
    +
    Team
    +
    Settings
    -
    +
    Overview -
    +
    -
    Drop dashboard widgets and cards here
    +
    Drop dashboard widgets and cards here
    `, }, - // ── Headers & Nav ─────────────────────────────────────────────────────────── + // --- Headers & Navigation --- { id: "wf-nav-modern", label: "Modern SaaS Navbar", category: "headers", desc: "Logo, pill links, search & CTA buttons", - icon: "🧭", - content: `
    + icon: Box, + content: `
    -
    - Brand +
    + Brand
    -
    - - + +
    `, }, { id: "wf-segmented-tabs", - label: "Figma Segmented Control", + label: "Segmented Control Tabs", category: "headers", - desc: "iOS/Figma style pill segmented tabs", - icon: "🗂️", - content: `
    - - - + desc: "Pill segmented navigation bar", + icon: Layout, + content: `
    + + +
    `, }, { id: "wf-page-header", label: "Page Header with Actions", category: "headers", - desc: "Title, breadcrumb, badge & action buttons", - icon: "🔝", - content: `
    + desc: "Title, breadcrumb, live badge and button controls", + icon: AlignLeft, + content: `
    Workspace/Settings @@ -152,30 +167,30 @@ const FIGMA_STENCILS = [
    - - + +
    `, }, - // ── Hero Sections ─────────────────────────────────────────────────────────── + // --- Hero & Banner --- { id: "wf-hero-centered", label: "Hero Centered Section", category: "hero", - desc: "Headline, badge, CTA buttons & mockup frame", - icon: "🌟", - content: `
    + desc: "Headline, badge, CTA buttons & screen mockup", + icon: Sparkles, + content: `
    - ✨ Just Released v2.0 + Release v2.0 Live Now
    -

    Design systems that scale with ease

    -

    Create beautiful wireframes, mockups, and interface flows directly inside your documentation.

    -
    - - +

    Design systems that scale with ease

    +

    Create beautiful wireframes, mockups, and interface flows directly inside your documentation.

    +
    + +
    -
    +
    [ App Preview Screen Mockup ]
    `, @@ -185,294 +200,350 @@ const FIGMA_STENCILS = [ label: "Call to Action Banner", category: "hero", desc: "Dark accent conversion box with buttons", - icon: "📣", - content: `
    + icon: Zap, + content: `
    -

    Ready to upgrade your workflow?

    -

    Collaborate in real time with high-velocity interface components.

    +

    Ready to upgrade your workflow?

    +

    Collaborate in real time with high-velocity interface components.

    -
    - +
    +
    `, }, - // ── Content & Grids ───────────────────────────────────────────────────────── + // --- Content & Grids --- { id: "wf-feature-grid-3", label: "3-Column Feature Cards", category: "content", - desc: "Feature icons with title and descriptions", - icon: "🗃️", - content: `
    -
    -
    âš¡
    -

    Lightning Fast

    + desc: "Feature cards with icons, titles & descriptions", + icon: Grid3X3, + content: `
    +
    +
    ⚡
    +

    Lightning Fast

    Instant drag-and-drop elements designed for rapid wireframing.

    -
    -
    🎨
    -

    Figma Precision

    +
    +
    🎨
    +

    Figma Precision

    Pixel-calibrated spacing, modern typography, and clean tokens.

    -
    -
    🔒
    -

    Offline Native

    +
    +
    🔒
    +

    Offline Native

    100% saved locally alongside notes with instant export capabilities.

    `, }, + { + id: "wf-bento-grid", + label: "Bento Grid Layout", + category: "content", + desc: "Asymmetric 4-tile modern showcase layout", + icon: Layout, + content: `
    +
    + Core Feature +

    Interactive Canvas Controls

    +

    Manipulate layout, typography, borders, and fills directly in the property inspector.

    +
    Feature Visual Placeholder
    +
    +
    +
    +

    Instant PNG Export

    +

    Generate high-res graphics embedded in notes automatically.

    +
    +
    +

    Local-First Security

    +

    No third-party cloud required. Everything lives on your disk.

    +
    +
    +
    `, + }, { id: "wf-pricing-card-group", label: "Pricing Tier Cards", category: "content", - desc: "Basic vs Pro pricing comparison tier", - icon: "🏷️", - content: `
    -
    -
    Starter
    -
    $0/mo
    -
      -
    • ✓ Up to 10 wireframes
    • -
    • ✓ Standard export (PNG)
    • -
    • ✓ Core component library
    • + desc: "Starter vs Professional pricing comparison", + icon: CreditCard, + content: `
      +
      +
      Starter
      +
      $0/mo
      +
        +
      • ✓ Up to 10 wireframes
      • +
      • ✓ Standard export (PNG)
      • +
      • ✓ Core stencil library
      - +
      -
      - Popular -
      Professional
      -
      $19/mo
      -
        -
      • ✓ Unlimited wireframes
      • -
      • ✓ Vector & SVG export
      • -
      • ✓ Full UI stencil packs
      • +
        + Popular +
        Professional
        +
        $19/mo
        +
          +
        • ✓ Unlimited wireframes
        • +
        • ✓ Vector & SVG export
        • +
        • ✓ Full stencil packs
        - +
      `, }, + + // --- Metrics & Stats --- { - id: "wf-kpi-row", - label: "Metric KPI Stats Row", - category: "content", - desc: "3 metric numbers with trends", - icon: "📈", - content: `
      -
      -
      Active Users
      -
      24,520
      -
      ↑ 14.8% this week
      + id: "wf-kpi-stats-row", + label: "KPI Metric Stats Row", + category: "metrics", + desc: "3 metric KPI cards with delta percentages", + icon: BarChart3, + content: `
      +
      +
      Monthly Revenue
      +
      + $48,250 + +12.4% +
      -
      -
      Conversion Rate
      -
      3.84%
      -
      ↑ 2.1% average
      +
      +
      Active Projects
      +
      + 1,420 + +8.1% +
      -
      -
      Total Notes
      -
      1,420
      -
      ● Syncing live
      +
      +
      Avg. Response Time
      +
      + 184ms + -2.3% +
      `, }, - // ── UI Components ─────────────────────────────────────────────────────────── + // --- UI Components --- { - id: "wf-card-media", - label: "Article / Media Card", + id: "wf-button-suite", + label: "Button Styles Suite", category: "components", - desc: "Post card with tag, author, title & image", - icon: "🃏", - content: `
      -
      [ Cover Photo ]
      -
      - Engineering -

      Designing resilient distributed architectures

      -

      Key architectural patterns for high-throughput node applications.

      -
      -
      - David Kim · 5m read -
      + desc: "Primary, secondary, outline, ghost and danger buttons", + icon: Square, + content: `
      + + + + + +
      `, + }, + { + id: "wf-avatar-stack", + label: "Avatar Stack & Badge", + category: "components", + desc: "Collaborator face avatars with count chip", + icon: User, + content: `
      +
      + JD + AL + RK
      + +8 contributors active
      `, }, { - id: "wf-user-profile-widget", - label: "User Profile Card", + id: "wf-alert-banner", + label: "Alert Notification Banner", category: "components", - desc: "Avatar, follower count, and follow button", - icon: "👤", - content: `
      -
      OK
      -

      Sarah Jenkins

      -

      Senior Product Designer

      -
      -
      128
      Projects
      -
      4.9k
      Followers
      + desc: "Info notification banner with icon and dismiss link", + icon: Shield, + content: `
      +
      + Notice: Your workspace was upgraded to the latest version.
      - + View Changelog
      `, }, - // ── Forms & Inputs ─────────────────────────────────────────────────────────── + // --- Forms & Inputs --- { - id: "wf-modern-login-form", - label: "Modern Auth Form", + id: "wf-auth-card", + label: "Auth Sign-in Card", category: "forms", - desc: "Clean login form with social sign-in", - icon: "🔒", - content: `
      -

      Welcome back

      -

      Enter your details to access your account

      -
      -
      - - -
      -
      -
      - - Forgot? -
      - -
      - + desc: "Centered sign-in card with email, password & button", + icon: FormInput, + content: `
      +

      Welcome back

      +

      Enter your credentials to access your notes

      +
      + +
      +
      + + +
      +
      `, }, { - id: "wf-filter-panel", - label: "Filter & Search Bar", + id: "wf-search-filter-bar", + label: "Search & Filter Bar", category: "forms", - desc: "Search bar, select dropdowns & view toggle", - icon: "🔍", - content: `
      - -
      - - + desc: "Search bar with category dropdown and action button", + icon: Search, + content: `
      +
      + 🔍 +
      + +
      `, }, - // ── Data & Tables ─────────────────────────────────────────────────────────── + // --- Data & Tables --- { - id: "wf-rich-table", - label: "Figma Interactive Table", + id: "wf-data-table", + label: "Modern Data Table", category: "tables", - desc: "Zebra table with avatars, badges & checkboxes", - icon: "📊", - content: `
      + desc: "Structured data table with status pills and actions", + icon: Layers, + content: `
      - - - - - - + + + + + - - - - - + + + + - - - - - - + + + + + + + + + + +
      UserRoleStatusAction
      NameStatusRoleActions
      -
      EM
      -
      Elena Morales
      elena@company.com
      -
      AdminActiveEditBikash PandaActiveAdmin•••
      -
      TH
      -
      Thomas Hayes
      thomas@company.com
      -
      EditorPendingEdit
      Sarah ConnorPendingEditor•••
      Alex MurphyInactiveViewer•••
      `, }, - // ── Modals & Feedback ─────────────────────────────────────────────────────── + // --- Modals & Feedback --- { - id: "wf-modal-figma", - label: "Figma Clean Dialog", + id: "wf-modal-dialog", + label: "Confirmation Modal Dialog", category: "feedback", - desc: "Centered popup with cancel/confirm buttons", - icon: "🪟", - content: `
      -
      -

      Publish Project Changes

      - ✕ -
      -

      Your changes will immediately become visible to all team members collaborating in this workspace.

      -
      - - + desc: "Dialog card with title, body text and cancel/confirm buttons", + icon: MousePointer, + content: `
      +

      Delete Project

      +

      Are you sure you want to delete this project? This action cannot be undone.

      +
      + +
      `, }, { - id: "wf-toast-notification", - label: "Toast Notification", + id: "wf-empty-state-card", + label: "Empty State Placeholder", category: "feedback", - desc: "Floating success/info message pill", - icon: "🔔", - content: `
      - ✓ - Document exported successfully to PNG. - ✕ + desc: "Icon, empty message and primary action button", + icon: MessageSquare, + content: `
      +
      📁
      +

      No documents yet

      +

      Create your first document or import notes from Markdown to get started.

      +
      `, }, ]; -// ── Export SVG rasterizer ─────────────────────────────────────────────────── +// --- Export to PNG helper --- -async function exportWireframeToPng(editor) { +function exportWireframeToPng(editor) { return new Promise((resolve) => { - try { - if (!editor) { - resolve(createFallbackPng(editor)); - return; - } - - const html = editor.getHtml?.() || ""; - const css = editor.getCss?.() || ""; + if (!editor) { + resolve(createFallbackPng(editor)); + return; + } + try { const width = 1200; const height = 800; + const frameDoc = editor.Canvas?.getDocument?.(); + const frameBody = frameDoc?.body; + let bodyXml = ""; + let cssText = editor.getCss?.() || ""; + + if (frameDoc && frameBody) { + // Collect canvas iframe styles + const styleTags = frameDoc.querySelectorAll("style"); + styleTags.forEach((s) => { + cssText += "\n" + (s.textContent || ""); + }); + + // Clone and sanitize selection markers + const clone = frameBody.cloneNode(true); + clone.querySelectorAll(".gjs-selected, .gjs-hovered").forEach((el) => { + el.classList.remove("gjs-selected", "gjs-hovered"); + }); + + const serializer = new XMLSerializer(); + bodyXml = serializer.serializeToString(clone); + } else { + const rawHtml = editor.getHtml?.() || ""; + bodyXml = `
      ${rawHtml}
      `; + } + const svgDoc = `
      -
      - ${html} -
      + ${bodyXml}
      - `; + `.trim(); - const blob = new Blob([svgDoc], { type: "image/svg+xml;charset=utf-8" }); - const url = URL.createObjectURL(blob); const img = new Image(); + const dataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgDoc)}`; + + const fallbackTimer = setTimeout(() => { + resolve(createFallbackPng(editor)); + }, 2000); img.onload = () => { + clearTimeout(fallbackTimer); try { const canvas = document.createElement("canvas"); canvas.width = width; @@ -481,20 +552,18 @@ async function exportWireframeToPng(editor) { ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, width, height); ctx.drawImage(img, 0, 0); - URL.revokeObjectURL(url); resolve(canvas.toDataURL("image/png")); } catch { - URL.revokeObjectURL(url); resolve(createFallbackPng(editor)); } }; img.onerror = () => { - URL.revokeObjectURL(url); + clearTimeout(fallbackTimer); resolve(createFallbackPng(editor)); }; - img.src = url; + img.src = dataUri; } catch { resolve(createFallbackPng(editor)); } @@ -507,24 +576,44 @@ function createFallbackPng(editor) { canvas.height = 800; const ctx = canvas.getContext("2d"); - ctx.fillStyle = "#ffffff"; + // Canvas background + ctx.fillStyle = "#f8fafc"; ctx.fillRect(0, 0, 1200, 800); - ctx.strokeStyle = "#e2e8f0"; + + // Border frame + ctx.strokeStyle = "#cbd5e1"; ctx.lineWidth = 2; - ctx.strokeRect(16, 16, 1168, 768); + ctx.strokeRect(20, 20, 1160, 760); + + // Header mockup + ctx.fillStyle = "#ffffff"; + ctx.fillRect(20, 20, 1160, 60); + ctx.fillStyle = "#2563eb"; + ctx.fillRect(44, 40, 20, 20); + + ctx.fillStyle = "#0f172a"; + ctx.font = "bold 16px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; + ctx.textAlign = "left"; + ctx.fillText("Wireframe Mockup", 74, 55); + + // Content area + ctx.fillStyle = "#ffffff"; + ctx.fillRect(60, 120, 1080, 600); + ctx.strokeStyle = "#e2e8f0"; + ctx.strokeRect(60, 120, 1080, 600); ctx.fillStyle = "#64748b"; - ctx.font = "bold 18px system-ui, sans-serif"; + ctx.font = "14px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; ctx.textAlign = "center"; const html = editor?.getHtml?.() || ""; const hasContent = html.replace(/<[^>]+>/g, "").trim().length > 10; - ctx.fillText(hasContent ? "Wireframe Mockup" : "Empty Wireframe", 600, 400); + ctx.fillText(hasContent ? "Wireframe UI Design" : "Wireframe Artboard", 600, 420); return canvas.toDataURL("image/png"); } -// ── WireframeEditor Component ────────────────────────────────────────────── +// --- WireframeEditor Component --- export function WireframeEditor({ initialData, @@ -550,9 +639,10 @@ export function WireframeEditor({ const [activeDevice, setActiveDevice] = useState("Desktop"); const [gridVisible, setGridVisible] = useState(true); const [activeRightTab, setActiveRightTab] = useState("styles"); + const [zoomLevel, setZoomLevel] = useState(100); const filteredStencils = useMemo(() => { - return FIGMA_STENCILS.filter((item) => { + return WIREFRAME_STENCILS.filter((item) => { const matchCat = activeCategory === "all" || item.category === activeCategory; const matchSearch = !searchQuery || @@ -605,7 +695,7 @@ export function WireframeEditor({ appendTo: ".wireframe-sm-container", sectors: [ { - name: "Layout & Auto-Layout", + name: "Layout & Flexbox", open: true, properties: [ "display", @@ -650,37 +740,42 @@ export function WireframeEditor({ traitManager: { appendTo: ".wireframe-traits-container", }, + cssIcons: "", canvas: { - styles: [ - ` + styles: [], + scripts: [], + frameStyle: ` *, *::before, *::after { box-sizing: border-box; } + html { + height: 100%; + background: #f1f5f9; + } body { margin: 0; - padding: 40px; - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + padding: 40px 24px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: #f8fafc; - min-height: 100vh; + min-height: 100%; + color: #0f172a; } .gjs-selected { - outline: 2px solid #7c6af7 !important; + outline: 2px solid var(--accent-solid, #2f5d62) !important; outline-offset: 2px !important; - box-shadow: 0 0 0 4px rgba(124,106,247,0.18) !important; + box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-solid, #2f5d62) 20%, transparent) !important; } .gjs-hovered { - outline: 1px dashed #a78bfa !important; + outline: 1px dashed var(--accent-solid, #2f5d62) !important; outline-offset: 1px !important; } `, - ], }, - }); editorRef.current = editor; // Register components into BlockManager const bm = editor.BlockManager; - FIGMA_STENCILS.forEach((stencil) => { + WIREFRAME_STENCILS.forEach((stencil) => { bm.add(stencil.id, { label: stencil.label, category: stencil.category, @@ -761,6 +856,18 @@ export function WireframeEditor({ editorRef.current?.setDevice(device); }; + // Zoom controls + const handleZoom = (delta) => { + const nextZoom = Math.min(Math.max(zoomLevel + delta, 40), 200); + setZoomLevel(nextZoom); + editorRef.current?.Canvas?.setZoom(nextZoom); + }; + + const handleZoomReset = () => { + setZoomLevel(100); + editorRef.current?.Canvas?.setZoom(100); + }; + // Canvas Actions const handleUndo = () => editorRef.current?.UndoManager?.undo(); const handleRedo = () => editorRef.current?.UndoManager?.redo(); @@ -789,6 +896,17 @@ export function WireframeEditor({ setHasUnsavedChanges(true); }; + // Drag-and-drop handler for stencils + const handleStencilDragStart = (e, stencil) => { + try { + e.dataTransfer.setData("text/html", stencil.content); + e.dataTransfer.setData("text/plain", stencil.content); + e.dataTransfer.effectAllowed = "copy"; + } catch { + // fallback + } + }; + // Save handler const handleSave = async () => { const editor = editorRef.current; @@ -864,15 +982,14 @@ export function WireframeEditor({ size="" initialFocusRef={saveButtonRef} > - {/* ── Dark Figma-style Top Toolbar ──────────────────────────────── */} + {/* Dark Studio Top Toolbar */}
      {/* Brand */}
      -
      ✦
      -
      -

      Wireframe Studio

      -
      Visual UI Builder
      +
      +
      + Wireframe Studio
      @@ -883,27 +1000,30 @@ export function WireframeEditor({ type="button" className={`wireframe-vp-btn ${activeDevice === "Desktop" ? "active" : ""}`} onClick={() => handleSetDevice("Desktop")} - title="Desktop canvas" + data-tooltip="Desktop viewport (Full)" + aria-label="Desktop viewport" > - + Desktop
      @@ -916,7 +1036,8 @@ export function WireframeEditor({ type="button" className="wireframe-tool-icon-btn" onClick={handleUndo} - title="Undo (Ctrl+Z)" + data-tooltip="Undo (Ctrl+Z)" + aria-label="Undo" > @@ -924,7 +1045,8 @@ export function WireframeEditor({ type="button" className="wireframe-tool-icon-btn" onClick={handleRedo} - title="Redo (Ctrl+Y)" + data-tooltip="Redo (Ctrl+Y)" + aria-label="Redo" > @@ -933,7 +1055,8 @@ export function WireframeEditor({ type="button" className={`wireframe-tool-icon-btn ${gridVisible ? "active" : ""}`} onClick={handleToggleBorders} - title="Toggle Layout Bounds" + data-tooltip="Toggle Layout Bounds" + aria-label="Toggle layout bounds" > {gridVisible ? : } @@ -941,7 +1064,8 @@ export function WireframeEditor({ type="button" className="wireframe-tool-icon-btn danger" onClick={handleClear} - title="Clear Canvas" + data-tooltip="Clear Canvas" + aria-label="Clear canvas" > @@ -950,54 +1074,56 @@ export function WireframeEditor({ {/* Action buttons */}
      {hasUnsavedChanges && } - - - +
      - {/* ── Studio Body ─────────────────────────────────────────────────── */} + {/* Studio Body */}
      {isLoading && (
      - Loading Wireframe Studio… + Loading Wireframe Studio...
      )} - {/* ── Left Sidebar ──────────────────────────────────────────── */} + {/* Left Sidebar: Stencil Library */}
      @@ -1034,29 +1163,37 @@ export function WireframeEditor({ {searchQuery}
      ) : ( - filteredStencils.map((stencil) => ( -
      handleInsertStencil(stencil)} - title={stencil.desc} - > -
      {stencil.icon}
      -
      -
      {stencil.label}
      -
      {stencil.desc}
      + filteredStencils.map((stencil) => { + const StencilIcon = stencil.icon || Layout; + return ( +
      handleStencilDragStart(e, stencil)} + onClick={() => handleInsertStencil(stencil)} + title={`${stencil.label}\n${stencil.desc}\n• Click or drag to canvas`} + > +
      + +
      + {stencil.label}
      -
      - -
      -
      - )) + ); + }) )}
      - {/* ── Center Canvas ─────────────────────────────────────────── */} + {/* Center Canvas */}
      +
      + + {activeDevice === "Desktop" && "Desktop Screen · 1200px"} + {activeDevice === "Tablet" && "Tablet Viewport · 768px"} + {activeDevice === "Mobile" && "Mobile Device · 375px"} + +
      - {/* Status bar */} + {/* Status bar with Zoom */}
      - Canvas ready · {activeDevice} + Ready · {activeDevice} + + {/* Zoom Controls */} +
      + + + +
      +
      - Click stencil to insert  Â·  Ctrl+S to save + Drag or click stencil to add + · + Ctrl+S to save
      - {/* ── Right Inspector Panel ──────────────────────────────── */} + {/* Right Inspector Panel */}
      diff --git a/src/styles/WireframeEditor.css b/src/styles/WireframeEditor.css index 4f413144..bb4515ef 100644 --- a/src/styles/WireframeEditor.css +++ b/src/styles/WireframeEditor.css @@ -1,116 +1,102 @@ -/* ══════════════════════════════════════════════════════════════════ - Wireframe Studio — Figma-Quality Dark Design System - ══════════════════════════════════════════════════════════════════ */ +/* ========================================================================== + Wireframe Studio — Visual UI Builder (Notely Theme Integrated & Sleek) + ========================================================================== */ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); - -/* ── Root Tokens ──────────────────────────────────────────────────── */ +/* --- Modal Container Tokens & Sizing (Unified with Notely Theme) --- */ .wireframe-modal-container { - --wf-bg: #1e1e2e; - --wf-surface: #252535; - --wf-surface2: #2d2d42; - --wf-surface3: #323248; - --wf-border: rgba(255,255,255,0.07); - --wf-border2: rgba(255,255,255,0.12); - --wf-text: #e2e4f0; - --wf-text-muted: #8b8eab; - --wf-text-dim: #5c5f7a; - --wf-accent: #7c6af7; - --wf-accent-glow: rgba(124,106,247,0.3); - --wf-green: #4ade80; - --wf-radius: 10px; - --wf-radius-sm: 6px; - --wf-radius-lg: 14px; - font-family: 'Inter', system-ui, -apple-system, sans-serif; - - background: var(--wf-bg) !important; - width: 96vw !important; - max-width: 1600px !important; - height: 93vh !important; + --wf-bg: var(--app-bg); + --wf-surface: var(--surface-bg); + --wf-surface2: var(--surface-elevated); + --wf-surface3: var(--surface-muted); + --wf-border: var(--border-subtle); + --wf-border2: var(--border-default); + --wf-text: var(--text-strong); + --wf-text-muted: var(--text-muted); + --wf-text-dim: var(--text-subtle); + --wf-accent: var(--accent-solid); + --wf-accent-hover: var(--accent-strong); + --wf-accent-glow: color-mix(in srgb, var(--accent-solid) 20%, transparent); + --wf-green: var(--status-success-text); + --wf-radius: var(--radius-lg, 8px); + --wf-radius-sm: var(--radius-sm, 4px); + --wf-radius-lg: var(--radius-lg, 8px); + --wf-canvas-bg: var(--surface-muted); + --wf-canvas-dot: color-mix(in srgb, var(--text-strong) 8%, transparent); + + background: var(--surface-bg) !important; + color: var(--text-strong) !important; + font-family: var(--app-font-family, inherit); + border: 1px solid var(--border-soft) !important; + border-radius: var(--radius-md, 6px) !important; + box-shadow: var(--shadow-overlay) !important; + width: calc(100vw - 12px) !important; + height: calc(100vh - 60px - 12px) !important; + max-width: none !important; + max-height: none !important; display: flex; flex-direction: column; overflow: hidden; - border-radius: 16px; - border: 1px solid var(--wf-border2); - box-shadow: - 0 0 0 1px rgba(255,255,255,0.04), - 0 32px 80px rgba(0,0,0,0.6), - 0 8px 24px rgba(0,0,0,0.4); } -/* ── Top Bar / Studio Header ──────────────────────────────────────── */ +/* --- Top Bar / Studio Header (40px compact standard) --- */ .wireframe-studio-header { display: flex; align-items: center; - gap: 12px; - padding: 0 16px; - height: 48px; - background: var(--wf-surface); - border-bottom: 1px solid var(--wf-border); + gap: 10px; + padding: 0 12px; + height: 40px; + min-height: 40px; + background: color-mix(in srgb, var(--surface-bg) 95%, var(--surface-elevated)); + border-bottom: 1px solid var(--border-soft); flex-shrink: 0; position: relative; z-index: 10; } -/* thin rainbow accent line at the very top */ -.wireframe-studio-header::before { - content: ''; - position: absolute; - top: 0; left: 0; right: 0; - height: 2px; - background: linear-gradient(90deg, #7c6af7, #a78bfa, #60a5fa, #34d399, #fbbf24); - border-radius: 16px 16px 0 0; -} - .wireframe-studio-title-group { display: flex; align-items: center; - gap: 10px; + gap: 8px; flex-shrink: 0; } .wireframe-studio-logo { - width: 28px; - height: 28px; - background: linear-gradient(135deg, #7c6af7 0%, #60a5fa 100%); - border-radius: 7px; + width: 20px; + height: 20px; + background: var(--accent-solid); + border-radius: var(--radius-sm, 4px); display: flex; align-items: center; justify-content: center; - font-size: 14px; - box-shadow: 0 2px 8px rgba(124,106,247,0.35); flex-shrink: 0; } .wireframe-studio-title { - font-size: 13px; - font-weight: 700; - color: var(--wf-text); + font-size: 12px; + font-weight: 600; + color: var(--text-strong); margin: 0; letter-spacing: -0.01em; -} - -.wireframe-studio-subtitle { - font-size: 10px; - color: var(--wf-text-dim); - letter-spacing: 0.01em; + white-space: nowrap; } .wireframe-header-divider { width: 1px; - height: 20px; - background: var(--wf-border2); + height: 18px; + background: var(--border-soft); flex-shrink: 0; } -/* ── Viewport Device Switcher ─────────────────────────────────────── */ +/* --- Viewport Device Switcher (Sleek Segmented Control) --- */ .wireframe-viewport-controls { display: flex; align-items: center; - background: var(--wf-bg); - padding: 3px; - border-radius: var(--wf-radius-sm); - border: 1px solid var(--wf-border2); + height: var(--btn-height-sm, 28px); + box-sizing: border-box; + background: var(--surface-elevated); + padding: 2px; + border-radius: var(--radius-sm, 4px); + border: 1px solid var(--border-default); gap: 1px; flex-shrink: 0; } @@ -118,41 +104,45 @@ .wireframe-vp-btn { display: flex; align-items: center; - gap: 5px; - padding: 4px 10px; + justify-content: center; + gap: 4px; + height: 100%; + padding: 0 8px; border: none; background: transparent; - color: var(--wf-text-muted); + color: var(--text-muted); font-size: 11px; font-weight: 500; - font-family: inherit; - border-radius: 4px; + border-radius: var(--radius-sm, 4px); cursor: pointer; - transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); + transition: all 0.12s ease; white-space: nowrap; + line-height: 1; + box-sizing: border-box; } .wireframe-vp-btn:hover { - color: var(--wf-text); - background: var(--wf-surface2); + color: var(--text-strong); + background: var(--surface-subtle); } .wireframe-vp-btn.active { - background: var(--wf-accent); - color: #fff; + background: var(--accent-solid); + color: var(--text-on-accent, #ffffff); font-weight: 600; - box-shadow: 0 2px 8px var(--wf-accent-glow); } -/* ── Canvas Toolbar (Undo/Redo/Grid/etc) ──────────────────────────── */ +/* --- Canvas Tools (Undo, Redo, Bounds, Clear) --- */ .wireframe-canvas-tools { display: flex; align-items: center; + height: var(--btn-height-sm, 28px); + box-sizing: border-box; + background: var(--surface-elevated); + padding: 2px; + border-radius: var(--radius-sm, 4px); + border: 1px solid var(--border-default); gap: 1px; - background: var(--wf-bg); - padding: 3px; - border-radius: var(--wf-radius-sm); - border: 1px solid var(--wf-border2); flex-shrink: 0; } @@ -160,41 +150,41 @@ display: flex; align-items: center; justify-content: center; - width: 28px; - height: 28px; + width: 22px; + height: 100%; border: none; background: transparent; - color: var(--wf-text-muted); - border-radius: 4px; + color: var(--text-muted); + border-radius: var(--radius-sm, 4px); cursor: pointer; - transition: all 0.15s ease; - font-family: inherit; + transition: all 0.12s ease; + box-sizing: border-box; } .wireframe-tool-icon-btn:hover { - background: var(--wf-surface2); - color: var(--wf-text); + background: var(--surface-subtle); + color: var(--text-strong); } .wireframe-tool-icon-btn.active { - background: color-mix(in srgb, var(--wf-accent) 20%, transparent); - color: var(--wf-accent); + background: color-mix(in srgb, var(--accent-solid) 14%, var(--surface-bg)); + color: var(--accent-solid); } .wireframe-tool-icon-btn.danger:hover { - background: rgba(239, 68, 68, 0.15); - color: #f87171; + background: var(--status-danger-bg); + color: var(--status-danger-text); } .wireframe-tool-sep { width: 1px; height: 14px; - background: var(--wf-border2); - margin: 0 2px; + background: var(--border-soft); + margin: 0 1px; flex-shrink: 0; } -/* ── Action Buttons Row ───────────────────────────────────────────── */ +/* --- Action Buttons Row --- */ .wireframe-action-buttons { display: flex; align-items: center; @@ -203,53 +193,24 @@ flex-shrink: 0; } -.wf-btn { +.wireframe-action-buttons button, +.wireframe-action-buttons .primary-button, +.wireframe-action-buttons .small-button { + height: var(--btn-height-sm, 28px); + min-height: var(--btn-height-sm, 28px); + max-height: var(--btn-height-sm, 28px); + padding: 0 10px; + font-size: 11px; + border-radius: var(--radius-sm, 4px); + box-sizing: border-box; display: inline-flex; align-items: center; - gap: 6px; - padding: 5px 12px; - border-radius: var(--wf-radius-sm); - font-size: 12px; - font-weight: 600; - font-family: inherit; - cursor: pointer; - transition: all 0.15s ease; - border: 1px solid transparent; - white-space: nowrap; - flex-shrink: 0; + justify-content: center; + gap: 5px; line-height: 1; } -.wf-btn-ghost { - background: transparent; - color: var(--wf-text-muted); - border-color: var(--wf-border2); -} - -.wf-btn-ghost:hover { - background: var(--wf-surface2); - color: var(--wf-text); -} - -.wf-btn-primary { - background: var(--wf-accent); - color: #fff; - box-shadow: 0 2px 8px var(--wf-accent-glow); -} - -.wf-btn-primary:hover:not(:disabled) { - background: #6d5ce7; - box-shadow: 0 4px 14px var(--wf-accent-glow); - transform: translateY(-1px); -} - -.wf-btn:disabled { - opacity: 0.4; - cursor: not-allowed; - transform: none !important; -} - -/* ── Studio Body Layout ───────────────────────────────────────────── */ +/* --- Studio Body Layout --- */ .wireframe-studio-body { display: flex; flex: 1; @@ -258,11 +219,11 @@ position: relative; } -/* ── Left Sidebar: Stencil Library ────────────────────────────────── */ +/* --- Left Sidebar: Stencil Library (Sleek, Uncrowded) --- */ .wireframe-stencil-sidebar { - width: 252px; - background: var(--wf-surface); - border-right: 1px solid var(--wf-border); + width: 236px; + background: var(--surface-bg); + border-right: 1px solid var(--border-soft); display: flex; flex-direction: column; flex-shrink: 0; @@ -270,223 +231,188 @@ } .wireframe-sidebar-header { - padding: 10px 12px 6px; + padding: 8px 10px 8px; flex-shrink: 0; + display: flex; + flex-direction: column; + gap: 6px; + border-bottom: 1px solid var(--border-subtle); + position: relative; + z-index: 20; } -.wireframe-sidebar-label { - font-size: 9px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--wf-text-dim); - margin-bottom: 7px; - padding-left: 2px; -} - -/* Search */ +/* Search Input */ .wireframe-sidebar-search { position: relative; display: flex; align-items: center; - margin-bottom: 8px; } .wireframe-search-icon { position: absolute; - left: 9px; - color: var(--wf-text-dim); + left: 8px; + color: var(--text-subtle); pointer-events: none; z-index: 1; } .wireframe-search-input { width: 100%; - padding: 6px 28px 6px 28px; - border: 1px solid var(--wf-border2); - border-radius: var(--wf-radius-sm); + height: 26px; + padding: 0 24px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm, 4px); font-size: 11px; - font-family: inherit; - background: var(--wf-bg); - color: var(--wf-text); + background: var(--surface-elevated); + color: var(--text-strong); outline: none; - transition: border-color 0.15s, box-shadow 0.15s; + transition: border-color 0.12s, box-shadow 0.12s; } -.wireframe-search-input::placeholder { color: var(--wf-text-dim); } +.wireframe-search-input::placeholder { + color: var(--text-subtle); + font-size: 11px; +} .wireframe-search-input:focus { - border-color: var(--wf-accent); - box-shadow: 0 0 0 2px var(--wf-accent-glow); + border-color: var(--focus-ring-color); + box-shadow: 0 0 0 1px var(--focus-ring-color); } .wireframe-search-clear { position: absolute; - right: 8px; + right: 6px; background: transparent; border: none; - font-size: 12px; - color: var(--wf-text-muted); + font-size: 10px; + color: var(--text-subtle); cursor: pointer; - padding: 2px 4px; - border-radius: 3px; + padding: 2px; line-height: 1; - transition: color 0.1s; } -.wireframe-search-clear:hover { color: var(--wf-text); } +.wireframe-search-clear:hover { + color: var(--text-strong); +} -/* Category chips */ -.wireframe-category-chips { - display: flex; - flex-wrap: wrap; - gap: 4px; - padding: 0 12px 10px; - border-bottom: 1px solid var(--wf-border); +/* Category Filter Dropdown */ +.wireframe-category-select-wrapper { + width: 100%; } -.wireframe-category-chip { - padding: 3px 9px; - border: 1px solid var(--wf-border2); - background: transparent; - color: var(--wf-text-muted); - border-radius: 999px; - font-size: 10px; - font-weight: 500; - font-family: inherit; - white-space: nowrap; - cursor: pointer; - transition: all 0.14s ease; +.wireframe-category-select.app-select-root { + width: 100%; } -.wireframe-category-chip:hover { - background: var(--wf-surface2); - color: var(--wf-text); +.wireframe-category-select .app-select-trigger { + min-height: 26px; + height: 26px; + padding: 0 8px; + font-size: 11px; + border-radius: var(--radius-sm, 4px); + background: var(--surface-elevated); + border: 1px solid var(--border-default); + color: var(--text-strong); } -.wireframe-category-chip.active { - background: var(--wf-accent); - color: #fff; - border-color: transparent; - font-weight: 600; - box-shadow: 0 1px 6px var(--wf-accent-glow); +.wireframe-category-select .app-select-trigger:hover:not(:disabled) { + border-color: var(--border-strong); } -/* Stencil list */ +.wireframe-category-select .app-select-panel { + width: 100%; + max-width: 100%; + box-sizing: border-box; + z-index: 25; +} + +/* Stencil Grid (Clean 2-Column Visual Tiles) */ .wireframe-stencil-grid { flex: 1; overflow-y: auto; - padding: 8px 10px 16px; - display: flex; - flex-direction: column; - gap: 2px; + padding: 8px 10px 14px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 6px; + align-content: start; scrollbar-width: thin; - scrollbar-color: var(--wf-border2) transparent; + scrollbar-color: var(--border-soft) transparent; } -.wireframe-stencil-grid::-webkit-scrollbar { width: 4px; } -.wireframe-stencil-grid::-webkit-scrollbar-track { background: transparent; } -.wireframe-stencil-grid::-webkit-scrollbar-thumb { - background: var(--wf-border2); - border-radius: 4px; +.wireframe-stencil-grid::-webkit-scrollbar { + width: 4px; } -/* Section headers */ -.wireframe-stencil-section { - font-size: 9px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--wf-text-dim); - padding: 10px 4px 4px; +.wireframe-stencil-grid::-webkit-scrollbar-thumb { + background: var(--border-soft); + border-radius: var(--radius-sm, 4px); } -.wireframe-stencil-card { +.wireframe-stencil-tile { display: flex; + flex-direction: column; align-items: center; - gap: 10px; - padding: 8px 8px; - background: transparent; - border: 1px solid transparent; - border-radius: var(--wf-radius-sm); - cursor: pointer; + justify-content: center; + text-align: center; + gap: 5px; + padding: 8px 4px; + background: var(--surface-elevated); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm, 4px); + cursor: grab; + transition: all 0.12s ease; user-select: none; - transition: all 0.14s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; + min-height: 56px; + box-sizing: border-box; } -.wireframe-stencil-card:hover { - background: var(--wf-surface2); - border-color: var(--wf-border2); +.wireframe-stencil-tile:active { + cursor: grabbing; } -.wireframe-stencil-card:hover .wireframe-stencil-add { - opacity: 1; - transform: scale(1); +.wireframe-stencil-tile:hover { + background: color-mix(in srgb, var(--accent-solid) 8%, var(--surface-bg)); + border-color: var(--accent-solid); + transform: translateY(-1px); + box-shadow: var(--shadow-sm); } -.wireframe-stencil-card:active { transform: scale(0.98); } - -.wireframe-stencil-icon { - width: 32px; - height: 32px; - border-radius: var(--wf-radius-sm); - background: var(--wf-surface3); +.wireframe-stencil-tile-icon { + color: var(--accent-solid); display: flex; align-items: center; justify-content: center; - font-size: 16px; - flex-shrink: 0; - border: 1px solid var(--wf-border); -} - -.wireframe-stencil-info { - flex: 1; - min-width: 0; + transition: transform 0.12s ease; } -.wireframe-stencil-name { - font-size: 11.5px; - font-weight: 600; - color: var(--wf-text); - margin-bottom: 1px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; +.wireframe-stencil-tile:hover .wireframe-stencil-tile-icon { + transform: scale(1.1); } -.wireframe-stencil-desc { +.wireframe-stencil-tile-name { font-size: 10px; - color: var(--wf-text-dim); - white-space: nowrap; + font-weight: 500; + color: var(--text-strong); + line-height: 1.2; + display: -webkit-box; + -webkit-line-clamp: 2; + line-clamp: 2; + -webkit-box-orient: vertical; overflow: hidden; - text-overflow: ellipsis; -} - -.wireframe-stencil-add { - width: 18px; - height: 18px; - background: var(--wf-accent); - color: #fff; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - opacity: 0; - transform: scale(0.6); - transition: all 0.15s ease; + word-break: break-word; + max-width: 100%; } .wireframe-empty-stencils { - padding: 32px 16px; + grid-column: span 2; + padding: 32px 10px; text-align: center; - color: var(--wf-text-dim); + color: var(--text-subtle); font-size: 11px; - line-height: 1.6; + line-height: 1.5; } -/* ── Center Canvas ────────────────────────────────────────────────── */ +/* --- Center Canvas --- */ .wireframe-canvas-container { flex: 1; display: flex; @@ -494,105 +420,155 @@ overflow: hidden; min-width: 0; position: relative; - background-color: #131320; - background-image: - linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px), - linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px); - background-size: 24px 24px; + background-color: var(--wf-canvas-bg); + background-image: radial-gradient(var(--wf-canvas-dot) 1.2px, transparent 1.2px); + background-size: 20px 20px; } -.wireframe-canvas-statusbar { +.wireframe-canvas-top-tag { display: flex; - align-items: center; - gap: 10px; - padding: 4px 14px; - background: var(--wf-surface); - border-top: 1px solid var(--wf-border); - flex-shrink: 0; - font-size: 10px; - color: var(--wf-text-dim); + justify-content: center; + padding: 6px 0 0; + pointer-events: none; + z-index: 5; } -.wireframe-canvas-statusbar-dot { - width: 6px; - height: 6px; - border-radius: 50%; - background: var(--wf-green); - box-shadow: 0 0 4px var(--wf-green); - flex-shrink: 0; +.wireframe-artboard-pill { + background: var(--surface-bg); + color: var(--text-muted); + border: 1px solid var(--border-soft); + padding: 2px 8px; + border-radius: 999px; + font-size: 9.5px; + font-weight: 600; + letter-spacing: 0.02em; + box-shadow: var(--shadow-sm); } -.wireframe-canvas-tip { - margin-left: auto; +.wireframe-gjs-host { + flex: 1; + min-height: 0; + overflow: hidden; + position: relative; display: flex; align-items: center; - gap: 5px; + justify-content: center; } -.wireframe-canvas-tip kbd { - background: var(--wf-surface2); - border: 1px solid var(--wf-border2); - border-radius: 3px; - padding: 1px 4px; - font-size: 9px; - font-family: inherit; - color: var(--wf-text-muted); +/* GrapesJS canvas frame */ +.wireframe-gjs-host .gjs-editor { + background: transparent !important; + border: none !important; + width: 100% !important; + height: 100% !important; } -.wireframe-gjs-host { - flex: 1; - min-height: 0; +.wireframe-gjs-host .gjs-cv-canvas { + background: transparent !important; + width: 100% !important; + height: 100% !important; +} + +.wireframe-gjs-host .gjs-frame-wrapper { + margin: 8px auto; + box-shadow: var(--shadow-lg); + border-radius: var(--radius-lg, 8px); + border: 1px solid var(--border-soft); overflow: hidden; - position: relative; + background: #ffffff; } -/* empty state overlay */ -.wireframe-canvas-empty-hint { - position: absolute; - inset: 0; +/* Status bar (24px compact) */ +.wireframe-canvas-statusbar { display: flex; - flex-direction: column; align-items: center; - justify-content: center; gap: 8px; - pointer-events: none; - user-select: none; + padding: 0 12px; + height: 24px; + min-height: 24px; + background: var(--surface-bg); + border-top: 1px solid var(--border-soft); + flex-shrink: 0; + font-size: 10px; + color: var(--text-subtle); + box-sizing: border-box; } -.wf-empty-icon { - font-size: 40px; - opacity: 0.15; +.wireframe-canvas-statusbar-dot { + width: 5px; + height: 5px; + background: var(--status-success-text); + border-radius: 999px; +} + +/* Zoom controls */ +.wireframe-zoom-controls { + display: inline-flex; + align-items: center; + background: var(--surface-elevated); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm, 4px); + padding: 1px; +} + +.wireframe-zoom-btn { + display: flex; + align-items: center; + justify-content: center; + width: 18px; + height: 16px; + border: none; + background: transparent; + color: var(--text-muted); + border-radius: var(--radius-sm, 4px); + cursor: pointer; } -.wf-empty-label { - font-size: 13px; +.wireframe-zoom-btn:hover { + background: var(--surface-subtle); + color: var(--text-strong); +} + +.wireframe-zoom-label { + padding: 0 4px; + font-size: 9px; font-weight: 600; - color: rgba(255,255,255,0.1); - letter-spacing: 0.02em; + color: var(--text-muted); + background: transparent; + border: none; + cursor: pointer; } -.wf-empty-sub { - font-size: 11px; - color: rgba(255,255,255,0.06); +.wireframe-zoom-label:hover { + color: var(--text-strong); } -/* GrapesJS canvas overrides */ -.wireframe-gjs-host .gjs-editor { - background: transparent !important; - border: none !important; +.wireframe-canvas-tip { + margin-left: auto; + display: flex; + align-items: center; + gap: 5px; + font-size: 9.5px; } -.wireframe-gjs-host .gjs-cv-canvas { - background: transparent !important; - width: 100% !important; - height: 100% !important; +.wf-tip-dot { + opacity: 0.4; +} + +.wireframe-canvas-tip kbd { + background: var(--surface-elevated); + border: 1px solid var(--border-default); + border-radius: var(--radius-sm, 4px); + padding: 0 3px; + font-size: 9px; + color: var(--text-muted); } -/* ── Right Inspector Panel ────────────────────────────────────────── */ +/* --- Right Inspector Panel (236px compact) --- */ .wireframe-inspector-panel { - width: 248px; - background: var(--wf-surface); - border-left: 1px solid var(--wf-border); + width: 236px; + background: var(--surface-bg); + border-left: 1px solid var(--border-soft); display: flex; flex-direction: column; flex-shrink: 0; @@ -601,11 +577,13 @@ .wireframe-inspector-tabs { display: flex; - border-bottom: 1px solid var(--wf-border); - background: var(--wf-bg); - padding: 4px 8px 0; + border-bottom: 1px solid var(--border-soft); + background: var(--surface-elevated); + padding: 3px 6px 0; gap: 2px; flex-shrink: 0; + height: 32px; + box-sizing: border-box; } .wireframe-inspector-tab { @@ -613,45 +591,48 @@ display: flex; align-items: center; justify-content: center; - gap: 5px; - padding: 7px 4px; + gap: 4px; + padding: 4px 4px 6px; border: none; background: transparent; - color: var(--wf-text-dim); + color: var(--text-subtle); font-size: 11px; - font-weight: 600; - font-family: inherit; + font-weight: 500; cursor: pointer; border-bottom: 2px solid transparent; - transition: all 0.15s ease; - border-radius: 4px 4px 0 0; + transition: all 0.12s ease; + border-radius: var(--radius-sm, 4px) var(--radius-sm, 4px) 0 0; margin-bottom: -1px; + line-height: 1; } .wireframe-inspector-tab:hover { - color: var(--wf-text-muted); - background: var(--wf-surface2); + color: var(--text-muted); + background: var(--surface-subtle); } .wireframe-inspector-tab.active { - color: var(--wf-accent); - border-bottom-color: var(--wf-accent); - background: var(--wf-surface); + color: var(--accent-solid); + border-bottom-color: var(--accent-solid); + background: var(--surface-bg); + font-weight: 600; } .wireframe-inspector-content { flex: 1; overflow-y: auto; - padding: 10px; + padding: 8px; scrollbar-width: thin; - scrollbar-color: var(--wf-border2) transparent; + scrollbar-color: var(--border-soft) transparent; +} + +.wireframe-inspector-content::-webkit-scrollbar { + width: 4px; } -.wireframe-inspector-content::-webkit-scrollbar { width: 4px; } -.wireframe-inspector-content::-webkit-scrollbar-track { background: transparent; } .wireframe-inspector-content::-webkit-scrollbar-thumb { - background: var(--wf-border2); - border-radius: 4px; + background: var(--border-soft); + border-radius: var(--radius-sm, 4px); } .wireframe-inspector-empty { @@ -659,130 +640,164 @@ flex-direction: column; align-items: center; justify-content: center; - gap: 8px; - padding: 40px 16px; - color: var(--wf-text-dim); + gap: 6px; + padding: 36px 12px; + color: var(--text-subtle); font-size: 11px; text-align: center; - line-height: 1.5; + line-height: 1.4; +} + +.wireframe-empty-icon-svg { + opacity: 0.4; + color: var(--text-subtle); +} + +/* --- GrapesJS Studio Component Theming --- */ +.wireframe-modal-container .gjs-one-bg { + background-color: var(--surface-bg) !important; +} + +.wireframe-modal-container .gjs-two-color { + color: var(--text-strong) !important; +} + +.wireframe-modal-container .gjs-three-bg { + background-color: var(--surface-elevated) !important; + color: var(--text-strong) !important; } -.wireframe-inspector-empty-icon { font-size: 26px; opacity: 0.4; } +.wireframe-modal-container .gjs-four-color, +.wireframe-modal-container .gjs-four-color-h:hover { + color: var(--accent-solid) !important; +} -/* GrapesJS Style Manager inside inspector */ +/* Style Manager */ .wireframe-sm-container .gjs-sm-sector, .wireframe-inspector-panel .gjs-sm-sector { - border-bottom: 1px solid var(--wf-border); - padding: 6px 0; + border-bottom: 1px solid var(--border-subtle); + padding: 4px 0; } .wireframe-sm-container .gjs-sm-sector-title, .wireframe-inspector-panel .gjs-sm-sector-title { - color: var(--wf-text-muted) !important; + color: var(--text-muted) !important; background: transparent !important; - font-size: 10px !important; + font-size: 9.5px !important; font-weight: 700 !important; text-transform: uppercase; letter-spacing: 0.06em; - padding: 5px 0 !important; + padding: 4px 0 !important; border: none !important; cursor: pointer; } .wireframe-sm-container .gjs-sm-sector-title:hover, .wireframe-inspector-panel .gjs-sm-sector-title:hover { - color: var(--wf-text) !important; + color: var(--text-strong) !important; } .wireframe-inspector-panel .gjs-field, .wireframe-sm-container .gjs-field { - background: var(--wf-bg) !important; - border: 1px solid var(--wf-border2) !important; - border-radius: var(--wf-radius-sm) !important; - color: var(--wf-text) !important; + background: var(--surface-elevated) !important; + border: 1px solid var(--border-default) !important; + border-radius: var(--radius-sm, 4px) !important; + color: var(--text-strong) !important; font-size: 11px !important; } +.wireframe-inspector-panel .gjs-field:focus-within, +.wireframe-sm-container .gjs-field:focus-within { + border-color: var(--focus-ring-color) !important; + outline: 1px solid var(--focus-ring-color) !important; +} + .wireframe-inspector-panel .gjs-field input, .wireframe-inspector-panel .gjs-field select, .wireframe-sm-container .gjs-field input, .wireframe-sm-container .gjs-field select { background: transparent !important; - color: var(--wf-text) !important; + color: var(--text-strong) !important; border: none !important; font-size: 11px !important; - font-family: inherit !important; } .wireframe-inspector-panel .gjs-sm-label, .wireframe-sm-container .gjs-sm-label { - color: var(--wf-text-muted) !important; + color: var(--text-muted) !important; font-size: 10px !important; } /* Layers */ .wireframe-inspector-panel .gjs-layer, .wireframe-layers-container .gjs-layer { - color: var(--wf-text) !important; + color: var(--text-strong) !important; background: transparent !important; - border-bottom: 1px solid var(--wf-border) !important; + border-bottom: 1px solid var(--border-subtle) !important; font-size: 11px !important; } .wireframe-inspector-panel .gjs-layer:hover, .wireframe-layers-container .gjs-layer:hover { - background: var(--wf-surface2) !important; + background: var(--surface-elevated) !important; } .wireframe-inspector-panel .gjs-layer.gjs-selected, .wireframe-layers-container .gjs-layer.gjs-selected { - background: color-mix(in srgb, var(--wf-accent) 15%, transparent) !important; - color: var(--wf-accent) !important; + background: color-mix(in srgb, var(--accent-solid) 14%, var(--surface-bg)) !important; + color: var(--accent-solid) !important; } -/* ── Loading overlay ──────────────────────────────────────────────── */ +/* Loading overlay */ .wireframe-editor-loading { position: absolute; inset: 0; - background: rgba(19, 19, 32, 0.9); - backdrop-filter: blur(6px); + background: color-mix(in srgb, var(--surface-bg) 88%, transparent); + backdrop-filter: blur(4px); display: flex; flex-direction: column; align-items: center; justify-content: center; - gap: 14px; + gap: 12px; z-index: 50; font-size: 12px; font-weight: 500; - color: var(--wf-text-muted); + color: var(--text-muted); letter-spacing: 0.02em; } .wireframe-spinner { - width: 30px; - height: 30px; - border: 2.5px solid var(--wf-border2); - border-top-color: var(--wf-accent); - border-radius: 50%; + width: 24px; + height: 24px; + border: 2px solid var(--border-default); + border-top-color: var(--accent-solid); + border-radius: 999px; animation: wf-spin 0.75s linear infinite; } -@keyframes wf-spin { to { transform: rotate(360deg); } } +@keyframes wf-spin { + to { + transform: rotate(360deg); + } +} -/* Unsaved dot */ +/* Unsaved changes indicator dot */ .wf-unsaved-dot { display: inline-block; - width: 7px; - height: 7px; + width: 6px; + height: 6px; background: #f59e0b; - border-radius: 50%; - box-shadow: 0 0 6px rgba(245,158,11,0.6); + border-radius: 999px; + box-shadow: 0 0 6px rgba(245, 158, 11, 0.6); flex-shrink: 0; animation: wf-pulse 2s ease-in-out infinite; } @keyframes wf-pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.4; } + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.4; + } } - From 17d34c072280a9fb4ce932bd27c4b66de7329ddd Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Thu, 24 Sep 2026 00:25:28 +0530 Subject: [PATCH 4/7] feat(wireframe): modularize stencils, add layouts, thingworx and fontawesome --- package-lock.json | 10 + package.json | 1 + src/components/WireframeEditor.jsx | 655 +-------------- src/components/wireframe/exportUtils.js | 134 ++++ .../wireframe/stencils/categories.js | 15 + src/components/wireframe/stencils/content.js | 185 +++++ src/components/wireframe/stencils/feedback.js | 89 +++ .../wireframe/stencils/fontawesome.js | 202 +++++ src/components/wireframe/stencils/forms.js | 144 ++++ src/components/wireframe/stencils/frames.js | 110 +++ src/components/wireframe/stencils/headers.js | 100 +++ src/components/wireframe/stencils/hero.js | 117 +++ src/components/wireframe/stencils/index.js | 34 + src/components/wireframe/stencils/layouts.js | 590 ++++++++++++++ src/components/wireframe/stencils/metrics.js | 103 +++ src/components/wireframe/stencils/shells.js | 752 ++++++++++++++++++ src/components/wireframe/stencils/tables.js | 125 +++ .../wireframe/stencils/thingworx.js | 398 +++++++++ src/components/wireframe/stencils/ui.js | 100 +++ src/main.jsx | 1 + src/styles/WireframeEditor.css | 65 +- .../components/WireframeStencils.unit.test.js | 31 + 22 files changed, 3315 insertions(+), 646 deletions(-) create mode 100644 src/components/wireframe/exportUtils.js create mode 100644 src/components/wireframe/stencils/categories.js create mode 100644 src/components/wireframe/stencils/content.js create mode 100644 src/components/wireframe/stencils/feedback.js create mode 100644 src/components/wireframe/stencils/fontawesome.js create mode 100644 src/components/wireframe/stencils/forms.js create mode 100644 src/components/wireframe/stencils/frames.js create mode 100644 src/components/wireframe/stencils/headers.js create mode 100644 src/components/wireframe/stencils/hero.js create mode 100644 src/components/wireframe/stencils/index.js create mode 100644 src/components/wireframe/stencils/layouts.js create mode 100644 src/components/wireframe/stencils/metrics.js create mode 100644 src/components/wireframe/stencils/shells.js create mode 100644 src/components/wireframe/stencils/tables.js create mode 100644 src/components/wireframe/stencils/thingworx.js create mode 100644 src/components/wireframe/stencils/ui.js create mode 100644 src/tests/components/WireframeStencils.unit.test.js diff --git a/package-lock.json b/package-lock.json index e3cf5e68..a313297c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@ai-sdk/google": "^4.0.18", "@ai-sdk/groq": "^4.0.12", "@ai-sdk/openai": "^4.0.16", + "@fortawesome/fontawesome-free": "^7.3.1", "@huggingface/transformers": "^4.2.0", "@modelcontextprotocol/sdk": "^1.30.0", "ai": "^7.0.31", @@ -2950,6 +2951,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.3.1.tgz", + "integrity": "sha512-wmglKKPDIkgV3aWlZzWECCPoGIkYCulzBwxG9+w7rc5BGapZ6cPMpoPOT8k36J0Ni7PPX6c/rsoMWfS4d1MUMg==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, "node_modules/@hapi/address": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", diff --git a/package.json b/package.json index 926bcf78..54a163ab 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@ai-sdk/google": "^4.0.18", "@ai-sdk/groq": "^4.0.12", "@ai-sdk/openai": "^4.0.16", + "@fortawesome/fontawesome-free": "^7.3.1", "@huggingface/transformers": "^4.2.0", "@modelcontextprotocol/sdk": "^1.30.0", "ai": "^7.0.31", diff --git a/src/components/WireframeEditor.jsx b/src/components/WireframeEditor.jsx index 3a65491e..405e34ef 100644 --- a/src/components/WireframeEditor.jsx +++ b/src/components/WireframeEditor.jsx @@ -12,26 +12,12 @@ import { Trash2, Eye, EyeOff, - Grid3X3, Layers, Palette, Layout, - Square, - Box, Sliders, - Sparkles, - MousePointer, ZoomIn, - ZoomOut, - BarChart3, - FormInput, - Shield, - Zap, - CreditCard, - User, - AlignLeft, - Columns, - MessageSquare, + ZoomOut } from "lucide-react"; import AppButton from "./AppButton"; import AppSelect from "./AppSelect"; @@ -39,580 +25,12 @@ import OverlayDialog from "./OverlayDialog"; import useConfirm from "../hooks/useConfirm"; import { writeWireframeSource, writeWireframeImage } from "../services/wireframeService"; import { runExport } from "../services/electronService"; +import { CATEGORIES, WIREFRAME_STENCILS } from "./wireframe/stencils"; +import { exportWireframeToPng } from "./wireframe/exportUtils"; import "grapesjs/dist/css/grapes.min.css"; import "../styles/ExcalidrawEditor.css"; import "../styles/WireframeEditor.css"; -// --- Stencil Categories --- - -const CATEGORIES = [ - { id: "all", label: "All" }, - { id: "frames", label: "Frames" }, - { id: "headers", label: "Nav" }, - { id: "hero", label: "Hero" }, - { id: "content", label: "Content" }, - { id: "metrics", label: "Stats" }, - { id: "components", label: "UI" }, - { id: "forms", label: "Forms" }, - { id: "tables", label: "Tables" }, - { id: "feedback", label: "Modals" }, -]; - -// --- Curated Modern Lo-Fi / Mid-Fi Stencil Library --- - -const WIREFRAME_STENCILS = [ - // --- Artboards & Frames --- - { - id: "wf-desktop-canvas", - label: "Desktop Canvas (1200px)", - category: "frames", - desc: "Clean desktop artboard frame with header boundary", - icon: Monitor, - content: `
      -
      Desktop Artboard Boundary (1200px)
      -
      `, - }, - { - id: "wf-mobile-device", - label: "Mobile iPhone Frame", - category: "frames", - desc: "375x720px mobile viewport with speaker notch", - icon: Smartphone, - content: `
      -
      - -
      -
      Mobile Viewport (375px)
      -
      `, - }, - { - id: "wf-app-shell", - label: "SaaS Dashboard Shell", - category: "frames", - desc: "Sidebar navigation + topbar + main canvas container", - icon: Columns, - content: `
      -
      -
      - Notely App -
      -
      Dashboard
      -
      Projects
      -
      Team
      -
      Settings
      -
      -
      -
      - Overview -
      -
      -
      -
      Drop dashboard widgets and cards here
      -
      -
      -
      `, - }, - - // --- Headers & Navigation --- - { - id: "wf-nav-modern", - label: "Modern SaaS Navbar", - category: "headers", - desc: "Logo, pill links, search & CTA buttons", - icon: Box, - content: `
      -
      -
      - Brand -
      - -
      -
      - - -
      -
      `, - }, - { - id: "wf-segmented-tabs", - label: "Segmented Control Tabs", - category: "headers", - desc: "Pill segmented navigation bar", - icon: Layout, - content: `
      - - - -
      `, - }, - { - id: "wf-page-header", - label: "Page Header with Actions", - category: "headers", - desc: "Title, breadcrumb, live badge and button controls", - icon: AlignLeft, - content: `
      -
      -
      - Workspace/Settings -
      -
      -

      Project Configuration

      - Live -
      -
      -
      - - -
      -
      `, - }, - - // --- Hero & Banner --- - { - id: "wf-hero-centered", - label: "Hero Centered Section", - category: "hero", - desc: "Headline, badge, CTA buttons & screen mockup", - icon: Sparkles, - content: `
      -
      - Release v2.0 Live Now -
      -

      Design systems that scale with ease

      -

      Create beautiful wireframes, mockups, and interface flows directly inside your documentation.

      -
      - - -
      -
      - [ App Preview Screen Mockup ] -
      -
      `, - }, - { - id: "wf-cta-banner", - label: "Call to Action Banner", - category: "hero", - desc: "Dark accent conversion box with buttons", - icon: Zap, - content: `
      -
      -

      Ready to upgrade your workflow?

      -

      Collaborate in real time with high-velocity interface components.

      -
      -
      - -
      -
      `, - }, - - // --- Content & Grids --- - { - id: "wf-feature-grid-3", - label: "3-Column Feature Cards", - category: "content", - desc: "Feature cards with icons, titles & descriptions", - icon: Grid3X3, - content: `
      -
      -
      ⚡
      -

      Lightning Fast

      -

      Instant drag-and-drop elements designed for rapid wireframing.

      -
      -
      -
      🎨
      -

      Figma Precision

      -

      Pixel-calibrated spacing, modern typography, and clean tokens.

      -
      -
      -
      🔒
      -

      Offline Native

      -

      100% saved locally alongside notes with instant export capabilities.

      -
      -
      `, - }, - { - id: "wf-bento-grid", - label: "Bento Grid Layout", - category: "content", - desc: "Asymmetric 4-tile modern showcase layout", - icon: Layout, - content: `
      -
      - Core Feature -

      Interactive Canvas Controls

      -

      Manipulate layout, typography, borders, and fills directly in the property inspector.

      -
      Feature Visual Placeholder
      -
      -
      -
      -

      Instant PNG Export

      -

      Generate high-res graphics embedded in notes automatically.

      -
      -
      -

      Local-First Security

      -

      No third-party cloud required. Everything lives on your disk.

      -
      -
      -
      `, - }, - { - id: "wf-pricing-card-group", - label: "Pricing Tier Cards", - category: "content", - desc: "Starter vs Professional pricing comparison", - icon: CreditCard, - content: `
      -
      -
      Starter
      -
      $0/mo
      -
        -
      • ✓ Up to 10 wireframes
      • -
      • ✓ Standard export (PNG)
      • -
      • ✓ Core stencil library
      • -
      - -
      -
      - Popular -
      Professional
      -
      $19/mo
      -
        -
      • ✓ Unlimited wireframes
      • -
      • ✓ Vector & SVG export
      • -
      • ✓ Full stencil packs
      • -
      - -
      -
      `, - }, - - // --- Metrics & Stats --- - { - id: "wf-kpi-stats-row", - label: "KPI Metric Stats Row", - category: "metrics", - desc: "3 metric KPI cards with delta percentages", - icon: BarChart3, - content: `
      -
      -
      Monthly Revenue
      -
      - $48,250 - +12.4% -
      -
      -
      -
      Active Projects
      -
      - 1,420 - +8.1% -
      -
      -
      -
      Avg. Response Time
      -
      - 184ms - -2.3% -
      -
      -
      `, - }, - - // --- UI Components --- - { - id: "wf-button-suite", - label: "Button Styles Suite", - category: "components", - desc: "Primary, secondary, outline, ghost and danger buttons", - icon: Square, - content: `
      - - - - - -
      `, - }, - { - id: "wf-avatar-stack", - label: "Avatar Stack & Badge", - category: "components", - desc: "Collaborator face avatars with count chip", - icon: User, - content: `
      -
      - JD - AL - RK -
      - +8 contributors active -
      `, - }, - { - id: "wf-alert-banner", - label: "Alert Notification Banner", - category: "components", - desc: "Info notification banner with icon and dismiss link", - icon: Shield, - content: `
      -
      - Notice: Your workspace was upgraded to the latest version. -
      - View Changelog -
      `, - }, - - // --- Forms & Inputs --- - { - id: "wf-auth-card", - label: "Auth Sign-in Card", - category: "forms", - desc: "Centered sign-in card with email, password & button", - icon: FormInput, - content: `
      -

      Welcome back

      -

      Enter your credentials to access your notes

      -
      - - -
      -
      - - -
      - -
      `, - }, - { - id: "wf-search-filter-bar", - label: "Search & Filter Bar", - category: "forms", - desc: "Search bar with category dropdown and action button", - icon: Search, - content: `
      -
      - 🔍 - -
      - - -
      `, - }, - - // --- Data & Tables --- - { - id: "wf-data-table", - label: "Modern Data Table", - category: "tables", - desc: "Structured data table with status pills and actions", - icon: Layers, - content: `
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      NameStatusRoleActions
      Bikash PandaActiveAdmin•••
      Sarah ConnorPendingEditor•••
      Alex MurphyInactiveViewer•••
      -
      `, - }, - - // --- Modals & Feedback --- - { - id: "wf-modal-dialog", - label: "Confirmation Modal Dialog", - category: "feedback", - desc: "Dialog card with title, body text and cancel/confirm buttons", - icon: MousePointer, - content: `
      -

      Delete Project

      -

      Are you sure you want to delete this project? This action cannot be undone.

      -
      - - -
      -
      `, - }, - { - id: "wf-empty-state-card", - label: "Empty State Placeholder", - category: "feedback", - desc: "Icon, empty message and primary action button", - icon: MessageSquare, - content: `
      -
      📁
      -

      No documents yet

      -

      Create your first document or import notes from Markdown to get started.

      - -
      `, - }, -]; - -// --- Export to PNG helper --- - -function exportWireframeToPng(editor) { - return new Promise((resolve) => { - if (!editor) { - resolve(createFallbackPng(editor)); - return; - } - - try { - const width = 1200; - const height = 800; - - const frameDoc = editor.Canvas?.getDocument?.(); - const frameBody = frameDoc?.body; - let bodyXml = ""; - let cssText = editor.getCss?.() || ""; - - if (frameDoc && frameBody) { - // Collect canvas iframe styles - const styleTags = frameDoc.querySelectorAll("style"); - styleTags.forEach((s) => { - cssText += "\n" + (s.textContent || ""); - }); - - // Clone and sanitize selection markers - const clone = frameBody.cloneNode(true); - clone.querySelectorAll(".gjs-selected, .gjs-hovered").forEach((el) => { - el.classList.remove("gjs-selected", "gjs-hovered"); - }); - - const serializer = new XMLSerializer(); - bodyXml = serializer.serializeToString(clone); - } else { - const rawHtml = editor.getHtml?.() || ""; - bodyXml = `
      ${rawHtml}
      `; - } - - const svgDoc = ` - - -
      - - ${bodyXml} -
      -
      -
      - `.trim(); - - const img = new Image(); - const dataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgDoc)}`; - - const fallbackTimer = setTimeout(() => { - resolve(createFallbackPng(editor)); - }, 2000); - - img.onload = () => { - clearTimeout(fallbackTimer); - try { - const canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; - const ctx = canvas.getContext("2d"); - ctx.fillStyle = "#ffffff"; - ctx.fillRect(0, 0, width, height); - ctx.drawImage(img, 0, 0); - resolve(canvas.toDataURL("image/png")); - } catch { - resolve(createFallbackPng(editor)); - } - }; - - img.onerror = () => { - clearTimeout(fallbackTimer); - resolve(createFallbackPng(editor)); - }; - - img.src = dataUri; - } catch { - resolve(createFallbackPng(editor)); - } - }); -} - -function createFallbackPng(editor) { - const canvas = document.createElement("canvas"); - canvas.width = 1200; - canvas.height = 800; - const ctx = canvas.getContext("2d"); - - // Canvas background - ctx.fillStyle = "#f8fafc"; - ctx.fillRect(0, 0, 1200, 800); - - // Border frame - ctx.strokeStyle = "#cbd5e1"; - ctx.lineWidth = 2; - ctx.strokeRect(20, 20, 1160, 760); - - // Header mockup - ctx.fillStyle = "#ffffff"; - ctx.fillRect(20, 20, 1160, 60); - ctx.fillStyle = "#2563eb"; - ctx.fillRect(44, 40, 20, 20); - - ctx.fillStyle = "#0f172a"; - ctx.font = "bold 16px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; - ctx.textAlign = "left"; - ctx.fillText("Wireframe Mockup", 74, 55); - - // Content area - ctx.fillStyle = "#ffffff"; - ctx.fillRect(60, 120, 1080, 600); - ctx.strokeStyle = "#e2e8f0"; - ctx.strokeRect(60, 120, 1080, 600); - - ctx.fillStyle = "#64748b"; - ctx.font = "14px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; - ctx.textAlign = "center"; - - const html = editor?.getHtml?.() || ""; - const hasContent = html.replace(/<[^>]+>/g, "").trim().length > 10; - ctx.fillText(hasContent ? "Wireframe UI Design" : "Wireframe Artboard", 600, 420); - - return canvas.toDataURL("image/png"); -} - // --- WireframeEditor Component --- export function WireframeEditor({ @@ -621,7 +39,7 @@ export function WireframeEditor({ documentPath, onClose, onSave, - onNotify, + onNotify }) { const editorRef = useRef(null); const editorContainerRef = useRef(null); @@ -659,7 +77,7 @@ export function WireframeEditor({ message: "You have unsaved wireframe changes. Are you sure you want to discard them?", confirmLabel: "Discard", cancelLabel: "Cancel", - variant: "danger", + variant: "danger" }); if (!confirmed) return; } @@ -687,8 +105,8 @@ export function WireframeEditor({ devices: [ { name: "Desktop", width: "" }, { name: "Tablet", width: "768px" }, - { name: "Mobile", width: "375px" }, - ], + { name: "Mobile", width: "375px" } + ] }, panels: { defaults: [] }, styleManager: { @@ -707,42 +125,30 @@ export function WireframeEditor({ "margin", "width", "max-width", - "min-height", - ], + "min-height" + ] }, { name: "Typography", open: true, - properties: [ - "font-size", - "font-weight", - "color", - "text-align", - "line-height", - ], + properties: ["font-size", "font-weight", "color", "text-align", "line-height"] }, { name: "Fill & Stroke", open: true, - properties: [ - "background-color", - "border", - "border-radius", - "box-shadow", - "opacity", - ], - }, - ], + properties: ["background-color", "border", "border-radius", "box-shadow", "opacity"] + } + ] }, layerManager: { - appendTo: ".wireframe-layers-container", + appendTo: ".wireframe-layers-container" }, traitManager: { - appendTo: ".wireframe-traits-container", + appendTo: ".wireframe-traits-container" }, cssIcons: "", canvas: { - styles: [], + styles: ["https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"], scripts: [], frameStyle: ` *, *::before, *::after { box-sizing: border-box; } @@ -767,8 +173,8 @@ export function WireframeEditor({ outline: 1px dashed var(--accent-solid, #2f5d62) !important; outline-offset: 1px !important; } - `, - }, + ` + } }); editorRef.current = editor; @@ -779,7 +185,7 @@ export function WireframeEditor({ bm.add(stencil.id, { label: stencil.label, category: stencil.category, - content: stencil.content, + content: stencil.content }); }); @@ -802,6 +208,23 @@ export function WireframeEditor({ setHasUnsavedChanges(true); }); + // Ensure canvas iframe head has FontAwesome + editor.on("load", () => { + try { + const doc = editor.Canvas?.getDocument?.(); + if (doc && !doc.querySelector("link[data-fa='true']")) { + const link = doc.createElement("link"); + link.rel = "stylesheet"; + link.href = + "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"; + link.setAttribute("data-fa", "true"); + doc.head?.appendChild(link); + } + } catch { + // ignore canvas frame access errors + } + }); + setIsLoading(false); } catch (err) { console.error("Failed to initialize GrapesJS:", err); @@ -822,6 +245,7 @@ export function WireframeEditor({ editorRef.current = null; } }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Escape key handler @@ -955,7 +379,7 @@ export function WireframeEditor({ dataUrl: pngDataUrl, filename, customExportType: "diagram_wireframe", - category: "diagram", + category: "diagram" }); if (result?.success) { @@ -1159,7 +583,8 @@ export function WireframeEditor({
      {filteredStencils.length === 0 ? (
      - No components match
      + No components match +
      {searchQuery}
      ) : ( diff --git a/src/components/wireframe/exportUtils.js b/src/components/wireframe/exportUtils.js new file mode 100644 index 00000000..d7881aa2 --- /dev/null +++ b/src/components/wireframe/exportUtils.js @@ -0,0 +1,134 @@ +/** + * Export helpers for Wireframe Studio + * Serializes GrapesJS canvas DOM to PNG using SVG foreignObject and Canvas 2D + */ + +export function createFallbackPng(editor) { + const canvas = document.createElement("canvas"); + canvas.width = 1200; + canvas.height = 800; + const ctx = canvas.getContext("2d"); + + // Canvas background + ctx.fillStyle = "#f8fafc"; + ctx.fillRect(0, 0, 1200, 800); + + // Border frame + ctx.strokeStyle = "#cbd5e1"; + ctx.lineWidth = 2; + ctx.strokeRect(20, 20, 1160, 760); + + // Header mockup + ctx.fillStyle = "#ffffff"; + ctx.fillRect(20, 20, 1160, 60); + ctx.fillStyle = "#2563eb"; + ctx.fillRect(44, 40, 20, 20); + + ctx.fillStyle = "#0f172a"; + ctx.font = "bold 16px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; + ctx.textAlign = "left"; + ctx.fillText("Wireframe Mockup", 74, 55); + + // Content area + ctx.fillStyle = "#ffffff"; + ctx.fillRect(60, 120, 1080, 600); + ctx.strokeStyle = "#e2e8f0"; + ctx.strokeRect(60, 120, 1080, 600); + + ctx.fillStyle = "#64748b"; + ctx.font = "14px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; + ctx.textAlign = "center"; + + const html = editor?.getHtml?.() || ""; + const hasContent = html.replace(/<[^>]+>/g, "").trim().length > 10; + ctx.fillText(hasContent ? "Wireframe UI Design" : "Wireframe Artboard", 600, 420); + + return canvas.toDataURL("image/png"); +} + +export function exportWireframeToPng(editor) { + return new Promise((resolve) => { + if (!editor) { + resolve(createFallbackPng(editor)); + return; + } + + try { + const width = 1200; + const height = 800; + + const frameDoc = editor.Canvas?.getDocument?.(); + const frameBody = frameDoc?.body; + let bodyXml = ""; + let cssText = editor.getCss?.() || ""; + + if (frameDoc && frameBody) { + // Collect canvas iframe styles + const styleTags = frameDoc.querySelectorAll("style"); + styleTags.forEach((s) => { + cssText += "\n" + (s.textContent || ""); + }); + + // Clone and sanitize selection markers + const clone = frameBody.cloneNode(true); + clone.querySelectorAll(".gjs-selected, .gjs-hovered").forEach((el) => { + el.classList.remove("gjs-selected", "gjs-hovered"); + }); + + const serializer = new XMLSerializer(); + bodyXml = serializer.serializeToString(clone); + } else { + const rawHtml = editor.getHtml?.() || ""; + bodyXml = `
      ${rawHtml}
      `; + } + + const svgDoc = ` + + +
      + + + ${bodyXml} +
      +
      +
      + `.trim(); + + const img = new Image(); + const dataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgDoc)}`; + + const fallbackTimer = setTimeout(() => { + resolve(createFallbackPng(editor)); + }, 2000); + + img.onload = () => { + clearTimeout(fallbackTimer); + try { + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, width, height); + ctx.drawImage(img, 0, 0); + resolve(canvas.toDataURL("image/png")); + } catch { + resolve(createFallbackPng(editor)); + } + }; + + img.onerror = () => { + clearTimeout(fallbackTimer); + resolve(createFallbackPng(editor)); + }; + + img.src = dataUri; + } catch { + resolve(createFallbackPng(editor)); + } + }); +} diff --git a/src/components/wireframe/stencils/categories.js b/src/components/wireframe/stencils/categories.js new file mode 100644 index 00000000..cf888bb8 --- /dev/null +++ b/src/components/wireframe/stencils/categories.js @@ -0,0 +1,15 @@ +export const CATEGORIES = [ + { id: "all", label: "All Components" }, + { id: "layouts", label: "Layouts & App Shells" }, + { id: "icons", label: "FontAwesome Icons" }, + { id: "thingworx", label: "ThingWorx & Industrial IoT" }, + { id: "frames", label: "Artboards & Frames" }, + { id: "headers", label: "Navigation & Headers" }, + { id: "hero", label: "Hero & Banners" }, + { id: "content", label: "Content & Grids" }, + { id: "metrics", label: "Metrics & Charts" }, + { id: "components", label: "UI Controls & Badges" }, + { id: "forms", label: "Forms & Inputs" }, + { id: "tables", label: "Tables & Kanban" }, + { id: "feedback", label: "Modals & Feedback" } +]; diff --git a/src/components/wireframe/stencils/content.js b/src/components/wireframe/stencils/content.js new file mode 100644 index 00000000..225bdef7 --- /dev/null +++ b/src/components/wireframe/stencils/content.js @@ -0,0 +1,185 @@ +import { Grid3X3, Layout, CreditCard, FileText, Clock, HelpCircle } from "lucide-react"; + +export const contentStencils = [ + { + id: "wf-feature-grid-3", + label: "3-Column Feature Cards", + category: "content", + desc: "Feature cards with icons, titles & descriptions", + icon: Grid3X3, + content: `
      +
      +
      ⚡
      +

      Lightning Fast

      +

      Instant drag-and-drop elements designed for rapid wireframing.

      +
      +
      +
      🎨
      +

      Figma Precision

      +

      Pixel-calibrated spacing, modern typography, and clean tokens.

      +
      +
      +
      🔒
      +

      Offline Native

      +

      100% saved locally alongside notes with instant export capabilities.

      +
      +
      ` + }, + { + id: "wf-bento-grid", + label: "Bento Grid Layout", + category: "content", + desc: "Asymmetric 4-tile modern showcase layout", + icon: Layout, + content: `
      +
      + Core Feature +

      Interactive Canvas Controls

      +

      Manipulate layout, typography, borders, and fills directly in the property inspector.

      +
      Feature Visual Placeholder
      +
      +
      +
      +

      Instant PNG Export

      +

      Generate high-res graphics embedded in notes automatically.

      +
      +
      +

      Local-First Security

      +

      No third-party cloud required. Everything lives on your disk.

      +
      +
      +
      ` + }, + { + id: "wf-pricing-card-group", + label: "Pricing Tier Cards", + category: "content", + desc: "Starter vs Professional pricing comparison", + icon: CreditCard, + content: `
      +
      +
      Starter
      +
      $0/mo
      +
        +
      • ✓ Up to 10 wireframes
      • +
      • ✓ Standard export (PNG)
      • +
      • ✓ Core stencil library
      • +
      + +
      +
      + Popular +
      Professional
      +
      $19/mo
      +
        +
      • ✓ Unlimited wireframes
      • +
      • ✓ Vector & SVG export
      • +
      • ✓ Full stencil packs
      • +
      + +
      +
      ` + }, + { + id: "wf-blog-cards", + label: "3-Column Article / Blog Cards", + category: "content", + desc: "Cards with cover image placeholder, tag & metadata", + icon: FileText, + content: `
      +
      +
      [ Cover Image ]
      +
      + Design Systems +

      Scaling lo-fi wireframes to production

      +
      5 min read • Jun 12
      +
      +
      +
      +
      [ Cover Image ]
      +
      + Engineering +

      Offline-first local file architecture

      +
      8 min read • Jun 18
      +
      +
      +
      ` + }, + { + id: "wf-timeline", + label: "Vertical Timeline & History", + category: "content", + desc: "Chronological milestone entries with node dots", + icon: Clock, + content: `
      +

      Release History

      +
      +
      +
      +
      v2.1.0 - Wireframe Studio
      +
      Added GrapesJS canvas with 40+ stencils.
      +
      +
      +
      +
      v2.0.4 - Performance
      +
      Improved media rendering speeds.
      +
      +
      +
      ` + }, + { + id: "wf-faq-accordion", + label: "FAQ Accordion Rows", + category: "content", + desc: "Expandable question & answer cards", + icon: HelpCircle, + content: `
      +
      +
      + Are wireframes stored locally on disk? + ▲ +
      +

      Yes, wireframes are stored as JSON and PNG previews directly inside your note folder.

      +
      +
      +
      + Can I export wireframes as PNG images? + ▼ +
      +
      +
      ` + }, + { + id: "wf-feature-matrix", + label: "Feature Comparison Matrix", + category: "content", + desc: "Tiered feature checkmark table", + icon: Grid3X3, + content: `
      + + + + + + + + + + + + + + + + + + + + + + + +
      FeatureFreeProEnterprise
      Local-first notes✓✓✓
      Interactive Wireframes5✓✓
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/feedback.js b/src/components/wireframe/stencils/feedback.js new file mode 100644 index 00000000..18302f1f --- /dev/null +++ b/src/components/wireframe/stencils/feedback.js @@ -0,0 +1,89 @@ +import { MousePointer, MessageSquare, Layout, Shield, Bell } from "lucide-react"; + +export const feedbackStencils = [ + { + id: "wf-modal-dialog", + label: "Confirmation Modal Dialog", + category: "feedback", + desc: "Dialog card with title, body text and cancel/confirm buttons", + icon: MousePointer, + content: `
      +

      Delete Project

      +

      Are you sure you want to delete this project? This action cannot be undone.

      +
      + + +
      +
      ` + }, + { + id: "wf-empty-state-card", + label: "Empty State Placeholder", + category: "feedback", + desc: "Icon, empty message and primary action button", + icon: MessageSquare, + content: `
      +
      📁
      +

      No documents yet

      +

      Create your first document or import notes from Markdown to get started.

      + +
      ` + }, + { + id: "wf-slideover", + label: "Slide-over Drawer / Sheet", + category: "feedback", + desc: "Right-hand sidebar inspection drawer", + icon: Layout, + content: `
      +
      Background Canvas View
      +
      +
      + Inspect Element + ✕ +
      +
      Select properties to adjust attributes.
      + +
      +
      ` + }, + { + id: "wf-gdpr-banner", + label: "Cookie & Consent Bar", + category: "feedback", + desc: "Floating bottom privacy notification bar", + icon: Shield, + content: `
      +
      + We use local storage cookies to remember your workspace state and active themes. +
      +
      + + +
      +
      ` + }, + { + id: "wf-toast-stack", + label: "Toast Notifications Stack", + category: "feedback", + desc: "Success and alert notification popups", + icon: Bell, + content: `
      +
      + ✓ +
      +
      Note saved
      +
      Diagram files updated on disk
      +
      +
      +
      + ⚠ +
      +
      Export alert
      +
      Canvas contains unsaved elements
      +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/fontawesome.js b/src/components/wireframe/stencils/fontawesome.js new file mode 100644 index 00000000..3d78fe6e --- /dev/null +++ b/src/components/wireframe/stencils/fontawesome.js @@ -0,0 +1,202 @@ +import { Sparkles, Star, Award, ShieldCheck, Tag, Compass, Bookmark } from "lucide-react"; + +export const fontawesomeStencils = [ + { + id: "wf-fa-icon-cloud", + label: "FontAwesome Popular Icons Pack", + category: "icons", + desc: "Grid of standard FontAwesome icons ready to duplicate & customize", + icon: Sparkles, + content: `
      +
      + FontAwesome Icon Palette +
      +
      +
      + +
      house
      +
      +
      + +
      user
      +
      +
      + +
      gear
      +
      +
      + +
      bell
      +
      +
      + +
      envelope
      +
      +
      + +
      search
      +
      +
      + +
      bolt
      +
      +
      + +
      check
      +
      +
      + +
      warn
      +
      +
      + +
      heart
      +
      +
      + +
      cloud
      +
      +
      + +
      lock
      +
      +
      +
      ` + }, + { + id: "wf-fa-icon-buttons", + label: "FontAwesome Icon Buttons Bar", + category: "icons", + desc: "Row of action buttons with leading FontAwesome icons", + icon: Tag, + content: `
      + + + + +
      ` + }, + { + id: "wf-fa-feature-cards", + label: "FontAwesome 3-Column Features", + category: "icons", + desc: "Feature cards with FontAwesome icon headers & descriptions", + icon: Award, + content: `
      +
      +
      + +
      +

      Enterprise Security

      +

      Encrypted local files, zero cloud exposure, and air-gapped support.

      +
      +
      +
      + +
      +

      Instant Real-Time

      +

      Millisecond vector rendering and direct drag-and-drop mechanics.

      +
      +
      +
      + +
      +

      Figma Tokens

      +

      Precision typography, spacing variables, and border-radius compliance.

      +
      +
      ` + }, + { + id: "wf-fa-alert-badges", + label: "FontAwesome Status & Alert Badges", + category: "icons", + desc: "Success, Warning, Danger, and Info badges with FontAwesome icons", + icon: ShieldCheck, + content: `
      +
      + + Success: System is operating normally within parameters. +
      +
      + + Warning: High telemetry memory consumption detected. +
      +
      + + Critical: Controller lost heartbeat connection. +
      +
      + + Info: Firmware version 4.2.1 is available for download. +
      +
      ` + }, + { + id: "wf-fa-social-bar", + label: "FontAwesome Brands & Social Bar", + category: "icons", + desc: "Brand icons for GitHub, X, LinkedIn, Discord, and Slack", + icon: Compass, + content: `
      + Connect: + + + + + +
      ` + }, + { + id: "wf-fa-rating-card", + label: "FontAwesome 5-Star Testimonial", + category: "icons", + desc: "Review testimonial with gold FontAwesome star rating", + icon: Star, + content: `
      +
      + + + + + +
      +

      "The wireframing studio with ThingWorx & FontAwesome stencils cuts our industrial UI prototyping from days to minutes."

      +
      +
      EM
      +
      +
      Elena Morales
      +
      Principal IoT Architect
      +
      +
      +
      ` + }, + { + id: "wf-fa-nav-pills", + label: "FontAwesome Icon Navigation Tabs", + category: "icons", + desc: "Segmented tab bar with leading FontAwesome icons", + icon: Bookmark, + content: `
      + + + + +
      ` + } +]; diff --git a/src/components/wireframe/stencils/forms.js b/src/components/wireframe/stencils/forms.js new file mode 100644 index 00000000..09bf99c4 --- /dev/null +++ b/src/components/wireframe/stencils/forms.js @@ -0,0 +1,144 @@ +import { FormInput, Search, Zap, CreditCard, Sliders } from "lucide-react"; + +export const formStencils = [ + { + id: "wf-auth-card", + label: "Auth Sign-in Card", + category: "forms", + desc: "Centered sign-in card with email, password & button", + icon: FormInput, + content: `
      +

      Welcome back

      +

      Enter your credentials to access your notes

      +
      + + +
      +
      + + +
      + +
      ` + }, + { + id: "wf-search-filter-bar", + label: "Search & Filter Bar", + category: "forms", + desc: "Search bar with category dropdown and action button", + icon: Search, + content: `
      +
      + 🔍 + +
      + + +
      ` + }, + { + id: "wf-wizard-stepper", + label: "Multi-Step Wizard Stepper", + category: "forms", + desc: "Step 1-2-3 horizontal progress indicator", + icon: Zap, + content: `
      +
      + 1 + Account +
      +
      +
      + 2 + Workspace +
      +
      +
      + 3 + Review +
      +
      ` + }, + { + id: "wf-contact-form", + label: "Contact & Feedback Form", + category: "forms", + desc: "Support request form with input fields and textarea", + icon: FormInput, + content: `
      +

      Contact Support

      +

      We typically respond within an hour.

      +
      +
      + + +
      +
      + + +
      +
      +
      + + +
      + +
      ` + }, + { + id: "wf-credit-card", + label: "Credit Card Payment Form", + category: "forms", + desc: "Card number, expiration and security code fields", + icon: CreditCard, + content: `
      +

      Payment Method

      +
      + + +
      +
      +
      + + +
      +
      + + +
      +
      + +
      ` + }, + { + id: "wf-settings-toggles", + label: "Preference Toggles List", + category: "forms", + desc: "Switch toggle rows for feature settings", + icon: Sliders, + content: `
      +
      +
      +
      Dark Theme
      +
      Follow system appearance
      +
      +
      +
      +
      +
      +
      +
      +
      Auto-save Notes
      +
      Save diagrams on change
      +
      +
      +
      +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/frames.js b/src/components/wireframe/stencils/frames.js new file mode 100644 index 00000000..8ab019bd --- /dev/null +++ b/src/components/wireframe/stencils/frames.js @@ -0,0 +1,110 @@ +import { Monitor, Smartphone, Columns, Tablet, Sliders } from "lucide-react"; + +export const frameStencils = [ + { + id: "wf-desktop-canvas", + label: "Desktop Canvas (1200px)", + category: "frames", + desc: "Clean desktop artboard frame with header boundary", + icon: Monitor, + content: `
      +
      Desktop Artboard Boundary (1200px)
      +
      ` + }, + { + id: "wf-mobile-device", + label: "Mobile iPhone Frame", + category: "frames", + desc: "375x720px mobile viewport with speaker notch", + icon: Smartphone, + content: `
      +
      + +
      +
      Mobile Viewport (375px)
      +
      ` + }, + { + id: "wf-app-shell", + label: "SaaS Dashboard Shell", + category: "frames", + desc: "Sidebar navigation + topbar + main canvas container", + icon: Columns, + content: `
      +
      +
      + Notely App +
      +
      Dashboard
      +
      Projects
      +
      Team
      +
      Settings
      +
      +
      +
      + Overview +
      +
      +
      +
      Drop dashboard widgets and cards here
      +
      +
      +
      ` + }, + { + id: "wf-tablet-frame", + label: "Tablet Viewport Frame", + category: "frames", + desc: "768px tablet layout with camera indicator", + icon: Tablet, + content: `
      +
      +
      Tablet Viewport (768px)
      +
      ` + }, + { + id: "wf-split-screen", + label: "50/50 Split Screen Onboarding", + category: "frames", + desc: "Two-column hero brand showcase and signup form", + icon: Columns, + content: `
      +
      + Notely Platform +

      Next generation technical note-taking

      +

      Write markdown, sketch diagrams, design responsive wireframes, and collaborate offline.

      +
      +
      +

      Create your account

      +

      Start building notes and wireframes locally.

      + + + +
      +
      ` + }, + { + id: "wf-two-col-settings", + label: "2-Column Settings View", + category: "frames", + desc: "Sidebar category navigation + form content pane", + icon: Sliders, + content: `
      +
      +
      Settings
      +
      General
      +
      Team
      +
      Security
      +
      +
      +

      Profile Details

      +

      Manage your public workspace presence.

      +
      + + +
      + +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/headers.js b/src/components/wireframe/stencils/headers.js new file mode 100644 index 00000000..7f546b0c --- /dev/null +++ b/src/components/wireframe/stencils/headers.js @@ -0,0 +1,100 @@ +import { Box, Layout, AlignLeft, Compass, Smartphone } from "lucide-react"; + +export const headerStencils = [ + { + id: "wf-nav-modern", + label: "Modern SaaS Navbar", + category: "headers", + desc: "Logo, pill links, search & CTA buttons", + icon: Box, + content: `
      +
      +
      + Brand +
      + +
      +
      + + +
      +
      ` + }, + { + id: "wf-segmented-tabs", + label: "Segmented Control Tabs", + category: "headers", + desc: "Pill segmented navigation bar", + icon: Layout, + content: `
      + + + +
      ` + }, + { + id: "wf-page-header", + label: "Page Header with Actions", + category: "headers", + desc: "Title, breadcrumb, live badge and button controls", + icon: AlignLeft, + content: `
      +
      +
      + Workspace/Settings +
      +
      +

      Project Configuration

      + Live +
      +
      +
      + + +
      +
      ` + }, + { + id: "wf-breadcrumb-bar", + label: "Breadcrumb Navigation Bar", + category: "headers", + desc: "Hierarchical trail with active note indicator", + icon: Compass, + content: `` + }, + { + id: "wf-mobile-bottom-tabs", + label: "Mobile Bottom Navigation", + category: "headers", + desc: "4-icon mobile tab bar with active highlights", + icon: Smartphone, + content: `
      +
      + 🏠 Home +
      +
      + 🔍 Search +
      +
      + ⚡ Activity +
      +
      + 👤 Profile +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/hero.js b/src/components/wireframe/stencils/hero.js new file mode 100644 index 00000000..b0e058d4 --- /dev/null +++ b/src/components/wireframe/stencils/hero.js @@ -0,0 +1,117 @@ +import { Sparkles, Zap, Layout, MessageSquare } from "lucide-react"; + +export const heroStencils = [ + { + id: "wf-hero-centered", + label: "Hero Centered Section", + category: "hero", + desc: "Headline, badge, CTA buttons & screen mockup", + icon: Sparkles, + content: `
      +
      + Release v2.0 Live Now +
      +

      Design systems that scale with ease

      +

      Create beautiful wireframes, mockups, and interface flows directly inside your documentation.

      +
      + + +
      +
      + [ App Preview Screen Mockup ] +
      +
      ` + }, + { + id: "wf-cta-banner", + label: "Call to Action Banner", + category: "hero", + desc: "Dark accent conversion box with buttons", + icon: Zap, + content: `
      +
      +

      Ready to upgrade your workflow?

      +

      Collaborate in real time with high-velocity interface components.

      +
      +
      + +
      +
      ` + }, + { + id: "wf-hero-split-form", + label: "Hero with Lead Capture Form", + category: "hero", + desc: "Headline, value proposition and quick signup box", + icon: Sparkles, + content: `
      +
      + Enterprise Ready +

      Build wireframes at the speed of thought

      +

      Collaborative UI stencils designed directly for engineers and product teams.

      +
      + ✓ Local-first + ✓ Zero latency + ✓ PNG export +
      +
      +
      +

      Request Live Demo

      +

      Instant access to the documentation suite.

      + + + +
      +
      ` + }, + { + id: "wf-video-hero", + label: "Media Video Player Showcase", + category: "hero", + desc: "16:9 video player card with play button overlay", + icon: Layout, + content: `
      +
      +
      + ▶ +
      + 03:45 +
      +
      +

      Product Walkthrough: Architecture & Flows

      +

      Learn how to embed interactive wireframes inside your markdown files.

      +
      +
      ` + }, + { + id: "wf-testimonials", + label: "Customer Quotes Showcase", + category: "hero", + desc: "Two-card social proof and customer ratings", + icon: MessageSquare, + content: `
      +
      +
      ★★★★★
      +

      "The ability to design wireframes directly in notes revolutionized our product specification process."

      +
      +
      AM
      +
      +
      Alex Morgan
      +
      Staff Product Manager
      +
      +
      +
      +
      +
      ★★★★★
      +

      "Super clean, sleek and lightning fast. No heavy browser tabs or cloud logins required to sketch."

      +
      +
      SL
      +
      +
      Sarah Lin
      +
      Principal Architect
      +
      +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/index.js b/src/components/wireframe/stencils/index.js new file mode 100644 index 00000000..56003ede --- /dev/null +++ b/src/components/wireframe/stencils/index.js @@ -0,0 +1,34 @@ +import { CATEGORIES } from "./categories.js"; +import { shellStencils } from "./shells.js"; +import { layoutStencils } from "./layouts.js"; +import { fontawesomeStencils } from "./fontawesome.js"; +import { thingworxStencils } from "./thingworx.js"; +import { frameStencils } from "./frames.js"; +import { headerStencils } from "./headers.js"; +import { heroStencils } from "./hero.js"; +import { contentStencils } from "./content.js"; +import { metricStencils } from "./metrics.js"; +import { uiStencils } from "./ui.js"; +import { formStencils } from "./forms.js"; +import { tableStencils } from "./tables.js"; +import { feedbackStencils } from "./feedback.js"; + +export { CATEGORIES }; + +export const WIREFRAME_STENCILS = [ + ...shellStencils, + ...layoutStencils, + ...fontawesomeStencils, + ...thingworxStencils, + ...frameStencils, + ...headerStencils, + ...heroStencils, + ...contentStencils, + ...metricStencils, + ...uiStencils, + ...formStencils, + ...tableStencils, + ...feedbackStencils +]; + +export default WIREFRAME_STENCILS; diff --git a/src/components/wireframe/stencils/layouts.js b/src/components/wireframe/stencils/layouts.js new file mode 100644 index 00000000..178a87a6 --- /dev/null +++ b/src/components/wireframe/stencils/layouts.js @@ -0,0 +1,590 @@ +import { + Layout, + LayoutDashboard, + LayoutGrid, + Columns, + Sidebar, + Split, + PanelsTopLeft, + FileText, + Compass, + ShoppingBag, + Sliders, + Smartphone, + Trello, + Layers, + Gauge, + CheckSquare +} from "lucide-react"; + +export const layoutStencils = [ + { + id: "wf-layout-3col-dashboard", + label: "3-Column Workspace", + category: "layouts", + desc: "Navigation rail + central main workspace + right activity pane", + icon: PanelsTopLeft, + content: `
      +
      +
      + App Nav +
      +
      Workspace
      +
      Reports
      +
      Documents
      +
      Settings
      +
      +
      +
      Central Workspace
      +

      Main content stage, tables, or document body.

      +
      + Main Stage Area +
      +
      +
      +
      Context & Activity
      +
      +
      Recent Updates
      +
      3 notes modified today
      +
      +
      +
      Collaborators
      +
      2 active members
      +
      +
      +
      ` + }, + { + id: "wf-layout-holy-grail", + label: "Holy Grail Web Layout", + category: "layouts", + desc: "Header + Left sidebar + Main canvas + Right aside + Footer", + icon: Layout, + content: `
      +
      + Site Header & Brand +
      + Docs + API + Community +
      +
      +
      + +
      +

      Main Article Content

      +

      Standard responsive Holy Grail layout pattern with full multi-column distribution.

      +
      Content Body Placeholder
      +
      + +
      +
      + © 2026 Wireframe Design. All rights reserved. + Privacy • Terms • Status +
      +
      ` + }, + { + id: "wf-layout-master-detail", + label: "Master-Detail Inbox Split", + category: "layouts", + desc: "Searchable master item list on left + detail reading pane on right", + icon: Split, + content: `
      +
      +
      + +
      +
      +
      +
      Design System Sync
      +
      Updated typography tokens and card heights...
      +
      +
      +
      Sprint Review Notes
      +
      Wireframe studio testing is now 100% complete...
      +
      +
      +
      Export Capabilities
      +
      Direct SVG to PNG renderer support added...
      +
      +
      +
      +
      +
      +
      +

      Design System Sync

      +
      From: Sarah Jenkins • 10:42 AM Today
      +
      +
      + + +
      +
      +

      We just rolled out the modularized stencil library and normalized all toolbar icon heights across the entire studio.

      +
      Selected detail pane preview
      +
      +
      ` + }, + { + id: "wf-layout-document-canvas", + label: "Centered Document / Canvas", + category: "layouts", + desc: "Notion / Medium style centered reading & writing layout", + icon: FileText, + content: `
      +
      📝
      +

      Product Architecture & Specs

      +
      + Engineering + Draft v1.4 + Updated 2 hours ago +
      +

      This document captures the end-to-end user experience, wireframe component hierarchy, and offline storage models.

      +
      + "Great design is making something memorable and meaningful." +
      +
      + Add document blocks, images, or callouts here +
      +
      ` + }, + { + id: "wf-layout-grid-4col", + label: "4-Column Dashboard Grid", + category: "layouts", + desc: "Balanced 4-column responsive grid layout with cards", + icon: LayoutGrid, + content: `
      +
      +
      Column 1
      +
      Card Alpha
      +

      Flexible metric or feature card block.

      +
      +
      +
      Column 2
      +
      Card Beta
      +

      Flexible metric or feature card block.

      +
      +
      +
      Column 3
      +
      Card Gamma
      +

      Flexible metric or feature card block.

      +
      +
      +
      Column 4
      +
      Card Delta
      +

      Flexible metric or feature card block.

      +
      +
      ` + }, + { + id: "wf-layout-docs-wiki", + label: "Docs & Knowledge Wiki", + category: "layouts", + desc: "Sidebar navigation tree + markdown body + right table of contents", + icon: Sidebar, + content: `
      +
      +
      Documentation
      +
      Overview
      +
      Architecture
      +
      Design Tokens
      +
      Component API
      +
      +
      +
      Docs / Core Systems / Overview
      +

      System Overview

      +

      The wireframe subsystem provides offline-first, native note integrations with vector precision.

      +
      + npm run dev:wireframes +
      +
      +
      +
      Sections
      +
      Architecture
      +
      Prerequisites
      +
      Troubleshooting
      +
      +
      ` + }, + { + id: "wf-layout-ecommerce-catalog", + label: "E-Commerce Product Catalog", + category: "layouts", + desc: "Left faceted filter rail + top sort bar + 3-card product grid", + icon: ShoppingBag, + content: `
      +
      +
      Filters
      +
      +
      Category
      + + + +
      +
      +
      Price Range
      +
      + + +
      +
      +
      +
      +
      + Showing 1-12 of 48 items + +
      +
      +
      +
      Product 1
      +
      Studio Monitor
      +
      $299.00
      +
      +
      +
      Product 2
      +
      Mechanical Keyboard
      +
      $129.00
      +
      +
      +
      Product 3
      +
      Wireless Trackpad
      +
      $89.00
      +
      +
      +
      +
      ` + }, + { + id: "wf-layout-masonry-gallery", + label: "Masonry Portfolio Gallery", + category: "layouts", + desc: "Staggered height card grid layout for visuals & media", + icon: Columns, + content: `
      +
      +
      +
      Visual 1
      +
      Brand Identity Kit
      +
      +
      +
      Visual 2
      +
      Icon Package
      +
      +
      +
      +
      +
      Visual 3
      +
      Editorial Layout
      +
      +
      +
      Visual 4
      +
      Mobile Dashboard UI
      +
      +
      +
      +
      +
      Visual 5
      +
      Design System Showcase
      +
      +
      +
      Visual 6
      +
      Component Tokens
      +
      +
      +
      ` + }, + { + id: "wf-layout-settings-portal", + label: "Settings & Profile Portal", + category: "layouts", + desc: "Header banner + horizontal tabs + form content pane", + icon: Sliders, + content: `
      +
      +
      JD
      +
      +
      Jane Doe
      +
      jane@company.com • Administrator
      +
      +
      +
      +
      Account
      +
      Security
      +
      Billing
      +
      Integrations
      +
      +
      +

      Public Profile

      +

      This will be displayed on your technical documents.

      +
      +
      + + +
      +
      + + +
      +
      + +
      +
      ` + }, + { + id: "wf-layout-social-feed", + label: "Timeline & Activity Feed", + category: "layouts", + desc: "Centered post composer + stream cards + right trending rail", + icon: Compass, + content: `
      +
      +
      + +
      + +
      +
      +
      +
      +
      +
      +
      Alex Morgan
      +
      15m ago
      +
      +
      +

      Excited to announce the new modular wireframing stencils! Clean layout structures and zero clipping.

      +
      + 👍 12 Likes + 💬 4 Comments + ↗ Share +
      +
      +
      +
      +
      +
      Trending Topics
      +
      #DesignSystems
      +
      #WireframeStudio
      +
      #LocalFirst
      +
      +
      +
      ` + }, + { + id: "wf-layout-wizard-stepper", + label: "Multi-Step Onboarding Wizard", + category: "layouts", + desc: "Top step tracker + centered card stage + navigation footer", + icon: CheckSquare, + content: `
      +
      +
      +
      1
      + Account +
      +
      +
      +
      2
      + Workspace +
      +
      +
      +
      3
      + Complete +
      +
      +
      +

      Setup your organization

      +

      Provide basic details to configure your local space.

      +
      + + +
      +
      + + +
      +
      +
      + + +
      +
      ` + }, + { + id: "wf-layout-horizontal-split", + label: "Horizontal Editor + Console", + category: "layouts", + desc: "Top editor viewport + draggable handle + bottom output drawer", + icon: Layers, + content: `
      +
      + + + + main.ts +
      +
      +
      import { WireframeEditor } from "./WireframeEditor";
      +
      // Editor surface content placeholder
      +
      +
      + +
      +
      +
      [Ready] Compilation successful in 240ms
      +
      Listening on port 5173...
      +
      +
      ` + }, + { + id: "wf-layout-kanban-board", + label: "4-Column Kanban Swimlanes", + category: "layouts", + desc: "Backlog, In Progress, Review, and Done column board layout", + icon: Trello, + content: `
      +
      +
      + Backlog3 +
      +
      Design audit tokens
      +
      +
      +
      + In Progress2 +
      +
      Modular layout stencils
      +
      +
      +
      + Review1 +
      +
      Icon scale compliance
      +
      +
      +
      + Done8 +
      +
      Header button alignment
      +
      +
      ` + }, + { + id: "wf-layout-hero-zigzag", + label: "Zig-Zag Feature Showcase", + category: "layouts", + desc: "Alternating 2-column image/text marketing layout rows", + icon: LayoutDashboard, + content: `
      +
      +
      Feature Visual Left
      +
      + Capability 01 +

      Drag-and-Drop Speed

      +

      Instant drag interaction with pre-calibrated stencils for wireframing at lightspeed.

      +
      +
      +
      +
      + Capability 02 +

      Local Privacy

      +

      All designs and vector assets persist directly alongside notes in your local disk.

      +
      +
      Feature Visual Right
      +
      +
      ` + }, + { + id: "wf-layout-mobile-screen", + label: "Mobile App Screen with Bottom Nav", + category: "layouts", + desc: "Complete smartphone viewport with header and 5-tab bottom navigation", + icon: Smartphone, + content: `
      +
      + 9:41 + Mobile App + 100% 🔋 +
      +
      +
      +
      Today's Feed
      +
      3 new wireframes updated
      +
      +
      +
      Quick Actions
      +
      Create new project or export PNG
      +
      +
      +
      + 🏠 Home + 🔍 Search + ➕ New + 🔔 Alerts + 👤 Profile +
      +
      ` + }, + { + id: "wf-layout-analytics-dashboard", + label: "Executive Analytics Overview", + category: "layouts", + desc: "Top date filter + 4 KPI stat cards + wide trend chart + 2-col lower split", + icon: Gauge, + content: `
      +
      + Executive Analytics Overview + Last 30 Days ▾ +
      +
      +
      +
      TOTAL REVENUE
      +
      $48,290
      +
      +12.4% vs last mo
      +
      +
      +
      ACTIVE USERS
      +
      3,842
      +
      +8.1% vs last mo
      +
      +
      +
      CONVERSION RATE
      +
      4.6%
      +
      -0.3% vs last mo
      +
      +
      +
      NPS SCORE
      +
      72
      +
      Top 5% quartile
      +
      +
      +
      +
      + Wide Performance Trend Chart +
      +
      + Distribution Donut / Breakdown +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/metrics.js b/src/components/wireframe/stencils/metrics.js new file mode 100644 index 00000000..700eab1f --- /dev/null +++ b/src/components/wireframe/stencils/metrics.js @@ -0,0 +1,103 @@ +import { BarChart3, TrendingUp, CheckSquare } from "lucide-react"; + +export const metricStencils = [ + { + id: "wf-kpi-stats-row", + label: "KPI Metric Stats Row", + category: "metrics", + desc: "3 metric KPI cards with delta percentages", + icon: BarChart3, + content: `
      +
      +
      Monthly Revenue
      +
      + $48,250 + +12.4% +
      +
      +
      +
      Active Projects
      +
      + 1,420 + +8.1% +
      +
      +
      +
      Avg. Response Time
      +
      + 184ms + -2.3% +
      +
      +
      ` + }, + { + id: "wf-chart-line", + label: "Line Trend Graph Card", + category: "metrics", + desc: "Stat metric with vector trendline polyline", + icon: TrendingUp, + content: `
      +
      +
      +
      Daily Pageviews
      +
      128,490
      +
      + +24.5% +
      +
      + + + +
      +
      ` + }, + { + id: "wf-chart-bars", + label: "Monthly Bar Graph Card", + category: "metrics", + desc: "Histogram comparison columns", + icon: BarChart3, + content: `
      +
      Quarterly Growth
      +
      +
      +
      + Jan +
      +
      +
      + Feb +
      +
      +
      + Mar +
      +
      +
      + Apr +
      +
      +
      ` + }, + { + id: "wf-goal-tracker", + label: "Progress & Goal Tracker", + category: "metrics", + desc: "Target milestone bar with percentage indicator", + icon: CheckSquare, + content: `
      +
      + Sprint Goals + 72% +
      +
      +
      +
      +
      + 18 of 25 done + 4 days left +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/shells.js b/src/components/wireframe/stencils/shells.js new file mode 100644 index 00000000..223d19a4 --- /dev/null +++ b/src/components/wireframe/stencils/shells.js @@ -0,0 +1,752 @@ +import { + Laptop, + Monitor, + Smartphone, + Tablet, + Terminal, + Store, + Columns, + AppWindow, + BarChart2, + Users, + DollarSign, + Server, + Headset, + PanelLeft, + Menu +} from "lucide-react"; + +export const shellStencils = [ + { + id: "wf-shell-saas-master", + label: "SaaS Multi-Tenant Shell", + category: "layouts", + desc: "Complete SaaS app shell with workspace switcher, global search & user menu", + icon: AppWindow, + content: `
      +
      +
      +
      +
      N
      + Acme Cloud +
      + ▾ +
      +
      +
      📊 Dashboard
      +
      📁 Projects
      +
      👥 Team Members
      +
      📈 Analytics
      +
      ⚙️ Settings
      +
      +
      +
      +
      +
      + Projects/Q3 Wireframes +
      +
      + +
      JD
      +
      +
      +
      +
      + Drop main dashboard cards, grids, or tables here +
      +
      +
      +
      ` + }, + { + id: "wf-shell-developer-ide", + label: "Developer IDE Studio Shell", + category: "layouts", + desc: "Activity icon rail + collapsible file tree + tabbed editor + status bar", + icon: Laptop, + content: `
      +
      + 📄 + 🔍 + 🌿 + ⚙️ +
      +
      +
      Explorer
      +
      ▾ src/
      +
      ▾ components/
      +
      • WireframeEditor.jsx
      +
      • WireframeBlock.jsx
      +
      ▸ styles/
      +
      +
      +
      +
      + WireframeEditor.jsx + ✕ +
      +
      +
      +
      import React, { useState } from 'react';
      +
      // Main editor surface
      +
      +
      + Ready · UTF-8 · JavaScript React + Ln 1, Col 1 +
      +
      +
      ` + }, + { + id: "wf-shell-admin-console", + label: "Enterprise Admin Console Shell", + category: "layouts", + desc: "Header with global tenant selector + dark sidebar with badge counts + viewport", + icon: Monitor, + content: `
      +
      +
      + Enterprise Admin + Production (us-east-1) +
      +
      + System Status: Operational +
      A
      +
      +
      +
      + +
      +
      + Main admin table, audit stream, or management cards +
      +
      +
      +
      ` + }, + { + id: "wf-shell-mobile-device", + label: "Smartphone Frame with Dynamic Notch", + category: "layouts", + desc: "iPhone style mobile frame with speaker notch, status bar & bottom indicator", + icon: Smartphone, + content: `
      +
      + +
      +
      + 9:41 + 5G 📶 100% 🔋 +
      +
      + Mobile application screen content viewport +
      +
      +
      ` + }, + { + id: "wf-shell-tablet-landscape", + label: "Tablet Landscape Split-View Shell", + category: "layouts", + desc: "iPad style landscape tablet shell with master pane & detail stage", + icon: Tablet, + content: `
      +
      + Tablet Viewport · 780px + Landscape Mode +
      +
      +
      +
      Master Navigation
      +
      Active Document
      +
      Archived Records
      +
      +
      + Detail Inspection Canvas +
      +
      +
      ` + }, + { + id: "wf-shell-ecommerce-store", + label: "E-Commerce Storefront Shell", + category: "layouts", + desc: "Top announcement bar + mega navigation + product stage + footer", + icon: Store, + content: `
      +
      + ⚡ Free shipping on all technical gear orders over $75 +
      +
      +
      Storefront
      +
      + New ArrivalsComputersSensorsAccessories +
      +
      + + +
      +
      +
      +
      + Drop storefront hero banners, product grids, or reviews here +
      +
      +
      + © 2026 Storefront Inc. + Customer Support • Shipping Info • Returns +
      +
      ` + }, + { + id: "wf-shell-terminal-cli", + label: "Terminal & CLI Command Shell", + category: "layouts", + desc: "Window frame with traffic light controls + monospace interactive CLI surface", + icon: Terminal, + content: `
      +
      +
      + + + +
      + bash — notely-cli + +
      +
      +
      notely@local:~/workspace$ wireframe --init saas-shell
      +
      [info] Loaded 83 wireframe stencils across 13 categories...
      +
      [ok] Generated wireframe canvas preview at 1200x800
      +
      notely@local:~/workspace$
      +
      +
      ` + }, + { + id: "wf-shell-split-onboarding", + label: "Split-Screen Brand Onboarding Shell", + category: "layouts", + desc: "50% dark brand showcase on left + 50% clean auth & registration on right", + icon: Columns, + content: `
      +
      + Notely Platform +

      Unified local technical workspace

      +

      Notes, offline diagrams, GrapesJS wireframes, and ThingWorx IoT telemetry.

      +
      + "The fastest way to mock up full-stack industrial applications." +
      +
      +
      +

      Create your account

      +

      Start designing wireframes immediately.

      + +
      or with work email
      + + +
      +
      ` + }, + { + id: "wf-shell-admin-bi", + label: "Admin BI & Analytics Shell", + category: "layouts", + desc: "Executive BI dashboard with date filter, 4 KPI cards, chart stage & breakdown", + icon: BarChart2, + content: `
      +
      +
      + ⚡ Nexus BI Admin +
      +
      Executive Overview
      +
      Revenue & MRR
      +
      Customer Churn
      +
      Cohorts & Retention
      +
      System Settings
      +
      +
      +
      +
      Executive Analytics Overview
      +
      + + +
      +
      +
      +
      +
      +
      Monthly Recurring
      +
      $128,450
      +
      ▲ +14.2% MoM
      +
      +
      +
      Active Accounts
      +
      14,290
      +
      ▲ +8.6% MoM
      +
      +
      +
      Gross Churn Rate
      +
      0.82%
      +
      ▼ -0.15% (Healthy)
      +
      +
      +
      Average LTV
      +
      $2,450
      +
      ▲ +5.1% MoM
      +
      +
      +
      + Full-Width Revenue & Cohort Performance Chart Stage +
      +
      +
      +
      Top Acquisition Channels
      +
      Organic Search (42%) • Direct Referrals (28%) • Partner API (18%)
      +
      +
      +
      Regional Breakdown
      +
      North America (64%) • EMEA (24%) • APAC (12%)
      +
      +
      +
      +
      +
      ` + }, + { + id: "wf-shell-admin-users", + label: "Admin IAM User Management Shell", + category: "layouts", + desc: "Enterprise user administration with role filters, bulk actions & table pagination", + icon: Users, + content: `
      +
      +
      + Identity & Access Management + Org: Acme-Global +
      + +
      +
      +
      + + +
      +
      + + +
      +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      User NameEmail AddressRole2FA SecurityLast ActiveActions
      +
      SJ
      + Sarah Jenkins +
      sarah@company.comSUPER ADMINENABLED (HARDWARE)4 minutes ago•••
      +
      MR
      + Marcus Reed +
      marcus@company.comEDITORENABLED (APP)1 hour ago•••
      +
      AL
      + Anna Lin +
      anna.lin@partner.orgVIEWERPENDING SETUP3 days ago•••
      +
      +
      + Showing 1 to 3 of 142 members +
      + + + + +
      +
      +
      ` + }, + { + id: "wf-shell-admin-finance", + label: "Admin Fintech & Billing Shell", + category: "layouts", + desc: "Payment operations console with balance banner, payout actions & transactions", + icon: DollarSign, + content: `
      +
      +
      + Total Available Balance +
      $384,920.40 USD
      +
      ● Instant payout ready ($42,100 in transit)
      +
      +
      + + +
      +
      +
      +
      +
      +
      GROSS VOLUME (30D)
      +
      $1.24M
      +
      +
      +
      PENDING DISPUTES
      +
      2 cases ($640)
      +
      +
      +
      PAYOUT SCHEDULE
      +
      Daily (Automatic)
      +
      +
      +
      +
      Recent Payment Transactions
      + + + + + + + + + + + + + + + + + + + + + +
      Enterprise Tier Annualcus_918237SUCCEEDED+$12,000.00
      Pro Team Monthlycus_481029SUCCEEDED+$240.00
      Starter Plan Monthlycus_330912CARD DECLINED$29.00
      +
      +
      +
      ` + }, + { + id: "wf-shell-admin-devops", + label: "Admin DevOps & Cloud Cluster Shell", + category: "layouts", + desc: "Cluster health, CPU/RAM utilization gauges, service matrix & incident stream", + icon: Server, + content: `
      +
      +
      + ☸️ K8s Cluster Monitor + ● 24 / 24 Nodes Healthy +
      +
      Uptime: 99.98% (Last 90 days)
      +
      +
      +
      +
      +
      CPU UTILIZATION
      +
      42.8%
      +
      +
      +
      +
      MEMORY USAGE
      +
      64.2%
      +
      +
      +
      +
      NETWORK INGRESS
      +
      1.42 GB/s
      +
      +
      +
      +
      ACTIVE PODS
      +
      184 / 200
      +
      +
      +
      +
      +
      +
      Microservice Mesh Status
      +
      +
      auth-api.prod● OK (14ms)
      +
      billing-service.prod● OK (28ms)
      +
      graphql-gateway.prod● OK (8ms)
      +
      worker-sync.prod▲ High Load (120ms)
      +
      +
      +
      +
      Cluster Incident Log
      +
      [11:40:12] Pod auto-scaled: worker-sync +2 replicas
      +
      [11:35:00] Ingress certificate renewed successfully
      +
      [11:20:18] Deployment release: v2.4.0 deployed to us-east-1
      +
      +
      +
      +
      ` + }, + { + id: "wf-shell-admin-support", + label: "Admin CRM & Ticket Helpdesk Shell", + category: "layouts", + desc: "Helpdesk queue switcher, SLA timers, customer detail & response thread", + icon: Headset, + content: `
      +
      +
      +
      Support Inboxes
      +
      + Unassigned (14) + Mine (3) +
      +
      +
      +
      +
      + P1 URGENT + ⏱ 18m left +
      +
      SSO Login redirect failing
      +
      Acme Corp • 4 min ago
      +
      +
      +
      + P2 HIGH + ⏱ 2h left +
      +
      Billing invoice tax ID update
      +
      TechCorp LLC • 22 min ago
      +
      +
      +
      +
      +
      +
      +
      Ticket #4819: SSO Login redirect failing
      +
      Requester: devops@acme.com • Enterprise SLA Tier
      +
      +
      + + +
      +
      +
      +
      +
      Customer Message — 11:32 AM
      +

      "Our Okta SAML 2.0 assertions are returning 403 on the callback endpoint since 11:00 AM. Please verify the IdP certificate."

      +
      +
      +
      + Public Reply + Internal Note +
      + +
      + +
      +
      +
      +
      +
      ` + }, + { + id: "wf-shell-sidenav-topbar", + label: "Side Nav & Top App Bar Shell", + category: "layouts", + desc: "Primary left side navigation bar + top app bar with breadcrumbs, search & user menu", + icon: PanelLeft, + content: `
      + +
      +
      +
      + +
      + Workspaces/ + Production/ + Overview +
      +
      +
      +
      + +
      +
      + 🔔 + +
      + +
      +
      +
      +
      +
      +

      Project Overview

      +

      Manage and monitor active production services and teams.

      +
      +
      + + +
      +
      +
      +
      +
      TOTAL REVENUE
      +
      $48,290
      +
      +
      +
      ACTIVE SESSIONS
      +
      1,429
      +
      +
      +
      SYSTEM STATUS
      +
      ● All Services Up
      +
      +
      +
      + Main Content Area (Tables, Wireframe Blocks, or Dashboard Cards) +
      +
      +
      +
      ` + }, + { + id: "wf-shell-compact-sidenav-topbar", + label: "Compact Icon Rail & Top App Bar", + category: "layouts", + desc: "64px slim icon rail + topbar navigation maximizing canvas content width", + icon: Menu, + content: `
      + +
      +
      +
      Application Workspace
      +
      + + +
      +
      +
      +
      + Expanded High-Density Canvas Area +
      +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/tables.js b/src/components/wireframe/stencils/tables.js new file mode 100644 index 00000000..014dee55 --- /dev/null +++ b/src/components/wireframe/stencils/tables.js @@ -0,0 +1,125 @@ +import { Layers, Columns, FileText } from "lucide-react"; + +export const tableStencils = [ + { + id: "wf-data-table", + label: "Modern Data Table", + category: "tables", + desc: "Structured data table with status pills and actions", + icon: Layers, + content: `
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      NameStatusRoleActions
      Bikash PandaActiveAdmin•••
      Sarah ConnorPendingEditor•••
      Alex MurphyInactiveViewer•••
      +
      ` + }, + { + id: "wf-kanban-board", + label: "3-Column Kanban Board", + category: "tables", + desc: "To Do, In Progress, and Done task board", + icon: Columns, + content: `
      +
      +
      + To Do + 2 +
      +
      + Urgent +
      Auth token expiry bug
      +
      +
      +
      +
      + In Progress + 1 +
      +
      + Feature +
      Wireframe Stencil Library
      +
      +
      +
      +
      + Done + 3 +
      +
      + Core +
      Dropdown category filter
      +
      +
      +
      ` + }, + { + id: "wf-invoice-table", + label: "Invoice Summary Table", + category: "tables", + desc: "Line item billing receipt with totals breakdown", + icon: FileText, + content: `
      +
      +
      +
      Invoice #INV-2048
      +
      Issued on Jun 15, 2026
      +
      + Paid +
      + + + + + + + + + + + + + + + + + + + + +
      ItemQtyPrice
      Notely Team Seat5$95.00
      Storage Tier1$10.00
      +
      +
      +
      Subtotal:$105.00
      +
      Total:$105.00
      +
      +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/thingworx.js b/src/components/wireframe/stencils/thingworx.js new file mode 100644 index 00000000..ec934736 --- /dev/null +++ b/src/components/wireframe/stencils/thingworx.js @@ -0,0 +1,398 @@ +import { + Cpu, + Activity, + Radio, + AlertTriangle, + Disc, + Gauge, + Zap, + ListTree, + Sliders, + Droplets, + Power, + BarChart3 +} from "lucide-react"; + +export const thingworxStencils = [ + { + id: "wf-twx-asset-card", + label: "Thing Asset Health Card", + category: "thingworx", + desc: "ThingWorx Thing asset card with live beacon, OEE & property KPIs", + icon: Cpu, + content: `
      +
      +
      + +
      +
      CNC-Milling-04
      +
      ThingTemplate: GenericMachinery
      +
      +
      + CONNECTED +
      +
      +
      +
      TEMP
      +
      72.4°C
      +
      +
      +
      SPEED
      +
      1,420 RPM
      +
      +
      +
      OEE
      +
      88.6%
      +
      +
      +
      + Last scan: 2s ago + Quality: Good (192) +
      +
      ` + }, + { + id: "wf-twx-radial-gauge", + label: "ThingWorx Radial Dial Gauge", + category: "thingworx", + desc: "Industrial circular gauge with safe, warning & alarm zones", + icon: Gauge, + content: `
      +
      Hydraulic Pressure
      +
      + + + + + + +
      +
      84.5 PSI
      +
      + 0 + Normal + 150 +
      +
      ` + }, + { + id: "wf-twx-timeseries-chart", + label: "TimeSeries Telemetry Chart", + category: "thingworx", + desc: "Industrial telemetry line chart with time window selector & live feed", + icon: Activity, + content: `
      +
      +
      + Motor Vibration Telemetry + LIVE STREAM +
      +
      + + + + +
      +
      +
      + + + + + + + + +
      +
      +
      + — Axis X (mm/s) + -- Axis Y (mm/s) +
      + Threshold limit: 4.5 mm/s +
      +
      ` + }, + { + id: "wf-twx-alarm-grid", + label: "ThingWorx Alarm & Incident Grid", + category: "thingworx", + desc: "Active alarm console with severity, code, thing name & ack button", + icon: AlertTriangle, + content: `
      +
      +
      + 🚨 Industrial Alarm Console + 3 Active +
      + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      SeverityTimestampThing NameAlarm MessageAction
      CRITICAL11:42:08Extruder-Line-01Barrel Temperature High High (> 280°C)
      WARNING11:38:15Coolant-Pump-03Flow Rate Deviation > 15%
      INFO11:30:00Plant-Gateway-NorthPeriodic edge sync complete
      +
      ` + }, + { + id: "wf-twx-property-grid", + label: "Thing Property Display Grid", + category: "thingworx", + desc: "Standard ThingWorx Thing properties table with data type & quality", + icon: BarChart3, + content: `
      +
      + Thing Properties: PackagingUnit_02 + Auto-refresh: 1000ms +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Property NameValueTypeQualityTimestamp
      conveyorSpeed2.4 m/sNUMBERGOOD (192)11:43:02
      cycleCount18,492INTEGERGOOD (192)11:43:01
      emergencyStopActivefalseBOOLEANGOOD (192)11:43:00
      operatingStateRUNNINGSTRINGGOOD (192)11:43:02
      +
      ` + }, + { + id: "wf-twx-tank-level", + label: "P&ID Process Tank & Level", + category: "thingworx", + desc: "Industrial tank visual with dynamic level fill %, inlet/outlet valves", + icon: Droplets, + content: `
      +
      Storage Tank TK-102
      +
      +
      +
      +
      68%
      +
      +
      +
      +
      Volume
      +
      6,800 L
      +
      +
      +
      Inlet Valve V-1
      + OPEN (92%) +
      +
      +
      Outlet Valve V-2
      + CLOSED +
      +
      +
      +
      ` + }, + { + id: "wf-twx-led-indicators", + label: "Industrial LED Status Indicators", + category: "thingworx", + desc: "Machinery status beacon strip (Power, Ready, Run, Alarm, Comm)", + icon: Disc, + content: `
      +
      + + POWER +
      +
      + + READY +
      +
      + + RUN +
      +
      + + REMOTE +
      +
      + + FAULT +
      +
      ` + }, + { + id: "wf-twx-numeric-readout", + label: "Digital Telemetry Readout (KPI)", + category: "thingworx", + desc: "Industrial 7-segment style high-visibility numeric display", + icon: Zap, + content: `
      +
      Flow Rate Sensor 01
      +
      + 428.6 GPM +
      +
      + MIN: 120.0 + ▲ +4.2% + MAX: 500.0 +
      +
      ` + }, + { + id: "wf-twx-asset-tree", + label: "Thing Asset Hierarchy Tree", + category: "thingworx", + desc: "Industrial Enterprise / Site / Line / Machine hierarchy tree selector", + icon: ListTree, + content: `
      +
      Asset Hierarchy
      +
      +
      ▾ 🏭 Plant North America
      +
      ▾ ⚙️ Assembly Line 01
      +
      • 🤖 Robotic Arm 04 [Active]
      +
      • 📦 Packaging Station 02
      +
      ▸ ⚙️ Assembly Line 02
      +
      ▸ ❄️ Utilities & HVAC
      +
      +
      ` + }, + { + id: "wf-twx-control-panel", + label: "Operator Control Switch & E-Stop", + category: "thingworx", + desc: "Industrial physical controls with Start, Stop, and Emergency E-Stop", + icon: Power, + content: `
      +
      Operator Control Console
      +
      + + +
      + +
      EMERGENCY
      +
      +
      +
      ` + }, + { + id: "wf-twx-oee-summary", + label: "ThingWorx OEE Metric Breakdown", + category: "thingworx", + desc: "Overall Equipment Effectiveness with Availability, Performance, Quality", + icon: Radio, + content: `
      +
      + OEE Performance Scorecard + 84.2% +
      +
      +
      +
      + Availability (Uptime) + 92.0% +
      +
      +
      +
      +
      +
      +
      + Performance (Speed vs Rated) + 88.5% +
      +
      +
      +
      +
      +
      +
      + Quality (Good Parts %) + 99.2% +
      +
      +
      +
      +
      +
      +
      ` + }, + { + id: "wf-twx-shift-filter", + label: "Industrial Shift & Time Picker", + category: "thingworx", + desc: "Shift 1, Shift 2, Night shift buttons + custom telemetry interval", + icon: Sliders, + content: `
      +
      + Shift: + + + +
      +
      + Interval: + +
      +
      ` + } +]; diff --git a/src/components/wireframe/stencils/ui.js b/src/components/wireframe/stencils/ui.js new file mode 100644 index 00000000..d41130cc --- /dev/null +++ b/src/components/wireframe/stencils/ui.js @@ -0,0 +1,100 @@ +import { Square, User, Shield, MousePointer, Box, Folder } from "lucide-react"; + +export const uiStencils = [ + { + id: "wf-button-suite", + label: "Button Styles Suite", + category: "components", + desc: "Primary, secondary, outline, ghost and danger buttons", + icon: Square, + content: `
      + + + + + +
      ` + }, + { + id: "wf-avatar-stack", + label: "Avatar Stack & Badge", + category: "components", + desc: "Collaborator face avatars with count chip", + icon: User, + content: `
      +
      + JD + AL + RK +
      + +8 contributors active +
      ` + }, + { + id: "wf-alert-banner", + label: "Alert Notification Banner", + category: "components", + desc: "Info notification banner with icon and dismiss link", + icon: Shield, + content: `
      +
      + Notice: Your workspace was upgraded to the latest version. +
      + View Changelog +
      ` + }, + { + id: "wf-tags-chips", + label: "Tags & Status Badges", + category: "components", + desc: "Pills for tags, status indicators and metadata", + icon: Shield, + content: `
      + Design System + Verified + In Review + Urgent +
      ` + }, + { + id: "wf-context-menu", + label: "Dropdown Context Menu", + category: "components", + desc: "Floating contextual action list", + icon: MousePointer, + content: `
      +
      Duplicate
      +
      Rename
      +
      Export PNG
      +
      +
      Delete
      +
      ` + }, + { + id: "wf-pagination", + label: "Pagination Control Bar", + category: "components", + desc: "Page navigation with active state", + icon: Box, + content: `
      + + + + + +
      ` + }, + { + id: "wf-dropzone", + label: "File Upload Dropzone", + category: "components", + desc: "Dashed border file upload placeholder", + icon: Folder, + content: `
      +
      ☁️
      +
      Drag and drop files here
      +

      PNG, JPG, SVG up to 25MB

      + +
      ` + } +]; diff --git a/src/main.jsx b/src/main.jsx index 950927e7..dacc221f 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -4,6 +4,7 @@ import App from "./App.jsx"; import { ErrorBoundary } from "./components/ErrorBoundary.jsx"; import { ConfirmationProvider } from "./components/ConfirmationProvider.jsx"; import { UIStateProvider } from "./contexts/UIStateContext.jsx"; +import "@fortawesome/fontawesome-free/css/all.min.css"; import "./styles.css"; import { RecordingOverlayApp } from "./components/RecordingOverlayApp.jsx"; diff --git a/src/styles/WireframeEditor.css b/src/styles/WireframeEditor.css index bb4515ef..0a9401b3 100644 --- a/src/styles/WireframeEditor.css +++ b/src/styles/WireframeEditor.css @@ -4,24 +4,24 @@ /* --- Modal Container Tokens & Sizing (Unified with Notely Theme) --- */ .wireframe-modal-container { - --wf-bg: var(--app-bg); - --wf-surface: var(--surface-bg); - --wf-surface2: var(--surface-elevated); - --wf-surface3: var(--surface-muted); - --wf-border: var(--border-subtle); - --wf-border2: var(--border-default); - --wf-text: var(--text-strong); - --wf-text-muted: var(--text-muted); - --wf-text-dim: var(--text-subtle); - --wf-accent: var(--accent-solid); + --wf-bg: var(--app-bg); + --wf-surface: var(--surface-bg); + --wf-surface2: var(--surface-elevated); + --wf-surface3: var(--surface-muted); + --wf-border: var(--border-subtle); + --wf-border2: var(--border-default); + --wf-text: var(--text-strong); + --wf-text-muted: var(--text-muted); + --wf-text-dim: var(--text-subtle); + --wf-accent: var(--accent-solid); --wf-accent-hover: var(--accent-strong); --wf-accent-glow: color-mix(in srgb, var(--accent-solid) 20%, transparent); - --wf-green: var(--status-success-text); - --wf-radius: var(--radius-lg, 8px); - --wf-radius-sm: var(--radius-sm, 4px); - --wf-radius-lg: var(--radius-lg, 8px); - --wf-canvas-bg: var(--surface-muted); - --wf-canvas-dot: color-mix(in srgb, var(--text-strong) 8%, transparent); + --wf-green: var(--status-success-text); + --wf-radius: var(--radius-lg, 8px); + --wf-radius-sm: var(--radius-sm, 4px); + --wf-radius-lg: var(--radius-lg, 8px); + --wf-canvas-bg: var(--surface-muted); + --wf-canvas-dot: color-mix(in srgb, var(--text-strong) 8%, transparent); background: var(--surface-bg) !important; color: var(--text-strong) !important; @@ -221,7 +221,7 @@ /* --- Left Sidebar: Stencil Library (Sleek, Uncrowded) --- */ .wireframe-stencil-sidebar { - width: 236px; + width: 260px; background: var(--surface-bg); border-right: 1px solid var(--border-soft); display: flex; @@ -266,7 +266,9 @@ background: var(--surface-elevated); color: var(--text-strong); outline: none; - transition: border-color 0.12s, box-shadow 0.12s; + transition: + border-color 0.12s, + box-shadow 0.12s; } .wireframe-search-input::placeholder { @@ -333,7 +335,7 @@ padding: 8px 10px 14px; display: grid; grid-template-columns: repeat(2, 1fr); - gap: 6px; + gap: 8px; align-content: start; scrollbar-width: thin; scrollbar-color: var(--border-soft) transparent; @@ -354,15 +356,16 @@ align-items: center; justify-content: center; text-align: center; - gap: 5px; - padding: 8px 4px; + gap: 6px; + padding: 10px 8px; background: var(--surface-elevated); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm, 4px); cursor: grab; transition: all 0.12s ease; user-select: none; - min-height: 56px; + min-height: 68px; + height: auto; box-sizing: border-box; } @@ -390,16 +393,15 @@ } .wireframe-stencil-tile-name { - font-size: 10px; + font-size: 10.5px; font-weight: 500; color: var(--text-strong); - line-height: 1.2; - display: -webkit-box; - -webkit-line-clamp: 2; - line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - word-break: break-word; + line-height: 1.25; + display: block; + overflow: visible; + white-space: normal; + word-break: normal; + overflow-wrap: break-word; max-width: 100%; } @@ -794,7 +796,8 @@ } @keyframes wf-pulse { - 0%, 100% { + 0%, + 100% { opacity: 1; } 50% { diff --git a/src/tests/components/WireframeStencils.unit.test.js b/src/tests/components/WireframeStencils.unit.test.js new file mode 100644 index 00000000..02084113 --- /dev/null +++ b/src/tests/components/WireframeStencils.unit.test.js @@ -0,0 +1,31 @@ +import { describe, expect, it } from "vitest"; +import { CATEGORIES, WIREFRAME_STENCILS } from "../../components/wireframe/stencils"; + +describe("Wireframe Stencils Modularity & Integrity", () => { + it("exports valid CATEGORIES array with distinct IDs", () => { + expect(CATEGORIES.length).toBeGreaterThan(5); + const ids = CATEGORIES.map((c) => c.id); + const uniqueIds = new Set(ids); + expect(uniqueIds.size).toBe(ids.length); + }); + + it("exports WIREFRAME_STENCILS with required fields", () => { + expect(WIREFRAME_STENCILS.length).toBeGreaterThan(20); + const validCategoryIds = new Set(CATEGORIES.map((c) => c.id)); + + for (const stencil of WIREFRAME_STENCILS) { + expect(stencil.id).toBeTruthy(); + expect(stencil.label).toBeTruthy(); + expect(stencil.category).toBeTruthy(); + expect(validCategoryIds.has(stencil.category)).toBe(true); + expect(stencil.content).toContain("<"); + expect(stencil.icon).toBeTruthy(); + } + }); + + it("has unique stencil IDs", () => { + const ids = WIREFRAME_STENCILS.map((s) => s.id); + const uniqueIds = new Set(ids); + expect(uniqueIds.size).toBe(ids.length); + }); +}); From 93d4a8f7acff902351fb6d734511186328f93ffe Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Thu, 24 Sep 2026 00:28:59 +0530 Subject: [PATCH 5/7] fix(wireframe): dynamically calculate full page bounds for image export --- src/components/wireframe/exportUtils.js | 164 ++++++++++++++++++------ 1 file changed, 125 insertions(+), 39 deletions(-) diff --git a/src/components/wireframe/exportUtils.js b/src/components/wireframe/exportUtils.js index d7881aa2..7f33e26a 100644 --- a/src/components/wireframe/exportUtils.js +++ b/src/components/wireframe/exportUtils.js @@ -3,24 +3,26 @@ * Serializes GrapesJS canvas DOM to PNG using SVG foreignObject and Canvas 2D */ -export function createFallbackPng(editor) { +export function createFallbackPng(editor, fallbackWidth = 1200, fallbackHeight = 800) { const canvas = document.createElement("canvas"); - canvas.width = 1200; - canvas.height = 800; + const width = Math.max(fallbackWidth || 1200, 400); + const height = Math.max(fallbackHeight || 800, 400); + canvas.width = width; + canvas.height = height; const ctx = canvas.getContext("2d"); // Canvas background ctx.fillStyle = "#f8fafc"; - ctx.fillRect(0, 0, 1200, 800); + ctx.fillRect(0, 0, width, height); // Border frame ctx.strokeStyle = "#cbd5e1"; ctx.lineWidth = 2; - ctx.strokeRect(20, 20, 1160, 760); + ctx.strokeRect(20, 20, width - 40, height - 40); // Header mockup ctx.fillStyle = "#ffffff"; - ctx.fillRect(20, 20, 1160, 60); + ctx.fillRect(20, 20, width - 40, 60); ctx.fillStyle = "#2563eb"; ctx.fillRect(44, 40, 20, 20); @@ -31,9 +33,9 @@ export function createFallbackPng(editor) { // Content area ctx.fillStyle = "#ffffff"; - ctx.fillRect(60, 120, 1080, 600); + ctx.fillRect(40, 100, width - 80, height - 140); ctx.strokeStyle = "#e2e8f0"; - ctx.strokeRect(60, 120, 1080, 600); + ctx.strokeRect(40, 100, width - 80, height - 140); ctx.fillStyle = "#64748b"; ctx.font = "14px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"; @@ -41,7 +43,7 @@ export function createFallbackPng(editor) { const html = editor?.getHtml?.() || ""; const hasContent = html.replace(/<[^>]+>/g, "").trim().length > 10; - ctx.fillText(hasContent ? "Wireframe UI Design" : "Wireframe Artboard", 600, 420); + ctx.fillText(hasContent ? "Wireframe UI Design" : "Wireframe Artboard", width / 2, height / 2); return canvas.toDataURL("image/png"); } @@ -53,14 +55,14 @@ export function exportWireframeToPng(editor) { return; } - try { - const width = 1200; - const height = 800; + let fullWidth = 1200; + let fullHeight = 800; + try { const frameDoc = editor.Canvas?.getDocument?.(); const frameBody = frameDoc?.body; - let bodyXml = ""; let cssText = editor.getCss?.() || ""; + let contentXml = ""; if (frameDoc && frameBody) { // Collect canvas iframe styles @@ -69,31 +71,115 @@ export function exportWireframeToPng(editor) { cssText += "\n" + (s.textContent || ""); }); - // Clone and sanitize selection markers - const clone = frameBody.cloneNode(true); - clone.querySelectorAll(".gjs-selected, .gjs-hovered").forEach((el) => { - el.classList.remove("gjs-selected", "gjs-hovered"); + // Determine device constraints + const currentDevice = editor.getDevice ? editor.getDevice() : "Desktop"; + let minDeviceWidth = 1200; + if (currentDevice === "Tablet") minDeviceWidth = 768; + if (currentDevice === "Mobile") minDeviceWidth = 375; + + // Measure true full height across all rendered elements in the document + const bodyScrollH = frameBody.scrollHeight || 0; + const docScrollH = frameDoc.documentElement?.scrollHeight || 0; + const bodyOffsetH = frameBody.offsetHeight || 0; + + let maxBottom = 0; + let maxRight = 0; + + const allElements = frameBody.querySelectorAll("*"); + allElements.forEach((el) => { + const className = el.className; + if ( + typeof className === "string" && + (className.includes("gjs-toolbar") || + className.includes("gjs-resizer") || + className.includes("gjs-badge")) + ) { + return; + } + + const offsetBottom = (el.offsetTop || 0) + (el.offsetHeight || 0); + if (offsetBottom > maxBottom) maxBottom = offsetBottom; + + const offsetRight = (el.offsetLeft || 0) + (el.offsetWidth || 0); + if (offsetRight > maxRight) maxRight = offsetRight; + + try { + const rect = el.getBoundingClientRect(); + const scrollY = frameDoc.defaultView?.scrollY || 0; + const scrollX = frameDoc.defaultView?.scrollX || 0; + const clientBottom = rect.bottom + scrollY; + const clientRight = rect.right + scrollX; + if (clientBottom > maxBottom) maxBottom = clientBottom; + if (clientRight > maxRight) maxRight = clientRight; + } catch { + // ignore rect measurement errors + } }); + const computedStyle = frameDoc.defaultView?.getComputedStyle?.(frameBody); + const paddingBottom = parseInt(computedStyle?.paddingBottom || "40", 10) || 40; + const paddingTop = parseInt(computedStyle?.paddingTop || "40", 10) || 40; + + fullHeight = Math.ceil( + Math.max(bodyScrollH, docScrollH, bodyOffsetH, maxBottom + paddingBottom, 600) + ); + + fullWidth = Math.ceil(Math.max(frameBody.scrollWidth || 0, maxRight, minDeviceWidth)); + + // Clone and sanitize selection markers & UI overlays + const clone = frameBody.cloneNode(true); + clone + .querySelectorAll(".gjs-selected, .gjs-hovered, .gjs-badge, .gjs-toolbar, .gjs-resizer") + .forEach((el) => { + el.classList?.remove("gjs-selected", "gjs-hovered"); + if ( + el.classList?.contains("gjs-toolbar") || + el.classList?.contains("gjs-resizer") || + el.classList?.contains("gjs-badge") + ) { + el.remove(); + } + }); + const serializer = new XMLSerializer(); - bodyXml = serializer.serializeToString(clone); + let innerXml = ""; + for (let i = 0; i < clone.childNodes.length; i++) { + innerXml += serializer.serializeToString(clone.childNodes[i]); + } + + const sanitizedCss = cssText + .replace(/\bhtml\s*\{/gi, ".wireframe-export-stage {") + .replace(/\bbody\s*\{/gi, ".wireframe-export-stage {"); + + contentXml = ` +
      + + + ${innerXml} +
      + `.trim(); } else { const rawHtml = editor.getHtml?.() || ""; - bodyXml = `
      ${rawHtml}
      `; + contentXml = ` +
      + + + ${rawHtml} +
      + `.trim(); } const svgDoc = ` - - -
      - - - ${bodyXml} -
      + + + ${contentXml} `.trim(); @@ -102,33 +188,33 @@ export function exportWireframeToPng(editor) { const dataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgDoc)}`; const fallbackTimer = setTimeout(() => { - resolve(createFallbackPng(editor)); - }, 2000); + resolve(createFallbackPng(editor, fullWidth, fullHeight)); + }, 3500); img.onload = () => { clearTimeout(fallbackTimer); try { const canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; + canvas.width = fullWidth; + canvas.height = fullHeight; const ctx = canvas.getContext("2d"); ctx.fillStyle = "#ffffff"; - ctx.fillRect(0, 0, width, height); - ctx.drawImage(img, 0, 0); + ctx.fillRect(0, 0, fullWidth, fullHeight); + ctx.drawImage(img, 0, 0, fullWidth, fullHeight); resolve(canvas.toDataURL("image/png")); } catch { - resolve(createFallbackPng(editor)); + resolve(createFallbackPng(editor, fullWidth, fullHeight)); } }; img.onerror = () => { clearTimeout(fallbackTimer); - resolve(createFallbackPng(editor)); + resolve(createFallbackPng(editor, fullWidth, fullHeight)); }; img.src = dataUri; } catch { - resolve(createFallbackPng(editor)); + resolve(createFallbackPng(editor, fullWidth, fullHeight)); } }); } From 4bdb3ddcb47ffd85d5653f84a32995b0b64b17aa Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Thu, 24 Sep 2026 08:04:25 +0530 Subject: [PATCH 6/7] fix(media): resolve webview diagrams, pdf video cards, and ppt render --- electron/lib/media/imageMedia.cjs | 8 + electron/lib/web/websiteRenderer.cjs | 9 + electron/preload.cjs | 22 ++ src/components/ExcalidrawBlock.jsx | 2 +- src/components/WebViewPreview.jsx | 71 +++- src/components/media/PresentationViewer.jsx | 405 +++++++++++++++++--- src/components/media/mediaUtils.js | 4 +- 7 files changed, 454 insertions(+), 67 deletions(-) diff --git a/electron/lib/media/imageMedia.cjs b/electron/lib/media/imageMedia.cjs index 1846563f..335e5bc3 100644 --- a/electron/lib/media/imageMedia.cjs +++ b/electron/lib/media/imageMedia.cjs @@ -226,6 +226,14 @@ function buildPdfExportHtml({ title, markdownContent, baseHref, sourceDir, downs let annotation = null; if (srcIndex >= 0) { const rawSrc = String(tokens[idx].attrs[srcIndex][1] || "").trim(); + const isVideo = /\.(webm|mp4|ogg|mov|mkv|avi|m4v)(\?|#|$)/i.test(rawSrc); + if (isVideo) { + const altText = tokens[idx].content || tokens[idx].attrGet("alt") || "Video Recording"; + const fileName = rawSrc.split(/[?#]/)[0].split(/[/\\]/).pop() || "recording"; + const ext = fileName.split(".").pop()?.toUpperCase() || "VIDEO"; + return `
      🎬
      ${escapeCodeHtml(altText)}${escapeCodeHtml(fileName)} (${escapeCodeHtml(ext)})
      `; + } + if (rawSrc && !/^(https?:|data:|blob:)/i.test(rawSrc)) { const pathPart = rawSrc.split(/[?#]/)[0]; annotation = getImageAnnotationForMarkdownAsset(path.join(sourceDir || getNotesRoot(), "__notely_export__.md"), pathPart); diff --git a/electron/lib/web/websiteRenderer.cjs b/electron/lib/web/websiteRenderer.cjs index 9d2b83c1..a1cc3db0 100644 --- a/electron/lib/web/websiteRenderer.cjs +++ b/electron/lib/web/websiteRenderer.cjs @@ -227,6 +227,15 @@ function buildWebsiteMarkdownRenderer() { let annotation = null; if (srcIndex >= 0) { const src = String(tokens[idx].attrs[srcIndex][1] || "").trim(); + const isVideo = /\.(webm|mp4|ogg|mov|mkv|avi|m4v)(\?|#|$)/i.test(src); + if (isVideo) { + const [pathPart, queryPart = ""] = src.split("?"); + const rewritten = !/^(https?:|data:|blob:)/i.test(src) ? rewriteAssetPath(pathPart, env) : src; + const finalSrc = queryPart && !/^(https?:|data:|blob:)/i.test(src) ? `${rewritten}?${queryPart}` : rewritten; + const altText = tokens[idx].content || tokens[idx].attrGet("alt") || "Video Recording"; + return `
      ${escapeCodeHtml(altText)}
      `; + } + if (src && !/^(https?:|data:|blob:)/i.test(src)) { const [pathPart, queryPart = ""] = src.split("?"); annotation = getImageAnnotationForMarkdownAsset(path.resolve(getNotesRoot(), env?.relMdPath || "__notely__.md"), pathPart); diff --git a/electron/preload.cjs b/electron/preload.cjs index 5e785ae0..c6159d3d 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -409,6 +409,28 @@ contextBridge.exposeInMainWorld("notesApi", { ipcRenderer.on("exports:record-added", listener); return () => ipcRenderer.removeListener("exports:record-added", listener); }, + + // ── Diagrams (Excalidraw, Draw.io, Wireframe) ──────────────────────────── + readDiagramSource: (p) => ipcRenderer.invoke("diagram:read-source", p), + writeDiagramSource: (p) => ipcRenderer.invoke("diagram:write-source", p), + writeDiagramImage: (p) => ipcRenderer.invoke("diagram:write-image", p), + readDiagramImage: (p) => ipcRenderer.invoke("diagram:read-image", p), + deleteDiagram: (p) => ipcRenderer.invoke("diagram:delete", p), + diagramExists: (p) => ipcRenderer.invoke("diagram:exists", p), + + drawioReadSource: (p) => ipcRenderer.invoke("drawio:read-source", p), + drawioWriteSource: (p) => ipcRenderer.invoke("drawio:write-source", p), + drawioWriteImage: (p) => ipcRenderer.invoke("drawio:write-image", p), + drawioReadImage: (p) => ipcRenderer.invoke("drawio:read-image", p), + drawioDelete: (p) => ipcRenderer.invoke("drawio:delete", p), + drawioExists: (p) => ipcRenderer.invoke("drawio:exists", p), + + wireframeReadSource: (p) => ipcRenderer.invoke("wireframe:read-source", p), + wireframeWriteSource: (p) => ipcRenderer.invoke("wireframe:write-source", p), + wireframeWriteImage: (p) => ipcRenderer.invoke("wireframe:write-image", p), + wireframeReadImage: (p) => ipcRenderer.invoke("wireframe:read-image", p), + wireframeDelete: (p) => ipcRenderer.invoke("wireframe:delete", p), + wireframeExists: (p) => ipcRenderer.invoke("wireframe:exists", p), }); diff --git a/src/components/ExcalidrawBlock.jsx b/src/components/ExcalidrawBlock.jsx index 2a876659..58712b3e 100644 --- a/src/components/ExcalidrawBlock.jsx +++ b/src/components/ExcalidrawBlock.jsx @@ -13,7 +13,7 @@ export function ExcalidrawBlock({ imagePath, diagramId, documentPath, originAsse const [diagramData, setDiagramData] = useState(null); useEffect(() => { - if (!diagramId || !documentPath) return; + if (!diagramId) return; let cancelled = false; const loadDiagram = async () => { diff --git a/src/components/WebViewPreview.jsx b/src/components/WebViewPreview.jsx index fe6028c7..85d93960 100644 --- a/src/components/WebViewPreview.jsx +++ b/src/components/WebViewPreview.jsx @@ -1,21 +1,74 @@ -import { useMemo } from "react"; +import { useMemo, useEffect, useRef, useState } from "react"; import { renderMarkdown, parseDiagramBlocks, normalizeMarkdownImagePaths, } from "../utils/renderUtils"; +import { readImage } from "../services/electronService"; import { MermaidBlock } from "./MermaidBlock"; import { ExcalidrawBlock } from "./ExcalidrawBlock"; import { DrawioBlock } from "./DrawioBlock"; import { WireframeBlock } from "./WireframeBlock"; +import { VideoPlayerModal } from "./VideoPlayerModal"; export function WebViewPreview({ content, basePath }) { const parts = useMemo(() => parseDiagramBlocks(content), [content]); + const pageRef = useRef(null); + const [activeVideo, setActiveVideo] = useState(null); + + useEffect(() => { + let cancelled = false; + const container = pageRef.current; + if (!container || !basePath) return undefined; + + const mediaElements = Array.from(container.querySelectorAll("img, video")); + for (const el of mediaElements) { + const isImg = el instanceof HTMLImageElement; + const rawSrc = el.getAttribute("data-asset-path") || el.getAttribute("data-video-src") || el.getAttribute("src") || ""; + if (!rawSrc || /^(data:|blob:|https?:)/i.test(rawSrc)) continue; + + const cleanPath = rawSrc.split(/[?#]/)[0]; + readImage(basePath, cleanPath, { thumbnail: false }) + .then((resolved) => { + if (!cancelled && resolved) { + el.src = resolved; + if (!isImg && el instanceof HTMLVideoElement) { + el.onloadeddata = () => { + try { + if (el.currentTime === 0) el.currentTime = 0.1; + } catch { + // Ignore seek error + } + }; + } + } + }) + .catch(() => {}); + } + + return () => { + cancelled = true; + }; + }, [parts, basePath]); const handlePageClick = async (event) => { const target = event.target; if (!(target instanceof HTMLElement)) return; + // Handle video card click + const videoCard = target.closest(".markdown-video-card"); + if (videoCard) { + event.preventDefault(); + event.stopPropagation(); + const videoEl = videoCard.querySelector("video"); + const videoSrc = videoEl?.src || videoCard.getAttribute("data-video-src") || ""; + const videoTitle = videoCard.getAttribute("data-video-title") || "Screen Recording"; + if (videoSrc) { + setActiveVideo({ src: videoSrc, title: videoTitle }); + } + return; + } + const copyButton = target.closest('[data-code-copy="true"]'); if (!(copyButton instanceof HTMLButtonElement)) return; @@ -49,7 +102,7 @@ export function WebViewPreview({ content, basePath }) {
      https://notely.local/note
      -
      +
      {parts.map((part, index) => part.type === "mermaid" ? ( @@ -57,8 +110,9 @@ export function WebViewPreview({ content, basePath }) { @@ -88,6 +142,15 @@ export function WebViewPreview({ content, basePath }) { ) )}
      + + {activeVideo ? ( + setActiveVideo(null)} + /> + ) : null} ); } diff --git a/src/components/media/PresentationViewer.jsx b/src/components/media/PresentationViewer.jsx index 55b76e6f..d1a920d5 100644 --- a/src/components/media/PresentationViewer.jsx +++ b/src/components/media/PresentationViewer.jsx @@ -1,21 +1,98 @@ import { useState, useEffect, useCallback } from "react"; import JSZip from "jszip"; -import { ChevronLeft, ChevronRight, Maximize, Minimize } from "lucide-react"; +import { ChevronLeft, ChevronRight, Maximize, Minimize, FileText, Image as ImageIcon } from "lucide-react"; import AppButton from "../AppButton"; import AppIconButton from "../AppIconButton"; -import { dataUrlToUint8Array } from "./mediaUtils"; -export function PresentationViewer({ dataUrl }) { +/** + * Robust asynchronous binary resolver for data URLs, blob URLs, http/file URLs, and base64 strings. + */ +async function resolveBinaryBytes(source) { + if (!source) return null; + if (source instanceof Uint8Array) return source; + if (source instanceof ArrayBuffer) return new Uint8Array(source); + + if (typeof source === "string") { + const trimmed = source.trim(); + if (trimmed.startsWith("data:")) { + const commaIndex = trimmed.indexOf(","); + if (commaIndex !== -1) { + const base64Str = trimmed.slice(commaIndex + 1); + try { + const binary = atob(base64Str); + const len = binary.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i += 1) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; + } catch { + return null; + } + } + } + + if (/^(blob:|https?:|file:)/i.test(trimmed)) { + try { + const res = await fetch(trimmed); + const buf = await res.arrayBuffer(); + return new Uint8Array(buf); + } catch { + // Continue to fallback + } + } + + try { + const binary = atob(trimmed); + const len = binary.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i += 1) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; + } catch { + return null; + } + } + + return null; +} + +function getElements(parent, tagName) { + if (!parent) return []; + if (typeof parent.getElementsByTagNameNS === "function") { + const nsNodes = Array.from(parent.getElementsByTagNameNS("*", tagName)); + if (nsNodes.length > 0) return nsNodes; + } + const prefixed = Array.from(parent.getElementsByTagName(`a:${tagName}`)); + if (prefixed.length > 0) return prefixed; + const pPrefixed = Array.from(parent.getElementsByTagName(`p:${tagName}`)); + if (pPrefixed.length > 0) return pPrefixed; + return Array.from(parent.getElementsByTagName(tagName)); +} + +function extractTextFromNode(node) { + if (!node) return ""; + const tNodes = getElements(node, "t"); + let text = ""; + for (let i = 0; i < tNodes.length; i += 1) { + text += tNodes[i].textContent || ""; + } + return text.trim(); +} + +export function PresentationViewer({ dataUrl, fileName }) { const [slides, setSlides] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [currentSlideIndex, setCurrentSlideIndex] = useState(0); const [isFullscreen, setIsFullscreen] = useState(false); + const [showNotes, setShowNotes] = useState(false); useEffect(() => { let cancelled = false; - async function parsePptx() { + async function parsePresentation() { if (!dataUrl) { if (!cancelled) { setSlides([]); @@ -28,72 +105,215 @@ export function PresentationViewer({ dataUrl }) { setError(null); try { - const bytes = dataUrlToUint8Array(dataUrl); - if (!bytes) throw new Error("Could not decode presentation data."); + const bytes = await resolveBinaryBytes(dataUrl); + if (!bytes || bytes.length === 0) { + throw new Error("Could not decode presentation data."); + } + + // Check for legacy binary .ppt OLE header (D0 CF 11 E0) + if (bytes.length >= 4 && bytes[0] === 0xd0 && bytes[1] === 0xcf && bytes[2] === 0x11 && bytes[3] === 0xe0) { + throw new Error("Legacy PowerPoint (.ppt) binary format is not supported in the embedded viewer. Please open externally or convert to .pptx."); + } const zip = await JSZip.loadAsync(bytes); - // Find all slide XML files - const slideFileNames = Object.keys(zip.files) - .filter((name) => /^ppt\/slides\/slide\d+\.xml$/i.test(name)) - .sort((a, b) => { - const numA = parseInt(a.match(/\d+/)?.[0] || "0", 10); - const numB = parseInt(b.match(/\d+/)?.[0] || "0", 10); - return numA - numB; - }); + // Discover slide order from presentation.xml + relationships if present + let orderedSlidePaths = []; + + try { + const presRelsFile = zip.file("ppt/_rels/presentation.xml.rels"); + const presXmlFile = zip.file("ppt/presentation.xml"); + + if (presRelsFile && presXmlFile) { + const relsXml = await presRelsFile.async("string"); + const presXml = await presXmlFile.async("string"); + const parser = new DOMParser(); + const relsDoc = parser.parseFromString(relsXml, "application/xml"); + const presDoc = parser.parseFromString(presXml, "application/xml"); + + const relsMap = {}; + const relationshipNodes = getElements(relsDoc, "Relationship"); + relationshipNodes.forEach((rel) => { + const id = rel.getAttribute("Id") || rel.getAttribute("r:id") || rel.getAttribute("id"); + const target = rel.getAttribute("Target"); + if (id && target) { + const normTarget = target.startsWith("slides/") ? `ppt/${target}` : target.startsWith("/") ? target.slice(1) : `ppt/${target}`; + relsMap[id] = normTarget; + } + }); + + const sldIdNodes = getElements(presDoc, "sldId"); + sldIdNodes.forEach((sld) => { + const rId = sld.getAttribute("r:id") || sld.getAttribute("id") || sld.getAttribute("r:Id"); + if (rId && relsMap[rId] && zip.file(relsMap[rId])) { + orderedSlidePaths.push(relsMap[rId]); + } + }); + } + } catch { + // Fallback to sorting slide filenames directly + } - if (!slideFileNames.length) { + if (orderedSlidePaths.length === 0) { + orderedSlidePaths = Object.keys(zip.files) + .filter((name) => /^ppt\/slides\/slide\d+\.xml$/i.test(name)) + .sort((a, b) => { + const numA = parseInt(a.match(/\d+/)?.[0] || "0", 10); + const numB = parseInt(b.match(/\d+/)?.[0] || "0", 10); + return numA - numB; + }); + } + + if (orderedSlidePaths.length === 0) { throw new Error("No slides found in this presentation."); } - const parsed = []; + const parsedSlides = []; - for (let i = 0; i < slideFileNames.length; i += 1) { - const slidePath = slideFileNames[i]; - const xmlContent = await zip.file(slidePath).async("string"); + for (let i = 0; i < orderedSlidePaths.length; i += 1) { + const slidePath = orderedSlidePaths[i]; + const slideXmlContent = await zip.file(slidePath).async("string"); const parser = new DOMParser(); - const doc = parser.parseFromString(xmlContent, "application/xml"); + const doc = parser.parseFromString(slideXmlContent, "application/xml"); + + // Load slide relationships to resolve embedded images + const slideFileName = slidePath.split("/").pop(); + const relsPath = `ppt/slides/_rels/${slideFileName}.rels`; + const slideRels = {}; + if (zip.file(relsPath)) { + try { + const relsXml = await zip.file(relsPath).async("string"); + const relsDoc = parser.parseFromString(relsXml, "application/xml"); + const relNodes = getElements(relsDoc, "Relationship"); + for (const rel of relNodes) { + const id = rel.getAttribute("Id") || rel.getAttribute("id"); + const target = rel.getAttribute("Target"); + if (id && target) { + const mediaPath = target.startsWith("../") + ? `ppt/${target.replace(/^\.\.\//, "")}` + : `ppt/slides/${target}`; + slideRels[id] = mediaPath; + } + } + } catch { + // Ignore relationship errors + } + } + + // Extract slide images + const slideImages = []; + const blipNodes = getElements(doc, "blip"); + for (const blip of blipNodes) { + const embedId = blip.getAttribute("r:embed") || blip.getAttribute("embed"); + const mediaZipPath = slideRels[embedId]; + if (mediaZipPath && zip.file(mediaZipPath)) { + try { + const imgData = await zip.file(mediaZipPath).async("base64"); + const ext = mediaZipPath.split(".").pop()?.toLowerCase() || "png"; + const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "svg" ? "image/svg+xml" : `image/${ext}`; + slideImages.push(`data:${mime};base64,${imgData}`); + } catch { + // Ignore image conversion failure + } + } + } - // Helper to retrieve elements by tag name regardless of namespace prefix - const getChildElements = (parent, tag) => { - if (parent.getElementsByTagNameNS) { - const nsNodes = Array.from(parent.getElementsByTagNameNS("*", tag)); - if (nsNodes.length > 0) return nsNodes; + // Parse shapes, titles, paragraphs, and tables + let titleText = ""; + let subtitleText = ""; + const bodyParagraphs = []; + const tables = []; + + const shapes = getElements(doc, "sp"); + for (const sp of shapes) { + const phNode = getElements(sp, "ph")[0]; + const phType = (phNode?.getAttribute("type") || "").toLowerCase(); + const isTitle = phType === "title" || phType === "ctrtitle" || phType === "header"; + const isSubTitle = phType === "subtitle" || phType === "sub"; + + const pNodes = getElements(sp, "p"); + const shapeParagraphs = []; + for (const p of pNodes) { + const text = extractTextFromNode(p); + if (text) { + shapeParagraphs.push(text); + } + } + + if (isTitle && shapeParagraphs.length > 0) { + if (!titleText) titleText = shapeParagraphs.join(" "); + else bodyParagraphs.push(...shapeParagraphs); + } else if (isSubTitle && shapeParagraphs.length > 0) { + if (!subtitleText) subtitleText = shapeParagraphs.join(" "); + else bodyParagraphs.push(...shapeParagraphs); + } else { + bodyParagraphs.push(...shapeParagraphs); } - const prefixed = Array.from(parent.getElementsByTagName(`a:${tag}`)); - if (prefixed.length > 0) return prefixed; - return Array.from(parent.getElementsByTagName(tag)); - }; - - // Extract text runs - const paragraphs = []; - const pElements = getChildElements(doc, "p"); - - for (let p = 0; p < pElements.length; p += 1) { - const textNodes = getChildElements(pElements[p], "t"); - let pText = ""; - for (let t = 0; t < textNodes.length; t += 1) { - pText += textNodes[t].textContent || ""; + } + + // If no title found via placeholders, check first paragraph + if (!titleText && bodyParagraphs.length > 0) { + titleText = bodyParagraphs.shift(); + } + + // Parse tables + const tblNodes = getElements(doc, "tbl"); + for (const tbl of tblNodes) { + const rows = []; + const trNodes = getElements(tbl, "tr"); + for (const tr of trNodes) { + const rowCells = []; + const tcNodes = getElements(tr, "tc"); + for (const tc of tcNodes) { + rowCells.push(extractTextFromNode(tc)); + } + if (rowCells.some(Boolean)) { + rows.push(rowCells); + } } - const trimmed = pText.trim(); - if (trimmed) { - paragraphs.push(trimmed); + if (rows.length > 0) { + tables.push(rows); } } - // Check if first paragraph is a slide title - const title = paragraphs[0] || `Slide ${i + 1}`; - const body = paragraphs.length > 1 ? paragraphs.slice(1) : []; + // Check for notes slide + let slideNotes = ""; + const noteSlidePath = `ppt/notesSlides/notesSlide${i + 1}.xml`; + if (zip.file(noteSlidePath)) { + try { + const noteXml = await zip.file(noteSlidePath).async("string"); + const noteDoc = parser.parseFromString(noteXml, "application/xml"); + const noteTexts = []; + const noteShapes = getElements(noteDoc, "sp"); + for (const sp of noteShapes) { + const ph = getElements(sp, "ph")[0]; + if (ph?.getAttribute("type") === "body") { + const pNodes = getElements(sp, "p"); + for (const p of pNodes) { + const t = extractTextFromNode(p); + if (t) noteTexts.push(t); + } + } + } + slideNotes = noteTexts.join("\n"); + } catch { + // Ignore notes parse errors + } + } - parsed.push({ + parsedSlides.push({ slideNumber: i + 1, - title, - body, + title: titleText || `Slide ${i + 1}`, + subtitle: subtitleText, + body: bodyParagraphs, + tables, + images: slideImages, + notes: slideNotes, }); } if (!cancelled) { - setSlides(parsed); + setSlides(parsedSlides); setLoading(false); } } catch (err) { @@ -104,7 +324,7 @@ export function PresentationViewer({ dataUrl }) { } } - parsePptx(); + void parsePresentation(); return () => { cancelled = true; }; @@ -139,7 +359,7 @@ export function PresentationViewer({ dataUrl }) { return (
      -

      Loading slides…

      +

      Loading presentation slides…

      ); } @@ -148,7 +368,8 @@ export function PresentationViewer({ dataUrl }) { return (

      Unable to preview presentation

      -

      {error || "No slide content found."}

      +

      {error || "No slide content found in file."}

      + {fileName && {fileName}}
      ); } @@ -159,9 +380,22 @@ export function PresentationViewer({ dataUrl }) {
      Slide {currentSlide?.slideNumber} + {currentSlide?.images?.length > 0 && ( + + + {currentSlide.images.length} {currentSlide.images.length === 1 ? "Image" : "Images"} + + )}
      +

      {currentSlide?.title}

      + {currentSlide?.subtitle && ( +

      + {currentSlide.subtitle} +

      + )} + {currentSlide?.body?.length > 0 && (
        {currentSlide.body.map((item, idx) => ( @@ -171,6 +405,44 @@ export function PresentationViewer({ dataUrl }) { ))}
      )} + + {currentSlide?.tables?.map((tableData, tIdx) => ( +
      + + + {tableData.map((row, rIdx) => ( + + {row.map((cell, cIdx) => ( + + ))} + + ))} + +
      + {cell} +
      +
      + ))} + + {currentSlide?.images?.length > 0 && ( +
      + {currentSlide.images.map((imgSrc, imgIdx) => ( + {`Slide + ))} +
      + )} + + {showNotes && currentSlide?.notes && ( +
      + Speaker Notes: +

      {currentSlide.notes}

      +
      + )}
      @@ -202,14 +474,27 @@ export function PresentationViewer({ dataUrl }) { - setIsFullscreen(!isFullscreen)} - data-tooltip={isFullscreen ? "Exit fullscreen" : "Fullscreen presentation"} - aria-label="Toggle fullscreen" - > - {isFullscreen ? : } - +
      + {currentSlide?.notes ? ( + setShowNotes(!showNotes)} + data-tooltip={showNotes ? "Hide speaker notes" : "Show speaker notes"} + > + + Notes + + ) : null} + + setIsFullscreen(!isFullscreen)} + data-tooltip={isFullscreen ? "Exit fullscreen" : "Fullscreen presentation"} + aria-label="Toggle fullscreen" + > + {isFullscreen ? : } + +
      {slides.length > 1 && ( diff --git a/src/components/media/mediaUtils.js b/src/components/media/mediaUtils.js index f4024efb..955375bc 100644 --- a/src/components/media/mediaUtils.js +++ b/src/components/media/mediaUtils.js @@ -5,9 +5,9 @@ export function dataUrlToUint8Array(dataUrl) { if (!dataUrl || typeof dataUrl !== "string") return null; const commaIndex = dataUrl.indexOf(","); - if (commaIndex === -1) return null; + const base64Str = commaIndex !== -1 ? dataUrl.slice(commaIndex + 1) : dataUrl; try { - const binary = atob(dataUrl.slice(commaIndex + 1)); + const binary = atob(base64Str); const len = binary.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i += 1) { From 4b787230dade4e05cb85bab53e53d099dbaf5419 Mon Sep 17 00:00:00 2001 From: Bikash Panda Date: Thu, 24 Sep 2026 08:54:52 +0530 Subject: [PATCH 7/7] AI Cleanup --- THIRD_PARTY_NOTICES.txt | 7327 +++++++++++------ ai/README.md | 11 +- ai/context/ContextEngine.js | 84 - ai/context/ContextManager.js | 239 - ai/context/GraphRetriever.js | 247 - ai/context/HybridRetriever.js | 178 - ai/context/SemanticRetriever.js | 156 - ai/context/index.js | 25 - ai/core/AIService.js | 29 +- ai/core/Agent.js | 106 +- ai/database/LegacyDBManager.js | 419 - ai/database/LegacyMigrations.js | 201 - ai/database/index.js | 14 - ai/embeddings/HuggingFaceEmbeddingProvider.js | 179 + ai/embeddings/index.js | 3 + ai/formatter/TaskSummaryFormatter.js | 51 - ai/formatter/index.js | 34 - ai/graph/semantic/SemanticExtractionEngine.js | 11 +- ai/graph/semantic/adapters/LLMGraphAdapter.js | 187 + ai/index.js | 23 +- ai/memory/InteractionLog.js | 204 - ai/memory/MemoryDB.js | 87 - ai/memory/MemoryOptimizer.js | 221 - ai/memory/PatternAnalyzer.js | 209 - ai/memory/index.js | 18 - ai/tools/DocumentReader.js | 270 - ai/tools/QueryTools.js | 364 - ai/tools/SemanticTools.js | 142 - ai/tools/ToolRegistry.js | 52 - ai/tools/index.js | 19 - electron/ai/aiHandlers.cjs | 89 +- electron/main.cjs | 34 +- electron/preload.cjs | 23 +- src/tests/utils/aiSubsystem.test.js | 74 - tests/ai/auditTools.spec.js | 135 - tests/ai/knowledgeGraph.spec.js | 28 +- tests/ai/pipeline.spec.js | 13 +- tests/ai/provider.spec.js | 24 + tests/ai/retriever.spec.js | 44 - tests/ai/search.spec.js | 85 - tests/ai/tools.spec.js | 22 - 41 files changed, 5239 insertions(+), 6442 deletions(-) delete mode 100644 ai/context/ContextEngine.js delete mode 100644 ai/context/ContextManager.js delete mode 100644 ai/context/GraphRetriever.js delete mode 100644 ai/context/HybridRetriever.js delete mode 100644 ai/context/SemanticRetriever.js delete mode 100644 ai/context/index.js delete mode 100644 ai/database/LegacyDBManager.js delete mode 100644 ai/database/LegacyMigrations.js delete mode 100644 ai/database/index.js create mode 100644 ai/embeddings/HuggingFaceEmbeddingProvider.js delete mode 100644 ai/formatter/TaskSummaryFormatter.js delete mode 100644 ai/formatter/index.js create mode 100644 ai/graph/semantic/adapters/LLMGraphAdapter.js delete mode 100644 ai/memory/InteractionLog.js delete mode 100644 ai/memory/MemoryDB.js delete mode 100644 ai/memory/MemoryOptimizer.js delete mode 100644 ai/memory/PatternAnalyzer.js delete mode 100644 ai/memory/index.js delete mode 100644 ai/tools/DocumentReader.js delete mode 100644 ai/tools/QueryTools.js delete mode 100644 ai/tools/SemanticTools.js delete mode 100644 ai/tools/ToolRegistry.js delete mode 100644 ai/tools/index.js delete mode 100644 src/tests/utils/aiSubsystem.test.js delete mode 100644 tests/ai/auditTools.spec.js delete mode 100644 tests/ai/retriever.spec.js delete mode 100644 tests/ai/search.spec.js delete mode 100644 tests/ai/tools.spec.js diff --git a/THIRD_PARTY_NOTICES.txt b/THIRD_PARTY_NOTICES.txt index 6614eb85..53daccca 100644 --- a/THIRD_PARTY_NOTICES.txt +++ b/THIRD_PARTY_NOTICES.txt @@ -1,10 +1,10 @@ THIRD-PARTY SOFTWARE NOTICES AND INFORMATION Notely incorporates components from the projects listed below. -This file was generated automatically on 2026-09-18 by +This file was generated automatically on 2026-09-24 by scripts/generate-notices.cjs. Do not edit by hand. -Total third-party packages: 167 +Total third-party packages: 189 ================================================================================ @@ -114,6 +114,179 @@ Homepage: https://ai-sdk.dev/docs -------------------------------------------------------------------------------- +@fortawesome/fontawesome-free@7.3.1 +License: (CC-BY-4.0 AND OFL-1.1 AND MIT) +Author: The Font Awesome Team (https://github.com/orgs/FortAwesome/people) +Homepage: https://fontawesome.com + +Fonticons, Inc. (https://fontawesome.com) + +-------------------------------------------------------------------------------- + +Font Awesome Free License + +Font Awesome Free is free, open source, and GPL friendly. You can use it for +commercial projects, open source projects, or really almost whatever you want. +Full Font Awesome Free license: https://fontawesome.com/license/free. + +-------------------------------------------------------------------------------- + +# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + +The Font Awesome Free download is licensed under a Creative Commons +Attribution 4.0 International License and applies to all icons packaged +as SVG and JS file types. + +-------------------------------------------------------------------------------- + +# Fonts: SIL OFL 1.1 License + +In the Font Awesome Free download, the SIL OFL license applies to all icons +packaged as web and desktop font files. + +Copyright (c) 2026 Fonticons, Inc. (https://fontawesome.com) +with Reserved Font Name: "Font Awesome". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting — in part or in whole — any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +-------------------------------------------------------------------------------- + +# Code: MIT License (https://opensource.org/licenses/MIT) + +In the Font Awesome Free download, the MIT license applies to all non-font and +non-icon files. + +Copyright 2026 Fonticons, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +# Attribution + +Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font +Awesome Free files already contain embedded comments with sufficient +attribution, so you shouldn't need to do anything additional when using these +files normally. + +We've kept attribution comments terse, so we ask that you do not actively work +to remove them from files, especially code. They're a great way for folks to +learn about Font Awesome. + +-------------------------------------------------------------------------------- + +# Brand Icons + +All brand icons are trademarks of their respective owners. The use of these +trademarks does not indicate endorsement of the trademark holder by Font +Awesome, nor vice versa. **Please do not use brand logos for any purpose except +to represent the company, product, or service to which they refer.** + +-------------------------------------------------------------------------------- + @hono/node-server@2.1.1 License: MIT Author: Yusuke Wada (https://github.com/yusukebe) @@ -1388,105 +1561,314 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -adm-zip@0.5.18 -License: MIT -Author: Nasca Iacob (https://github.com/cthackers) -Homepage: https://github.com/cthackers/adm-zip +adler-32@1.3.1 +License: Apache-2.0 +Author: sheetjs +Homepage: http://sheetjs.com/opensource -MIT License +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2012 Another-D-Mention Software and other contributors + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 1. Definitions. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. --------------------------------------------------------------------------------- + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -ai@7.0.31 -License: Apache-2.0 -Homepage: https://ai-sdk.dev/docs + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Copyright 2023 Vercel, Inc. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. - http://www.apache.org/licenses/LICENSE-2.0 + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. --------------------------------------------------------------------------------- + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -ajv@6.15.0 -License: MIT -Author: Evgeny Poberezkin -Homepage: https://github.com/ajv-validator/ajv + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -The MIT License (MIT) + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Copyright (c) 2015-2017 Evgeny Poberezkin + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and --------------------------------------------------------------------------------- + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -ajv-formats@3.0.1 -License: MIT -Author: Evgeny Poberezkin -Homepage: https://github.com/ajv-validator/ajv-formats#readme + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -MIT License + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Copyright (c) 2020 Evgeny Poberezkin + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2014-present SheetJS LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +adm-zip@0.5.18 +License: MIT +Author: Nasca Iacob (https://github.com/cthackers) +Homepage: https://github.com/cthackers/adm-zip + +MIT License + +Copyright (c) 2012 Another-D-Mention Software and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +ai@7.0.31 +License: Apache-2.0 +Homepage: https://ai-sdk.dev/docs + +Copyright 2023 Vercel, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +-------------------------------------------------------------------------------- + +ajv@6.15.0 +License: MIT +Author: Evgeny Poberezkin +Homepage: https://github.com/ajv-validator/ajv + +The MIT License (MIT) + +Copyright (c) 2015-2017 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +ajv-formats@3.0.1 +License: MIT +Author: Evgeny Poberezkin +Homepage: https://github.com/ajv-validator/ajv-formats#readme + +MIT License + +Copyright (c) 2020 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, @@ -1917,344 +2299,258 @@ SOFTWARE. -------------------------------------------------------------------------------- -content-disposition@1.1.0 -License: MIT -Author: Douglas Christopher Wilson -Homepage: jshttp/content-disposition - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson +cfb@1.2.2 +License: Apache-2.0 +Author: sheetjs +Homepage: http://sheetjs.com/ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Definitions. --------------------------------------------------------------------------------- + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -content-type@1.0.5 -License: MIT -Author: Douglas Christopher Wilson -Homepage: jshttp/content-type + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -(The MIT License) + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Copyright (c) 2015 Douglas Christopher Wilson + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). --------------------------------------------------------------------------------- + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -cookie@0.7.2 -License: MIT -Author: Roman Shtylman -Homepage: jshttp/cookie + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -(The MIT License) + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Copyright (c) 2012-2014 Roman Shtylman -Copyright (c) 2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: --------------------------------------------------------------------------------- + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -cookie-signature@1.2.2 -License: MIT -Author: TJ Holowaychuk -Homepage: https://github.com/visionmedia/node-cookie-signature.git + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -(The MIT License) + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -Copyright (c) 2012–2024 LearnBoost and other contributors; + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. --------------------------------------------------------------------------------- + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -cors@2.8.6 -License: MIT -Author: Troy Goode (https://github.com/troygoode/) -Homepage: expressjs/cors + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -(The MIT License) + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -Copyright (c) 2013 Troy Goode + END OF TERMS AND CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + APPENDIX: How to apply the Apache License to your work. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Copyright (C) 2013-present SheetJS LLC --------------------------------------------------------------------------------- + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -cross-spawn@7.0.6 -License: MIT -Author: André Cruz -Homepage: https://github.com/moxystudio/node-cross-spawn + http://www.apache.org/licenses/LICENSE-2.0 -The MIT License (MIT) + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -Copyright (c) 2018 Made With MOXY Lda +-------------------------------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +codepage@1.15.0 +License: Apache-2.0 +Author: SheetJS +Homepage: https://sheetjs.com/ -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION --------------------------------------------------------------------------------- + 1. Definitions. -debug@4.4.3 -License: MIT -Author: Josh Junon (https://github.com/qix-) -Homepage: git://github.com/debug-js/debug.git + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -(The MIT License) + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -Copyright (c) 2014-2017 TJ Holowaychuk -Copyright (c) 2018-2021 Josh Junon + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software -and associated documentation files (the 'Software'), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. --------------------------------------------------------------------------------- - -define-data-property@1.1.4 -License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/define-data-property#readme - -MIT License - -Copyright (c) 2023 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -define-properties@1.2.1 -License: MIT -Author: Jordan Harband -Homepage: git://github.com/ljharb/define-properties.git - -The MIT License (MIT) - -Copyright (C) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - --------------------------------------------------------------------------------- - -depd@2.0.0 -License: MIT -Author: Douglas Christopher Wilson -Homepage: dougwilson/nodejs-depd - -(The MIT License) - -Copyright (c) 2014-2018 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -detect-libc@2.1.2 -License: Apache-2.0 -Author: Lovell Fuller -Homepage: git://github.com/lovell/detect-libc.git - -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the @@ -2405,7 +2701,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright (C) 2013-present SheetJS LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2421,100 +2717,75 @@ Apache License -------------------------------------------------------------------------------- -detect-node@2.1.0 -License: MIT -Author: Ilya Kantor -Homepage: https://github.com/iliakan/detect-node - -MIT License - -Copyright (c) 2017 Ilya Kantor - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -dunder-proto@1.0.1 +content-disposition@1.1.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/es-shims/dunder-proto#readme +Author: Douglas Christopher Wilson +Homepage: jshttp/content-disposition -MIT License +(The MIT License) -Copyright (c) 2024 ECMAScript Shims +Copyright (c) 2014-2017 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -ee-first@1.1.1 +content-type@1.0.5 License: MIT -Author: Jonathan Ong -Homepage: jonathanong/ee-first +Author: Douglas Christopher Wilson +Homepage: jshttp/content-type -The MIT License (MIT) +(The MIT License) -Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) 2015 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -encodeurl@2.0.0 +cookie@0.7.2 License: MIT -Homepage: pillarjs/encodeurl +Author: Roman Shtylman +Homepage: jshttp/cookie (The MIT License) -Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -2537,150 +2808,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -entities@4.5.0 -License: BSD-2-Clause -Author: Felix Boehm -Homepage: git://github.com/fb55/entities.git - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- - -es-define-property@1.0.1 -License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/es-define-property#readme - -MIT License - -Copyright (c) 2024 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -es-errors@1.3.0 -License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/es-errors#readme - -MIT License - -Copyright (c) 2024 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -es-object-atoms@1.1.2 -License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/es-object-atoms#readme - -MIT License - -Copyright (c) 2024 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -es6-error@4.1.1 -License: MIT -Author: Ben Youngblood -Homepage: https://github.com/bjyoungblood/es6-error - -The MIT License (MIT) - -Copyright (c) 2015 Ben Youngblood - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -escape-html@1.0.3 +cookie-signature@1.2.2 License: MIT -Homepage: component/escape-html +Author: TJ Holowaychuk +Homepage: https://github.com/visionmedia/node-cookie-signature.git (The MIT License) -Copyright (c) 2012-2013 TJ Holowaychuk -Copyright (c) 2015 Andreas Lubbe -Copyright (c) 2015 Tiancheng "Timothy" Gu +Copyright (c) 2012–2024 LearnBoost and other contributors; Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -2703,30 +2838,41 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -escape-string-regexp@4.0.0 +core-util-is@1.0.2 License: MIT -Author: Sindre Sorhus -Homepage: sindresorhus/escape-string-regexp - -MIT License +Author: Isaac Z. Schlueter (http://blog.izs.me/) +Homepage: git://github.com/isaacs/core-util-is -Copyright (c) Sindre Sorhus (https://sindresorhus.com) +Copyright Node.js contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. -------------------------------------------------------------------------------- -etag@1.8.1 +cors@2.8.6 License: MIT -Homepage: jshttp/etag +Author: Troy Goode (https://github.com/troygoode/) +Homepage: expressjs/cors (The MIT License) -Copyright (c) 2014-2016 Douglas Christopher Wilson +Copyright (c) 2013 Troy Goode Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -2749,265 +2895,57 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -eventsource@3.0.7 -License: MIT -Author: Espen Hovlandsdal -Homepage: https://github.com/EventSource/eventsource#readme - -The MIT License - -Copyright (c) EventSource GitHub organisation +crc-32@1.2.2 +License: Apache-2.0 +Author: sheetjs +Homepage: https://sheetjs.com/ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 1. Definitions. --------------------------------------------------------------------------------- + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -eventsource-parser@3.1.0 -License: MIT -Author: Espen Hovlandsdal -Homepage: https://github.com/rexxars/eventsource-parser#readme + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -MIT License + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -Copyright (c) 2026 Espen Hovlandsdal + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). --------------------------------------------------------------------------------- - -express@5.2.1 -License: MIT -Author: TJ Holowaychuk -Homepage: https://expressjs.com/ - -(The MIT License) - -Copyright (c) 2009-2014 TJ Holowaychuk -Copyright (c) 2013-2014 Roman Shtylman -Copyright (c) 2014-2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -express-rate-limit@8.7.0 -License: MIT -Author: Nathan Friedly -Homepage: https://github.com/express-rate-limit/express-rate-limit - -MIT License - -Copyright 2023 Nathan Friedly, Vedant K - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -fast-deep-equal@3.1.3 -License: MIT -Author: Evgeny Poberezkin -Homepage: https://github.com/epoberezkin/fast-deep-equal#readme - -MIT License - -Copyright (c) 2017 Evgeny Poberezkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -fast-json-stable-stringify@2.1.0 -License: MIT -Author: James Halliday -Homepage: https://github.com/epoberezkin/fast-json-stable-stringify - -This software is released under the MIT license: - -Copyright (c) 2017 Evgeny Poberezkin -Copyright (c) 2013 James Halliday - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -finalhandler@2.1.1 -License: MIT -Author: Douglas Christopher Wilson -Homepage: pillarjs/finalhandler - -(The MIT License) - -Copyright (c) 2014-2022 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -flatbuffers@25.9.23 -License: Apache-2.0 -Author: The FlatBuffers project -Homepage: https://google.github.io/flatbuffers/ - -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions @@ -3142,7 +3080,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -3150,7 +3088,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright (C) 2014-present SheetJS LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -3166,130 +3104,70 @@ Apache License -------------------------------------------------------------------------------- -forwarded@0.2.0 +cross-spawn@7.0.6 License: MIT -Homepage: jshttp/forwarded +Author: André Cruz +Homepage: https://github.com/moxystudio/node-cross-spawn -(The MIT License) +The MIT License (MIT) -Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2018 Made With MOXY Lda -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -fresh@2.0.0 +debug@4.4.3 License: MIT -Author: TJ Holowaychuk (http://tjholowaychuk.com) -Homepage: jshttp/fresh +Author: Josh Junon (https://github.com/qix-) +Homepage: git://github.com/debug-js/debug.git (The MIT License) -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2016-2017 Douglas Christopher Wilson +Copyright (c) 2014-2017 TJ Holowaychuk +Copyright (c) 2018-2021 Josh Junon -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -function-bind@1.1.2 -License: MIT -Author: Raynos -Homepage: https://github.com/Raynos/function-bind - -Copyright (c) 2013 Raynos. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - --------------------------------------------------------------------------------- - -get-intrinsic@1.3.0 -License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/get-intrinsic#readme - -MIT License - -Copyright (c) 2020 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - --------------------------------------------------------------------------------- - -get-proto@1.0.1 +define-data-property@1.1.4 License: MIT Author: Jordan Harband -Homepage: https://github.com/ljharb/get-proto#readme +Homepage: https://github.com/ljharb/define-data-property#readme MIT License -Copyright (c) 2025 Jordan Harband +Copyright (c) 2023 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3311,46 +3189,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -global-agent@3.0.0 -License: BSD-3-Clause -Author: Gajus Kuizinas -Homepage: https://github.com/gajus/global-agent - -Copyright (c) 2019, Gajus Kuizinas (http://gajus.com/) -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --------------------------------------------------------------------------------- - -globalthis@1.0.4 +define-properties@1.2.1 License: MIT Author: Jordan Harband -Homepage: git://github.com/ljharb/System.global.git +Homepage: git://github.com/ljharb/define-properties.git The MIT License (MIT) -Copyright (c) 2016 Jordan Harband +Copyright (C) 2015 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3359,52 +3205,53 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -gopd@1.2.0 +depd@2.0.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/gopd#readme +Author: Douglas Christopher Wilson +Homepage: dougwilson/nodejs-depd -MIT License +(The MIT License) -Copyright (c) 2022 Jordan Harband +Copyright (c) 2014-2018 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -groq-sdk@1.3.0 +detect-libc@2.1.2 License: Apache-2.0 -Author: Groq -Homepage: github:groq/groq-typescript +Author: Lovell Fuller +Homepage: git://github.com/lovell/detect-libc.git Apache License Version 2.0, January 2004 @@ -3586,7 +3433,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -3594,7 +3441,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2026 Groq + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -3610,21 +3457,14 @@ Apache License -------------------------------------------------------------------------------- -guid-typescript@1.0.9 -License: ISC -Author: nicolas -Homepage: https://github.com/NicolasDeveloper/guid-typescript - --------------------------------------------------------------------------------- - -has-property-descriptors@1.0.2 +detect-node@2.1.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/inspect-js/has-property-descriptors#readme +Author: Ilya Kantor +Homepage: https://github.com/iliakan/detect-node MIT License -Copyright (c) 2022 Inspect JS +Copyright (c) 2017 Ilya Kantor Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3646,14 +3486,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -has-symbols@1.1.0 +dunder-proto@1.0.1 License: MIT Author: Jordan Harband -Homepage: https://github.com/ljharb/has-symbols#readme +Homepage: https://github.com/es-shims/dunder-proto#readme MIT License -Copyright (c) 2016 Jordan Harband +Copyright (c) 2024 ECMAScript Shims Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3675,14 +3515,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -hasown@2.0.4 +ee-first@1.1.1 License: MIT -Author: Jordan Harband -Homepage: https://github.com/inspect-js/hasOwn#readme +Author: Jonathan Ong +Homepage: jonathanong/ee-first -MIT License +The MIT License (MIT) -Copyright (c) Jordan Harband and contributors +Copyright (c) 2014 Jonathan Ong me@jongleberry.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3691,64 +3531,75 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -highlight.js@11.11.1 -License: BSD-3-Clause -Author: Josh Goebel -Homepage: https://highlightjs.org/ +encodeurl@2.0.0 +License: MIT +Homepage: pillarjs/encodeurl -BSD 3-Clause License +(The MIT License) -Copyright (c) 2006, Ivan Sagalaev. -All rights reserved. +Copyright (c) 2016 Douglas Christopher Wilson -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. +-------------------------------------------------------------------------------- -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +entities@4.5.0 +License: BSD-2-Clause +Author: Felix Boehm +Homepage: git://github.com/fb55/entities.git + +Copyright (c) Felix Böhm +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -hono@4.13.7 +es-define-property@1.0.1 License: MIT -Author: Yusuke Wada (https://github.com/yusukebe) -Homepage: https://hono.dev +Author: Jordan Harband +Homepage: https://github.com/ljharb/es-define-property#readme MIT License -Copyright (c) 2021 - present, Yusuke Wada and Hono contributors +Copyright (c) 2024 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3770,15 +3621,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -http-errors@2.0.1 +es-errors@1.3.0 License: MIT -Author: Jonathan Ong (http://jongleberry.com) -Homepage: jshttp/http-errors +Author: Jordan Harband +Homepage: https://github.com/ljharb/es-errors#readme -The MIT License (MIT) +MIT License -Copyright (c) 2014 Jonathan Ong me@jongleberry.com -Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com +Copyright (c) 2024 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3787,75 +3637,27 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -iconv-lite@0.6.3 +es-object-atoms@1.1.2 License: MIT -Author: Alexander Shtuchkin -Homepage: https://github.com/ashtuchkin/iconv-lite - -Copyright (c) 2011 Alexander Shtuchkin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -inherits@2.0.4 -License: ISC -Homepage: git://github.com/isaacs/inherits - -The ISC License - -Copyright (c) Isaac Z. Schlueter - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - --------------------------------------------------------------------------------- +Author: Jordan Harband +Homepage: https://github.com/ljharb/es-object-atoms#readme -ip-address@10.7.0 -License: MIT -Author: Beau Gunderson (https://beaugunderson.com/) -Homepage: https://github.com/beaugunderson/ip-address.git +MIT License -Copyright (C) 2011 by Beau Gunderson +Copyright (c) 2024 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3864,25 +3666,27 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -ipaddr.js@1.9.1 +es6-error@4.1.1 License: MIT -Author: whitequark -Homepage: git://github.com/whitequark/ipaddr.js +Author: Ben Youngblood +Homepage: https://github.com/bjyoungblood/es6-error -Copyright (C) 2011-2017 whitequark +The MIT License (MIT) + +Copyright (c) 2015 Ben Youngblood Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3891,309 +3695,134 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -is-promise@4.0.0 +escape-html@1.0.3 License: MIT -Author: ForbesLindesay -Homepage: https://github.com/then/is-promise.git +Homepage: component/escape-html -Copyright (c) 2014 Forbes Lindesay +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2012-2013 TJ Holowaychuk +Copyright (c) 2015 Andreas Lubbe +Copyright (c) 2015 Tiancheng "Timothy" Gu -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -isexe@2.0.0 -License: ISC -Author: Isaac Z. Schlueter (http://blog.izs.me/) -Homepage: https://github.com/isaacs/isexe#readme +escape-string-regexp@4.0.0 +License: MIT +Author: Sindre Sorhus +Homepage: sindresorhus/escape-string-regexp -The ISC License +MIT License -Copyright (c) Isaac Z. Schlueter and Contributors +Copyright (c) Sindre Sorhus (https://sindresorhus.com) -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -jose@6.2.12 +etag@1.8.1 License: MIT -Author: Filip Skokan -Homepage: https://github.com/panva/jose +Homepage: jshttp/etag -The MIT License (MIT) +(The MIT License) -Copyright (c) 2018 Filip Skokan +Copyright (c) 2014-2016 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -json-schema@0.4.0 -License: (AFL-2.1 OR BSD-3-Clause) -Author: Kris Zyp -Homepage: http://github.com/kriszyp/json-schema - -Dojo is available under *either* the terms of the BSD 3-Clause "New" License *or* the -Academic Free License version 2.1. As a recipient of Dojo, you may choose which -license to receive this code under (except as noted in per-module LICENSE -files). Some modules may not be the copyright of the Dojo Foundation. These -modules contain explicit declarations of copyright in both the LICENSE files in -the directories in which they reside and in the code itself. No external -contributions are allowed under licenses which are fundamentally incompatible -with the AFL-2.1 OR and BSD-3-Clause licenses that Dojo is distributed under. - -The text of the AFL-2.1 and BSD-3-Clause licenses is reproduced below. - -------------------------------------------------------------------------------- -BSD 3-Clause "New" License: -********************** - -Copyright (c) 2005-2015, The Dojo Foundation -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the Dojo Foundation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------------------- -The Academic Free License, v. 2.1: -********************************** - -This Academic Free License (the "License") applies to any original work of -authorship (the "Original Work") whose owner (the "Licensor") has placed the -following notice immediately following the copyright notice for the Original -Work: - -Licensed under the Academic Free License version 2.1 - -1) Grant of Copyright License. Licensor hereby grants You a world-wide, -royalty-free, non-exclusive, perpetual, sublicenseable license to do the -following: - -a) to reproduce the Original Work in copies; - -b) to prepare derivative works ("Derivative Works") based upon the Original -Work; - -c) to distribute copies of the Original Work and Derivative Works to the -public; - -d) to perform the Original Work publicly; and - -e) to display the Original Work publicly. - -2) Grant of Patent License. Licensor hereby grants You a world-wide, -royalty-free, non-exclusive, perpetual, sublicenseable license, under patent -claims owned or controlled by the Licensor that are embodied in the Original -Work as furnished by the Licensor, to make, use, sell and offer for sale the -Original Work and Derivative Works. - -3) Grant of Source Code License. The term "Source Code" means the preferred -form of the Original Work for making modifications to it and all available -documentation describing how to modify the Original Work. Licensor hereby -agrees to provide a machine-readable copy of the Source Code of the Original -Work along with each copy of the Original Work that Licensor distributes. -Licensor reserves the right to satisfy this obligation by placing a -machine-readable copy of the Source Code in an information repository -reasonably calculated to permit inexpensive and convenient access by You for as -long as Licensor continues to distribute the Original Work, and by publishing -the address of that information repository in a notice immediately following -the copyright notice that applies to the Original Work. - -4) Exclusions From License Grant. Neither the names of Licensor, nor the names -of any contributors to the Original Work, nor any of their trademarks or -service marks, may be used to endorse or promote products derived from this -Original Work without express prior written permission of the Licensor. Nothing -in this License shall be deemed to grant any rights to trademarks, copyrights, -patents, trade secrets or any other intellectual property of Licensor except as -expressly stated herein. No patent license is granted to make, use, sell or -offer to sell embodiments of any patent claims other than the licensed claims -defined in Section 2. No right is granted to the trademarks of Licensor even if -such marks are included in the Original Work. Nothing in this License shall be -interpreted to prohibit Licensor from licensing under different terms from this -License any Original Work that Licensor otherwise would have a right to -license. - -5) This section intentionally omitted. - -6) Attribution Rights. You must retain, in the Source Code of any Derivative -Works that You create, all copyright, patent or trademark notices from the -Source Code of the Original Work, as well as any notices of licensing and any -descriptive text identified therein as an "Attribution Notice." You must cause -the Source Code for any Derivative Works that You create to carry a prominent -Attribution Notice reasonably calculated to inform recipients that You have -modified the Original Work. - -7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that -the copyright in and to the Original Work and the patent rights granted herein -by Licensor are owned by the Licensor or are sublicensed to You under the terms -of this License with the permission of the contributor(s) of those copyrights -and patent rights. Except as expressly stated in the immediately proceeding -sentence, the Original Work is provided under this License on an "AS IS" BASIS -and WITHOUT WARRANTY, either express or implied, including, without limitation, -the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. -This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No -license to Original Work is granted hereunder except under this disclaimer. - -8) Limitation of Liability. Under no circumstances and under no legal theory, -whether in tort (including negligence), contract, or otherwise, shall the -Licensor be liable to any person for any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License -or the use of the Original Work including, without limitation, damages for loss -of goodwill, work stoppage, computer failure or malfunction, or any and all -other commercial damages or losses. This limitation of liability shall not -apply to liability for death or personal injury resulting from Licensor's -negligence to the extent applicable law prohibits such limitation. Some -jurisdictions do not allow the exclusion or limitation of incidental or -consequential damages, so this exclusion and limitation may not apply to You. - -9) Acceptance and Termination. If You distribute copies of the Original Work or -a Derivative Work, You must make a reasonable effort under the circumstances to -obtain the express assent of recipients to the terms of this License. Nothing -else but this License (or another written agreement between Licensor and You) -grants You permission to create Derivative Works based upon the Original Work -or to exercise any of the rights granted in Section 1 herein, and any attempt -to do so except under the terms of this License (or another written agreement -between Licensor and You) is expressly prohibited by U.S. copyright law, the -equivalent laws of other countries, and by international treaty. Therefore, by -exercising any of the rights granted to You in Section 1 herein, You indicate -Your acceptance of this License and all of its terms and conditions. - -10) Termination for Patent Action. This License shall terminate automatically -and You may no longer exercise any of the rights granted to You by this License -as of the date You commence an action, including a cross-claim or counterclaim, -against Licensor or any licensee alleging that the Original Work infringes a -patent. This termination provision shall not apply for an action alleging -patent infringement by combinations of the Original Work with other software or -hardware. - -11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this -License may be brought only in the courts of a jurisdiction wherein the -Licensor resides or in which Licensor conducts its primary business, and under -the laws of that jurisdiction excluding its conflict-of-law provisions. The -application of the United Nations Convention on Contracts for the International -Sale of Goods is expressly excluded. Any use of the Original Work outside the -scope of this License or after its termination shall be subject to the -requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et -seq., the equivalent laws of other countries, and international treaty. This -section shall survive the termination of this License. +eventsource@3.0.7 +License: MIT +Author: Espen Hovlandsdal +Homepage: https://github.com/EventSource/eventsource#readme -12) Attorneys Fees. In any action to enforce the terms of this License or -seeking damages relating thereto, the prevailing party shall be entitled to -recover its costs and expenses, including, without limitation, reasonable -attorneys' fees and costs incurred in connection with such action, including -any appeal of such action. This section shall survive the termination of this -License. +The MIT License -13) Miscellaneous. This License represents the complete agreement concerning -the subject matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent necessary to -make it enforceable. +Copyright (c) EventSource GitHub organisation -14) Definition of "You" in This License. "You" throughout this License, whether -in upper or lower case, means an individual or a legal entity exercising rights -under, and complying with all of the terms of, this License. For legal -entities, "You" includes any entity that controls, is controlled by, or is -under common control with you. For purposes of this definition, "control" means -(i) the power, direct or indirect, to cause the direction or management of such -entity, whether by contract or otherwise, or (ii) ownership of fifty percent -(50%) or more of the outstanding shares, or (iii) beneficial ownership of such -entity. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -15) Right to Use. You may use the Original Work in all ways not otherwise -restricted or conditioned by this License or by law, and Licensor promises not -to interfere with or be responsible for such uses by You. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. -Permission is hereby granted to copy and distribute this license without -modification. This license may not be modified without the express written -permission of its copyright owner. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -json-schema-traverse@0.4.1 +eventsource-parser@3.1.0 License: MIT -Author: Evgeny Poberezkin -Homepage: https://github.com/epoberezkin/json-schema-traverse#readme +Author: Espen Hovlandsdal +Homepage: https://github.com/rexxars/eventsource-parser#readme MIT License -Copyright (c) 2017 Evgeny Poberezkin +Copyright (c) 2026 Espen Hovlandsdal Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4215,127 +3844,159 @@ SOFTWARE. -------------------------------------------------------------------------------- -json-schema-typed@8.0.2 -License: BSD-2-Clause -Author: Remy Rylan -Homepage: https://github.com/RemyRylan/json-schema-typed/tree/main/dist/node +express@5.2.1 +License: MIT +Author: TJ Holowaychuk +Homepage: https://expressjs.com/ -BSD 2-Clause License +(The MIT License) -Original source code is copyright (c) 2019-2025 Remy Rylan - +Copyright (c) 2009-2014 TJ Holowaychuk +Copyright (c) 2013-2014 Roman Shtylman +Copyright (c) 2014-2015 Douglas Christopher Wilson -All JSON Schema documentation and descriptions are copyright (c): +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -2009 [draft-0] IETF Trust , Kris Zyp , -and SitePen (USA) . +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -2009 [draft-1] IETF Trust , Kris Zyp , -and SitePen (USA) . +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -2010 [draft-2] IETF Trust , Kris Zyp , -and SitePen (USA) . +-------------------------------------------------------------------------------- -2010 [draft-3] IETF Trust , Kris Zyp , -Gary Court , and SitePen (USA) . +express-rate-limit@8.7.0 +License: MIT +Author: Nathan Friedly +Homepage: https://github.com/express-rate-limit/express-rate-limit -2013 [draft-4] IETF Trust ), Francis Galiegue -, Kris Zyp , Gary Court -, and SitePen (USA) . +MIT License -2018 [draft-7] IETF Trust , Austin Wright , -Henry Andrews , Geraint Luff , and -Cloudflare, Inc. . +Copyright 2023 Nathan Friedly, Vedant K -2019 [draft-2019-09] IETF Trust , Austin Wright -, Henry Andrews , Ben Hutton -, and Greg Dennis . +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -2020 [draft-2020-12] IETF Trust , Austin Wright -, Henry Andrews , Ben Hutton -, and Greg Dennis . +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -All rights reserved. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +-------------------------------------------------------------------------------- -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +fast-deep-equal@3.1.3 +License: MIT +Author: Evgeny Poberezkin +Homepage: https://github.com/epoberezkin/fast-deep-equal#readme -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +MIT License -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright (c) 2017 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -json-stringify-safe@5.0.1 -License: ISC -Author: Isaac Z. Schlueter (http://blog.izs.me) -Homepage: https://github.com/isaacs/json-stringify-safe +fast-json-stable-stringify@2.1.0 +License: MIT +Author: James Halliday +Homepage: https://github.com/epoberezkin/fast-json-stable-stringify -The ISC License +This software is released under the MIT license: -Copyright (c) Isaac Z. Schlueter and Contributors +Copyright (c) 2017 Evgeny Poberezkin +Copyright (c) 2013 James Halliday -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -linkify-it@5.0.1 +finalhandler@2.1.1 License: MIT -Homepage: markdown-it/linkify-it +Author: Douglas Christopher Wilson +Homepage: pillarjs/finalhandler -Copyright (c) 2015 Vitaly Puzrin. +(The MIT License) -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) 2014-2022 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -long@5.3.2 +flatbuffers@25.9.23 License: Apache-2.0 -Author: Daniel Wirtz -Homepage: https://github.com/dcodeIO/long.js.git +Author: The FlatBuffers project +Homepage: https://google.github.io/flatbuffers/ Apache License Version 2.0, January 2004 @@ -4541,118 +4202,99 @@ Apache License -------------------------------------------------------------------------------- -markdown-it@14.2.0 +forwarded@0.2.0 License: MIT -Homepage: markdown-it/markdown-it +Homepage: jshttp/forwarded -Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. +(The MIT License) -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -matcher@3.0.0 -License: MIT -Author: Sindre Sorhus -Homepage: sindresorhus/matcher - -MIT License +frac@1.1.2 +License: Apache-2.0 +Author: SheetJS +Homepage: http://sheetjs.com/opensource -Copyright (c) Sindre Sorhus (https://sindresorhus.com) +Copyright (C) 2012-present SheetJS -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -------------------------------------------------------------------------------- -math-intrinsics@1.1.0 +fresh@2.0.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/es-shims/math-intrinsics#readme - -MIT License +Author: TJ Holowaychuk (http://tjholowaychuk.com) +Homepage: jshttp/fresh -Copyright (c) 2024 ECMAScript Shims +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2016-2017 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -mdurl@2.0.0 +function-bind@1.1.2 License: MIT -Homepage: markdown-it/mdurl - -Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- +Author: Raynos +Homepage: https://github.com/Raynos/function-bind -.parse() is based on Joyent's node.js `url` code: +Copyright (c) 2013 Raynos. -Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -4662,127 +4304,110 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -media-typer@1.1.1 -License: MIT -Author: Douglas Christopher Wilson -Homepage: jshttp/media-typer - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -merge-descriptors@2.0.0 +get-intrinsic@1.3.0 License: MIT -Homepage: sindresorhus/merge-descriptors +Author: Jordan Harband +Homepage: https://github.com/ljharb/get-intrinsic#readme MIT License -Copyright (c) Jonathan Ong -Copyright (c) Douglas Christopher Wilson -Copyright (c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) 2020 Jordan Harband -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -mime-db@1.52.0 +get-proto@1.0.1 License: MIT -Homepage: jshttp/mime-db +Author: Jordan Harband +Homepage: https://github.com/ljharb/get-proto#readme -(The MIT License) +MIT License -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015-2022 Douglas Christopher Wilson +Copyright (c) 2025 Jordan Harband -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -mime-types@2.1.35 -License: MIT -Homepage: jshttp/mime-types - -(The MIT License) - -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson +global-agent@3.0.0 +License: BSD-3-Clause +Author: Gajus Kuizinas +Homepage: https://github.com/gajus/global-agent -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) 2019, Gajus Kuizinas (http://gajus.com/) +All rights reserved. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- -ms@2.1.3 +globalthis@1.0.4 License: MIT -Homepage: vercel/ms +Author: Jordan Harband +Homepage: git://github.com/ljharb/System.global.git The MIT License (MIT) -Copyright (c) 2020 Vercel, Inc. +Copyright (c) 2016 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4804,43 +4429,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -negotiator@1.1.0 +gopd@1.2.0 License: MIT -Homepage: jshttp/negotiator - -(The MIT License) - -Copyright (c) 2012-2014 Federico Romero -Copyright (c) 2012-2014 Isaac Z. Schlueter -Copyright (c) 2014-2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- +Author: Jordan Harband +Homepage: https://github.com/ljharb/gopd#readme -node-pty@1.1.0 -License: MIT -Author: Microsoft Corporation -Homepage: https://github.com/microsoft/node-pty +MIT License -Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/) +Copyright (c) 2022 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4849,22 +4445,243 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +-------------------------------------------------------------------------------- -The MIT License (MIT) +groq-sdk@1.3.0 +License: Apache-2.0 +Author: Groq +Homepage: github:groq/groq-typescript -Copyright (c) 2016, Daniel Imms (http://www.growingwiththeweb.com) +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Groq + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +guid-typescript@1.0.9 +License: ISC +Author: nicolas +Homepage: https://github.com/NicolasDeveloper/guid-typescript + +-------------------------------------------------------------------------------- + +has-property-descriptors@1.0.2 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/inspect-js/has-property-descriptors#readme + +MIT License + +Copyright (c) 2022 Inspect JS Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4884,13 +4701,16 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +has-symbols@1.1.0 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/ljharb/has-symbols#readme MIT License -Copyright (c) 2018 - present Microsoft Corporation - -All rights reserved. +Copyright (c) 2016 Jordan Harband Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4912,14 +4732,14 @@ SOFTWARE. -------------------------------------------------------------------------------- -object-assign@4.1.1 +hasown@2.0.4 License: MIT -Author: Sindre Sorhus -Homepage: sindresorhus/object-assign +Author: Jordan Harband +Homepage: https://github.com/inspect-js/hasOwn#readme -The MIT License (MIT) +MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) Jordan Harband and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4928,27 +4748,64 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -object-inspect@1.13.4 +highlight.js@11.11.1 +License: BSD-3-Clause +Author: Josh Goebel +Homepage: https://highlightjs.org/ + +BSD 3-Clause License + +Copyright (c) 2006, Ivan Sagalaev. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +hono@4.13.7 License: MIT -Author: James Halliday -Homepage: https://github.com/inspect-js/object-inspect +Author: Yusuke Wada (https://github.com/yusukebe) +Homepage: https://hono.dev MIT License -Copyright (c) 2013 James Halliday +Copyright (c) 2021 - present, Yusuke Wada and Hono contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4970,14 +4827,15 @@ SOFTWARE. -------------------------------------------------------------------------------- -object-keys@1.1.1 +http-errors@2.0.1 License: MIT -Author: Jordan Harband -Homepage: git://github.com/ljharb/object-keys.git +Author: Jonathan Ong (http://jongleberry.com) +Homepage: jshttp/http-errors The MIT License (MIT) -Copyright (C) 2013 Jordan Harband +Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -4999,18 +4857,16 @@ THE SOFTWARE. -------------------------------------------------------------------------------- -on-finished@2.4.1 +iconv-lite@0.6.3 License: MIT -Homepage: jshttp/on-finished - -(The MIT License) +Author: Alexander Shtuchkin +Homepage: https://github.com/ashtuchkin/iconv-lite -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2014 Douglas Christopher Wilson +Copyright (c) 2011 Alexander Shtuchkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -5019,72 +4875,25 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -once@1.4.0 -License: ISC -Author: Isaac Z. Schlueter (http://blog.izs.me/) -Homepage: git://github.com/isaacs/once - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --------------------------------------------------------------------------------- - -onnxruntime-common@1.27.0 -License: MIT -Author: fs-eire -Homepage: https://github.com/Microsoft/onnxruntime.git - --------------------------------------------------------------------------------- - -onnxruntime-node@1.27.0 -License: MIT -Author: fs-eire -Homepage: https://github.com/Microsoft/onnxruntime.git - --------------------------------------------------------------------------------- - -onnxruntime-web@1.27.0 -License: MIT -Author: fs-eire -Homepage: https://github.com/Microsoft/onnxruntime.git +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -parseurl@1.3.3 +immediate@3.0.6 License: MIT -Homepage: pillarjs/parseurl - -(The MIT License) +Homepage: git://github.com/calvinmetcalf/immediate.git -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, Domenic Denicola, Brian Cavalier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -5093,40 +4902,44 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -path-key@3.1.1 -License: MIT -Author: Sindre Sorhus -Homepage: sindresorhus/path-key - -MIT License +inherits@2.0.4 +License: ISC +Homepage: git://github.com/isaacs/inherits -Copyright (c) Sindre Sorhus (sindresorhus.com) +The ISC License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) Isaac Z. Schlueter -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- -path-to-regexp@8.4.2 +ip-address@10.7.0 License: MIT -Homepage: https://github.com/pillarjs/path-to-regexp.git - -The MIT License (MIT) +Author: Beau Gunderson (https://beaugunderson.com/) +Homepage: https://github.com/beaugunderson/ip-address.git -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) +Copyright (C) 2011 by Beau Gunderson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5148,45 +4961,39 @@ THE SOFTWARE. -------------------------------------------------------------------------------- -pend@1.2.0 +ipaddr.js@1.9.1 License: MIT -Author: Andrew Kelley -Homepage: git://github.com/andrewrk/node-pend.git - -The MIT License (Expat) +Author: whitequark +Homepage: git://github.com/whitequark/ipaddr.js -Copyright (c) 2014 Andrew Kelley +Copyright (C) 2011-2017 whitequark -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation files -(the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -pkce-challenge@5.0.1 +is-promise@4.0.0 License: MIT -Author: crouchcd -Homepage: https://github.com/crouchcd/pkce-challenge#readme - -MIT License +Author: ForbesLindesay +Homepage: https://github.com/then/is-promise.git -Copyright (c) 2019 +Copyright (c) 2014 Forbes Lindesay Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5195,166 +5002,117 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------------------- -platform@1.3.6 +isarray@1.0.0 License: MIT -Author: Benjamin Tan -Homepage: bestiejs/platform.js +Author: Julian Gruber +Homepage: https://github.com/juliangruber/isarray -Copyright 2014-2020 Benjamin Tan -Copyright 2011-2013 John-David Dalton +-------------------------------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +isexe@2.0.0 +License: ISC +Author: Isaac Z. Schlueter (http://blog.izs.me/) +Homepage: https://github.com/isaacs/isexe#readme -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The ISC License -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - --------------------------------------------------------------------------------- - -protobufjs@7.6.5 -License: BSD-3-Clause -Author: Daniel Wirtz -Homepage: https://protobufjs.github.io/protobuf.js/ - -This license applies to all parts of protobuf.js except those files -either explicitly including or referencing a different license or -located in a directory containing a different LICENSE file. - ---- - -Copyright (c) 2016, Daniel Wirtz All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -* Neither the name of its author, nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Copyright (c) Isaac Z. Schlueter and Contributors ---- +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Code generated by the command line utilities is owned by the owner -of the input file used when generating it. This code is not -standalone and requires a support library to be linked with it. This -support library is itself covered by the above license. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- -proxy-addr@2.0.7 +jose@6.2.12 License: MIT -Author: Douglas Christopher Wilson -Homepage: jshttp/proxy-addr - -(The MIT License) - -Copyright (c) 2014-2016 Douglas Christopher Wilson +Author: Filip Skokan +Homepage: https://github.com/panva/jose -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +The MIT License (MIT) -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) 2018 Filip Skokan -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: --------------------------------------------------------------------------------- +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -punycode@2.3.1 -License: MIT -Author: Mathias Bynens -Homepage: https://mths.be/punycode +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -punycode.js@2.3.1 -License: MIT -Author: Mathias Bynens -Homepage: https://mths.be/punycode +json-schema@0.4.0 +License: (AFL-2.1 OR BSD-3-Clause) +Author: Kris Zyp +Homepage: http://github.com/kriszyp/json-schema --------------------------------------------------------------------------------- +Dojo is available under *either* the terms of the BSD 3-Clause "New" License *or* the +Academic Free License version 2.1. As a recipient of Dojo, you may choose which +license to receive this code under (except as noted in per-module LICENSE +files). Some modules may not be the copyright of the Dojo Foundation. These +modules contain explicit declarations of copyright in both the LICENSE files in +the directories in which they reside and in the code itself. No external +contributions are allowed under licenses which are fundamentally incompatible +with the AFL-2.1 OR and BSD-3-Clause licenses that Dojo is distributed under. -qs@6.16.0 -License: BSD-3-Clause -Homepage: https://github.com/ljharb/qs +The text of the AFL-2.1 and BSD-3-Clause licenses is reproduced below. -BSD 3-Clause License +------------------------------------------------------------------------------- +BSD 3-Clause "New" License: +********************** -Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors) +Copyright (c) 2005-2015, The Dojo Foundation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER @@ -5362,140 +5120,171 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +The Academic Free License, v. 2.1: +********************************** -range-parser@1.3.0 -License: MIT -Author: TJ Holowaychuk (http://tjholowaychuk.com) -Homepage: jshttp/range-parser +This Academic Free License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following notice immediately following the copyright notice for the Original +Work: -(The MIT License) +Licensed under the Academic Free License version 2.1 -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson (http://jongleberry.com) -Homepage: stream-utils/raw-body +e) to display the Original Work publicly. -The MIT License (MIT) +2) Grant of Patent License. Licensor hereby grants You a world-wide, +royalty-free, non-exclusive, perpetual, sublicenseable license, under patent +claims owned or controlled by the Licensor that are embodied in the Original +Work as furnished by the Licensor, to make, use, sell and offer for sale the +Original Work and Derivative Works. -Copyright (c) 2013-2014 Jonathan Ong -Copyright (c) 2014-2022 Douglas Christopher Wilson +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor hereby +agrees to provide a machine-readable copy of the Source Code of the Original +Work along with each copy of the Original Work that Licensor distributes. +Licensor reserves the right to satisfy this obligation by placing a +machine-readable copy of the Source Code in an information repository +reasonably calculated to permit inexpensive and convenient access by You for as +long as Licensor continues to distribute the Original Work, and by publishing +the address of that information repository in a notice immediately following +the copyright notice that applies to the Original Work. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior written permission of the Licensor. Nothing +in this License shall be deemed to grant any rights to trademarks, copyrights, +patents, trade secrets or any other intellectual property of Licensor except as +expressly stated herein. No patent license is granted to make, use, sell or +offer to sell embodiments of any patent claims other than the licensed claims +defined in Section 2. No right is granted to the trademarks of Licensor even if +such marks are included in the Original Work. Nothing in this License shall be +interpreted to prohibit Licensor from licensing under different terms from this +License any Original Work that Licensor otherwise would have a right to +license. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +5) This section intentionally omitted. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - --------------------------------------------------------------------------------- - -roarr@2.15.4 -License: BSD-3-Clause -Author: Gajus Kuizinas -Homepage: git@github.com:gajus/roarr.git +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. -Copyright (c) 2019, Gajus Kuizinas (http://gajus.com/) -All rights reserved. +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the terms +of this License with the permission of the contributor(s) of those copyrights +and patent rights. Except as expressly stated in the immediately proceeding +sentence, the Original Work is provided under this License on an "AS IS" BASIS +and WITHOUT WARRANTY, either express or implied, including, without limitation, +the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. +This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No +license to Original Work is granted hereunder except under this disclaimer. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to any person for any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License +or the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to liability for death or personal injury resulting from Licensor's +negligence to the extent applicable law prohibits such limitation. Some +jurisdictions do not allow the exclusion or limitation of incidental or +consequential damages, so this exclusion and limitation may not apply to You. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +9) Acceptance and Termination. If You distribute copies of the Original Work or +a Derivative Work, You must make a reasonable effort under the circumstances to +obtain the express assent of recipients to the terms of this License. Nothing +else but this License (or another written agreement between Licensor and You) +grants You permission to create Derivative Works based upon the Original Work +or to exercise any of the rights granted in Section 1 herein, and any attempt +to do so except under the terms of this License (or another written agreement +between Licensor and You) is expressly prohibited by U.S. copyright law, the +equivalent laws of other countries, and by international treaty. Therefore, by +exercising any of the rights granted to You in Section 1 herein, You indicate +Your acceptance of this License and all of its terms and conditions. --------------------------------------------------------------------------------- +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this License +as of the date You commence an action, including a cross-claim or counterclaim, +against Licensor or any licensee alleging that the Original Work infringes a +patent. This termination provision shall not apply for an action alleging +patent infringement by combinations of the Original Work with other software or +hardware. -router@2.2.0 -License: MIT -Author: Douglas Christopher Wilson -Homepage: pillarjs/router +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the International +Sale of Goods is expressly excluded. Any use of the Original Work outside the +scope of this License or after its termination shall be subject to the +requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et +seq., the equivalent laws of other countries, and international treaty. This +section shall survive the termination of this License. -(The MIT License) +12) Attorneys Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. -Copyright (c) 2013 Roman Shtylman -Copyright (c) 2014-2022 Douglas Christopher Wilson +13) Miscellaneous. This License represents the complete agreement concerning +the subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to +make it enforceable. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +14) Definition of "You" in This License. "You" throughout this License, whether +in upper or lower case, means an individual or a legal entity exercising rights +under, and complying with all of the terms of, this License. For legal +entities, "You" includes any entity that controls, is controlled by, or is +under common control with you. For purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management of such +entity, whether by contract or otherwise, or (ii) ownership of fifty percent +(50%) or more of the outstanding shares, or (iii) beneficial ownership of such +entity. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. +Permission is hereby granted to copy and distribute this license without +modification. This license may not be modified without the express written +permission of its copyright owner. -------------------------------------------------------------------------------- -safer-buffer@2.1.2 +json-schema-traverse@0.4.1 License: MIT -Author: Nikita Skovoroda -Homepage: https://github.com/ChALkeR/safer-buffer.git +Author: Evgeny Poberezkin +Homepage: https://github.com/epoberezkin/json-schema-traverse#readme MIT License -Copyright (c) 2018 Nikita Skovoroda +Copyright (c) 2017 Evgeny Poberezkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5517,10 +5306,75 @@ SOFTWARE. -------------------------------------------------------------------------------- -semver@6.3.1 +json-schema-typed@8.0.2 +License: BSD-2-Clause +Author: Remy Rylan +Homepage: https://github.com/RemyRylan/json-schema-typed/tree/main/dist/node + +BSD 2-Clause License + +Original source code is copyright (c) 2019-2025 Remy Rylan + + +All JSON Schema documentation and descriptions are copyright (c): + +2009 [draft-0] IETF Trust , Kris Zyp , +and SitePen (USA) . + +2009 [draft-1] IETF Trust , Kris Zyp , +and SitePen (USA) . + +2010 [draft-2] IETF Trust , Kris Zyp , +and SitePen (USA) . + +2010 [draft-3] IETF Trust , Kris Zyp , +Gary Court , and SitePen (USA) . + +2013 [draft-4] IETF Trust ), Francis Galiegue +, Kris Zyp , Gary Court +, and SitePen (USA) . + +2018 [draft-7] IETF Trust , Austin Wright , +Henry Andrews , Geraint Luff , and +Cloudflare, Inc. . + +2019 [draft-2019-09] IETF Trust , Austin Wright +, Henry Andrews , Ben Hutton +, and Greg Dennis . + +2020 [draft-2020-12] IETF Trust , Austin Wright +, Henry Andrews , Ben Hutton +, and Greg Dennis . + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +json-stringify-safe@5.0.1 License: ISC -Author: GitHub Inc. -Homepage: https://github.com/npm/node-semver.git +Author: Isaac Z. Schlueter (http://blog.izs.me) +Homepage: https://github.com/isaacs/json-stringify-safe The ISC License @@ -5540,316 +5394,248 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- -semver-compare@1.0.0 +jszip@3.10.2 +License: (MIT OR GPL-3.0-or-later) +Author: Stuart Knightley +Homepage: https://github.com/Stuk/jszip.git + +-------------------------------------------------------------------------------- + +lie@3.3.0 License: MIT -Author: James Halliday -Homepage: https://github.com/substack/semver-compare +Homepage: https://github.com/calvinmetcalf/lie.git -This software is released under the MIT license: +#Copyright (c) 2014-2018 Calvin Metcalf, Jordan Harband -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.** -------------------------------------------------------------------------------- -send@1.2.1 +linkify-it@5.0.1 License: MIT -Author: TJ Holowaychuk -Homepage: pillarjs/send - -(The MIT License) +Homepage: markdown-it/linkify-it -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2014-2022 Douglas Christopher Wilson +Copyright (c) 2015 Vitaly Puzrin. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -serialize-error@7.0.1 -License: MIT -Author: Sindre Sorhus -Homepage: sindresorhus/serialize-error +long@5.3.2 +License: Apache-2.0 +Author: Daniel Wirtz +Homepage: https://github.com/dcodeIO/long.js.git -MIT License +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) Sindre Sorhus (https://sindresorhus.com) + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + 1. Definitions. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. --------------------------------------------------------------------------------- + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -serve-static@2.2.1 -License: MIT -Author: Douglas Christopher Wilson -Homepage: expressjs/serve-static + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -(The MIT License) + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Copyright (c) 2010 Sencha Inc. -Copyright (c) 2011 LearnBoost -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2014-2016 Douglas Christopher Wilson + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." --------------------------------------------------------------------------------- + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -setprototypeof@1.2.0 -License: ISC -Author: Wes Todd -Homepage: https://github.com/wesleytodd/setprototypeof + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Copyright (c) 2015, Wes Todd + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and --------------------------------------------------------------------------------- + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -sharp@0.34.5 -License: Apache-2.0 -Author: Lovell Fuller -Homepage: https://sharp.pixelplumbing.com + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -1. Definitions. + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. + END OF TERMS AND CONDITIONS -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work + APPENDIX: How to apply the Apache License to your work. -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "[]" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. Copyright [yyyy] [name of copyright owner] @@ -5857,7 +5643,7 @@ third-party archives. you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -5867,31 +5653,43 @@ third-party archives. -------------------------------------------------------------------------------- -shebang-command@2.0.0 +markdown-it@14.2.0 License: MIT -Author: Kevin Mårtensson -Homepage: kevva/shebang-command - -MIT License +Homepage: markdown-it/markdown-it -Copyright (c) Kevin Mårtensson (github.com/kevva) +Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- -shebang-regex@3.0.0 +matcher@3.0.0 License: MIT Author: Sindre Sorhus -Homepage: sindresorhus/shebang-regex +Homepage: sindresorhus/matcher MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) Sindre Sorhus (https://sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -5901,14 +5699,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI -------------------------------------------------------------------------------- -side-channel@1.1.1 +math-intrinsics@1.1.0 License: MIT Author: Jordan Harband -Homepage: https://github.com/ljharb/side-channel#readme +Homepage: https://github.com/es-shims/math-intrinsics#readme MIT License -Copyright (c) 2019 Jordan Harband +Copyright (c) 2024 ECMAScript Shims Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5930,43 +5728,173 @@ SOFTWARE. -------------------------------------------------------------------------------- -side-channel-list@1.0.1 +mdurl@2.0.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/side-channel-list#readme +Homepage: markdown-it/mdurl -MIT License +Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. -Copyright (c) 2024 Jordan Harband +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +.parse() is based on Joyent's node.js `url` code: +Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. -------------------------------------------------------------------------------- -side-channel-map@1.0.1 +media-typer@1.1.1 License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/side-channel-map#readme +Author: Douglas Christopher Wilson +Homepage: jshttp/media-typer + +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +merge-descriptors@2.0.0 +License: MIT +Homepage: sindresorhus/merge-descriptors MIT License -Copyright (c) 2024 Jordan Harband +Copyright (c) Jonathan Ong +Copyright (c) Douglas Christopher Wilson +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +mime-db@1.52.0 +License: MIT +Homepage: jshttp/mime-db + +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015-2022 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +mime-types@2.1.35 +License: MIT +Homepage: jshttp/mime-types + +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +ms@2.1.3 +License: MIT +Homepage: vercel/ms + +The MIT License (MIT) + +Copyright (c) 2020 Vercel, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -5988,14 +5916,67 @@ SOFTWARE. -------------------------------------------------------------------------------- -side-channel-weakmap@1.0.2 +negotiator@1.1.0 License: MIT -Author: Jordan Harband -Homepage: https://github.com/ljharb/side-channel-weakmap#readme +Homepage: jshttp/negotiator -MIT License +(The MIT License) -Copyright (c) 2019 Jordan Harband +Copyright (c) 2012-2014 Federico Romero +Copyright (c) 2012-2014 Isaac Z. Schlueter +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +node-pty@1.1.0 +License: MIT +Author: Microsoft Corporation +Homepage: https://github.com/microsoft/node-pty + +Copyright (c) 2012-2015, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + +The MIT License (MIT) + +Copyright (c) 2016, Daniel Imms (http://www.growingwiththeweb.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -6015,55 +5996,42 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -simple-git@3.36.0 -License: MIT -Author: Steve King -Homepage: https://github.com/steveukx/git-js.git --------------------------------------------------------------------------------- +MIT License -sprintf-js@1.1.3 -License: BSD-3-Clause -Author: Alexandru Mărășteanu -Homepage: https://github.com/alexei/sprintf.js.git +Copyright (c) 2018 - present Microsoft Corporation -Copyright (c) 2007-present, Alexandru Mărășteanu All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -* Neither the name of this software nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------------------- -statuses@2.0.2 +object-assign@4.1.1 License: MIT -Homepage: jshttp/statuses +Author: Sindre Sorhus +Homepage: sindresorhus/object-assign The MIT License (MIT) -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) Sindre Sorhus (sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -6085,14 +6053,14 @@ THE SOFTWARE. -------------------------------------------------------------------------------- -toidentifier@1.0.1 +object-inspect@1.13.4 License: MIT -Author: Douglas Christopher Wilson -Homepage: component/toidentifier +Author: James Halliday +Homepage: https://github.com/inspect-js/object-inspect MIT License -Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2013 James Halliday Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -6114,246 +6082,2477 @@ SOFTWARE. -------------------------------------------------------------------------------- -type-fest@0.13.1 -License: (MIT OR CC0-1.0) -Author: Sindre Sorhus -Homepage: sindresorhus/type-fest +object-keys@1.1.1 +License: MIT +Author: Jordan Harband +Homepage: git://github.com/ljharb/object-keys.git + +The MIT License (MIT) + +Copyright (C) 2013 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +on-finished@2.4.1 +License: MIT +Homepage: jshttp/on-finished + +(The MIT License) + +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2014 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +once@1.4.0 +License: ISC +Author: Isaac Z. Schlueter (http://blog.izs.me/) +Homepage: git://github.com/isaacs/once + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-------------------------------------------------------------------------------- + +onnxruntime-common@1.27.0 +License: MIT +Author: fs-eire +Homepage: https://github.com/Microsoft/onnxruntime.git + +-------------------------------------------------------------------------------- + +onnxruntime-node@1.27.0 +License: MIT +Author: fs-eire +Homepage: https://github.com/Microsoft/onnxruntime.git + +-------------------------------------------------------------------------------- + +onnxruntime-web@1.27.0 +License: MIT +Author: fs-eire +Homepage: https://github.com/Microsoft/onnxruntime.git + +-------------------------------------------------------------------------------- + +pako@2.0.3 +License: (MIT AND Zlib) +Homepage: nodeca/pako + +(The MIT License) + +Copyright (C) 2014-2017 by Vitaly Puzrin and Andrei Tuputcyn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +parseurl@1.3.3 +License: MIT +Homepage: pillarjs/parseurl + +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +path-key@3.1.1 +License: MIT +Author: Sindre Sorhus +Homepage: sindresorhus/path-key + +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +path-to-regexp@8.4.2 +License: MIT +Homepage: https://github.com/pillarjs/path-to-regexp.git + +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +pend@1.2.0 +License: MIT +Author: Andrew Kelley +Homepage: git://github.com/andrewrk/node-pend.git + +The MIT License (Expat) + +Copyright (c) 2014 Andrew Kelley + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +pkce-challenge@5.0.1 +License: MIT +Author: crouchcd +Homepage: https://github.com/crouchcd/pkce-challenge#readme + +MIT License + +Copyright (c) 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +platform@1.3.6 +License: MIT +Author: Benjamin Tan +Homepage: bestiejs/platform.js + +Copyright 2014-2020 Benjamin Tan +Copyright 2011-2013 John-David Dalton + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +process-nextick-args@2.0.1 +License: MIT +Homepage: https://github.com/calvinmetcalf/process-nextick-args + +# Copyright (c) 2015 Calvin Metcalf + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.** + +-------------------------------------------------------------------------------- + +protobufjs@7.6.5 +License: BSD-3-Clause +Author: Daniel Wirtz +Homepage: https://protobufjs.github.io/protobuf.js/ + +This license applies to all parts of protobuf.js except those files +either explicitly including or referencing a different license or +located in a directory containing a different LICENSE file. + +--- + +Copyright (c) 2016, Daniel Wirtz All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of its author, nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +Code generated by the command line utilities is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + +-------------------------------------------------------------------------------- + +proxy-addr@2.0.7 +License: MIT +Author: Douglas Christopher Wilson +Homepage: jshttp/proxy-addr + +(The MIT License) + +Copyright (c) 2014-2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +punycode@2.3.1 +License: MIT +Author: Mathias Bynens +Homepage: https://mths.be/punycode + +-------------------------------------------------------------------------------- + +punycode.js@2.3.1 +License: MIT +Author: Mathias Bynens +Homepage: https://mths.be/punycode + +-------------------------------------------------------------------------------- + +qs@6.16.0 +License: BSD-3-Clause +Homepage: https://github.com/ljharb/qs + +BSD 3-Clause License + +Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +range-parser@1.3.0 +License: MIT +Author: TJ Holowaychuk (http://tjholowaychuk.com) +Homepage: jshttp/range-parser + +(The MIT License) + +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson (http://jongleberry.com) +Homepage: stream-utils/raw-body + +The MIT License (MIT) + +Copyright (c) 2013-2014 Jonathan Ong +Copyright (c) 2014-2022 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +readable-stream@2.3.8 +License: MIT +Homepage: git://github.com/nodejs/readable-stream + +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +-------------------------------------------------------------------------------- + +roarr@2.15.4 +License: BSD-3-Clause +Author: Gajus Kuizinas +Homepage: git@github.com:gajus/roarr.git + +Copyright (c) 2019, Gajus Kuizinas (http://gajus.com/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Gajus Kuizinas (http://gajus.com/) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL ANUARY BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +router@2.2.0 +License: MIT +Author: Douglas Christopher Wilson +Homepage: pillarjs/router + +(The MIT License) + +Copyright (c) 2013 Roman Shtylman +Copyright (c) 2014-2022 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +safe-buffer@5.1.2 +License: MIT +Author: Feross Aboukhadijeh +Homepage: https://github.com/feross/safe-buffer + +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +safer-buffer@2.1.2 +License: MIT +Author: Nikita Skovoroda +Homepage: https://github.com/ChALkeR/safer-buffer.git + +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +semver@6.3.1 +License: ISC +Author: GitHub Inc. +Homepage: https://github.com/npm/node-semver.git + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-------------------------------------------------------------------------------- + +semver-compare@1.0.0 +License: MIT +Author: James Halliday +Homepage: https://github.com/substack/semver-compare + +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +send@1.2.1 +License: MIT +Author: TJ Holowaychuk +Homepage: pillarjs/send + +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2014-2022 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +serialize-error@7.0.1 +License: MIT +Author: Sindre Sorhus +Homepage: sindresorhus/serialize-error + +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +serve-static@2.2.1 +License: MIT +Author: Douglas Christopher Wilson +Homepage: expressjs/serve-static + +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +setimmediate@1.0.5 +License: MIT +Author: YuzuJS +Homepage: YuzuJS/setImmediate + +Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +setprototypeof@1.2.0 +License: ISC +Author: Wes Todd +Homepage: https://github.com/wesleytodd/setprototypeof + +Copyright (c) 2015, Wes Todd + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-------------------------------------------------------------------------------- + +sharp@0.34.5 +License: Apache-2.0 +Author: Lovell Fuller +Homepage: https://sharp.pixelplumbing.com + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +shebang-command@2.0.0 +License: MIT +Author: Kevin Mårtensson +Homepage: kevva/shebang-command + +MIT License + +Copyright (c) Kevin Mårtensson (github.com/kevva) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +shebang-regex@3.0.0 +License: MIT +Author: Sindre Sorhus +Homepage: sindresorhus/shebang-regex + +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +side-channel@1.1.1 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/ljharb/side-channel#readme + +MIT License + +Copyright (c) 2019 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +side-channel-list@1.0.1 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/ljharb/side-channel-list#readme + +MIT License + +Copyright (c) 2024 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +side-channel-map@1.0.1 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/ljharb/side-channel-map#readme + +MIT License + +Copyright (c) 2024 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +side-channel-weakmap@1.0.2 +License: MIT +Author: Jordan Harband +Homepage: https://github.com/ljharb/side-channel-weakmap#readme + +MIT License + +Copyright (c) 2019 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +simple-git@3.36.0 +License: MIT +Author: Steve King +Homepage: https://github.com/steveukx/git-js.git + +-------------------------------------------------------------------------------- + +sprintf-js@1.1.3 +License: BSD-3-Clause +Author: Alexandru Mărășteanu +Homepage: https://github.com/alexei/sprintf.js.git + +Copyright (c) 2007-present, Alexandru Mărășteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this software nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +ssf@0.11.2 +License: Apache-2.0 +Author: sheetjs +Homepage: http://sheetjs.com/ + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2013-present SheetJS LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +statuses@2.0.2 +License: MIT +Homepage: jshttp/statuses + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +-------------------------------------------------------------------------------- + +string_decoder@1.1.1 +License: MIT +Homepage: https://github.com/nodejs/string_decoder + +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +-------------------------------------------------------------------------------- + +toidentifier@1.0.1 +License: MIT +Author: Douglas Christopher Wilson +Homepage: component/toidentifier + +MIT License + +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +type-fest@0.13.1 +License: (MIT OR CC0-1.0) +Author: Sindre Sorhus +Homepage: sindresorhus/type-fest + +MIT License + +Copyright (c) Sindre Sorhus (https:/sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +type-is@2.1.0 +License: MIT +Homepage: jshttp/type-is + +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +uc.micro@2.1.0 +License: MIT +Homepage: markdown-it/uc.micro + +Copyright Mathias Bynens + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +undici-types@6.21.0 +License: MIT +Homepage: https://undici.nodejs.org + +MIT License + +Copyright (c) Matteo Collina and Undici contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +-------------------------------------------------------------------------------- + +unpipe@1.0.0 +License: MIT +Author: Douglas Christopher Wilson +Homepage: stream-utils/unpipe + +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +uri-js@4.4.1 +License: BSD-2-Clause +Author: Gary Court +Homepage: https://github.com/garycourt/uri-js + +Copyright 2011 Gary Court. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY GARY COURT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Gary Court. + +-------------------------------------------------------------------------------- + +util-deprecate@1.0.2 +License: MIT +Author: Nathan Rajlich (http://n8.io/) +Homepage: https://github.com/TooTallNate/util-deprecate + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +uuid@14.0.1 +License: MIT +Homepage: https://github.com/uuidjs/uuid.git + +The MIT License (MIT) + +Copyright (c) 2010-2020 Robert Kieffer and other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +vary@1.1.2 +License: MIT +Author: Douglas Christopher Wilson +Homepage: jshttp/vary + +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-------------------------------------------------------------------------------- + +which@2.0.2 +License: ISC +Author: Isaac Z. Schlueter (http://blog.izs.me) +Homepage: git://github.com/isaacs/node-which.git + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +-------------------------------------------------------------------------------- + +wmf@1.0.2 +License: Apache-2.0 +Author: sheetjs +Homepage: https://sheetjs.com/ + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2020-present SheetJS LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +word@0.3.0 +License: Apache-2.0 +Author: sheetjs +Homepage: https://wordjs.com/ + +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -MIT License + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -Copyright (c) Sindre Sorhus (https:/sindresorhus.com) + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. --------------------------------------------------------------------------------- + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -type-is@2.1.0 -License: MIT -Homepage: jshttp/type-is + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -(The MIT License) + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and --------------------------------------------------------------------------------- + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -uc.micro@2.1.0 -License: MIT -Homepage: markdown-it/uc.micro + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -Copyright Mathias Bynens + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. --------------------------------------------------------------------------------- + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -undici-types@6.21.0 -License: MIT -Homepage: https://undici.nodejs.org + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -MIT License + END OF TERMS AND CONDITIONS -Copyright (c) Matteo Collina and Undici contributors + APPENDIX: How to apply the Apache License to your work. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + Copyright (C) 2020-present SheetJS LLC -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at --------------------------------------------------------------------------------- + http://www.apache.org/licenses/LICENSE-2.0 -unpipe@1.0.0 -License: MIT -Author: Douglas Christopher Wilson -Homepage: stream-utils/unpipe + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -(The MIT License) +-------------------------------------------------------------------------------- -Copyright (c) 2015 Douglas Christopher Wilson +wrappy@1.0.2 +License: ISC +Author: Isaac Z. Schlueter (http://blog.izs.me/) +Homepage: https://github.com/npm/wrappy -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +The ISC License -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) Isaac Z. Schlueter and Contributors -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- -uri-js@4.4.1 -License: BSD-2-Clause -Author: Gary Court -Homepage: https://github.com/garycourt/uri-js +xlsx@0.18.5 +License: Apache-2.0 +Author: sheetjs +Homepage: https://sheetjs.com/ -Copyright 2011 Gary Court. All rights reserved. +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 1. Definitions. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THIS SOFTWARE IS PROVIDED BY GARY COURT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Gary Court. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. --------------------------------------------------------------------------------- + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. -uuid@14.0.1 -License: MIT -Homepage: https://github.com/uuidjs/uuid.git + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -The MIT License (MIT) + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -Copyright (c) 2010-2020 Robert Kieffer and other contributors + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. --------------------------------------------------------------------------------- + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -vary@1.1.2 -License: MIT -Author: Douglas Christopher Wilson -Homepage: jshttp/vary + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -(The MIT License) + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: -Copyright (c) 2014-2017 Douglas Christopher Wilson + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. --------------------------------------------------------------------------------- + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -which@2.0.2 -License: ISC -Author: Isaac Z. Schlueter (http://blog.izs.me) -Homepage: git://github.com/isaacs/node-which.git + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -The ISC License + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -Copyright (c) Isaac Z. Schlueter and Contributors + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. --------------------------------------------------------------------------------- + END OF TERMS AND CONDITIONS -wrappy@1.0.2 -License: ISC -Author: Isaac Z. Schlueter (http://blog.izs.me/) -Homepage: https://github.com/npm/wrappy + APPENDIX: How to apply the Apache License to your work. -The ISC License + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -Copyright (c) Isaac Z. Schlueter and Contributors + Copyright (C) 2012-present SheetJS LLC -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -------------------------------------------------------------------------------- diff --git a/ai/README.md b/ai/README.md index ba457e57..faa734d7 100644 --- a/ai/README.md +++ b/ai/README.md @@ -10,17 +10,14 @@ Internal AI models and background workers are retained strictly for deterministi | Domain Directory | Entry Point Facade | Architectural Responsibilities | |---|---|---| -| **`ai/embeddings/`** | `index.js` | `EmbeddingDB`, `EmbeddingService`, ONNX BGE-small-en-v1.5 transformer embedder | +| **`ai/embeddings/`** | `index.js` | `EmbeddingDB`, `EmbeddingService`, ONNX BGE-small transformer embedder, HuggingFace embeddings | | **`ai/graph/`** | `index.js` | `GraphDB`, `GraphService`, `GraphBuilder`, GLiNER2-Relex neural entity/relation extraction | | **`ai/queue/`** | `index.js` | Background utility process workers (`IndexWorker`, `GraphWorker`) for non-blocking note indexing | -| **`ai/tools/`** | `index.js` | `ToolRegistry`, `SemanticTools`, `DocumentReader`, internal note querying primitives | -| **`ai/context/`** | `index.js` | `ContextManager`, `SemanticRetriever`, `GraphRetriever`, `HybridRetriever` | -| **`ai/memory/`** | `index.js` | `MemoryDB`, `InteractionLog`, `MemoryOptimizer`, `PatternAnalyzer` | | **`ai/telemetry/`**| `index.js` | `TelemetryDB`, `AIEventBus`, structured logging of MCP tool calls and durations | | **`ai/logs/`** | `index.js` | `LogDB` persistent log storage for indexing operations | -| **`ai/providers/`**| `index.js` | `LLMRegistry`, `HuggingFaceEmbeddingProvider`, `GeminiProvider`, `GroqProvider`, `OpenAICompatibleProvider` | -| **`ai/diagnostics/`**| `index.js`| `AIHealth` metrics aggregator for MCP `/health` and status screens | -| **`ai/formatter/`**| `index.js` | Markdown response formatting and task summary formatters | +| **`ai/core/`** | `AIConfig.js` | `AIConfig`, `logger`, `AIService` note indexing hooks | +| **`ai/utils/`** | `index.js` | `SearchQueryUtils`, `ipcProtocol`, `HttpClient`, `aiUtils` | + --- diff --git a/ai/context/ContextEngine.js b/ai/context/ContextEngine.js deleted file mode 100644 index 00ce7df1..00000000 --- a/ai/context/ContextEngine.js +++ /dev/null @@ -1,84 +0,0 @@ -const { createLogger } = require('../core/logger'); - -const log = createLogger('ContextEngine'); - -const DEFAULT_PERSONA_ID = 'general'; -// Max chars of note content to include in system context (rough token budget guard) -const NOTE_CONTEXT_LIMIT = 4000; - -/** - * ContextEngine - assembles the full context payload for every LLM call. - * - * Provides: - * - System prompt from the active persona (.md file or DB fallback) - * - Active note text (truncated to token budget) - * - Recent conversation history - * - Tool definitions: SemanticRetriever + GraphRetriever + HybridRetriever - */ -class ContextEngine { - /** - * @param {import('../memory/ConversationStore').ConversationStore} store - * @param {import('./SemanticRetriever').SemanticRetriever} semanticRetriever - * @param {import('./GraphRetriever').GraphRetriever} graphRetriever - * @param {import('./HybridRetriever').HybridRetriever} hybridRetriever - */ - constructor(store, semanticRetriever, graphRetriever, hybridRetriever = null) { - this.store = store; - this.semanticRetriever = semanticRetriever; - this.graphRetriever = graphRetriever; - this.hybridRetriever = hybridRetriever; - } - - /** - * Build a complete context bundle for the AI SDK streamText / generateText call. - * - * @param {object} opts - * @param {string} opts.conversationId - * @param {string} [opts.activeNotePath] - * @param {string} [opts.activeNoteContent] - * @param {number} [opts.historyLimit=20] Max messages from history to include - * @returns {{ system: string, messages: object[], tools: object }} - */ - buildContext({ conversationId, activeNotePath, activeNoteContent, historyLimit = 20 }) { - const conversation = this.store.getConversation(conversationId); - const personaId = conversation?.persona ?? DEFAULT_PERSONA_ID; - const persona = this.store.getPersona(personaId) ?? this.store.getPersona(DEFAULT_PERSONA_ID); - - // System prompt from persona - let system = persona?.prompt ?? 'You are a helpful assistant.'; - - // Append active note context to system block (not user message) - if (activeNotePath && activeNoteContent) { - const preview = activeNoteContent.length > NOTE_CONTEXT_LIMIT - ? activeNoteContent.slice(0, NOTE_CONTEXT_LIMIT) + '\n...[truncated]' - : activeNoteContent; - system += `\n\n---\nCURRENT NOTE (${activeNotePath}):\n${preview}`; - } - - // Conversation history (newest historyLimit messages) - const allMessages = this.store.getMessages(conversationId); - const messages = allMessages.slice(-historyLimit).map(m => ({ - role: m.role, - content: m.content - })); - - // Tool definitions for the LLM to call dynamically. - // NOTE: search_notes / searchNotes are intentionally omitted here — they are - // already registered in ApplicationToolRegistry and merged in QueryExecutor. - // Duplicating them here caused the LLM to call a weaker camelCase alias with - // empty args, leaking internal error strings into user responses. - const tools = { - exploreGraph: this.graphRetriever.toTool() - }; - - // hybridSearchNotes intentionally omitted — hybrid_search is already registered - // in ApplicationToolRegistry and merged in QueryExecutor. Duplicate camelCase - // aliases cause the LLM to call the weaker in-process path with malformed args. - - log.info(`Context built for conversation=${conversationId} persona=${personaId} msgs=${messages.length}`); - - return { system, messages, tools, personaId, persona }; - } -} - -module.exports = { ContextEngine }; diff --git a/ai/context/ContextManager.js b/ai/context/ContextManager.js deleted file mode 100644 index 67786b82..00000000 --- a/ai/context/ContextManager.js +++ /dev/null @@ -1,239 +0,0 @@ -/** - * ContextManager - Manages workspace context and document indexing - */ - -class ContextManager { - constructor(databaseManager, documentService) { - this.db = databaseManager; - this.documentService = documentService; - this.contextCache = new Map(); - this.workspaceMetadata = null; - } - - /** - * Initialize context for a workspace - */ - async initializeWorkspace(workspaceRoot) { - try { - console.log('[ContextManager] Initializing workspace context (lazy mode)...'); - - // Restore cached context first (fast) - await this._loadCachedContext(workspaceRoot); - - // Schedule full workspace indexing for next event loop (non-blocking) - // This allows the app UI to load while indexing happens in the background - setImmediate(() => { - console.log('[ContextManager] Starting background workspace indexing...'); - this.documentService.indexWorkspace((progress) => { - console.log(`[ContextManager] Indexing progress: ${progress.indexed}/${progress.total} files`); - }) - .then((documentCount) => { - this.workspaceMetadata = this.documentService.getWorkspaceStructure(); - console.log(`[ContextManager] Background indexing complete: ${documentCount} files`); - }) - .catch((error) => { - console.error('[ContextManager] Background indexing failed:', error.message); - }); - }); - - return { - success: true, - workspaceRoot, - documentsIndexed: 0, - metadata: null, // Will be available after background indexing completes - note: 'Full indexing scheduled for background; cached data available immediately' - }; - } catch (error) { - console.error('[ContextManager] Initialization failed:', error.message); - throw error; - } - } - - /** - * Refresh context - */ - async refresh() { - try { - const indexCount = await this.documentService.indexWorkspace(); - this.workspaceMetadata = this.documentService.getWorkspaceStructure(); - this.contextCache.clear(); - - return { - success: true, - documentsIndexed: indexCount, - metadata: this.workspaceMetadata - }; - } catch (error) { - console.error('[ContextManager] Refresh failed:', error.message); - throw error; - } - } - - /** - * Get current context snapshot - */ - getContextSnapshot() { - return { - workspace: this.workspaceMetadata, - documentCount: this.documentService.getAllDocuments().length, - cacheSize: this.contextCache.size, - timestamp: new Date().toISOString() - }; - } - - /** - * Get context for a specific file - */ - async getFileContext(filePath) { - const cacheKey = `file:${filePath}`; - - if (this.contextCache.has(cacheKey)) { - return this.contextCache.get(cacheKey); - } - - const metadata = this.documentService.getDocumentMetadata(filePath); - const content = this.documentService.getDocumentContent(filePath); - - const context = { - filePath, - metadata, - contentLength: content?.length || 0, - contentPreview: content?.substring(0, 500) || null, - timestamp: new Date().toISOString() - }; - - // Cache for 1 hour - this.contextCache.set(cacheKey, context); - - return context; - } - - /** - * Get related documents context - */ - async getRelatedContext(filePath) { - const cacheKey = `related:${filePath}`; - - if (this.contextCache.has(cacheKey)) { - return this.contextCache.get(cacheKey); - } - - const related = this.documentService.searchDocuments(filePath, 10); - - const context = { - filePath, - relatedDocuments: related, - timestamp: new Date().toISOString() - }; - - this.contextCache.set(cacheKey, context); - - return context; - } - - /** - * Build context for query - */ - async buildQueryContext(query, currentFile = null) { - try { - // Search for relevant documents - const searchResults = this.documentService.searchDocuments(query, 5); - - // Get current file context if available - let fileContext = null; - if (currentFile) { - fileContext = await this.getFileContext(currentFile); - } - - // Build system prompt with context - const context = { - query, - currentFile, - fileContext, - relatedDocuments: searchResults.map(r => ({ - path: r.filePath, - relevance: r.relevanceScore - })), - workspaceStructure: this.workspaceMetadata, - timestamp: new Date().toISOString() - }; - - return context; - } catch (error) { - console.error('[ContextManager] buildQueryContext failed:', error.message); - throw error; - } - } - - /** - * Build system prompt - */ - buildSystemPrompt(context = {}) { - const workspace = this.workspaceMetadata || {}; - const docCount = workspace.documentCount || 0; - - let prompt = `You are an AI assistant for a markdown notes application. -Current workspace: ${workspace.root || 'unknown'} -Total documents: ${docCount} -Last workspace update: ${workspace.lastUpdated} - -`; - - if (context.currentFile) { - prompt += `Current document: ${context.currentFile}\n`; - } - - if (context.relatedDocuments && context.relatedDocuments.length > 0) { - prompt += `Related documents:\n`; - context.relatedDocuments.forEach((doc) => { - prompt += `- ${doc.path} (relevance: ${(doc.relevance * 100).toFixed(0)}%)\n`; - }); - } - - prompt += `\nProvide helpful, accurate responses focused on markdown documentation and note-taking.`; - - return prompt; - } - - /** - * Load cached context from database - * @private - */ - async _loadCachedContext(workspaceRoot) { - try { - const cached = this.db.getCachedContext(workspaceRoot, 'index_metadata'); - if (cached) { - console.log('[ContextManager] Restored cached workspace metadata'); - // Could use this to speed up initialization - } - } catch { - // Ignore cache load errors - } - } - - /** - * Save context to cache - */ - saveCacheMetadata(workspaceRoot) { - try { - const data = { - indexedAt: new Date().toISOString(), - documentCount: this.documentService.getAllDocuments().length, - workspaceSize: this.workspaceMetadata?.totalSize || 0 - }; - - this.db.cacheContext(workspaceRoot, 'index_metadata', data, 86400000); // 24 hours - } catch (error) { - console.warn('[ContextManager] Failed to cache metadata:', error.message); - } - } - - /** - * Clear context cache - */ - clearCache() { - this.contextCache.clear(); - } -} - -module.exports = ContextManager; diff --git a/ai/context/GraphRetriever.js b/ai/context/GraphRetriever.js deleted file mode 100644 index 36a91948..00000000 --- a/ai/context/GraphRetriever.js +++ /dev/null @@ -1,247 +0,0 @@ -const { createLogger } = require('../core/logger'); - -const log = createLogger('GraphRetriever'); - -/** - * GraphRetriever - recursive CTE traversal over ai-graph.db Property Graph - * Exposed as an LLM tool via ContextEngine. - */ -class GraphRetriever { - /** - * @param {object} graphDB - GraphDB instance or object wrapping .db property - */ - constructor(graphDB) { - this.graphDB = graphDB; - this.cache = new Map(); - } - - /** - * Traverse all relations linked to a given note path or entity ID (up to maxDepth hops). - * @param {string} notePath - * @param {number} maxDepth - * @returns {Array<{from_path: string, relation: string, to_path: string, depth: number, weight: number}>} - */ - traverse(notePath, maxDepth = 2) { - const startTime = performance.now(); - const now = Date.now(); - const cacheKey = `${notePath}:${maxDepth}`; - const cached = this.cache.get(cacheKey); - if (cached && now - cached.timestamp < 60000) { - log.info(`Graph traversal hit cache in ${(performance.now() - startTime).toFixed(2)}ms.`); - return cached.rows; - } - try { - if (typeof this.graphDB?.traversePathOrId === 'function') { - const rows = this.graphDB.traversePathOrId(notePath, maxDepth); - this.cache.set(cacheKey, { timestamp: now, rows }); - const duration = performance.now() - startTime; - log.info(`Graph traversal completed in ${duration.toFixed(2)}ms. Found ${rows.length} relations.`); - return rows; - } - - const db = this.graphDB.db || this.graphDB; - if (!db || typeof db.prepare !== 'function') return []; - - let startId = notePath; - try { - const entityRow = db.prepare('SELECT id FROM entities WHERE note_path = ? OR LOWER(note_path) = LOWER(?) LIMIT 1').get(notePath, notePath); - if (entityRow && entityRow.id) startId = entityRow.id; - } catch { - // Mock DB prepare may return mock rows directly - } - - let rawRows = []; - try { - rawRows = db.prepare(` - WITH RECURSIVE graph_walk(source_id, target_id, type, weight, depth, path_str) AS ( - SELECT r.source_id, r.target_id, r.type, r.weight, 1, r.source_id || ',' || r.target_id - FROM relationships r - WHERE r.source_id = ? OR r.target_id = ? - UNION ALL - SELECT r.source_id, r.target_id, r.type, r.weight, gw.depth + 1, gw.path_str || ',' || r.target_id - FROM relationships r - JOIN graph_walk gw ON (r.source_id = gw.target_id OR r.target_id = gw.source_id) - WHERE gw.depth < ? AND gw.path_str NOT LIKE '%' || r.target_id || '%' - ) - SELECT DISTINCT - e_src.note_path as from_path, - e_src.name as from_name, - gw.type as relation, - e_tgt.note_path as to_path, - e_tgt.name as to_name, - gw.depth, - gw.weight - FROM graph_walk gw - JOIN entities e_src ON gw.source_id = e_src.id - JOIN entities e_tgt ON gw.target_id = e_tgt.id - ORDER BY gw.depth ASC, gw.weight DESC - LIMIT 50 - `).all(startId, startId, maxDepth); - } catch { - // Fallback for custom unit test mocks - try { - rawRows = db.prepare('').all(); - } catch { - rawRows = []; - } - } - - const formatted = (rawRows || []).map(r => ({ - from_path: r.from_path || r.from_name || r.from || notePath, - relation: r.relation || r.type || 'links', - to_path: r.to_path || r.to_name || r.to || 'target', - depth: r.depth || 1, - weight: r.weight || 1.0 - })); - - this.cache.set(cacheKey, { timestamp: now, rows: formatted }); - const duration = performance.now() - startTime; - log.info(`Graph traversal completed in ${duration.toFixed(2)}ms. Found ${formatted.length} relations.`); - return formatted; - } catch (err) { - log.warn('Graph traversal failed (graph may not be built yet):', err.message); - return []; - } - } - - /** - * Find entities by ontology type - */ - findEntitiesByType(type, limit = 20) { - if (!this.graphDB) return []; - try { - const db = this.graphDB.db || this.graphDB; - if (!db || typeof db.prepare !== 'function') return []; - const stmt = db.prepare('SELECT id, name, canonical_name, type, note_path FROM entities WHERE LOWER(type) = LOWER(?) OR LOWER(ontology_class) = LOWER(?) LIMIT ?'); - return stmt.all(type, type, limit); - } catch { - return []; - } - } - - /** - * Explain path between two entities - */ - explainPath(entityAName, entityBName) { - if (!this.graphDB) return null; - try { - const db = this.graphDB.db || this.graphDB; - if (!db || typeof db.prepare !== 'function') return null; - - const entA = db.prepare('SELECT id, name FROM entities WHERE LOWER(name) = LOWER(?) OR note_path = ? LIMIT 1').get(entityAName, entityAName); - const entB = db.prepare('SELECT id, name FROM entities WHERE LOWER(name) = LOWER(?) OR note_path = ? LIMIT 1').get(entityBName, entityBName); - - if (!entA || !entB) return null; - - let pathIds = null; - if (typeof this.graphDB.findPath === 'function') { - pathIds = this.graphDB.findPath(entA.id, entB.id); - } - if (!pathIds || pathIds.length < 2) return `${entA.name} and ${entB.name} are not connected in the graph.`; - - const names = pathIds.map(id => { - const row = db.prepare('SELECT name FROM entities WHERE id = ?').get(id); - return row?.name || id; - }); - - return names.join(' --> '); - } catch (err) { - log.warn('Failed explainPath:', err.message); - return null; - } - } - - /** - * Get workspace summary - */ - getWorkspaceSummary() { - if (!this.graphDB) return null; - try { - let workspaceEntity = null; - if (typeof this.graphDB.getWorkspaceEntity === 'function') { - workspaceEntity = this.graphDB.getWorkspaceEntity(); - } - const nodeCount = typeof this.graphDB.getNodeCount === 'function' ? this.graphDB.getNodeCount() : 0; - const edgeCount = typeof this.graphDB.getEdgeCount === 'function' ? this.graphDB.getEdgeCount() : 0; - - return { - workspace: workspaceEntity || { name: 'Workspace' }, - stats: { nodeCount, edgeCount } - }; - } catch { - return null; - } - } - - /** - * Get dependencies for an entity - */ - getDependencies(entityName, direction = 'both') { - if (!this.graphDB) return []; - try { - const db = this.graphDB.db || this.graphDB; - if (!db || typeof db.prepare !== 'function') return []; - - const ent = db.prepare('SELECT id, name FROM entities WHERE LOWER(name) = LOWER(?) OR note_path = ? LIMIT 1').get(entityName, entityName); - if (!ent) return []; - - let query = ''; - if (direction === 'outgoing') { - query = "SELECT e.name as target, r.type FROM relationships r JOIN entities e ON r.target_id = e.id WHERE r.source_id = ? AND r.type IN ('depends_on', 'uses', 'imports', 'connects_to')"; - } else if (direction === 'incoming') { - query = "SELECT e.name as source, r.type FROM relationships r JOIN entities e ON r.source_id = e.id WHERE r.target_id = ? AND r.type IN ('depends_on', 'uses', 'imports', 'connects_to')"; - } else { - query = "SELECT e_src.name as source, r.type, e_tgt.name as target FROM relationships r JOIN entities e_src ON r.source_id = e_src.id JOIN entities e_tgt ON r.target_id = e_tgt.id WHERE (r.source_id = ? OR r.target_id = ?) AND r.type IN ('depends_on', 'uses', 'imports', 'connects_to')"; - } - - const stmt = db.prepare(query); - return direction === 'both' ? stmt.all(ent.id, ent.id) : stmt.all(ent.id); - } catch { - return []; - } - } - - /** - * Get related documents for an entity - */ - getRelatedDocuments(entityName) { - if (!this.graphDB) return []; - try { - const rows = this.traverse(entityName, 2); - const paths = new Set(); - rows.forEach(r => { - if (r.from_path && r.from_path.endsWith('.md')) paths.add(r.from_path); - if (r.to_path && r.to_path.endsWith('.md')) paths.add(r.to_path); - }); - return Array.from(paths); - } catch { - return []; - } - } - - /** - * Vercel AI SDK tool definition for this retriever. - */ - toTool() { - return { - description: 'Explore how a note is connected to other notes in the workspace knowledge graph. Use when the user asks about related topics, linked documents, or note relationships.', - parameters: { - type: 'object', - properties: { - notePath: { type: 'string', description: 'The full path of the note to start graph traversal from.' }, - maxDepth: { type: 'number', description: 'Maximum traversal hops (default 2).', default: 2 } - }, - required: ['notePath'] - }, - execute: async ({ notePath, maxDepth = 2 }) => { - const rows = this.traverse(notePath, maxDepth); - if (!rows.length) return `No graph relations found for: ${notePath}`; - return rows.map(r => - `[depth ${r.depth}] ${r.from_path} --[${r.relation}]--> ${r.to_path}` - ).join('\n'); - } - }; - } -} - -module.exports = { GraphRetriever }; diff --git a/ai/context/HybridRetriever.js b/ai/context/HybridRetriever.js deleted file mode 100644 index 4ba51cb3..00000000 --- a/ai/context/HybridRetriever.js +++ /dev/null @@ -1,178 +0,0 @@ -const { createLogger } = require('../core/logger'); - -const log = createLogger('HybridRetriever'); - -class HybridRetriever { - constructor(semanticRetriever, graphRetriever) { - this.semanticRetriever = semanticRetriever; - this.graphRetriever = graphRetriever; - this._cache = new Map(); // cacheKey -> { timestamp, results } - this._cacheTTL = 60000; // 60s cache TTL - } - - async search(query, activeNotePath = null, topK = 5) { - const cacheKey = `${String(query).toLowerCase().trim()}_${activeNotePath || ''}_${topK}`; - const now = Date.now(); - if (this._cache.has(cacheKey)) { - const cached = this._cache.get(cacheKey); - if (now - cached.timestamp < this._cacheTTL) { - log.debug(`[HybridRetriever] Cache HIT for query: "${query.slice(0, 30)}"`); - return cached.results; - } - } - - const startTime = performance.now(); - - // 1. Run semantic search - const semanticResults = await this.semanticRetriever.search(query, topK * 2); - - // 2. Walk the graph relations - const graphHits = []; - const walkedNotes = new Set(); - - // Traverse from active note path if provided - if (activeNotePath) { - walkedNotes.add(activeNotePath); - const activeRelations = this.graphRetriever.traverse(activeNotePath, 2); - for (const r of activeRelations) { - if (r.to_path) { - graphHits.push({ path: r.to_path, weight: r.weight || 1.0, depth: r.depth || 1 }); - } - } - } - - // Traverse from top semantic matches to find connected entities - for (const match of semanticResults.slice(0, 3)) { - if (match.note_path && !walkedNotes.has(match.note_path)) { - walkedNotes.add(match.note_path); - const rels = this.graphRetriever.traverse(match.note_path, 1); - for (const r of rels) { - if (r.to_path) { - graphHits.push({ path: r.to_path, weight: r.weight || 1.0, depth: r.depth || 1 }); - } - } - } - } - - // 3. Reciprocal Rank Fusion (RRF) with Depth Attenuation & Weighting - const rrfScores = new Map(); // note_path -> score - const k = 60; // standard RRF constant - - // Add semantic ranks - semanticResults.forEach((res, index) => { - const rank = index + 1; - const score = 1 / (k + rank); - rrfScores.set(res.note_path, score); - }); - - // Add weighted graph ranks - const graphRankMap = new Map(); - graphHits.forEach((hit) => { - const decay = 1 / (1 + (hit.depth || 1)); - const score = (hit.weight || 1.0) * decay; - graphRankMap.set(hit.path, (graphRankMap.get(hit.path) || 0) + score); - }); - - // Sort graph hits by weighted connection score - const sortedGraphHits = Array.from(graphRankMap.entries()) - .sort((a, b) => b[1] - a[1]) - .map(entry => entry[0]); - - sortedGraphHits.forEach((path, index) => { - const rank = index + 1; - const baseRrf = 1 / (k + rank); - const graphWeightBonus = graphRankMap.get(path) || 1.0; - const score = baseRrf * (1 + 0.25 * graphWeightBonus); - const existing = rrfScores.get(path) || 0; - rrfScores.set(path, existing + score); - }); - - // Sort by merged RRF scores - const merged = Array.from(rrfScores.entries()) - .sort((a, b) => b[1] - a[1]) - .slice(0, topK); - - // Retrieve full contents for the final merged paths - const results = []; - for (const [notePath, score] of merged) { - let content = ''; - const semMatch = semanticResults.find(r => r.note_path === notePath); - if (semMatch) { - content = semMatch.content; - } else { - try { - const fs = require('fs'); - if (fs.existsSync(notePath) && fs.statSync(notePath).isFile()) { - content = fs.readFileSync(notePath, 'utf8'); - } - } catch (err) { - log.warn(`Failed to read note during hybrid search fallback: ${err.message}`); - } - } - - // Attach graph relations & evidence triples for the matched note - let graphTriples = []; - if (this.graphRetriever) { - try { - const rels = this.graphRetriever.traverse(notePath, 1); - graphTriples = (rels || []).map(r => { - let line = `(${r.from_type || 'Entity'}) ${r.from_name || r.from_path} --[${r.relation}]--> (${r.to_type || 'Entity'}) ${r.to_name || r.to_path}`; - if (r.evidence) { - line += ` (Evidence: "${r.evidence}")`; - } - return line; - }); - } catch { /* ignore graph lookup error */ } - } - - results.push({ - note_path: notePath, - content: content.slice(0, 4000), // budget preview limit - score: score, - graph_triples: graphTriples - }); - } - - const duration = performance.now() - startTime; - log.info(`Hybrid search completed in ${duration.toFixed(2)}ms. Merged ${results.length} documents.`); - this._cache.set(cacheKey, { timestamp: Date.now(), results }); - return results; - } - - toTool() { - return { - description: 'Search workspace notes using a hybrid algorithm combining semantic vector search and knowledge graph traversal. Highly recommended to use this for general queries.', - parameters: { - type: 'object', - properties: { - query: { type: 'string', description: 'The search phrase or question to find relevant note content for.' }, - activeNotePath: { type: 'string', description: 'Optional path to the currently active note to traverse relations from.' }, - topK: { type: 'number', description: 'Number of results to return (default 5).', default: 5 } - }, - required: ['query'] - }, - execute: async (args = {}) => { - let q = String(args?.query || '').trim(); - if (!q) { - return 'No search query provided — no results.'; - } - - const activeNotePath = args?.activeNotePath || null; - const topK = args?.topK || 5; - const results = await this.search(q, activeNotePath, topK); - if (!results.length) return `No note content matching "${q}" found in workspace.`; - return results.map((r, i) => { - const normPath = String(r.note_path).replace(/\\/g, '/'); - const fileUri = normPath.startsWith('/') ? normPath : '/' + normPath; - let output = `[${i + 1}] [${r.note_path}](file://${fileUri}) (RRF score: ${r.score.toFixed(4)})\n${r.content}`; - if (r.graph_triples && r.graph_triples.length) { - output += `\n\nKnowledge Graph Connections:\n * ` + r.graph_triples.slice(0, 10).join('\n * '); - } - return output; - }).join('\n\n---\n\n'); - } - }; - } -} - -module.exports = { HybridRetriever }; diff --git a/ai/context/SemanticRetriever.js b/ai/context/SemanticRetriever.js deleted file mode 100644 index aec79111..00000000 --- a/ai/context/SemanticRetriever.js +++ /dev/null @@ -1,156 +0,0 @@ -const { createLogger } = require('../core/logger'); - -const log = createLogger('SemanticRetriever'); - -/** - * SemanticRetriever - cosine similarity vector search over ai-embeddings.db - * Exposed as an LLM tool via ContextEngine. - */ -class SemanticRetriever { - /** - * @param {import('../embeddings/EmbeddingDB').EmbeddingDB} embeddingDB - * @param {import('../embeddings/EmbeddingService').EmbeddingService} embeddingService - */ - constructor(embeddingDB, embeddingService) { - this.embeddingDB = embeddingDB; - this.embeddingService = embeddingService; - } - - /** - * Search for top-K note chunks semantically similar to the query. - * @param {string} query - * @param {number} topK - * @returns {Promise>} - */ - async search(query, topK = 5) { - const startTime = performance.now(); - if (!this.embeddingService.isAvailable()) { - log.warn('Embedding service not available - falling back to keyword search.'); - return typeof this.embeddingDB.searchTextFallback === 'function' - ? this.embeddingDB.searchTextFallback(query, topK) - : []; - } - - let queryVec; - try { - queryVec = await this.embeddingService.generateVector(query); - } catch (err) { - log.error('Failed to generate query vector - falling back to keyword search', err); - return typeof this.embeddingDB.searchTextFallback === 'function' - ? this.embeddingDB.searchTextFallback(query, topK) - : []; - } - - // Scan the preloaded vector cache directly to bypass SQLite SELECT and buffer deserialization overhead - const scored = []; - const cache = this.embeddingDB.vectorCache || []; - for (const item of cache) { - if (item.embedding) { - scored.push({ - id: item.id, - note_path: item.note_path, - score: this._cosine(queryVec, item.embedding) - }); - } - } - - if (!scored.length) { - return typeof this.embeddingDB.searchTextFallback === 'function' - ? this.embeddingDB.searchTextFallback(query, topK) - : []; - } - - // Sort scored vector items by similarity descending - scored.sort((a, b) => b.score - a.score); - - // Filter by realistic local similarity threshold (>= 0.35 for ONNX BGE embeddings) - let thresholdFiltered = scored.filter(item => item.score >= 0.35); - - // Fallback to keyword search if no vector matches passed threshold - if (thresholdFiltered.length === 0 && typeof this.embeddingDB.searchTextFallback === 'function') { - return this.embeddingDB.searchTextFallback(query, topK); - } - - // Deduplicate by note_path to avoid duplicate chunks from the same note - const seenNotes = new Set(); - const uniqueScored = []; - for (const item of thresholdFiltered) { - if (!seenNotes.has(item.note_path)) { - seenNotes.add(item.note_path); - uniqueScored.push(item); - } - if (uniqueScored.length >= topK) break; - } - - // Retrieve note content only for the top scored chunks - const results = []; - const stmt = this.embeddingDB.db.prepare('SELECT content FROM chunks WHERE id = ?'); - for (const item of uniqueScored) { - const row = stmt.get(item.id); - results.push({ - note_path: item.note_path, - content: row ? row.content : '', - score: item.score - }); - } - - const duration = performance.now() - startTime; - log.info(`Semantic search finished in ${duration.toFixed(2)}ms. Found ${results.length} unique results.`); - return results; - } - - /** - * Vercel AI SDK tool definition for this retriever. - */ - toTool() { - return { - description: 'Search workspace notes by semantic meaning. Use when the user asks about topics, facts, or ideas that may be in their notes.', - parameters: { - type: 'object', - properties: { - query: { type: 'string', description: 'The search phrase or question to find relevant note content for.' }, - topK: { type: 'number', description: 'Number of results to return (default 5).', default: 5 } - }, - required: ['query'] - }, - execute: async (args = {}) => { - let q = String(args?.query || '').trim(); - if (!q) { - return 'No search query provided — no results.'; - } - - const topK = args?.topK || 5; - const results = await this.search(q, topK); - if (!results.length) return `No note content matching "${q}" found in workspace.`; - return results.map((r, i) => { - const normPath = String(r.note_path).replace(/\\/g, '/'); - const fileUri = normPath.startsWith('/') ? normPath : '/' + normPath; - return `[${i + 1}] [${r.note_path}](file://${fileUri}) (score: ${r.score.toFixed(3)})\n${r.content}`; - }).join('\n\n'); - } - }; - } - - // --- Helpers ------------------------------------------------- - - _cosine(a, b) { - if (a.length !== b.length) return 0; - let dot = 0, normA = 0, normB = 0; - for (let i = 0; i < a.length; i++) { - dot += a[i] * b[i]; - normA += a[i] * a[i]; - normB += b[i] * b[i]; - } - const denom = Math.sqrt(normA) * Math.sqrt(normB); - return denom === 0 ? 0 : dot / denom; - } - - _deserialize(blob) { - if (!blob) return []; - const buf = blob instanceof Buffer ? blob : Buffer.from(blob); - const arr = new Float32Array(buf.buffer, buf.byteOffset, buf.byteLength / 4); - return Array.from(arr); - } -} - -module.exports = { SemanticRetriever }; \ No newline at end of file diff --git a/ai/context/index.js b/ai/context/index.js deleted file mode 100644 index 78d2598d..00000000 --- a/ai/context/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Context Module Facade - * Single entry point for context assembly, workspace context management, and hybrid retrieval. - */ - -const { ContextEngine } = require('./ContextEngine'); -const ContextManager = require('./ContextManager'); -const { SemanticRetriever } = require('./SemanticRetriever'); -const { GraphRetriever } = require('./GraphRetriever'); -const { HybridRetriever } = require('./HybridRetriever'); - -module.exports = { - ContextEngine, - ContextManager, - SemanticRetriever, - GraphRetriever, - HybridRetriever, - - createContextEngine: (store, semanticRetriever, graphRetriever, hybridRetriever) => { - return new ContextEngine(store, semanticRetriever, graphRetriever, hybridRetriever); - }, - createContextManager: (db, documentService) => { - return new ContextManager(db, documentService); - } -}; diff --git a/ai/core/AIService.js b/ai/core/AIService.js index 7d25258e..753239fe 100644 --- a/ai/core/AIService.js +++ b/ai/core/AIService.js @@ -67,37 +67,10 @@ class AIService { // If we have paths, trigger full initialization if (this.appDataDir && this.workspaceRoot) { - const { PROVIDER_REGISTRY } = require('../providers/ProviderRegistry'); - const activeProviderName = prefs.aiProvider || 'gemini'; - - let llmProvider = null; - const activeApiKey = this.config.getAPIKey(activeProviderName); - - if (activeApiKey) { - const savedModel = this.config.getProviderModel(activeProviderName); - const entry = PROVIDER_REGISTRY[activeProviderName]; - llmProvider = { - name: activeProviderName, - config: { apiKey: activeApiKey, model: savedModel || entry?.defaultModel }, - }; - } else { - for (const entry of Object.values(PROVIDER_REGISTRY)) { - if (!entry.available) continue; - const apiKey = this.config.getAPIKey(entry.id); - if (apiKey) { - const savedModel = this.config.getProviderModel(entry.id); - llmProvider = { - name: entry.id, - config: { apiKey, model: savedModel || entry.defaultModel }, - }; - break; - } - } - } const hfToken = this.config.getAPIKey('huggingface'); const embeddingConfig = hfToken ? { token: hfToken } : null; - await this.initialize(this.appDataDir, this.workspaceRoot, llmProvider, embeddingConfig); + await this.initialize(this.appDataDir, this.workspaceRoot, null, embeddingConfig); } } diff --git a/ai/core/Agent.js b/ai/core/Agent.js index 25e4f5e9..38f4fc8f 100644 --- a/ai/core/Agent.js +++ b/ai/core/Agent.js @@ -2,28 +2,16 @@ * Agent - Main orchestrator for AI agent functionality */ -const { DocumentReader: DocumentService } = require('../tools'); const { EmbeddingService } = require('../embeddings'); -const { ContextManager } = require('../context'); -const { InteractionLog: MemoryManager } = require('../memory'); const { GraphDB, GraphService, GraphBuilder } = require('../graph'); const { LogDB } = require('../logs'); +const { LLMRegistry } = require('../providers'); class Agent { - constructor(databaseManager, llmRegistry) { - this.db = databaseManager; - this.llmRegistry = llmRegistry; + constructor(llmRegistry = null) { + this.llmRegistry = llmRegistry || new LLMRegistry(); this.logDb = null; - - // Initialize services — EmbeddingService receives null here; the actual - // embeddingProvider is injected after construction via setEmbeddingProvider() - // (called from initializeAISystem once the HF token is resolved). - this.documentService = new DocumentService(this.db, ''); - this.embeddingService = new EmbeddingService(this.db, null); - this.relationshipService = null; - this.contextManager = new ContextManager(this.db, this.documentService); - this.memoryManager = new MemoryManager(this.db); - + this.embeddingService = new EmbeddingService(null, null); this.graphDb = null; this.graphService = null; this.graphBuilder = null; @@ -48,18 +36,17 @@ class Agent { /** * Initialize agent for workspace */ - async initialize(workspaceRoot, llmProvider) { + async initialize(workspaceRoot, llmProvider = null) { try { console.log('[Agent] Initializing...'); - // Activate LLM provider - if (llmProvider) { + if (llmProvider && this.llmRegistry) { await this.llmRegistry.activateProvider(llmProvider.name, llmProvider.config); } // Store workspace root this.workspaceRoot = workspaceRoot; - this.documentService.workspaceRoot = workspaceRoot; + // Initialize LogDB for prompt and AI logging this.logDb = new LogDB(workspaceRoot); @@ -76,20 +63,11 @@ class Agent { this.graphService = new GraphService(this, this.graphDb); this.graphBuilder = new GraphBuilder(this, this.graphDb, this.graphService); - // Initialize database - if (!this.db.isInitialized) { - this.db.initialize(); - } - - // Initialize context for workspace - const contextResult = await this.contextManager.initializeWorkspace(workspaceRoot); - this.isInitialized = true; console.log('[Agent] Initialized successfully'); return { - success: true, - ...contextResult + success: true }; } catch (error) { console.error('[Agent] Initialization failed:', error.message); @@ -97,38 +75,6 @@ class Agent { } } - - // query() and stream() removed — chat moved to MCP layer - - - /** - * Generate embeddings for workspace - */ - async generateEmbeddings(_forceRefresh = false) { - try { - const docs = this.documentService.getAllDocuments(); - console.log(`[Agent] Generating embeddings for ${docs.length} documents...`); - - const results = await this.embeddingService.generateBatchEmbeddings(docs); - - const successful = results.filter(r => r.success).length; - console.log(`[Agent] Successfully generated ${successful}/${docs.length} embeddings`); - - return { - success: true, - embeddingsGenerated: successful, - total: docs.length, - results - }; - } catch (error) { - console.error('[Agent] Embedding generation failed:', error.message); - return { - success: false, - error: error.message - }; - } - } - /** * Build relationship graph */ @@ -140,29 +86,7 @@ class Agent { } /** - * Learn from interactions - */ - detectPatterns() { - try { - const patterns = this.memoryManager.detectPatterns(this.workspaceRoot); - console.log(`[Agent] Detected ${patterns.length} patterns`); - - return { - success: true, - patternsDetected: patterns.length, - patterns - }; - } catch (error) { - console.error('[Agent] Pattern detection failed:', error.message); - return { - success: false, - error: error.message - }; - } - } - - /** - * Log LLM prompt execution to LogDB (PromptTracker) + * Log prompt execution to LogDB */ logPrompt(query, systemPrompt, metadata = {}) { if (this.logDb && this.logDb.isInitialized) { @@ -182,11 +106,8 @@ class Agent { return { initialized: this.isInitialized, workspaceRoot: this.workspaceRoot, - llmProvider: this.llmRegistry.activeProvider?.name || null, embeddingProvider: this.embeddingService.embeddingProvider?.name || null, embeddingsAvailable: this.embeddingService.isAvailable(), - documentCount: this.documentService.getAllDocuments().length, - sessionInfo: this.memoryManager.getSessionSummary(), timestamp: new Date().toISOString() }; } @@ -195,12 +116,7 @@ class Agent { * Reset agent */ reset() { - this.memoryManager.clearSession(); - this.contextManager.clearCache(); this.embeddingService.clearCache(); - if (this.relationshipService?.clearCache) { - this.relationshipService.clearCache(); - } console.log('[Agent] Reset successfully'); } @@ -220,9 +136,7 @@ class Agent { } if (this.graphDb) { this.graphDb.close(); - } - if (this.db && this.db.isInitialized) { - this.db.close(); + this.graphDb = null; } this.isInitialized = false; console.log('[Agent] Shutdown complete'); diff --git a/ai/database/LegacyDBManager.js b/ai/database/LegacyDBManager.js deleted file mode 100644 index afe081b3..00000000 --- a/ai/database/LegacyDBManager.js +++ /dev/null @@ -1,419 +0,0 @@ -/** - * DatabaseManager - SQLite database handler for AI agent - * Manages schema initialization, migrations, and query execution - */ - -const path = require('path'); -const fs = require('fs'); -const { DatabaseSync } = require('node:sqlite'); -const { getPendingMigrations } = require('./LegacyMigrations'); -const { createLogger } = require('../core/logger'); - -const log = createLogger('DatabaseManager'); - -class DatabaseManager { - constructor(appDataDir) { - this.appDataDir = appDataDir; - this.dbPath = path.join(appDataDir, 'app.sqlite'); - this.db = null; - this.isInitialized = false; - } - - /** - * Initialize database connection and run migrations - */ - initialize() { - try { - // Ensure directory exists - if (!fs.existsSync(this.appDataDir)) { - fs.mkdirSync(this.appDataDir, { recursive: true }); - } - - // Open or create database - this.db = new DatabaseSync(this.dbPath); - - // Enable foreign keys - this.db.exec('PRAGMA foreign_keys = ON'); - - // Write-Ahead Logging improves concurrency and crash durability; - // synchronous=NORMAL is the recommended pairing for WAL. - try { - this.db.exec('PRAGMA journal_mode = WAL'); - this.db.exec('PRAGMA synchronous = NORMAL'); - this.db.exec('PRAGMA busy_timeout = 5000'); - } catch (pragmaError) { - log.warn('Could not enable WAL mode', pragmaError); - } - - // Run pending migrations - this._runMigrations(); - - this.isInitialized = true; - log.info('Initialized', { dbPath: this.dbPath }); - return true; - } catch (error) { - log.error('Initialization failed', error); - throw error; - } - } - - /** - * Run a function inside a database transaction, rolling back on error. - * The callback must be synchronous (node:sqlite is synchronous). - */ - transaction(fn) { - if (!this.db) throw new Error('Database not initialized'); - this.db.exec('BEGIN'); - try { - const result = fn(); - this.db.exec('COMMIT'); - return result; - } catch (error) { - try { - this.db.exec('ROLLBACK'); - } catch (rollbackError) { - log.error('Rollback failed', rollbackError); - } - throw error; - } - } - - /** - * Run pending database migrations - * @private - */ - _runMigrations() { - // Create migrations log table if it doesn't exist - this.db.exec(` - CREATE TABLE IF NOT EXISTS ai_migrations_log ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - migration_version INTEGER NOT NULL UNIQUE, - migration_name TEXT NOT NULL, - applied_at TEXT NOT NULL, - status TEXT DEFAULT 'applied' - ) - `); - - // Get current version - const result = this.db.prepare(` - SELECT MAX(migration_version) as version FROM ai_migrations_log - WHERE status = 'applied' - `).get(); - - const currentVersion = result?.version || 0; - const pending = getPendingMigrations(currentVersion); - - if (pending.length === 0) { - log.debug('Schema up-to-date'); - return; - } - - log.info(`Running ${pending.length} migrations`); - - pending.forEach(migration => { - try { - // Apply the migration DDL and record it atomically so a crash can't - // leave the schema changed but unlogged (or vice versa). - this.transaction(() => { - this.db.exec(migration.sql); - - this.db.prepare(` - INSERT INTO ai_migrations_log (migration_version, migration_name, applied_at) - VALUES (?, ?, ?) - `).run( - migration.version, - migration.name, - new Date().toISOString() - ); - }); - - log.info(`Applied migration ${migration.version}: ${migration.name}`); - } catch (error) { - log.error(`Migration ${migration.version} failed`, error); - throw error; - } - }); - } - - /** - * Insert or update document embedding - */ - saveEmbedding(filePath, embedding, contentHash, model = 'gemini-embedding-001') { - if (!this.db) throw new Error('Database not initialized'); - - const now = new Date().toISOString(); - const embeddingBlob = Buffer.from(JSON.stringify(embedding)); - - this.db.prepare(` - INSERT INTO ai_document_embeddings - (file_path, content_hash, embedding_vector, embedding_model, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?) - ON CONFLICT(file_path) DO UPDATE SET - content_hash = excluded.content_hash, - embedding_vector = excluded.embedding_vector, - updated_at = excluded.updated_at - `).run(filePath, contentHash, embeddingBlob, model, now, now); - } - - /** - * Get embedding for file - */ - getEmbedding(filePath) { - if (!this.db) throw new Error('Database not initialized'); - - const result = this.db.prepare(` - SELECT embedding_vector, content_hash, embedding_model FROM ai_document_embeddings - WHERE file_path = ? - `).get(filePath); - - if (!result) return null; - - return { - vector: JSON.parse(result.embedding_vector.toString()), - contentHash: result.content_hash, - model: result.embedding_model - }; - } - - /** - * Add document relationship - */ - addRelationship(sourceFile, targetFile, type, strength = 0.5, metadata = null) { - if (!this.db) throw new Error('Database not initialized'); - - this.db.prepare(` - INSERT INTO ai_document_relationships - (source_file, target_file, relationship_type, strength, metadata, detected_at) - VALUES (?, ?, ?, ?, ?, ?) - ON CONFLICT(source_file, target_file, relationship_type) DO UPDATE SET - strength = excluded.strength, - metadata = excluded.metadata - `).run( - sourceFile, - targetFile, - type, - strength, - metadata ? JSON.stringify(metadata) : null, - new Date().toISOString() - ); - } - - /** - * Get related documents - */ - getRelatedDocuments(filePath, relationshipType = null, minStrength = 0) { - if (!this.db) throw new Error('Database not initialized'); - - let query = ` - SELECT target_file, relationship_type, strength, metadata - FROM ai_document_relationships - WHERE source_file = ? AND strength >= ? - `; - - const params = [filePath, minStrength]; - - if (relationshipType) { - query += ' AND relationship_type = ?'; - params.push(relationshipType); - } - - query += ' ORDER BY strength DESC'; - - return this.db.prepare(query).all(...params); - } - - /** - * Record interaction - */ - recordInteraction(query, response, filePath, workspaceRoot, type = 'query', model = null, tokensUsed = 0) { - if (!this.db) throw new Error('Database not initialized'); - - this.db.prepare(` - INSERT INTO ai_interactions - (query, response, file_context, workspace_root, interaction_type, model_used, tokens_used, timestamp) - VALUES (?, ?, ?, ?, ?, ?, ?, ?) - `).run( - query, - response, - filePath, - workspaceRoot, - type, - model, - tokensUsed, - new Date().toISOString() - ); - } - - /** - * Rate interaction - */ - rateInteraction(interactionId, rating) { - if (!this.db) throw new Error('Database not initialized'); - if (![1, 0, -1].includes(rating)) throw new Error('Rating must be -1, 0, or 1'); - - this.db.prepare(` - UPDATE ai_interactions - SET helpful_rating = ?, rated_at = ? - WHERE id = ? - `).run(rating, new Date().toISOString(), interactionId); - } - - /** - * Get recent interactions - */ - getRecentInteractions(workspaceRoot, limit = 50, type = null) { - if (!this.db) throw new Error('Database not initialized'); - - let query = ` - SELECT * FROM ai_interactions - WHERE workspace_root = ? - `; - - const params = [workspaceRoot]; - - if (type) { - query += ' AND interaction_type = ?'; - params.push(type); - } - - query += ' ORDER BY timestamp DESC LIMIT ?'; - params.push(limit); - - return this.db.prepare(query).all(...params); - } - - /** - * Add or update pattern - */ - addPattern(workspaceRoot, type, name, data, confidence = 0.5) { - if (!this.db) throw new Error('Database not initialized'); - - const now = new Date().toISOString(); - - this.db.prepare(` - INSERT INTO ai_patterns - (workspace_root, pattern_type, pattern_name, pattern_data, confidence, first_seen, last_seen) - VALUES (?, ?, ?, ?, ?, ?, ?) - ON CONFLICT(workspace_root, pattern_type, pattern_name) DO UPDATE SET - frequency = frequency + 1, - confidence = excluded.confidence, - last_seen = excluded.last_seen - `).run( - workspaceRoot, - type, - name, - JSON.stringify(data), - confidence, - now, - now - ); - } - - /** - * Get patterns by type - */ - getPatterns(workspaceRoot, type, minConfidence = 0.3) { - if (!this.db) throw new Error('Database not initialized'); - - return this.db.prepare(` - SELECT pattern_name, pattern_data, frequency, confidence - FROM ai_patterns - WHERE workspace_root = ? AND pattern_type = ? AND confidence >= ? - ORDER BY frequency DESC, confidence DESC - `).all(workspaceRoot, type, minConfidence); - } - - /** - * Cache context value - */ - cacheContext(workspaceRoot, key, value, expiresInMs = 3600000) { - if (!this.db) throw new Error('Database not initialized'); - - const expiresAt = new Date(Date.now() + expiresInMs).toISOString(); - - this.db.prepare(` - INSERT INTO ai_context_cache - (workspace_root, context_key, context_value, created_at, expires_at) - VALUES (?, ?, ?, ?, ?) - ON CONFLICT(workspace_root, context_key) DO UPDATE SET - context_value = excluded.context_value, - expires_at = excluded.expires_at - `).run(workspaceRoot, key, JSON.stringify(value), new Date().toISOString(), expiresAt); - } - - /** - * Get cached context - */ - getCachedContext(workspaceRoot, key) { - if (!this.db) throw new Error('Database not initialized'); - - const result = this.db.prepare(` - SELECT context_value, expires_at - FROM ai_context_cache - WHERE workspace_root = ? AND context_key = ? - `).get(workspaceRoot, key); - - if (!result) return null; - - // Check expiration - if (result.expires_at && new Date(result.expires_at) < new Date()) { - this.db.prepare('DELETE FROM ai_context_cache WHERE workspace_root = ? AND context_key = ?') - .run(workspaceRoot, key); - return null; - } - - return JSON.parse(result.context_value); - } - - /** - * Clean expired cache - */ - cleanExpiredCache() { - if (!this.db) throw new Error('Database not initialized'); - - const now = new Date().toISOString(); - const result = this.db.prepare(` - DELETE FROM ai_context_cache - WHERE expires_at IS NOT NULL AND expires_at < ? - `).run(now); - - return result.changes; - } - - /** - * Execute raw query (use with caution) - */ - query(sql, params = []) { - if (!this.db) throw new Error('Database not initialized'); - return this.db.prepare(sql).all(...params); - } - - /** - * Close database connection - */ - close() { - if (this.db) { - this.db.close(); - this.db = null; - } - } - - /** - * Get database info - */ - getInfo() { - if (!this.db) throw new Error('Database not initialized'); - - const tables = this.db.prepare(` - SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'ai_%' - `).all(); - - return { - path: this.dbPath, - initialized: this.isInitialized, - tables: tables.map(t => t.name) - }; - } -} - -module.exports = DatabaseManager; diff --git a/ai/database/LegacyMigrations.js b/ai/database/LegacyMigrations.js deleted file mode 100644 index bfbd0536..00000000 --- a/ai/database/LegacyMigrations.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * Database migrations for AI agent features - * Extends the existing app.sqlite with vector embeddings, relationships, and learning tables - */ - -const MIGRATIONS = [ - { - version: 1, - name: 'create_ai_document_embeddings', - sql: ` - CREATE TABLE IF NOT EXISTS ai_document_embeddings ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - file_path TEXT NOT NULL UNIQUE, - content_hash TEXT NOT NULL, - embedding_vector BLOB, - embedding_model TEXT DEFAULT 'gemini-embedding-001', - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); - CREATE INDEX idx_ai_embeddings_file_path ON ai_document_embeddings(file_path); - CREATE INDEX idx_ai_embeddings_created_at ON ai_document_embeddings(created_at); - ` - }, - { - version: 2, - name: 'create_ai_document_relationships', - sql: ` - CREATE TABLE IF NOT EXISTS ai_document_relationships ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - source_file TEXT NOT NULL, - target_file TEXT NOT NULL, - relationship_type TEXT NOT NULL CHECK(relationship_type IN ('references', 'related', 'sibling', 'dependency', 'parent', 'child')), - strength REAL DEFAULT 0.5 CHECK(strength >= 0 AND strength <= 1), - metadata TEXT, - detected_at TEXT NOT NULL, - UNIQUE(source_file, target_file, relationship_type) - ); - CREATE INDEX idx_ai_relationships_source ON ai_document_relationships(source_file); - CREATE INDEX idx_ai_relationships_target ON ai_document_relationships(target_file); - CREATE INDEX idx_ai_relationships_type ON ai_document_relationships(relationship_type); - ` - }, - { - version: 3, - name: 'create_ai_interactions', - sql: ` - CREATE TABLE IF NOT EXISTS ai_interactions ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - query TEXT NOT NULL, - response TEXT, - file_context TEXT, - workspace_root TEXT NOT NULL, - interaction_type TEXT DEFAULT 'query' CHECK(interaction_type IN ('query', 'refactor', 'format', 'summarize', 'search')), - model_used TEXT, - tokens_used INTEGER, - timestamp TEXT NOT NULL, - helpful_rating INTEGER CHECK(helpful_rating IN (-1, 0, 1)), - rated_at TEXT - ); - CREATE INDEX idx_ai_interactions_workspace ON ai_interactions(workspace_root); - CREATE INDEX idx_ai_interactions_timestamp ON ai_interactions(timestamp); - CREATE INDEX idx_ai_interactions_type ON ai_interactions(interaction_type); - ` - }, - { - version: 4, - name: 'create_ai_patterns', - sql: ` - CREATE TABLE IF NOT EXISTS ai_patterns ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - workspace_root TEXT NOT NULL, - pattern_type TEXT NOT NULL CHECK(pattern_type IN ('editing_style', 'favorite_formats', 'common_queries', 'refactor_preferences', 'documentation_style')), - pattern_name TEXT NOT NULL, - pattern_data TEXT NOT NULL, - frequency INTEGER DEFAULT 1, - confidence REAL DEFAULT 0.5 CHECK(confidence >= 0 AND confidence <= 1), - first_seen TEXT NOT NULL, - last_seen TEXT NOT NULL, - UNIQUE(workspace_root, pattern_type, pattern_name) - ); - CREATE INDEX idx_ai_patterns_workspace ON ai_patterns(workspace_root); - CREATE INDEX idx_ai_patterns_type ON ai_patterns(pattern_type); - ` - }, - { - version: 5, - name: 'create_ai_context_cache', - sql: ` - CREATE TABLE IF NOT EXISTS ai_context_cache ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - workspace_root TEXT NOT NULL, - context_key TEXT NOT NULL, - context_value TEXT NOT NULL, - created_at TEXT NOT NULL, - expires_at TEXT, - UNIQUE(workspace_root, context_key) - ); - CREATE INDEX idx_ai_cache_workspace ON ai_context_cache(workspace_root); - CREATE INDEX idx_ai_cache_expires ON ai_context_cache(expires_at); - ` - }, - { - version: 6, - name: 'create_ai_migrations_log', - sql: ` - CREATE TABLE IF NOT EXISTS ai_migrations_log ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - migration_version INTEGER NOT NULL UNIQUE, - migration_name TEXT NOT NULL, - applied_at TEXT NOT NULL, - status TEXT DEFAULT 'applied' CHECK(status IN ('applied', 'rolled_back')) - ); - ` - }, - { - version: 7, - name: 'repair_ai_foreign_keys_for_history_schema', - sql: ` - PRAGMA foreign_keys = OFF; - - CREATE TABLE IF NOT EXISTS ai_document_embeddings_new ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - file_path TEXT NOT NULL UNIQUE, - content_hash TEXT NOT NULL, - embedding_vector BLOB, - embedding_model TEXT DEFAULT 'gemini-embedding-001', - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); - INSERT OR REPLACE INTO ai_document_embeddings_new (id, file_path, content_hash, embedding_vector, embedding_model, created_at, updated_at) - SELECT id, file_path, content_hash, embedding_vector, embedding_model, created_at, updated_at - FROM ai_document_embeddings; - DROP TABLE IF EXISTS ai_document_embeddings; - ALTER TABLE ai_document_embeddings_new RENAME TO ai_document_embeddings; - CREATE INDEX IF NOT EXISTS idx_ai_embeddings_file_path ON ai_document_embeddings(file_path); - CREATE INDEX IF NOT EXISTS idx_ai_embeddings_created_at ON ai_document_embeddings(created_at); - - CREATE TABLE IF NOT EXISTS ai_document_relationships_new ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - source_file TEXT NOT NULL, - target_file TEXT NOT NULL, - relationship_type TEXT NOT NULL CHECK(relationship_type IN ('references', 'related', 'sibling', 'dependency', 'parent', 'child')), - strength REAL DEFAULT 0.5 CHECK(strength >= 0 AND strength <= 1), - metadata TEXT, - detected_at TEXT NOT NULL, - UNIQUE(source_file, target_file, relationship_type) - ); - INSERT OR REPLACE INTO ai_document_relationships_new (id, source_file, target_file, relationship_type, strength, metadata, detected_at) - SELECT id, source_file, target_file, relationship_type, strength, metadata, detected_at - FROM ai_document_relationships; - DROP TABLE IF EXISTS ai_document_relationships; - ALTER TABLE ai_document_relationships_new RENAME TO ai_document_relationships; - CREATE INDEX IF NOT EXISTS idx_ai_relationships_source ON ai_document_relationships(source_file); - CREATE INDEX IF NOT EXISTS idx_ai_relationships_target ON ai_document_relationships(target_file); - CREATE INDEX IF NOT EXISTS idx_ai_relationships_type ON ai_document_relationships(relationship_type); - - CREATE TABLE IF NOT EXISTS ai_context_cache_new ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - workspace_root TEXT NOT NULL, - context_key TEXT NOT NULL, - context_value TEXT NOT NULL, - created_at TEXT NOT NULL, - expires_at TEXT, - UNIQUE(workspace_root, context_key) - ); - INSERT OR REPLACE INTO ai_context_cache_new (id, workspace_root, context_key, context_value, created_at, expires_at) - SELECT id, workspace_root, context_key, context_value, created_at, expires_at - FROM ai_context_cache; - DROP TABLE IF EXISTS ai_context_cache; - ALTER TABLE ai_context_cache_new RENAME TO ai_context_cache; - CREATE INDEX IF NOT EXISTS idx_ai_cache_workspace ON ai_context_cache(workspace_root); - CREATE INDEX IF NOT EXISTS idx_ai_cache_expires ON ai_context_cache(expires_at); - - PRAGMA foreign_keys = ON; - ` - } -]; - -/** - * Get all pending migrations - * @param {number} currentVersion - Current schema version - * @returns {Array} Pending migrations - */ -function getPendingMigrations(currentVersion = 0) { - return MIGRATIONS.filter(m => m.version > currentVersion); -} - -/** - * Get migration by version - * @param {number} version - Migration version - * @returns {Object|null} Migration object or null - */ -function getMigration(version) { - return MIGRATIONS.find(m => m.version === version) || null; -} - -module.exports = { - MIGRATIONS, - getPendingMigrations, - getMigration -}; diff --git a/ai/database/index.js b/ai/database/index.js deleted file mode 100644 index d8bb462a..00000000 --- a/ai/database/index.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Database Module Facade - * Single entry point for legacy database manager and SQLite migration runners. - */ - -const DatabaseManager = require('./LegacyDBManager'); -const LegacyMigrations = require('./LegacyMigrations'); - -module.exports = { - DatabaseManager, - LegacyMigrations, - - createDatabaseManager: (dbPath) => new DatabaseManager(dbPath) -}; diff --git a/ai/embeddings/HuggingFaceEmbeddingProvider.js b/ai/embeddings/HuggingFaceEmbeddingProvider.js new file mode 100644 index 00000000..a4e27a8f --- /dev/null +++ b/ai/embeddings/HuggingFaceEmbeddingProvider.js @@ -0,0 +1,179 @@ +/** + * HuggingFaceEmbeddingProvider - Embeddings via the HuggingFace Inference API. + * + * WHY THIS EXISTS + * --------------- + * Groq (and most fast-inference providers) do not expose an embeddings endpoint. + * Gemini does, but it requires the user to have a Gemini API key. We want + * embeddings to work for *any* combination of text provider and hardware, without + * expecting a powerful local machine. + * + * The HuggingFace Inference API solves this: + * - Free tier: no credit card, generous daily quota (~1 000 req/day) + * - Cloud inference: no GPU/RAM requirements on the user's machine + * - Simple token: one HF account, one token, all models + * + * MODEL + * ----- + * Default: sentence-transformers/all-MiniLM-L6-v2 + * - 384-dimensional vectors + * - Excellent semantic quality for document similarity + * - Small and fast on HF shared infrastructure + * + * INTERFACE + * --------- + * This class deliberately does NOT extend LLMProvider/OpenAICompatibleProvider + * because it is embedding-only — it has no generateText / generateChatCompletion. + * EmbeddingService is injected with this provider directly and calls only + * generateEmbeddings(). + */ + +const HttpClient = require('../utils/HttpClient'); +const { createLogger } = require('../core/logger'); + +const log = createLogger('HuggingFaceEmbeddingProvider'); + +const HF_API_BASE = 'https://api-inference.huggingface.co/pipeline/feature-extraction'; +const DEFAULT_MODEL = 'sentence-transformers/all-MiniLM-L6-v2'; + +// HF cold-start on shared infra can take ~20s for the first request. +const HF_TIMEOUT_MS = 30000; + +class HuggingFaceEmbeddingProvider { + /** + * @param {string} token - HuggingFace API token (hf_…) + * @param {Object} [config] + * @param {string} [config.model] - Override embedding model + */ + constructor(token, config = {}) { + this.name = 'HuggingFace'; + this.token = token; + this.model = config.model || DEFAULT_MODEL; + this.http = new HttpClient({ requestTimeoutMs: HF_TIMEOUT_MS, maxRetries: 2 }); + this.isInitialized = false; + } + + // ── Lifecycle ────────────────────────────────────────────────────────────── + + async initialize() { + this._validate(); + await this._testConnection(); + this.isInitialized = true; + log.info(`Initialized with model: ${this.model}`); + return true; + } + + _validate() { + if (!this.token || typeof this.token !== 'string' || !this.token.trim()) { + throw new Error('HuggingFace API token is required'); + } + } + + async isAvailable() { + return this.isInitialized; + } + + // ── Embeddings ───────────────────────────────────────────────────────────── + + /** + * Generate embedding vector(s) for one or more texts. + * + * HF feature-extraction returns: + * single string → float[] (1-D vector) + * string[] → float[][] (one vector per input) + * + * We normalise both cases so callers always get what they asked for. + * + * @param {string|string[]} texts + * @returns {Promise} + */ + async generateEmbeddings(texts) { + if (!this.isInitialized) throw new Error('HuggingFace provider not initialized'); + + const isArray = Array.isArray(texts); + const inputs = isArray ? texts : [String(texts)]; + + // HF expects { inputs: string | string[] } + const response = await this.http.fetchWithRetry( + `${HF_API_BASE}/${encodeURIComponent(this.model)}`, + { + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.token}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ inputs }), + } + ); + + if (!response.ok) { + const err = await response.json().catch(() => ({})); + const msg = err?.error || response.statusText; + + // HF returns 503 when the model is loading (cold start). + if (response.status === 503) { + throw new Error(`HuggingFace model is loading — retry in a moment. (${msg})`); + } + throw new Error(`HuggingFace API error ${response.status}: ${msg}`); + } + + const data = await response.json(); + + // Normalise: HF may return float[][] (one vector per input) or a nested + // array when inputs is a single string. Flatten to match what was requested. + const vectors = this._normaliseResponse(data, inputs.length); + + return isArray ? vectors : vectors[0]; + } + + // ── Internal ─────────────────────────────────────────────────────────────── + + /** + * Normalise HF response to always be an array of flat number vectors. + * @private + */ + _normaliseResponse(data, expectedCount) { + // If data is already float[][] of the right length — use as-is. + if (Array.isArray(data) && data.length === expectedCount && Array.isArray(data[0]) && typeof data[0][0] === 'number') { + return data; + } + + // Single vector returned as float[] — wrap in array. + if (Array.isArray(data) && typeof data[0] === 'number') { + return [data]; + } + + // Some models return [[float[]]] (extra nesting from mean-pooling). + if (Array.isArray(data) && Array.isArray(data[0]) && Array.isArray(data[0][0])) { + return data.map((item) => item[0]); + } + + throw new Error(`Unexpected HuggingFace embedding response shape: ${JSON.stringify(data).slice(0, 120)}`); + } + + /** + * Minimal connectivity check — embed a short string and verify we get a vector back. + * @private + */ + async _testConnection() { + try { + const result = await this.generateEmbeddings('test'); + if (!Array.isArray(result) || result.length === 0) { + throw new Error('Empty embedding vector returned'); + } + } catch (error) { + throw new Error(`HuggingFace connection test failed: ${error.message}`); + } + } + + getCapabilities() { + return { + supportsEmbeddings: true, + supportsChatCompletion: false, + model: this.model, + dimensions: 384, // all-MiniLM-L6-v2 default + }; + } +} + +module.exports = { HuggingFaceEmbeddingProvider, HF_API_BASE, DEFAULT_MODEL }; diff --git a/ai/embeddings/index.js b/ai/embeddings/index.js index c096197f..f47f0104 100644 --- a/ai/embeddings/index.js +++ b/ai/embeddings/index.js @@ -6,12 +6,15 @@ const EmbeddingDB = require('./EmbeddingDB'); const EmbeddingService = require('./EmbeddingService'); const ONNXEmbedder = require('./ONNXEmbedder'); +const HuggingFaceEmbeddingProvider = require('./HuggingFaceEmbeddingProvider'); module.exports = { EmbeddingDB, EmbeddingService, ONNXEmbedder, + HuggingFaceEmbeddingProvider, createEmbeddingDB: (workspaceRoot) => new EmbeddingDB(workspaceRoot), createEmbeddingService: (db, provider) => new EmbeddingService(db, provider) }; + diff --git a/ai/formatter/TaskSummaryFormatter.js b/ai/formatter/TaskSummaryFormatter.js deleted file mode 100644 index fbc1024b..00000000 --- a/ai/formatter/TaskSummaryFormatter.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * TaskSummaryFormatter - Deterministic task response formatter - * Formats task arrays directly into structured Markdown without LLM overhead. - */ - -function formatFileUriLink(filePath, label) { - const filename = label || (filePath ? filePath.split(/[\\/]/).pop() : 'note.md'); - if (!filePath) return `[${filename}]`; - const normPath = String(filePath).replace(/\\/g, '/'); - const fileUri = normPath.startsWith('/') ? normPath : '/' + normPath; - return `[${filename}](file://${fileUri})`; -} - -function TaskSummaryFormatter(tasks = []) { - if (!Array.isArray(tasks) || tasks.length === 0) { - return 'No open tasks found in your workspace notes.'; - } - - const openTasks = tasks.filter(t => !t.status || t.status === 'open' || t.status === 'in-progress'); - const totalOpen = openTasks.length > 0 ? openTasks.length : tasks.length; - const listToFormat = openTasks.length > 0 ? openTasks : tasks; - - const grouped = new Map(); - for (const t of listToFormat) { - const key = t.path || t.filePath || t.note || 'workspace'; - if (!grouped.has(key)) { - grouped.set(key, []); - } - grouped.get(key).push(t); - } - - let md = `## Workspace Task Summary\nFound a total of ${totalOpen} open task${totalOpen === 1 ? '' : 's'} across ${grouped.size} note${grouped.size === 1 ? '' : 's'}.\n\n### Open Tasks by Note\n`; - - for (const [notePath, noteTasks] of grouped.entries()) { - const noteName = noteTasks[0]?.note || (notePath ? notePath.split(/[\\/]/).pop() : 'note.md'); - const linkStr = formatFileUriLink(notePath, noteName); - md += `- **${linkStr}**: ${noteTasks.length} open task${noteTasks.length === 1 ? '' : 's'}\n`; - noteTasks.forEach((task, idx) => { - const lineStr = task.line ? ` (Line ${task.line})` : ''; - const text = task.text || task.task || task.content || 'Task'; - md += ` ${idx + 1}. ${text}${lineStr}\n`; - }); - } - - return md.trim(); -} - -module.exports = { - TaskSummaryFormatter, - formatFileUriLink -}; diff --git a/ai/formatter/index.js b/ai/formatter/index.js deleted file mode 100644 index 651b2a66..00000000 --- a/ai/formatter/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Formatter Module Facade - * Single entry point for response formatting, markdown clean-up, evidence context formatting, and citation links. - */ - -const { formatResponse } = require('../utils/aiUtils'); -const { TaskSummaryFormatter, formatFileUriLink } = require('./TaskSummaryFormatter'); - -module.exports = { - formatResponse, - TaskSummaryFormatter, - formatFileUriLink, - - formatToolOutput: (val) => { - if (typeof val === 'string') return val.trim(); - if (Array.isArray(val)) { - return val.map(item => { - if (typeof item === 'string') return `- ${item}`; - if (item.title || item.note || item.file || item.path) { - const label = item.title || item.note || item.file || item.path; - const detail = item.snippet || item.text || item.content || ''; - return `- **${label}**: ${detail}`; - } - return `- ${JSON.stringify(item)}`; - }).join('\n'); - } - if (typeof val === 'object' && val !== null) { - const label = val.title || val.note || val.file || val.path || 'Details'; - const detail = val.snippet || val.text || val.content || JSON.stringify(val); - return `- **${label}**: ${detail}`; - } - return String(val || ''); - } -}; diff --git a/ai/graph/semantic/SemanticExtractionEngine.js b/ai/graph/semantic/SemanticExtractionEngine.js index 8beb9d61..132778d0 100644 --- a/ai/graph/semantic/SemanticExtractionEngine.js +++ b/ai/graph/semantic/SemanticExtractionEngine.js @@ -7,9 +7,11 @@ const fs = require('fs'); const path = require('path'); const { createLogger } = require('../../core/logger'); const GLiNER2RelexAdapter = require('./adapters/GLiNER2RelexAdapter'); +const LLMGraphAdapter = require('./adapters/LLMGraphAdapter'); const ExtractionValidator = require('./validators/ExtractionValidator'); const { ExtractionResult } = require('./schemas/ExtractionResult'); + const log = createLogger('SemanticExtractionEngine'); class SemanticExtractionEngine { @@ -73,8 +75,15 @@ class SemanticExtractionEngine { path: this.config.path || 'models/gliner2-relex', appDataDir: this.appDataDir }); + } else if (provider === 'llm' || provider === 'gemini' || provider === 'groq' || provider === 'openai' || provider === 'cloud') { + this.adapter = new LLMGraphAdapter({ + providerInstance: this.config.providerInstance, + getProvider: this.config.getProvider, + modelId: this.config.modelId || modelName, + appDataDir: this.appDataDir + }); } else { - throw new Error(`Unknown semantic extraction provider: "${provider}". Supported: "onnx" (GLiNER2-Relex). Check ai-models.json.`); + throw new Error(`Unknown semantic extraction provider: "${provider}". Supported: "onnx" (GLiNER2-Relex), "llm" (Gemini/Groq/OpenAI).`); } } return this.adapter; diff --git a/ai/graph/semantic/adapters/LLMGraphAdapter.js b/ai/graph/semantic/adapters/LLMGraphAdapter.js new file mode 100644 index 00000000..87a25b4a --- /dev/null +++ b/ai/graph/semantic/adapters/LLMGraphAdapter.js @@ -0,0 +1,187 @@ +/** + * LLMGraphAdapter - Cloud LLM-powered Semantic Graph Extraction Adapter + * Supports Gemini, Groq, OpenAI, and compatible providers for Entity & Relation Extraction. + */ + +const ModelAdapter = require('../ModelAdapter'); +const { Entity, Relationship, Evidence, ExtractionResult } = require('../schemas/ExtractionResult'); +const { createLogger } = require('../../../core/logger'); + +const log = createLogger('LLMGraphAdapter'); + +const EXTRACTION_SYSTEM_PROMPT = `You are an expert knowledge graph extraction engine. +Analyze the provided document text and extract: +1. Significant Named Entities (People, Concepts, Tools, Technologies, Organizations, Projects, Topics). +2. Direct Semantic Relationships between the extracted entities. + +Return ONLY a valid JSON object matching this exact schema: +{ + "entities": [ + { "name": "Entity Name", "type": "Person|Concept|Tool|Technology|Organization|Project|Topic", "confidence": 0.95 } + ], + "relations": [ + { "source": "Entity Name 1", "target": "Entity Name 2", "type": "USES|RELATED_TO|PART_OF|DEPENDS_ON|CREATES|HAS_PERSON|BELONGS_TO", "confidence": 0.90, "sentence": "Context sentence explaining relation." } + ] +}`; + +class LLMGraphAdapter extends ModelAdapter { + constructor(config = {}) { + super(config); + this.provider = config.provider || null; // LLM Provider instance or name + this.providerInstance = config.providerInstance || null; + this.appDataDir = config.appDataDir || null; + this.modelId = config.modelId || config.model || 'cloud-llm'; + this.isLoaded = false; + } + + async load() { + this.isLoaded = true; + return true; + } + + /** + * Execute extraction via Cloud LLM + */ + async extract(document, _options = {}) { + const text = document?.content || ''; + const sourceFile = document?.id || document?.sourceFile || 'unknown'; + + if (!text.trim()) { + return new ExtractionResult({ entities: [], relations: [], evidence: [] }); + } + + // Limit text length to prevent context explosion + const truncatedText = text.length > 8000 ? text.slice(0, 8000) + '\n...(truncated)' : text; + + try { + let promptProvider = this.providerInstance; + if (!promptProvider && this.config.getProvider) { + promptProvider = this.config.getProvider(); + } + + if (!promptProvider) { + log.warn('No active LLM provider configured for graph extraction.'); + return new ExtractionResult({ entities: [], relations: [], evidence: [] }); + } + + const prompt = `Document:\n"""\n${truncatedText}\n"""\n\nExtract entities and relationships as JSON:`; + const rawOutput = await promptProvider.generateText(prompt, { + systemPrompt: EXTRACTION_SYSTEM_PROMPT, + temperature: 0.1 + }); + + const responseText = typeof rawOutput === 'string' ? rawOutput : rawOutput?.text || ''; + return this._parseJsonResponse(responseText, sourceFile); + } catch (err) { + log.error(`LLM graph extraction failed for ${sourceFile}:`, err.message); + return new ExtractionResult({ entities: [], relations: [], evidence: [] }); + } + } + + _parseJsonResponse(rawText, sourceFile) { + let cleanJson = rawText.trim(); + if (cleanJson.startsWith('```')) { + cleanJson = cleanJson.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim(); + } + + let parsed = null; + try { + parsed = JSON.parse(cleanJson); + } catch { + const match = cleanJson.match(/\{[\s\S]*\}/); + if (match) { + try { parsed = JSON.parse(match[0]); } catch { /* ignore */ } + } + } + + if (!parsed || (!Array.isArray(parsed.entities) && !Array.isArray(parsed.relations))) { + return new ExtractionResult({ entities: [], relations: [], evidence: [] }); + } + + const entityMap = new Map(); + const entities = []; + const evidenceList = []; + + for (const rawEnt of parsed.entities || []) { + if (!rawEnt?.name || typeof rawEnt.name !== 'string') continue; + const name = rawEnt.name.trim(); + if (!name || name.length < 2) continue; + + const type = rawEnt.type || 'Concept'; + const conf = typeof rawEnt.confidence === 'number' ? rawEnt.confidence : 0.9; + const ev = new Evidence({ + sourceFile, + rawSnippet: name, + extractionModel: this.modelId, + confidence: conf + }); + + try { + const entity = new Entity({ + text: name, + canonicalName: name, + type, + confidence: conf, + sourceEvidence: ev + }); + entityMap.set(name.toLowerCase(), entity); + entities.push(entity); + evidenceList.push(ev); + } catch { /* ignore entity validation error */ } + } + + const relations = []; + for (const rawRel of parsed.relations || []) { + if (!rawRel?.source || !rawRel?.target) continue; + const srcName = String(rawRel.source).trim(); + const tgtName = String(rawRel.target).trim(); + if (!srcName || !tgtName || srcName.toLowerCase() === tgtName.toLowerCase()) continue; + + let srcEnt = entityMap.get(srcName.toLowerCase()); + let tgtEnt = entityMap.get(tgtName.toLowerCase()); + + if (!srcEnt) { + srcEnt = new Entity({ text: srcName, type: 'Concept', confidence: 0.8 }); + entityMap.set(srcName.toLowerCase(), srcEnt); + entities.push(srcEnt); + } + if (!tgtEnt) { + tgtEnt = new Entity({ text: tgtName, type: 'Concept', confidence: 0.8 }); + entityMap.set(tgtName.toLowerCase(), tgtEnt); + entities.push(tgtEnt); + } + + const relType = rawRel.type || 'RELATED_TO'; + const conf = typeof rawRel.confidence === 'number' ? rawRel.confidence : 0.85; + const ev = new Evidence({ + sourceFile, + rawSnippet: rawRel.sentence || `${srcName} -> ${tgtName}`, + extractionModel: this.modelId, + confidence: conf + }); + + try { + const relationship = new Relationship({ + sourceEntityId: srcEnt.id, + targetEntityId: tgtEnt.id, + relationType: relType, + confidence: conf, + sourceEvidence: ev, + sourceText: srcName, + targetText: tgtName + }); + relations.push(relationship); + evidenceList.push(ev); + } catch { /* ignore relationship error */ } + } + + return new ExtractionResult({ + entities, + relations, + evidence: evidenceList, + metadata: { model: this.modelId, provider: 'cloud-llm' } + }); + } +} + +module.exports = LLMGraphAdapter; diff --git a/ai/index.js b/ai/index.js index e2ed536e..70dc4ec5 100644 --- a/ai/index.js +++ b/ai/index.js @@ -3,8 +3,7 @@ * Bootstrap file to initialize all AI components */ -const { DatabaseManager } = require('./database'); -const { LLMRegistry, HuggingFaceEmbeddingProvider } = require('./providers'); +const { HuggingFaceEmbeddingProvider } = require('./embeddings'); const Agent = require('./core/Agent'); const AIConfig = require('./core/AIConfig'); const { createLogger } = require('./core/logger'); @@ -18,10 +17,10 @@ let aiConfig = null; * Initialize AI agent system * @param {string} appDataDir * @param {string} workspaceRoot - * @param {object|null} llmProvider - { name, config } for text generation + * @param {object|null} llmProvider * @param {object|null} embeddingConfig - { token, model? } for HuggingFace embeddings */ -async function initializeAISystem(appDataDir, workspaceRoot, llmProvider, embeddingConfig = null) { +async function initializeAISystem(appDataDir, workspaceRoot, llmProvider = null, embeddingConfig = null) { try { console.log('[AI System] Initializing for workspace:', workspaceRoot); @@ -53,12 +52,7 @@ async function initializeAISystem(appDataDir, workspaceRoot, llmProvider, embedd } aiConfig = new AIConfig(); - - const databaseManager = new DatabaseManager(appDataDir); - databaseManager.initialize(); - - const llmRegistry = new LLMRegistry(); - aiAgent = new Agent(databaseManager, llmRegistry); + aiAgent = new Agent(); // Initialize embedding provider independently of the text provider. const prefs = aiConfig.loadPreferences(); @@ -103,8 +97,6 @@ async function initializeAISystem(appDataDir, workspaceRoot, llmProvider, embedd const result = await aiAgent.initialize(workspaceRoot, llmProvider); - // Local ONNX LLM provider (SmolLM2) is executed strictly inside background utilityProcess to prevent UI freezes - // Boot local BGE embeddings SQLite database & offload worker queue to background process try { const workerManager = require('../electron/ai/workerManager.cjs'); @@ -125,7 +117,7 @@ async function initializeAISystem(appDataDir, workspaceRoot, llmProvider, embedd console.warn('[AI System] Background Index Worker failed to boot:', embBootErr.message); } - // Context and Retrievers initialization (pure capability retrieval) + // Graph initialization try { if (aiAgent.embeddingDb && aiAgent.embeddingService) { const { GraphDB } = require('./graph'); @@ -180,13 +172,16 @@ function shutdownAISystem() { console.log('[AI System] Shutdown complete'); } +const { LLMRegistry } = require('./providers'); + module.exports = { initializeAISystem, getAIAgent, getAIConfig, shutdownAISystem, AIAgent: Agent, - DatabaseManager, LLMRegistry, AIConfig }; + + diff --git a/ai/memory/InteractionLog.js b/ai/memory/InteractionLog.js deleted file mode 100644 index 97b15138..00000000 --- a/ai/memory/InteractionLog.js +++ /dev/null @@ -1,204 +0,0 @@ -/** - * MemoryManager - Manages agent memory, patterns, and learning - */ - -class MemoryManager { - constructor(databaseManager) { - this.db = databaseManager; - this.sessionMemory = { - interactions: [], - patterns: [], - learnings: [] - }; - } - - /** - * Record user interaction - */ - recordInteraction(query, response, filePath, workspaceRoot, type = 'query', model = null, tokensUsed = 0) { - try { - this.db.recordInteraction(query, response, filePath, workspaceRoot, type, model, tokensUsed); - - // Add to session memory - this.sessionMemory.interactions.push({ - query, - response, - filePath, - type, - timestamp: new Date().toISOString(), - tokensUsed - }); - - // Keep session memory bounded - if (this.sessionMemory.interactions.length > 100) { - this.sessionMemory.interactions.shift(); - } - - return true; - } catch (error) { - console.error('[MemoryManager] Failed to record interaction:', error.message); - return false; - } - } - - /** - * Rate an interaction - */ - rateInteraction(interactionId, rating) { - try { - this.db.rateInteraction(interactionId, rating); - return true; - } catch (error) { - console.error('[MemoryManager] Failed to rate interaction:', error.message); - return false; - } - } - - /** - * Detect and record patterns - */ - detectPatterns(workspaceRoot) { - try { - const interactions = this.db.getRecentInteractions(workspaceRoot, 50); - - if (interactions.length === 0) { - return []; - } - - const patterns = []; - - // Detect interaction type patterns - const typeFrequency = {}; - interactions.forEach(i => { - typeFrequency[i.interaction_type] = (typeFrequency[i.interaction_type] || 0) + 1; - }); - - for (const [type, count] of Object.entries(typeFrequency)) { - const frequency = count / interactions.length; - if (frequency > 0.2) { - patterns.push({ - type: 'interaction_pattern', - name: `prefers_${type}_queries`, - data: { type, frequency }, - confidence: frequency - }); - - this.db.addPattern( - workspaceRoot, - 'common_queries', - `prefers_${type}_queries`, - { type, frequency }, - frequency - ); - } - } - - // Detect time-based patterns - const timePatterns = this._analyzeTimePatterns(interactions); - patterns.push(...timePatterns); - - return patterns; - } catch (error) { - console.error('[MemoryManager] Pattern detection failed:', error.message); - return []; - } - } - - /** - * Get learned patterns - */ - getPatterns(workspaceRoot, type, minConfidence = 0.3) { - try { - return this.db.getPatterns(workspaceRoot, type, minConfidence); - } catch (error) { - console.error('[MemoryManager] Failed to get patterns:', error.message); - return []; - } - } - - /** - * Get recent interactions - */ - getRecentInteractions(workspaceRoot, limit = 20, type = null) { - try { - return this.db.getRecentInteractions(workspaceRoot, limit, type); - } catch (error) { - console.error('[MemoryManager] Failed to get interactions:', error.message); - return []; - } - } - - /** - * Get personalized context - */ - getPersonalizedContext(workspaceRoot) { - try { - const patterns = this.db.getPatterns(workspaceRoot, 'common_queries', 0.3); - const recentInteractions = this.db.getRecentInteractions(workspaceRoot, 10); - - return { - learnedPatterns: patterns, - recentActivity: recentInteractions, - personalizedAt: new Date().toISOString() - }; - } catch (error) { - console.error('[MemoryManager] Failed to get personalized context:', error.message); - return null; - } - } - - /** - * Analyze time-based patterns - * @private - */ - _analyzeTimePatterns(interactions) { - const patterns = []; - const hours = {}; - - interactions.forEach(i => { - const date = new Date(i.timestamp); - const hour = date.getHours(); - hours[hour] = (hours[hour] || 0) + 1; - }); - - // Find peak hours - const sorted = Object.entries(hours) - .sort((a, b) => b[1] - a[1]) - .slice(0, 3); - - if (sorted.length > 0) { - patterns.push({ - type: 'time_pattern', - name: 'peak_activity_hours', - data: { hours: sorted.map(s => parseInt(s[0])) }, - confidence: sorted[0][1] / interactions.length - }); - } - - return patterns; - } - - /** - * Get session summary - */ - getSessionSummary() { - return { - sessionInteractions: this.sessionMemory.interactions.length, - sessionPatterns: this.sessionMemory.patterns.length, - timestamp: new Date().toISOString() - }; - } - - /** - * Clear session memory - */ - clearSession() { - this.sessionMemory = { - interactions: [], - patterns: [], - learnings: [] - }; - } -} - -module.exports = MemoryManager; diff --git a/ai/memory/MemoryDB.js b/ai/memory/MemoryDB.js deleted file mode 100644 index e695d361..00000000 --- a/ai/memory/MemoryDB.js +++ /dev/null @@ -1,87 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { createLogger } = require('../core/logger'); - -const log = createLogger('MemoryDB'); - -class MemoryDB { - constructor(workspaceRoot) { - this.workspaceRoot = workspaceRoot; - this.dbPath = path.join(workspaceRoot, '.notes-app', 'ai-memory.db'); - this.db = null; - } - - initialize() { - try { - const parentDir = path.dirname(this.dbPath); - if (!fs.existsSync(parentDir)) { - fs.mkdirSync(parentDir, { recursive: true }); - } - - const { DatabaseSync } = require('node:sqlite'); - this.db = new DatabaseSync(this.dbPath); - - this.db.exec('PRAGMA journal_mode = WAL'); - this.db.exec('PRAGMA synchronous = NORMAL'); - this.db.exec('PRAGMA foreign_keys = ON'); - - this._createTables(); - log.info(`MemoryDB initialized at: ${this.dbPath}`); - return true; - } catch (err) { - log.error('Failed to initialize MemoryDB', err); - throw err; - } - } - - _createTables() { - this.db.exec(` - CREATE TABLE IF NOT EXISTS conversations ( - id TEXT PRIMARY KEY, - title TEXT NOT NULL, - persona TEXT DEFAULT 'default', - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS messages ( - id TEXT PRIMARY KEY, - conversation_id TEXT NOT NULL, - role TEXT NOT NULL, - content TEXT NOT NULL, - metadata TEXT DEFAULT NULL, - created_at TEXT NOT NULL, - FOREIGN KEY(conversation_id) REFERENCES conversations(id) ON DELETE CASCADE - ); - - CREATE TABLE IF NOT EXISTS candidate_knowledge ( - id TEXT PRIMARY KEY, - source_path TEXT NOT NULL, - entity TEXT NOT NULL, - relation TEXT NOT NULL, - target TEXT NOT NULL, - extracted_at TEXT NOT NULL, - status TEXT DEFAULT 'pending' - ); - - CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id); - CREATE INDEX IF NOT EXISTS idx_ck_status ON candidate_knowledge(status); - `); - - // Migration: add metadata column if it doesn't exist yet (existing DBs) - try { - this.db.exec('ALTER TABLE messages ADD COLUMN metadata TEXT DEFAULT NULL'); - } catch { - // Column already exists — safe to ignore - } - } - - close() { - if (this.db) { - this.db.close(); - this.db = null; - } - } -} - -module.exports = { MemoryDB }; diff --git a/ai/memory/MemoryOptimizer.js b/ai/memory/MemoryOptimizer.js deleted file mode 100644 index 216fd499..00000000 --- a/ai/memory/MemoryOptimizer.js +++ /dev/null @@ -1,221 +0,0 @@ -/** - * MemoryOptimizer - Memory management and optimization - */ - -class MemoryOptimizer { - constructor(databaseManager) { - this.db = databaseManager; - this.cacheStats = { - hits: 0, - misses: 0, - evictions: 0 - }; - } - - /** - * Analyze memory usage - */ - analyzeMemoryUsage() { - const memUsage = process.memoryUsage(); - - return { - heapUsed: this._formatBytes(memUsage.heapUsed), - heapTotal: this._formatBytes(memUsage.heapTotal), - rss: this._formatBytes(memUsage.rss), - external: this._formatBytes(memUsage.external), - arrayBuffers: this._formatBytes(memUsage.arrayBuffers), - cacheStats: { ...this.cacheStats } - }; - } - - /** - * Clean expired data - */ - cleanExpiredData() { - let cleaned = 0; - - try { - // Clean expired cache entries - const expiredCache = this.db.cleanExpiredCache(); - cleaned += expiredCache; - - // Could add more cleanup logic here - // - Remove old interactions - // - Archive old patterns - // - Compact database - - console.log(`[MemoryOptimizer] Cleaned ${cleaned} expired entries`); - return { success: true, entriesRemoved: cleaned }; - } catch (error) { - console.error('[MemoryOptimizer] Cleanup failed:', error.message); - return { success: false, error: error.message }; - } - } - - /** - * Optimize database - */ - optimizeDatabase() { - try { - // Run VACUUM to reclaim space - this.db.query('VACUUM'); - - // Rebuild indexes - this.db.query('REINDEX'); - - console.log('[MemoryOptimizer] Database optimized'); - return { success: true, message: 'Database optimized' }; - } catch (error) { - console.error('[MemoryOptimizer] Database optimization failed:', error.message); - return { success: false, error: error.message }; - } - } - - /** - * Get database statistics - */ - getDatabaseStats() { - try { - const tableStats = {}; - - const tables = [ - 'ai_document_embeddings', - 'ai_document_relationships', - 'ai_interactions', - 'ai_patterns', - 'ai_context_cache' - ]; - - for (const table of tables) { - const result = this.db.query(`SELECT COUNT(*) as count FROM ${table}`); - const sizeResult = this.db.query(`SELECT page_count * page_size as size FROM pragma_page_count(), pragma_page_size()`); - - tableStats[table] = { - rows: result[0]?.count || 0, - estimatedSize: sizeResult[0]?.size || 0 - }; - } - - return { - tables: tableStats, - timestamp: new Date().toISOString() - }; - } catch (error) { - console.error('[MemoryOptimizer] Failed to get database stats:', error.message); - return null; - } - } - - /** - * Archive old interactions - */ - archiveOldInteractions(olderThanDays = 30) { - try { - const cutoffDate = new Date(); - cutoffDate.setDate(cutoffDate.getDate() - olderThanDays); - const cutoffISO = cutoffDate.toISOString(); - - // Move old interactions to archive - const result = this.db.query(` - DELETE FROM ai_interactions - WHERE timestamp < ? - `, [cutoffISO]); - - console.log(`[MemoryOptimizer] Archived interactions older than ${olderThanDays} days`); - return { success: true, archivedCount: result }; - } catch (error) { - console.error('[MemoryOptimizer] Archiving failed:', error.message); - return { success: false, error: error.message }; - } - } - - /** - * Get optimization recommendations - */ - getOptimizationRecommendations() { - const recommendations = []; - const memUsage = process.memoryUsage(); - const heapUsagePercent = (memUsage.heapUsed / memUsage.heapTotal) * 100; - - if (heapUsagePercent > 90) { - recommendations.push({ - level: 'critical', - message: 'High memory usage detected. Consider cleaning caches.', - action: 'cleanExpiredData' - }); - } - - if (heapUsagePercent > 75) { - recommendations.push({ - level: 'warning', - message: 'Memory usage is elevated.', - action: 'optimizeDatabase' - }); - } - - const dbStats = this.getDatabaseStats(); - if (dbStats) { - let totalRows = 0; - for (const table of Object.values(dbStats.tables)) { - totalRows += table.rows; - } - - if (totalRows > 100000) { - recommendations.push({ - level: 'info', - message: 'Consider archiving old interactions to free up space.', - action: 'archiveOldInteractions' - }); - } - } - - return recommendations; - } - - /** - * Record cache hit/miss - */ - recordCacheAccess(hit) { - if (hit) { - this.cacheStats.hits += 1; - } else { - this.cacheStats.misses += 1; - } - } - - /** - * Record cache eviction - */ - recordEviction() { - this.cacheStats.evictions += 1; - } - - /** - * Get cache efficiency - */ - getCacheEfficiency() { - const total = this.cacheStats.hits + this.cacheStats.misses; - - if (total === 0) { - return 0; - } - - return ((this.cacheStats.hits / total) * 100).toFixed(2); - } - - /** - * Format bytes to readable format - * @private - */ - _formatBytes(bytes) { - if (bytes === 0) return '0 Bytes'; - - const k = 1024; - const sizes = ['Bytes', 'KB', 'MB', 'GB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - - return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]; - } -} - -module.exports = MemoryOptimizer; diff --git a/ai/memory/PatternAnalyzer.js b/ai/memory/PatternAnalyzer.js deleted file mode 100644 index dceda5fd..00000000 --- a/ai/memory/PatternAnalyzer.js +++ /dev/null @@ -1,209 +0,0 @@ -/** - * PatternDetector - Advanced pattern detection and analysis - */ - -class PatternDetector { - constructor(memoryManager, documentService) { - this.memory = memoryManager; - this.documents = documentService; - } - - /** - * Analyze user editing patterns - */ - analyzeEditingPatterns(interactions) { - const patterns = { - editFrequency: this._analyzeFrequency(interactions), - documentTypes: this._analyzeDocumentPreferences(interactions), - commandPatterns: this._analyzeCommandPatterns(interactions), - timePatterns: this._analyzeTimePatterns(interactions), - workflowPatterns: this._analyzeWorkflowPatterns(interactions) - }; - - return patterns; - } - - /** - * Analyze interaction frequency - * @private - */ - _analyzeFrequency(interactions) { - if (interactions.length === 0) return null; - - const timeSpans = []; - for (let i = 1; i < interactions.length; i++) { - const prev = new Date(interactions[i - 1].timestamp); - const curr = new Date(interactions[i].timestamp); - timeSpans.push(curr - prev); - } - - const avgTimespan = timeSpans.reduce((a, b) => a + b, 0) / timeSpans.length; - const frequency = 1000 * 60 * 60 / avgTimespan; // interactions per hour - - return { - averageInteractionSpacing: avgTimespan, - estimatedFrequencyPerHour: frequency, - totalInteractions: interactions.length - }; - } - - /** - * Analyze document type preferences - * @private - */ - _analyzeDocumentPreferences(interactions) { - const docFrequency = {}; - - interactions.forEach(i => { - if (i.file_context) { - const ext = this._getFileExtension(i.file_context); - docFrequency[ext] = (docFrequency[ext] || 0) + 1; - } - }); - - return Object.entries(docFrequency) - .sort((a, b) => b[1] - a[1]) - .map(([type, count]) => ({ - type, - frequency: count, - percentage: (count / interactions.length * 100).toFixed(2) - })); - } - - /** - * Analyze command/query patterns - * @private - */ - _analyzeCommandPatterns(interactions) { - const queryPatterns = {}; - - interactions.forEach(i => { - const type = i.interaction_type || 'general'; - if (!queryPatterns[type]) { - queryPatterns[type] = { count: 0, avgTokens: 0, totalTokens: 0 }; - } - queryPatterns[type].count += 1; - queryPatterns[type].totalTokens += i.tokens_used || 0; - }); - - // Calculate averages - for (const data of Object.values(queryPatterns)) { - data.avgTokens = data.count > 0 ? data.totalTokens / data.count : 0; - } - - return queryPatterns; - } - - /** - * Analyze time-based patterns - * @private - */ - _analyzeTimePatterns(interactions) { - const hourlyActivity = {}; - const dayActivity = {}; - - interactions.forEach(i => { - const date = new Date(i.timestamp); - const hour = date.getHours(); - const day = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][date.getDay()]; - - hourlyActivity[hour] = (hourlyActivity[hour] || 0) + 1; - dayActivity[day] = (dayActivity[day] || 0) + 1; - }); - - const peakHours = Object.entries(hourlyActivity) - .sort((a, b) => b[1] - a[1]) - .slice(0, 3) - .map(([hour, count]) => ({ hour: parseInt(hour), count })); - - const activeDays = Object.entries(dayActivity) - .sort((a, b) => b[1] - a[1]) - .map(([day, count]) => ({ day, count })); - - return { peakHours, activeDays }; - } - - /** - * Analyze workflow patterns - * @private - */ - _analyzeWorkflowPatterns(interactions) { - const workflows = []; - let currentWorkflow = []; - - // Group consecutive interactions by type - for (let i = 0; i < interactions.length; i++) { - const curr = interactions[i]; - const prev = interactions[i - 1]; - - if (!prev || curr.interaction_type === prev.interaction_type) { - currentWorkflow.push(curr); - } else { - if (currentWorkflow.length > 1) { - workflows.push({ - type: currentWorkflow[0].interaction_type, - duration: new Date(currentWorkflow[currentWorkflow.length - 1].timestamp) - - new Date(currentWorkflow[0].timestamp), - steps: currentWorkflow.length - }); - } - currentWorkflow = [curr]; - } - } - - return workflows; - } - - /** - * Detect document relationship patterns - */ - detectRelationshipPatterns(minStrength = 0.5) { - const docs = this.documents.getAllDocuments(); - - // Find frequently co-edited documents - const coEditCounts = {}; - - // Find common reference patterns - for (const doc of docs) { - const related = this.relationships.getRelatedDocuments(doc.path, null, minStrength); - - related.forEach(rel => { - const key = [doc.path, rel.target_file].sort().join('|'); - coEditCounts[key] = (coEditCounts[key] || 0) + 1; - }); - } - - // Find strong co-editing patterns - const strongPairs = Object.entries(coEditCounts) - .filter(([, count]) => count > 2) - .map(([pair, count]) => ({ - documents: pair.split('|'), - coOccurrences: count - })); - - return strongPairs; - } - - /** - * Predict next document user might want - */ - predictNextDocument(currentDoc) { - const related = this.relationships.getRelatedDocuments(currentDoc, null, 0.5); - - return related - .sort((a, b) => b.strength - a.strength) - .slice(0, 5); - } - - /** - * Get file extension - * @private - */ - _getFileExtension(filePath) { - if (!filePath) return 'unknown'; - const parts = filePath.split('.'); - return parts.length > 1 ? parts[parts.length - 1] : 'unknown'; - } -} - -module.exports = PatternDetector; diff --git a/ai/memory/index.js b/ai/memory/index.js deleted file mode 100644 index c01462da..00000000 --- a/ai/memory/index.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Memory Module Facade - * Single entry point for MemoryDB, InteractionLog, MemoryOptimizer, and PatternAnalyzer. - */ - -const { MemoryDB } = require('./MemoryDB'); -const InteractionLog = require('./InteractionLog'); -const MemoryOptimizer = require('./MemoryOptimizer'); -const PatternAnalyzer = require('./PatternAnalyzer'); - -module.exports = { - MemoryDB, - InteractionLog, - MemoryOptimizer, - PatternAnalyzer, - - createMemoryDB: (workspaceRoot) => new MemoryDB(workspaceRoot) -}; diff --git a/ai/tools/DocumentReader.js b/ai/tools/DocumentReader.js deleted file mode 100644 index b705f422..00000000 --- a/ai/tools/DocumentReader.js +++ /dev/null @@ -1,270 +0,0 @@ -/** - * DocumentService - Manages document indexing and metadata - */ - -const fs = require('fs'); -const path = require('path'); -const crypto = require('crypto'); - -class DocumentService { - constructor(databaseManager, workspaceRoot) { - this.db = databaseManager; - this.workspaceRoot = workspaceRoot; - this.documentCache = new Map(); - this.indexedFiles = new Set(); - } - - /** - * Index all markdown files in workspace with optional progress callback - * @param {Function} onProgress - Optional callback(progress) with { indexed, total } properties - */ - async indexWorkspace(onProgress) { - console.log('[DocumentService] Indexing workspace...'); - const files = this._collectMarkdownFiles(this.workspaceRoot); - const BATCH_SIZE = 50; // Process files in batches to prevent event loop blocking - - for (let i = 0; i < files.length; i += BATCH_SIZE) { - const batch = files.slice(i, i + BATCH_SIZE); - - // Process batch in parallel - await Promise.all(batch.map((filePath) => this.indexFile(filePath))); - - // Report progress - if (onProgress) { - onProgress({ indexed: i + batch.length, total: files.length }); - } - - // Yield to event loop to prevent main thread blocking - await new Promise((resolve) => setImmediate(resolve)); - } - - console.log(`[DocumentService] Indexed ${files.length} files`); - return files.length; - } - - /** - * Index a single file - */ - async indexFile(filePath) { - try { - if (!fs.existsSync(filePath)) return false; - - const content = fs.readFileSync(filePath, 'utf8'); - const hash = this._hashContent(content); - - // Cache document metadata - this.documentCache.set(filePath, { - path: filePath, - size: content.length, - hash, - indexed_at: new Date().toISOString(), - headings: this._extractHeadings(content), - links: this._extractLinks(content), - codeBlocks: this._extractCodeBlocks(content) - }); - - this.indexedFiles.add(filePath); - - // Get cached embedding - const cached = this.db.getEmbedding(filePath); - - // Skip if content hasn't changed - if (cached && cached.contentHash === hash) { - return true; - } - - return true; - } catch (error) { - console.error(`[DocumentService] Failed to index ${filePath}:`, error.message); - return false; - } - } - - /** - * Get document metadata - */ - getDocumentMetadata(filePath) { - return this.documentCache.get(filePath) || null; - } - - /** - * Search documents by query - */ - searchDocuments(query, limit = 20) { - const results = []; - - for (const [filePath, metadata] of this.documentCache) { - const score = this._calculateSearchScore(query, metadata); - if (score > 0) { - results.push({ - filePath, - ...metadata, - relevanceScore: score - }); - } - } - - return results - .sort((a, b) => b.relevanceScore - a.relevanceScore) - .slice(0, limit); - } - - /** - * Get all documents in workspace - */ - getAllDocuments() { - return Array.from(this.documentCache.values()); - } - - /** - * Get document content - */ - getDocumentContent(filePath) { - try { - if (!fs.existsSync(filePath)) return null; - return fs.readFileSync(filePath, 'utf8'); - } catch (error) { - console.error(`[DocumentService] Failed to read ${filePath}:`, error.message); - return null; - } - } - - /** - * Get workspace structure - */ - getWorkspaceStructure() { - return { - root: this.workspaceRoot, - documentCount: this.documentCache.size, - totalSize: Array.from(this.documentCache.values()) - .reduce((sum, doc) => sum + doc.size, 0), - lastUpdated: new Date().toISOString() - }; - } - - /** - * Extract headings from content - * @private - */ - _extractHeadings(content) { - const headings = []; - const lines = content.split('\n'); - - lines.forEach((line, idx) => { - const match = line.match(/^(#{1,6})\s+(.+)$/); - if (match) { - headings.push({ - level: match[1].length, - text: match[2], - line: idx + 1 - }); - } - }); - - return headings; - } - - /** - * Extract links from content - * @private - */ - _extractLinks(content) { - const links = []; - const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; - let match; - - while ((match = linkRegex.exec(content)) !== null) { - links.push({ - text: match[1], - href: match[2] - }); - } - - return links; - } - - /** - * Extract code blocks - * @private - */ - _extractCodeBlocks(content) { - const blocks = []; - const codeRegex = /```(\w+)?\n([\s\S]*?)```/g; - let match; - - while ((match = codeRegex.exec(content)) !== null) { - blocks.push({ - language: match[1] || 'text', - code: match[2] - }); - } - - return blocks; - } - - /** - * Collect all markdown files - * @private - */ - _collectMarkdownFiles(dir, files = []) { - if (!fs.existsSync(dir)) return files; - - const entries = fs.readdirSync(dir); - - for (const entry of entries) { - // Skip hidden dirs and node_modules - if (entry.startsWith('.') || entry === 'node_modules') continue; - - const fullPath = path.join(dir, entry); - const stat = fs.statSync(fullPath); - - if (stat.isDirectory()) { - this._collectMarkdownFiles(fullPath, files); - } else if (entry.endsWith('.md')) { - files.push(fullPath); - } - } - - return files; - } - - /** - * Hash content for change detection - * @private - */ - _hashContent(content) { - return crypto.createHash('sha256').update(content).digest('hex'); - } - - /** - * Calculate search score - * @private - */ - _calculateSearchScore(query, metadata) { - const queryLower = query.toLowerCase(); - let score = 0; - - // Match in headings (high weight) - metadata.headings?.forEach(h => { - if (h.text.toLowerCase().includes(queryLower)) { - score += 10; - } - }); - - // Match in links - metadata.links?.forEach(l => { - if (l.text.toLowerCase().includes(queryLower) || l.href.includes(queryLower)) { - score += 5; - } - }); - - // Match in filename - if (metadata.path.toLowerCase().includes(queryLower)) { - score += 15; - } - - return score; - } -} - -module.exports = DocumentService; diff --git a/ai/tools/QueryTools.js b/ai/tools/QueryTools.js deleted file mode 100644 index 849b4680..00000000 --- a/ai/tools/QueryTools.js +++ /dev/null @@ -1,364 +0,0 @@ -/** - * QueryTools - Shared tool definitions and runners for QueryExecutor - */ - -const getOfficialTools = (agent) => { - const officialTools = [ - { - type: 'function', - function: { - name: 'read_note', - description: 'Read the contents of a specific note file in the workspace.', - parameters: { - type: 'object', - properties: { - file_path: { - type: 'string', - description: 'The absolute path to the note file to read.' - } - }, - required: ['file_path'] - } - } - }, - { - type: 'function', - function: { - name: 'search_notes', - description: 'Search for note files containing a query string in the workspace.', - parameters: { - type: 'object', - properties: { - query: { - type: 'string', - description: 'The search term or phrase.' - } - }, - required: ['query'] - } - } - }, - { - type: 'function', - function: { - name: 'get_tasks', - description: 'Get all checklist tasks across all notes in the workspace, including open, in-progress, and completed items.', - parameters: { - type: 'object', - properties: { - status: { - type: 'string', - enum: ['all', 'open', 'completed'], - description: 'Filter tasks by status: open (unchecked), completed (checked), or all.' - } - } - } - } - }, - { - type: 'function', - function: { - name: 'list_notes', - description: 'List all note files in the workspace (optionally filtered by subfolder).', - parameters: { - type: 'object', - properties: { - subfolder: { - type: 'string', - description: 'An optional relative subfolder path within the workspace to restrict listing to.' - } - } - } - } - }, - { - type: 'function', - function: { - name: 'get_current_date', - description: 'Returns the current date and time. Use before answering questions about today, this week, upcoming, or overdue items.', - parameters: { type: 'object', properties: {} } - } - }, - { - type: 'function', - function: { - name: 'get_people', - description: 'Find people mentioned in workspace notes via @mentions or frontmatter attendees/people fields.', - parameters: { - type: 'object', - properties: { - name: { - type: 'string', - description: 'Filter to notes that mention this specific person (case-insensitive).' - } - } - } - } - }, - { - type: 'function', - function: { - name: 'create_note', - description: 'Create a new markdown note in the workspace with title, content, and optional subfolder.', - parameters: { - type: 'object', - properties: { - title: { type: 'string', description: 'Title or file name for the new note (e.g. "Project Blueprint").' }, - content: { type: 'string', description: 'Markdown body content.' }, - subfolder: { type: 'string', description: 'Optional subfolder inside workspace.' } - }, - required: ['title', 'content'] - } - } - } - ]; - - // Add semantic_search if embedding service is available - if (agent.embeddingService?.isAvailable() && agent.contextEngine?.semanticRetriever) { - officialTools.push({ - type: 'function', - function: { - name: 'semantic_search', - description: 'Search workspace notes by semantic meaning using vector similarity. Use when keyword search may miss related concepts.', - parameters: { - type: 'object', - properties: { - query: { type: 'string', description: 'The question or topic to search for by meaning.' }, - topK: { type: 'number', description: 'Number of results (default 5).' } - }, - required: ['query'] - } - } - }); - } - - // Add explore_graph if graph DB or retriever is available - if (agent.contextEngine?.graphRetriever || agent.graphDb) { - officialTools.push({ - type: 'function', - function: { - name: 'explore_graph', - description: 'Explore how a note, person, concept, technology, or topic is linked to other entities in the knowledge graph.', - parameters: { - type: 'object', - properties: { - identifier: { type: 'string', description: 'The note path, title, person name, or topic (e.g., "Bikash Panda", "Semantic Search", "ai-and-search.md") to start graph traversal from.' }, - notePath: { type: 'string', description: 'Alias for identifier.' }, - maxDepth: { type: 'number', description: 'Maximum traversal hops (default 2).' } - } - } - } - }); - } - - return officialTools; -}; - -const runTool = async (agent, name, args) => { - if (name === 'read_note') { - const filePath = args.file_path || args.filePath; - try { - const fs = require('fs'); - if (!filePath || !fs.existsSync(filePath)) { - return `Note not found: the file "${filePath}" does not exist in this workspace.`; - } - return fs.readFileSync(filePath, 'utf8'); - } catch { - return 'Could not read note file — it may be locked or inaccessible.'; - } - } - if (name === 'search_notes') { - const queryStr = args.query || ''; - try { - const fs = require('fs'); - const { extractSearchKeywords } = require('../utils/SearchQueryUtils'); - const keywords = extractSearchKeywords(queryStr); - const cleanQuery = queryStr.trim().toLowerCase(); - const files = agent.documentService ? agent.documentService._collectMarkdownFiles(agent.workspaceRoot) : []; - const results = []; - - for (const filePath of files) { - try { - const text = fs.readFileSync(filePath, 'utf8'); - const lowerPath = filePath.toLowerCase(); - const lowerText = text.toLowerCase(); - - let match = false; - if (cleanQuery && (lowerPath.includes(cleanQuery) || lowerText.includes(cleanQuery))) { - match = true; - } else if (keywords.length > 0) { - match = keywords.some(kw => lowerPath.includes(kw) || lowerText.includes(kw)); - } - - if (match) { - results.push({ path: filePath, preview: text.slice(0, 150) + '...' }); - } - } catch { - // ignore unreadable files - } - } - return JSON.stringify(results.slice(0, 10), null, 2); - } catch { - return 'Search encountered an issue — no results available.'; - } - } - if (name === 'get_tasks') { - const statusFilter = args.status || 'all'; - try { - const fs = require('fs'); - const files = agent.documentService._collectMarkdownFiles(agent.workspaceRoot); - const tasksList = []; - for (const filePath of files) { - try { - const text = fs.readFileSync(filePath, 'utf8'); - const lines = text.split(/\r?\n/); - lines.forEach((line, index) => { - const match = line.match(/^\s*[-*+]?\s*\[([ xX/])\]\s+(.+)$/); - if (match) { - const symbol = match[1].toLowerCase(); - const taskText = match[2].trim(); - const isCompleted = symbol === 'x'; - const isOpen = symbol === ' ' || symbol === '/'; - - if (statusFilter === 'open' && !isOpen) return; - if (statusFilter === 'completed' && !isCompleted) return; - - tasksList.push({ - note: filePath.split(/[\\/]/).pop(), - path: filePath, - line: index + 1, - text: taskText, - status: isCompleted ? 'completed' : symbol === '/' ? 'in-progress' : 'open' - }); - } - }); - } catch { - // ignore unreadable files - } - } - return JSON.stringify(tasksList.slice(0, 50), null, 2); - } catch { - return 'Could not retrieve tasks from workspace.'; - } - } - if (name === 'list_notes') { - const subfolder = args.subfolder || ''; - try { - const path = require('path'); - const files = agent.documentService._collectMarkdownFiles(agent.workspaceRoot); - const matchedFiles = files.filter(filePath => { - if (!subfolder) return true; - const relativePath = path.relative(agent.workspaceRoot, filePath); - return relativePath.toLowerCase().includes(subfolder.toLowerCase()); - }); - return JSON.stringify(matchedFiles.map(filePath => ({ - fileName: filePath.split(/[\\/]/).pop(), - filePath - })).slice(0, 100), null, 2); - } catch { - return 'Could not list notes in workspace.'; - } - } - if (name === 'get_current_date') { - const now = new Date(); - return JSON.stringify({ - iso: now.toISOString(), - date: now.toLocaleDateString('en-CA'), - time: now.toLocaleTimeString('en-GB', { hour12: false }), - dayOfWeek: now.toLocaleDateString('en-US', { weekday: 'long' }), - }, null, 2); - } - if (name === 'get_people') { - const filterName = (args.name || '').toLowerCase(); - try { - const files = agent.documentService._collectMarkdownFiles(agent.workspaceRoot); - const personMap = {}; - for (const filePath of files) { - try { - const text = require('fs').readFileSync(filePath, 'utf8'); - const noteName = filePath.split(/[\\/]/).pop(); - const people = new Set(); - const fmMatch = text.match(/^---\r?\n([\s\S]*?)\r?\n---/); - if (fmMatch) { - for (const field of ['attendees', 'people', 'participants', 'authors']) { - const section = fmMatch[1].match(new RegExp(`^${field}:\\s*\\n((?:\\s+-\\s+.+\\n?)*)`, 'm')); - if (section) { for (const m of section[1].matchAll(/^\s+-\s+(.+)$/gm)) people.add(m[1].trim().toLowerCase()); } - const inline = fmMatch[1].match(new RegExp(`^${field}:\\s*(.+)$`, 'm')); - if (inline) { inline[1].split(',').forEach(p => people.add(p.trim().toLowerCase())); } - } - } - for (const m of text.matchAll(/@([\w.-]+)/g)) people.add(m[1].toLowerCase()); - for (const person of people) { - if (!personMap[person]) personMap[person] = []; - personMap[person].push(noteName); - } - } catch { /* skip */ } - } - if (filterName) { - const matched = Object.entries(personMap).filter(([p]) => p.includes(filterName)).reduce((a, [p, n]) => { a[p] = n; return a; }, {}); - return JSON.stringify(matched, null, 2); - } - return JSON.stringify(personMap, null, 2); - } catch { return 'Could not retrieve people from workspace notes.'; } - } - if (name === 'semantic_search') { - try { - const queryStr = args.query || args.topic || args.q || agent.lastQuery || ''; - if (!queryStr) return 'No search query provided for semantic search.'; - const results = await agent.contextEngine.semanticRetriever.search(queryStr, args.topK || 5); - if (!results.length) return 'No semantically similar notes found.'; - return results.map((r, i) => `[${i+1}] ${r.note_path} (score: ${r.score.toFixed(3)})\n${r.content}`).join('\n\n'); - } catch { return 'Semantic search is currently unavailable.'; } - } - if (name === 'explore_graph' || name === 'explore_topic_graph' || name === 'get_graph' || name === 'knowledge.related_topics') { - const target = args.topic || args.query || args.identifier || args.notePath || args.note_path || ''; - try { - let rows = []; - const gDb = agent.graphDB || agent.graphDb || agent.contextEngine?.graphDB || agent.contextEngine?.graphDb; - if (gDb && typeof gDb.traversePathOrId === 'function') { - rows = gDb.traversePathOrId(target, args.maxDepth || 2); - } else if (agent.contextEngine?.graphRetriever) { - rows = agent.contextEngine.graphRetriever.traverse(target, args.maxDepth || 2); - } - if (!rows || !rows.length) return `No knowledge graph connections found for: "${target}"`; - return rows.map(r => { - let line = `[(${r.from_type || 'Entity'}) ${r.from_name || r.from_path}] --[${r.relation}]--> [(${r.to_type || 'Entity'}) ${r.to_name || r.to_path}]`; - if (r.evidence) { - line += `\n Evidence: "${r.evidence}"`; - } - return line; - }).join('\n'); - } catch { return 'Knowledge graph traversal is currently unavailable.'; } - } - if (name === 'create_note') { - try { - const fs = require('fs'); - const path = require('path'); - const title = String(args.title || 'Untitled').trim(); - const fileName = title.endsWith('.md') ? title : `${title}.md`; - const targetDir = args.subfolder ? path.join(agent.workspaceRoot, args.subfolder) : agent.workspaceRoot; - if (!fs.existsSync(targetDir)) { - fs.mkdirSync(targetDir, { recursive: true }); - } - const fullPath = path.join(targetDir, fileName); - if (fs.existsSync(fullPath)) { - return `Notice: A note named "${fileName}" already exists. Updating or overwriting existing notes is strictly disabled to safeguard note content.`; - } - const content = String(args.content || ''); - fs.writeFileSync(fullPath, content, 'utf8'); - - if (agent.graphService) { - await agent.graphService.processNote(fullPath, content); - } - return `Created new note: [${fileName}](file:///${fullPath.replace(/\\/g, '/')})`; - } catch (err) { - return `Could not create note: ${err.message.replace(/[<>]/g, '')}`; - } - } - return 'Requested capability is not available.'; -}; - -module.exports = { - getOfficialTools, - runTool -}; diff --git a/ai/tools/SemanticTools.js b/ai/tools/SemanticTools.js deleted file mode 100644 index effbbe40..00000000 --- a/ai/tools/SemanticTools.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * SemanticTools - High-level semantic tool suite for Notely AI - * Exposes workspace knowledge capabilities in human-centered, domain-focused abstractions. - */ - -const semanticToolsCatalog = [ - { - name: 'find_discussions', - description: 'Find notes containing discussions, meetings, and decisions regarding a topic.', - parameters: { - type: 'object', - properties: { - topic: { type: 'string', description: 'The subject or topic to locate discussions for.' } - }, - required: ['topic'] - } - }, - { - name: 'find_architecture', - description: 'Locate technical specifications, system architecture designs, and component notes.', - parameters: { - type: 'object', - properties: { - component: { type: 'string', description: 'System component or architecture area.' } - }, - required: ['component'] - } - }, - { - name: 'find_people_and_tasks', - description: 'Discover people mentioned, assignees, and open action items across notes.', - parameters: { - type: 'object', - properties: { - personName: { type: 'string', description: 'Optional person name to filter by.' }, - status: { type: 'string', enum: ['all', 'open', 'completed'], description: 'Task status filter.' } - } - } - }, - { - name: 'reconstruct_timeline', - description: 'Build a chronological timeline of notes and updates for a project.', - parameters: { - type: 'object', - properties: { - topic: { type: 'string', description: 'Project or topic name.' } - }, - required: ['topic'] - } - }, - { - name: 'explore_topic_graph', - description: 'Traverse entity graph for connected notes, technologies, and concepts.', - parameters: { - type: 'object', - properties: { - topic: { type: 'string', description: 'Topic or entity to expand.' }, - maxHops: { type: 'number', description: 'Traversal depth (default 2).' } - }, - required: ['topic'] - } - } -]; - -class SemanticToolRunner { - constructor(agent) { - this.agent = agent; - } - - /** - * Execute tool dynamically via ApplicationToolRegistry or ContextEngine fallbacks - * @param {string} toolName - * @param {object} args - * @returns {Promise} - */ - async run(toolName, args = {}) { - try { - const { applicationToolRegistry } = require('../../electron/tools/ApplicationToolRegistry.cjs'); - if (this.agent) { - applicationToolRegistry.setAgentInstance(this.agent); - } - const resolved = applicationToolRegistry.resolveToolName(toolName); - if (resolved) { - const res = await applicationToolRegistry.executeTool(resolved, args, { - workspaceRoot: this.agent?.workspaceRoot, - caller: 'planner' - }); - if (res && res.success && res.data) { - if (typeof res.data === 'string') return res.data; - if (res.data.content && typeof res.data.content === 'string') return res.data.content; - if (Array.isArray(res.data.graph_triples) && res.data.graph_triples.length > 0) { - return res.data.graph_triples.join('\n'); - } - return res.data; - } - } - } catch { - // Ignore registry resolution errors in isolated unit test environments - } - - if (this.agent) { - try { - const QueryTools = require('./QueryTools'); - const rawRes = await QueryTools.runTool(this.agent, toolName, args); - if (rawRes && typeof rawRes === 'string' && (rawRes.startsWith('[') || rawRes.startsWith('{'))) { - try { return JSON.parse(rawRes); } catch { return rawRes; } - } - if (rawRes && !rawRes.startsWith('Error:')) return rawRes; - } catch { - // ignore fallback error - } - } - - const query = args.query || args.topic || args.component || args.notePath || ''; - - if (this.agent?.contextEngine?.hybridRetriever && query) { - return await this.agent.contextEngine.hybridRetriever.search(query, null, 5); - } - - if (this.agent?.graphDb && (toolName.includes('graph') || toolName.includes('topic'))) { - return await this.agent.graphDb.findRelatedEntities(query, args.maxHops || args.maxDepth || 2); - } - - if (this.agent?.workspaceBrain?.getWorkspaceFacts && query) { - return await this.agent.workspaceBrain.getWorkspaceFacts(query); - } - - return []; - } -} - -function getToolRunner(toolName, agent) { - const runner = new SemanticToolRunner(agent); - return (args) => runner.run(toolName, args); -} - -module.exports = { - semanticToolsCatalog, - SemanticToolRunner, - getToolRunner -}; - diff --git a/ai/tools/ToolRegistry.js b/ai/tools/ToolRegistry.js deleted file mode 100644 index bffb07a1..00000000 --- a/ai/tools/ToolRegistry.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * ToolRegistry.js - * AI Engine bridge to the central Application Tool Registry. - * Translates Vercel AI SDK getTools calls to applicationToolRegistry capabilities. - * Direct filesystem/DB access is strictly prohibited in this layer. - */ - -const { applicationToolRegistry } = require('../../electron/tools/ApplicationToolRegistry.cjs'); -const { createLogger } = require('../core/logger'); - -const log = createLogger('ToolRegistry'); - -async function getTools(agentInstance) { - try { - log.info('Binding Agent instance to Application Tool Registry'); - if (agentInstance) { - applicationToolRegistry.setAgentInstance(agentInstance); - } - - const context = { - workspaceRoot: agentInstance?.workspaceRoot || null, - caller: 'internal_ai' - }; - - return await applicationToolRegistry.toVercelTools(context); - } catch (err) { - log.error('Failed to initialize tools from ApplicationToolRegistry:', err.message); - return {}; - } -} - -/** - * Utility to fetch mapped tools from ApplicationToolRegistry - * @returns {Array} - */ -function getRegisteredTools() { - try { - return Array.from(applicationToolRegistry.tools.values()).map(t => ({ - name: t.sdkName || t.aliases?.[0] || t.name, - fullName: t.name, - aliases: t.aliases || [], - capability: t.capability || 'generic', - informationNeeds: Array.isArray(t.informationNeeds) ? t.informationNeeds : [], - description: t.description || '' - })); - } catch (err) { - log.warn('Failed to resolve ApplicationToolRegistry:', err.message); - return []; - } -} - -module.exports = { getTools, getRegisteredTools }; diff --git a/ai/tools/index.js b/ai/tools/index.js deleted file mode 100644 index 8a42ba5c..00000000 --- a/ai/tools/index.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Tools Module Facade - * Single entry point for tool registries, semantic tool runners, and document reading tools. - */ - -const { getTools, getRegisteredTools } = require('./ToolRegistry'); -const SemanticTools = require('./SemanticTools'); -const DocumentReader = require('./DocumentReader'); -const QueryTools = require('./QueryTools'); - -module.exports = { - getTools, - getRegisteredTools, - SemanticTools, - DocumentReader, - QueryTools, - - createDocumentReader: (db, workspaceRoot) => new DocumentReader(db, workspaceRoot) -}; diff --git a/electron/ai/aiHandlers.cjs b/electron/ai/aiHandlers.cjs index 66d1eef7..2a32a590 100644 --- a/electron/ai/aiHandlers.cjs +++ b/electron/ai/aiHandlers.cjs @@ -56,12 +56,9 @@ let handlersRegistered = false; // Input size limits (kept for config/payload validation) +const MIN_API_KEY_LENGTH = 1; const MAX_API_KEY_LENGTH = 2048; -const MIN_API_KEY_LENGTH = 8; - - -// Derived from providerRegistry — the single source of truth for valid provider ids. -const { ALLOWED_PROVIDER_IDS: ALLOWED_PROVIDERS } = require('../../ai/providers/ProviderRegistry'); +const { PROVIDER_REGISTRY, ALLOWED_PROVIDER_IDS: ALLOWED_PROVIDERS } = require('../../ai/providers/ProviderRegistry'); /** * Only accept IPC originating from a top-level application BrowserWindow frame. @@ -860,15 +857,10 @@ async function handleSetAPIKey(event, payload) { try { if (provider === 'huggingface') { // HuggingFace is an embedding-only provider — wire it directly. - const { HuggingFaceEmbeddingProvider } = require('../../ai/providers'); + const { HuggingFaceEmbeddingProvider } = require('../../ai/embeddings'); const hfProvider = new HuggingFaceEmbeddingProvider(apiKey); await hfProvider.initialize(); aiService.agent.setEmbeddingProvider(hfProvider); - } else { - const AIConfig = require('../../ai/core/AIConfig'); - const aiConfig = aiService.config || new AIConfig(); - const savedModel = aiConfig.getProviderModel(provider); - await aiService.agent.llmRegistry.activateProvider(provider, { apiKey, model: savedModel }); } } catch (activationError) { console.warn('[AI IPC] Provider activation after key save failed:', activationError.message); @@ -913,7 +905,7 @@ async function handleGetAPIKey(event, payload) { */ async function handleGetProviderList(_event, _payload) { try { - const { PROVIDER_REGISTRY } = require('../../ai/providers'); + const { PROVIDER_REGISTRY } = require('../../ai/providers/ProviderRegistry'); const serializableProviders = Object.values(PROVIDER_REGISTRY).map(p => { const { factory: _factory, ...rest } = p; return rest; @@ -925,6 +917,7 @@ async function handleGetProviderList(_event, _payload) { } } + /** * Handle get preferences */ @@ -959,7 +952,7 @@ async function handleSetPreferences(event, payload) { if (activeEmbProvider === 'huggingface') { const hfToken = config.getAPIKey("huggingface"); if (hfToken) { - const { HuggingFaceEmbeddingProvider } = require('../../ai/providers'); + const { HuggingFaceEmbeddingProvider } = require('../../ai/embeddings'); const hfProvider = new HuggingFaceEmbeddingProvider(hfToken); await hfProvider.initialize(); aiService.agent.setEmbeddingProvider(hfProvider); @@ -985,12 +978,11 @@ async function handleSetPreferences(event, payload) { aiService.agent.setEmbeddingProvider(null); } } else { - // Active LLM provider fallback (or null fallback) aiService.agent.setEmbeddingProvider(null); } } - // Apply graph provider choice (gliner2-relex ONNX vs text-provider Cloud LLM) + // Apply graph provider choice (gliner2-relex ONNX) if (aiService.agent) { const graphProviderPref = preferences.graphProvider || 'gliner2-relex'; if (graphProviderPref === 'gliner2-relex') { @@ -1010,25 +1002,6 @@ async function handleSetPreferences(event, payload) { } } - // Apply the active LLM provider choice immediately - if (aiService.agent) { - const activeProviderName = preferences.aiProvider || 'gemini'; - const AIConfig = require('../../ai/core/AIConfig'); - const aiConfig = aiService.config || new AIConfig(); - const apiKey = aiConfig.getAPIKey(activeProviderName); - const savedModel = aiConfig.getProviderModel(activeProviderName); - const { PROVIDER_REGISTRY } = require('../../ai/providers'); - const modelId = savedModel || PROVIDER_REGISTRY[activeProviderName]?.defaultModel; - - if (apiKey && modelId) { - try { - await aiService.agent.llmRegistry.activateProvider(activeProviderName, { apiKey, model: modelId }); - } catch (activationErr) { - console.warn('[AI IPC] Active LLM activation on preference set failed:', activationErr.message); - } - } - } - return new AIQueryResponse(true, { message: 'Preferences saved' }); } catch (error) { console.error('[AI IPC] Set preferences failed:', error); @@ -1052,34 +1025,18 @@ async function handleGetProviderModel(_event, payload) { } /** - * Save model selection for a provider and activate it immediately + * Save model selection for a provider */ async function handleSetProviderModel(_event, payload) { try { const provider = assertProvider(payload?.provider); - let modelId = typeof payload?.model === 'string' ? payload.model.trim() : ''; - if (!modelId) { - const { PROVIDER_REGISTRY } = require('../../ai/providers'); - modelId = PROVIDER_REGISTRY[provider]?.defaultModel || ''; - } + const modelId = typeof payload?.model === 'string' ? payload.model.trim() : ''; if (!modelId) throw new Error('Model id is required.'); const AIConfig = require('../../ai/core/AIConfig'); const config = new AIConfig(); config.saveProviderModel(provider, modelId); - // Re-activate with the new model if the agent is running - if (aiService.agent?.isInitialized && provider !== 'huggingface') { - const apiKey = config.getAPIKey(provider); - if (apiKey) { - try { - await aiService.agent.llmRegistry.activateProvider(provider, { apiKey, model: modelId }); - } catch (activationError) { - console.warn('[AI IPC] Re-activation with new model failed:', activationError.message); - } - } - } - return new AIQueryResponse(true, { message: 'Model saved' }); } catch (error) { console.error('[AI IPC] Set provider model failed:', error); @@ -1092,11 +1049,7 @@ async function handleSetProviderModel(_event, payload) { */ async function handleTestConnection(event, payload) { try { - if (!aiService.agent?.isInitialized) { - throw new Error('AI agent not initialized'); - } - - const providerName = assertProvider(payload?.provider || 'gemini'); + const providerName = assertProvider(payload?.provider || 'huggingface'); const AIConfig = require('../../ai/core/AIConfig'); const config = new AIConfig(); @@ -1109,28 +1062,32 @@ async function handleTestConnection(event, payload) { throw new Error(`No API key configured for ${providerName}`); } - // HuggingFace is an embedding-only provider tested separately. + // HuggingFace is an embedding provider if (providerName === 'huggingface') { - const { HuggingFaceEmbeddingProvider } = require('../../ai/providers/HuggingFaceEmbeddingProvider'); + const { HuggingFaceEmbeddingProvider } = require('../../ai/embeddings'); const hfProvider = new HuggingFaceEmbeddingProvider(apiKey); await hfProvider.initialize(); // throws on failure return new AIQueryResponse(true, { message: 'HuggingFace embeddings connected successfully' }); } - const provider = await aiService.agent.llmRegistry.activateProvider(providerName, { apiKey }); - const result = await provider.isAvailable(); - - if (result === true || (result && result.available)) { - return new AIQueryResponse(true, { message: 'Connected successfully' }); - } else { - throw new Error((result && result.error) || 'Provider is not available'); + const { PROVIDER_REGISTRY } = require('../../ai/providers/ProviderRegistry'); + const entry = PROVIDER_REGISTRY[providerName]; + if (entry && entry.factory) { + const providerInstance = entry.factory({ apiKey, model: entry.defaultModel }); + if (typeof providerInstance.initialize === 'function') { + await providerInstance.initialize(); + } + return new AIQueryResponse(true, { message: `Connected to ${entry.name} successfully!` }); } + + return new AIQueryResponse(true, { message: 'Connected successfully' }); } catch (error) { console.error('[AI IPC] Connection test failed:', error); return new AIQueryResponse(false, null, error.message); } } + /** * Handle clear data */ diff --git a/electron/main.cjs b/electron/main.cjs index b1e8dac9..cc250da0 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -152,7 +152,6 @@ async function initializeAIForWorkspace() { try { const { aiService } = require("../ai/core/AIService.js"); const AIConfig = require("../ai/core/AIConfig"); - const { PROVIDER_REGISTRY } = require("../ai/providers"); const config = new AIConfig(); const prefs = config.loadPreferences(); @@ -162,39 +161,12 @@ async function initializeAIForWorkspace() { return; } - const activeProviderName = prefs.aiProvider || 'gemini'; - - let llmProvider = null; - const activeApiKey = config.getAPIKey(activeProviderName); - - if (activeApiKey || activeProviderName === 'local') { - const savedModel = config.getProviderModel(activeProviderName); - const entry = PROVIDER_REGISTRY[activeProviderName]; - llmProvider = { - name: activeProviderName, - config: { apiKey: activeApiKey, model: savedModel || entry?.defaultModel }, - }; - } else { - for (const entry of Object.values(PROVIDER_REGISTRY)) { - if (!entry.available) continue; - const apiKey = config.getAPIKey(entry.id); - if (apiKey) { - const savedModel = config.getProviderModel(entry.id); - llmProvider = { - name: entry.id, - config: { apiKey, model: savedModel || entry.defaultModel }, - }; - break; - } - } - } - - // Resolve HuggingFace embedding token (independent of text provider). + // Resolve HuggingFace embedding token const hfToken = config.getAPIKey("huggingface"); const embeddingConfig = hfToken ? { token: hfToken } : null; const resolvedAppDataDir = path.join(app.getPath('appData'), 'Notely'); - const result = await aiService.initialize(resolvedAppDataDir, notesRoot, llmProvider, embeddingConfig); + const result = await aiService.initialize(resolvedAppDataDir, notesRoot, null, embeddingConfig); aiAgent = result.agent; const activeEmb = aiAgent?.embeddingService?.isAvailable() @@ -202,9 +174,9 @@ async function initializeAIForWorkspace() { : 'unavailable'; console.log( "[AI] System initialized", - llmProvider ? `text: ${llmProvider.name}` : "(no text provider)", `| embeddings: ${activeEmb}` ); + } catch (error) { aiAgent = null; console.error("[AI] Initialization failed:", error?.message || error); diff --git a/electron/preload.cjs b/electron/preload.cjs index c6159d3d..9446b97e 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -409,28 +409,7 @@ contextBridge.exposeInMainWorld("notesApi", { ipcRenderer.on("exports:record-added", listener); return () => ipcRenderer.removeListener("exports:record-added", listener); }, - - // ── Diagrams (Excalidraw, Draw.io, Wireframe) ──────────────────────────── - readDiagramSource: (p) => ipcRenderer.invoke("diagram:read-source", p), - writeDiagramSource: (p) => ipcRenderer.invoke("diagram:write-source", p), - writeDiagramImage: (p) => ipcRenderer.invoke("diagram:write-image", p), - readDiagramImage: (p) => ipcRenderer.invoke("diagram:read-image", p), - deleteDiagram: (p) => ipcRenderer.invoke("diagram:delete", p), - diagramExists: (p) => ipcRenderer.invoke("diagram:exists", p), - - drawioReadSource: (p) => ipcRenderer.invoke("drawio:read-source", p), - drawioWriteSource: (p) => ipcRenderer.invoke("drawio:write-source", p), - drawioWriteImage: (p) => ipcRenderer.invoke("drawio:write-image", p), - drawioReadImage: (p) => ipcRenderer.invoke("drawio:read-image", p), - drawioDelete: (p) => ipcRenderer.invoke("drawio:delete", p), - drawioExists: (p) => ipcRenderer.invoke("drawio:exists", p), - - wireframeReadSource: (p) => ipcRenderer.invoke("wireframe:read-source", p), - wireframeWriteSource: (p) => ipcRenderer.invoke("wireframe:write-source", p), - wireframeWriteImage: (p) => ipcRenderer.invoke("wireframe:write-image", p), - wireframeReadImage: (p) => ipcRenderer.invoke("wireframe:read-image", p), - wireframeDelete: (p) => ipcRenderer.invoke("wireframe:delete", p), - wireframeExists: (p) => ipcRenderer.invoke("wireframe:exists", p), }); + diff --git a/src/tests/utils/aiSubsystem.test.js b/src/tests/utils/aiSubsystem.test.js deleted file mode 100644 index d6df66f6..00000000 --- a/src/tests/utils/aiSubsystem.test.js +++ /dev/null @@ -1,74 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import OpenAICompatibleProvider from '../../../ai/providers/OpenAICompatibleProvider'; - -// Mock dependencies -vi.mock('ai', () => ({ - generateText: vi.fn().mockResolvedValue({ - text: 'Vercel AI response text', - usage: { totalTokens: 42 } - }), - wrapLanguageModel: vi.fn((opts) => opts.model) -})); - -// Inject mock directly into Node's require cache to intercept the CommonJS require('groq-sdk') -const groqPath = require.resolve('groq-sdk'); -const mockGroqInstance = { - chat: { - completions: { - create: async () => ({ - choices: [{ - message: { - content: 'Groq native response text' - } - }], - usage: { total_tokens: 100 } - }) - } - } -}; - -require.cache[groqPath] = { - id: groqPath, - filename: groqPath, - loaded: true, - exports: { - Groq: class { - constructor() { - return mockGroqInstance; - } - } - } -}; - -vi.mock('../../../ai/tools/ToolRegistry', () => ({ - getTools: vi.fn().mockResolvedValue({}) -})); - -describe('AI Subsystem Tests', () => { - let mockAgent; - - beforeEach(() => { - vi.clearAllMocks(); - mockAgent = { - workspaceRoot: '/mock/workspace', - db: { - getWorkspaceFiles: vi.fn().mockReturnValue([]) - }, - llmRegistry: { - getActiveProvider: vi.fn() - } - }; - }); - - describe('OpenAICompatibleProvider', () => { - it('should dynamically import and create Groq client when baseUrl points to api.groq.com', async () => { - const provider = new OpenAICompatibleProvider('gsk_mock', { - baseUrl: 'https://api.groq.com/openai/v1', - model: 'llama-3.3-70b-versatile' - }); - - const modelInstance = await provider.getModelInstance(); - expect(modelInstance).toBeDefined(); - }); - }); -}); diff --git a/tests/ai/auditTools.spec.js b/tests/ai/auditTools.spec.js deleted file mode 100644 index 9bbfcc4d..00000000 --- a/tests/ai/auditTools.spec.js +++ /dev/null @@ -1,135 +0,0 @@ -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); -const { getTools } = require('../../ai/tools/ToolRegistry'); -const EmbeddingDB = require('../../ai/embeddings/EmbeddingDB'); -const GraphDB = require('../../ai/graph/GraphDB'); - -describe('AI Subsystem Technical Audit Tests', () => { - let tempDir; - let db; - let graphDb; - - beforeAll(() => { - tempDir = path.join(__dirname, `temp-audit-test-${Date.now()}-${Math.random().toString(36).substring(2, 6)}`); - if (!fs.existsSync(tempDir)) { - fs.mkdirSync(tempDir, { recursive: true }); - } - db = new EmbeddingDB(tempDir); - db.initialize(); - - graphDb = new GraphDB(tempDir); - graphDb.initialize(); - }); - - afterAll(() => { - db?.close?.(); - graphDb?.close?.(); - if (fs.existsSync(tempDir)) { - try { - fs.rmSync(tempDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 }); - } catch (_err) { - // Ignore ephemeral Windows file lock cleanup error - } - } - }); - - it('should correctly cap read_note length and resolve ranges', async () => { - const testFile = path.join(tempDir, 'test-cap.md'); - const lines = []; - for (let i = 1; i <= 200; i++) { - lines.push(`Line content number ${i}`); - } - const fullText = lines.join('\n'); - fs.writeFileSync(testFile, fullText, 'utf8'); - - const tools = await getTools({ workspaceRoot: tempDir }); - const readNoteTool = tools.read_note; - - // Test line range slice - const sliced = await readNoteTool.execute({ - file_path: testFile, - start_line: 5, - end_line: 10 - }); - assert.strictEqual(sliced, lines.slice(4, 10).join('\n')); - - // Test relative path resolution - const relativeSliced = await readNoteTool.execute({ - file_path: 'test-cap.md', - start_line: 5, - end_line: 10 - }); - assert.strictEqual(relativeSliced, lines.slice(4, 10).join('\n')); - - // Test default cap - const longFile = path.join(tempDir, 'test-long.md'); - // Generate text longer than 10,000 characters - const longText = 'A'.repeat(12000); - fs.writeFileSync(longFile, longText, 'utf8'); - - const readDefault = await readNoteTool.execute({ file_path: longFile }); - assert.ok(readDefault.length < 11000); - assert.ok(readDefault.includes('truncated')); - }); - - it('should return keyword fallback search results in EmbeddingDB', () => { - const notePath = path.join(tempDir, 'test-fallback.md'); - db.upsertNoteHash(notePath, 'hash-1', 1); - - // Add custom chunks to database manually to simulate indexing - db.db.prepare(` - INSERT OR REPLACE INTO chunks (id, note_path, chunk_index, content, content_hash) - VALUES (?, ?, ?, ?, ?) - `).run('chunk-1', notePath, 0, 'Unique fallback secret word', 'hash-1'); - - const results = db.searchTextFallback('secret'); - assert.strictEqual(results.length, 1); - assert.strictEqual(results[0].note_path, notePath); - assert.strictEqual(results[0].content, 'Unique fallback secret word'); - }); - - it('should retrieve note stats counts correctly', () => { - const notePath = path.join(tempDir, 'test-stats.md'); - const entityId = 'test-stats'; - - // Add chunk stats - db.db.prepare(` - INSERT OR REPLACE INTO chunks (id, note_path, chunk_index, content, content_hash) - VALUES (?, ?, ?, ?, ?) - `).run('chunk-stats-1', notePath, 0, 'some content', 'hash-stats'); - - const chunkCount = db.getNoteChunkCount(notePath); - assert.strictEqual(chunkCount, 1); - - // Add graph entity and relationship stats - graphDb.upsertEntity({ id: entityId, type: 'Document', name: 'Stats doc', note_path: notePath, properties: { title: 'Stats doc' } }); - graphDb.upsertEntity({ id: 'entity-2', type: 'Document', name: 'Related doc', note_path: 'related.md', properties: { title: 'Related doc' } }); - graphDb.upsertRelationship({ source_id: entityId, target_id: 'entity-2', type: 'links', weight: 1.0, metadata: {} }); - - const relationshipCount = graphDb.getNoteRelationshipCount(notePath); - assert.strictEqual(relationshipCount, 1); - }); - - it('should support create_note for new notes and block overwriting existing notes', async () => { - const queryTools = require('../../ai/tools/QueryTools'); - const mockAgent = { workspaceRoot: tempDir, graphDb }; - - // 1. create_note for brand new note - const createRes = await queryTools.runTool(mockAgent, 'create_note', { - title: 'Agent New Note', - content: '# Agent Created Note\nInitial text.' - }); - assert.ok(createRes.includes('Created new note')); - const createdPath = path.join(tempDir, 'Agent New Note.md'); - assert.ok(fs.existsSync(createdPath)); - - // 2. verify existing notes cannot be overwritten - const overwriteRes = await queryTools.runTool(mockAgent, 'create_note', { - title: 'Agent New Note', - content: 'Overwriting content attempt' - }); - assert.ok(overwriteRes.includes('already exists')); - assert.ok(fs.readFileSync(createdPath, 'utf8').includes('Initial text.')); - }); -}); diff --git a/tests/ai/knowledgeGraph.spec.js b/tests/ai/knowledgeGraph.spec.js index b47a5cb0..9c2d7512 100644 --- a/tests/ai/knowledgeGraph.spec.js +++ b/tests/ai/knowledgeGraph.spec.js @@ -89,20 +89,20 @@ describe('Knowledge Graph Architecture Tests', () => { assert.strictEqual(resolved.canonical_name, 'JavaScript'); }); - it('should perform recursive CTE neighbor traversal over Property Graph', async () => { + it('should store note entities and relationships in GraphDB', async () => { const service = new GraphService({ appDataDir: tmpDir }, graphDb); const notePath = path.join(tmpDir, 'main.md'); const noteContent = `# Main Note\nConnecting to [[System Architecture]] and tagged #core.`; await service.processNote(notePath, noteContent); - const { GraphRetriever } = require('../../ai/context/GraphRetriever'); - const retriever = new GraphRetriever(graphDb); - const rows = retriever.traverse(notePath, 2); - assert.ok(rows.length >= 2); + const rootEntity = graphDb.getEntityByPath(notePath); + assert.ok(rootEntity); + const { relationships } = graphDb.getAll(); + assert.ok(relationships.length >= 2); }); - it('should support GraphRAG multi-hop query tool with sentence evidence', async () => { + it('should support multi-hop graph exploration with sentence evidence', async () => { const service = new GraphService({ appDataDir: tmpDir }, graphDb); const notePath = path.join(tmpDir, 'graphrag-note.md'); fs.writeFileSync(notePath, '# AI Note\nDiscussion with Bikash Panda regarding GraphRAG.'); @@ -129,15 +129,19 @@ describe('Knowledge Graph Architecture Tests', () => { evidence_id: evId }); - const queryTools = require('../../ai/tools/QueryTools'); - const result = await queryTools.runTool({ graphDb }, 'explore_graph', { identifier: 'Bikash Panda' }); + const { relationships } = graphDb.getAll(); + const rels = relationships.filter(r => r.target_id === personId); + assert.strictEqual(rels.length, 1); + assert.strictEqual(rels[0].type, 'has_person'); + assert.strictEqual(rels[0].evidence_id, evId); - assert.ok(result.includes('Bikash Panda'), 'Should include searched entity name'); - assert.ok(result.includes('has_person'), 'Should include relationship type'); - assert.ok(result.includes('Evidence:'), 'Should include evidence tag'); - assert.ok(result.includes('Discussion with Bikash Panda regarding GraphRAG.'), 'Should include exact evidence sentence'); + const ev = evStore.getEvidence(evId); + assert.ok(ev); + assert.strictEqual(ev.raw_sentence, 'Discussion with Bikash Panda regarding GraphRAG.'); }); + + it('should execute orphan cleanup in GraphMaintenance', () => { graphDb.upsertEntity({ id: 'ent-orphan', name: 'Orphan Entity', type: 'Concept' }); const maintenance = new GraphMaintenance(graphDb, new EntityResolver(graphDb)); diff --git a/tests/ai/pipeline.spec.js b/tests/ai/pipeline.spec.js index 9a006545..4bece2a4 100644 --- a/tests/ai/pipeline.spec.js +++ b/tests/ai/pipeline.spec.js @@ -7,7 +7,7 @@ const GraphDB = require('../../ai/graph/GraphDB'); const GraphService = require('../../ai/graph/GraphService'); const GraphQueue = require('../../ai/queue/GraphQueue'); const GraphWorker = require('../../ai/queue/GraphWorker'); -const { GraphRetriever } = require('../../ai/context/GraphRetriever'); + describe('Full Knowledge Graph Pipeline E2E Test', () => { let tmpDir; @@ -77,11 +77,10 @@ Referencing external documentation at [Electron Docs](https://electronjs.org). const evidenceList = graphDb.db.prepare('SELECT * FROM evidence WHERE source_id = ?').all(notePath); assert.ok(evidenceList.length > 0); - // 6. Verify recursive CTE traversal using GraphRetriever - const retriever = new GraphRetriever(graphDb); - const relations = retriever.traverse(notePath, 2); - assert.ok(relations.length >= 2); - const targetPaths = relations.map(r => r.to_path); - assert.ok(targetPaths.includes('Notely App') || targetPaths.includes('#ai')); + // 6. Verify relations stored in GraphDB + const { relationships } = graphDb.getAll(); + assert.ok(relationships.length >= 2); }); }); + + diff --git a/tests/ai/provider.spec.js b/tests/ai/provider.spec.js index 38aa2d9a..714d6330 100644 --- a/tests/ai/provider.spec.js +++ b/tests/ai/provider.spec.js @@ -22,4 +22,28 @@ describe('LLMProvider & Registry Tests', () => { assert.strictEqual(active.name.toLowerCase(), 'groq'); assert.strictEqual(active.model, 'llama-3.3-70b-specdec'); }); + + it('should extract entities and relations with LLMGraphAdapter', async () => { + const LLMGraphAdapter = require('../../ai/graph/semantic/adapters/LLMGraphAdapter'); + const mockLLM = { + generateText: async () => JSON.stringify({ + entities: [ + { name: 'GraphQL', type: 'Technology', confidence: 0.95 }, + { name: 'Node.js', type: 'Technology', confidence: 0.9 } + ], + relations: [ + { source: 'Node.js', target: 'GraphQL', type: 'USES', confidence: 0.9, sentence: 'Node.js uses GraphQL for APIs' } + ] + }) + }; + + const adapter = new LLMGraphAdapter({ providerInstance: mockLLM }); + const result = await adapter.extract({ content: 'We build Node.js APIs using GraphQL.' }); + + assert.strictEqual(result.entities.length, 2); + assert.strictEqual(result.entities[0].canonicalName, 'GraphQL'); + assert.strictEqual(result.relations.length, 1); + assert.strictEqual(result.relations[0].relationType, 'USES'); + }); }); + diff --git a/tests/ai/retriever.spec.js b/tests/ai/retriever.spec.js deleted file mode 100644 index 51689680..00000000 --- a/tests/ai/retriever.spec.js +++ /dev/null @@ -1,44 +0,0 @@ -const assert = require('assert'); -const { SemanticRetriever } = require('../../ai/context/SemanticRetriever'); -const { GraphRetriever } = require('../../ai/context/GraphRetriever'); - -describe('Semantic & Graph Retrievers Tests', () => { - it('should format tool parameters and return fallbacks if dependencies are absent', async () => { - // Stub service unavailable state - const mockEmbDB = { db: { prepare: () => ({ all: () => [] }) } }; - const mockEmbService = { isAvailable: () => false }; - const retriever = new SemanticRetriever(mockEmbDB, mockEmbService); - - const results = await retriever.search('test query'); - assert.strictEqual(results.length, 0); - - const tool = retriever.toTool(); - assert.ok(tool.description); - assert.ok(tool.parameters.properties.query); - - const response = await tool.execute({ query: 'testing' }); - assert.strictEqual(response, 'No note content matching "testing" found in workspace.'); - }); - - it('should format graph traversal tool output properly', async () => { - const mockGraphDB = { - db: { - prepare: () => ({ - all: () => [ - { from_path: 'a.md', relation: 'links', to_path: 'b.md', depth: 1 } - ] - }) - } - }; - - const retriever = new GraphRetriever(mockGraphDB); - const rows = retriever.traverse('a.md'); - assert.strictEqual(rows.length, 1); - - const tool = retriever.toTool(); - const response = await tool.execute({ notePath: 'a.md' }); - assert.ok(response.includes('[depth 1] a.md --[links]--> b.md')); - }); -}); - - diff --git a/tests/ai/search.spec.js b/tests/ai/search.spec.js deleted file mode 100644 index 8710acb5..00000000 --- a/tests/ai/search.spec.js +++ /dev/null @@ -1,85 +0,0 @@ -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); -const EmbeddingDB = require('../../ai/embeddings/EmbeddingDB'); -const EmbeddingService = require('../../ai/embeddings/EmbeddingService'); -const { SemanticRetriever } = require('../../ai/context/SemanticRetriever'); - -describe('Semantic Search Tests', () => { - let tempDir; - let db; - let service; - let retriever; - let mockProvider; - - beforeAll(() => { - tempDir = path.join(__dirname, 'temp-search-test'); - if (!fs.existsSync(tempDir)) { - fs.mkdirSync(tempDir, { recursive: true }); - } - db = new EmbeddingDB(tempDir); - db.initialize(); - - mockProvider = { - isInitialized: true, - model: 'mock-model', - generateEmbeddings: async (text) => { - if (text.includes('apple')) return [1.0, 0.0, 0.0]; - if (text.includes('fruit')) return [0.9, 0.1, 0.0]; - return [0.0, 1.0, 0.0]; - } - }; - - service = new EmbeddingService(db, mockProvider); - retriever = new SemanticRetriever(db, service); - }); - - afterAll(() => { - try { - db.close(); - } catch { - // ignore - } - if (fs.existsSync(tempDir)) { - try { - fs.rmSync(tempDir, { recursive: true, force: true }); - } catch { - // ignore Windows file handle lock - } - } - }); - - it('should calculate cosine similarity correctly and find closest matching vectors', async () => { - db.upsertChunk({ - id: 'chunk-1', - note_path: 'apple.md', - chunk_index: 0, - content: 'This note mentions apples', - chunk_type: 'paragraph', - start_line: 1, - end_line: 2, - content_hash: 'h1', - embedding: [1.0, 0.0, 0.0], - embedding_model: 'mock-model' - }); - - db.upsertChunk({ - id: 'chunk-2', - note_path: 'sky.md', - chunk_index: 0, - content: 'This note is about the blue sky', - chunk_type: 'paragraph', - start_line: 1, - end_line: 2, - content_hash: 'h2', - embedding: [0.0, 1.0, 0.0], - embedding_model: 'mock-model' - }); - - // Query for "fruit" (vector [0.9, 0.1, 0.0] should be closer to apple than sky) - const matches = await retriever.search('fruit', 1); - assert.strictEqual(matches.length, 1); - assert.strictEqual(matches[0].note_path, 'apple.md'); - assert.ok(matches[0].score > 0.8); - }); -}); diff --git a/tests/ai/tools.spec.js b/tests/ai/tools.spec.js deleted file mode 100644 index 23d4dcc4..00000000 --- a/tests/ai/tools.spec.js +++ /dev/null @@ -1,22 +0,0 @@ -const assert = require('assert'); -const { getTools } = require('../../ai/tools/ToolRegistry'); - -describe('ToolRegistry Tests', () => { - let mockAgent; - - beforeAll(() => { - mockAgent = { - workspaceRoot: 'mock/workspace', - db: { - getWorkspaceFiles: () => [] - } - }; - }); - - it('should return all tool registrations for LLM query execution', async () => { - const tools = await getTools(mockAgent); - assert.ok(tools.read_note); - assert.ok(tools.search_notes); - assert.strictEqual(typeof tools.read_note.execute, 'function'); - }); -});