diff --git a/.eslintrc.cjs b/.eslintrc.cjs
deleted file mode 100644
index f63fe7dc..00000000
--- a/.eslintrc.cjs
+++ /dev/null
@@ -1,15 +0,0 @@
-module.exports = {
- root: true,
- env: { browser: true, es2020: true },
- extends: [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:react-hooks/recommended",
- ],
- ignorePatterns: ["dist", ".eslintrc.cjs"],
- parser: "@typescript-eslint/parser",
- plugins: ["react-refresh"],
- rules: {
- "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
- },
-};
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..f54a72c5
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,25 @@
+* text=auto eol=lf
+
+*.bat text eol=crlf
+*.cmd text eol=crlf
+
+*.dll binary
+*.exe binary
+*.gif binary
+*.icns binary
+*.ico binary
+*.jpeg binary
+*.jpg binary
+*.mov binary
+*.mp3 binary
+*.mp4 binary
+*.node binary
+*.pdf binary
+*.png binary
+*.ttf binary
+*.wasm binary
+*.wav binary
+*.webm binary
+*.woff binary
+*.woff2 binary
+*.zip binary
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
new file mode 100644
index 00000000..45e5f651
--- /dev/null
+++ b/.github/workflows/quality.yml
@@ -0,0 +1,65 @@
+name: Code Quality
+
+on:
+ pull_request:
+ types: [opened, reopened, synchronize, ready_for_review]
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ quality:
+ name: Repository quality
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ env:
+ CI: true
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+ with:
+ persist-credentials: false
+
+ - name: Setup Node.js
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: '22'
+ cache: npm
+ cache-dependency-path: package-lock.json
+
+ - name: Install dependencies
+ id: install
+ run: npm ci --ignore-scripts
+
+ - name: Typecheck
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
+ run: npx tsc --noEmit
+
+ - name: Lint
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
+ run: npm run lint
+
+ - name: Check formatting (advisory)
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
+ continue-on-error: true
+ run: npm run format:check
+
+ - name: Test
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
+ run: npm test
+
+ # Main currently has known locale-parity debt covered by PR #710. Keep the
+ # check visible without blocking unrelated PRs; make it required once that
+ # existing translation PR (or an equivalent fix) lands.
+ - name: Check translations (advisory)
+ if: ${{ !cancelled() && steps.install.outcome == 'success' }}
+ continue-on-error: true
+ run: npm run i18n:check
diff --git a/biome.json b/biome.json
index 30eb475d..6c8695eb 100644
--- a/biome.json
+++ b/biome.json
@@ -1,7 +1,18 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
- "files": { "ignoreUnknown": false },
+ "files": {
+ "ignoreUnknown": false,
+ "includes": [
+ "**",
+ "!!**/dist",
+ "!!**/dist-electron",
+ "!!**/dist-ssr",
+ "!!**/release",
+ "!!**/.tmp",
+ "!!**/electron/native/**/build"
+ ]
+ },
"formatter": {
"enabled": true,
"indentStyle": "tab",
@@ -92,42 +103,11 @@
"noWith": "error",
"useGetterReturn": "error"
}
- },
- "includes": ["**", "**/dist", "**/.eslintrc.cjs", "**", "**/dist", "**/.eslintrc.cjs"]
+ }
},
"javascript": { "formatter": { "quoteStyle": "double" } },
- "css": { "parser": { "tailwindDirectives": true } },
+ "css": { "parser": { "cssModules": true, "tailwindDirectives": true } },
"overrides": [
- {
- "includes": ["*.ts", "*.tsx", "*.mts", "*.cts"],
- "linter": {
- "rules": {
- "complexity": { "noArguments": "error" },
- "correctness": {
- "noConstAssign": "off",
- "noGlobalObjectCalls": "off",
- "noInvalidBuiltinInstantiation": "off",
- "noInvalidConstructorSuper": "off",
- "noSetterReturn": "off",
- "noUndeclaredVariables": "off",
- "noUnreachable": "off",
- "noUnreachableSuper": "off"
- },
- "style": { "useConst": "error" },
- "suspicious": {
- "noDuplicateClassMembers": "off",
- "noDuplicateObjectKeys": "off",
- "noDuplicateParameters": "off",
- "noFunctionAssign": "off",
- "noImportAssign": "off",
- "noRedeclare": "off",
- "noUnsafeNegation": "off",
- "noVar": "error",
- "useGetterReturn": "off"
- }
- }
- }
- },
{
"includes": ["*.ts", "*.tsx", "*.mts", "*.cts"],
"linter": {
diff --git a/electron/extensions/errorUtils.test.ts b/electron/extensions/errorUtils.test.ts
new file mode 100644
index 00000000..5b834b3b
--- /dev/null
+++ b/electron/extensions/errorUtils.test.ts
@@ -0,0 +1,84 @@
+import { describe, expect, it } from "vitest";
+
+import { formatMarketplaceHttpError } from "./errorUtils";
+
+describe("formatMarketplaceHttpError", () => {
+ it("hides upstream HTML when the marketplace is unavailable", () => {
+ const html = "
SSL handshake failed";
+
+ const message = formatMarketplaceHttpError({
+ status: 525,
+ contentType: "text/html; charset=UTF-8",
+ body: html,
+ });
+
+ expect(message).toBe(
+ "Marketplace is temporarily unavailable (HTTP 525). Please try again later.",
+ );
+ expect(message).not.toContain(html);
+ });
+
+ it("keeps a short JSON error for client-side request failures", () => {
+ expect(
+ formatMarketplaceHttpError({
+ status: 400,
+ contentType: "application/json",
+ body: JSON.stringify({ error: "Invalid search query" }),
+ }),
+ ).toBe("Marketplace request failed (HTTP 400): Invalid search query");
+ });
+
+ it("uses a JSON message when an error field is absent", () => {
+ expect(
+ formatMarketplaceHttpError({
+ status: 409,
+ contentType: "application/json",
+ body: JSON.stringify({ message: "Extension version already exists" }),
+ }),
+ ).toBe("Marketplace request failed (HTTP 409): Extension version already exists");
+ });
+
+ it("prefers a string error when both JSON detail fields are present", () => {
+ expect(
+ formatMarketplaceHttpError({
+ status: 400,
+ contentType: "application/json",
+ body: JSON.stringify({ error: "Primary detail", message: "Secondary detail" }),
+ }),
+ ).toBe("Marketplace request failed (HTTP 400): Primary detail");
+ });
+
+ it("hides malformed JSON bodies", () => {
+ const body = '{"error":"internal route details"';
+ const message = formatMarketplaceHttpError({
+ status: 400,
+ contentType: "application/json",
+ body,
+ });
+
+ expect(message).toBe("Marketplace request failed (HTTP 400).");
+ expect(message).not.toContain(body);
+ });
+
+ it("bounds long JSON details and marks truncation without splitting Unicode", () => {
+ const detail = `🚀${"x".repeat(200)}`;
+ const message = formatMarketplaceHttpError({
+ status: 400,
+ contentType: "application/problem+json",
+ body: JSON.stringify({ error: detail }),
+ });
+
+ expect(message).toBe(`Marketplace request failed (HTTP 400): 🚀${"x".repeat(198)}…`);
+ expect(Array.from(message.split(": ")[1])).toHaveLength(200);
+ });
+
+ it("does not expose non-JSON response bodies", () => {
+ expect(
+ formatMarketplaceHttpError({
+ status: 404,
+ contentType: "text/plain",
+ body: "internal route details",
+ }),
+ ).toBe("Marketplace request failed (HTTP 404).");
+ });
+});
diff --git a/electron/extensions/errorUtils.ts b/electron/extensions/errorUtils.ts
index ae5ccfda..7d44675c 100644
--- a/electron/extensions/errorUtils.ts
+++ b/electron/extensions/errorUtils.ts
@@ -1,3 +1,43 @@
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error);
-}
\ No newline at end of file
+}
+
+const MAX_MARKETPLACE_ERROR_DETAIL_LENGTH = 200;
+
+export function formatMarketplaceHttpError({
+ status,
+ contentType,
+ body,
+}: {
+ status: number;
+ contentType: string | null;
+ body: string;
+}): string {
+ if (status >= 500) {
+ return `Marketplace is temporarily unavailable (HTTP ${status}). Please try again later.`;
+ }
+
+ let detail: string | null = null;
+ if (contentType?.toLowerCase().includes("json")) {
+ try {
+ const payload: unknown = JSON.parse(body);
+ if (payload && typeof payload === "object") {
+ const { error, message } = payload as { error?: unknown; message?: unknown };
+ const value = typeof error === "string" ? error : message;
+ if (typeof value === "string" && value.trim()) {
+ const normalized = value.trim().replace(/\s+/g, " ");
+ const codePoints = Array.from(normalized);
+ detail =
+ codePoints.length > MAX_MARKETPLACE_ERROR_DETAIL_LENGTH
+ ? `${codePoints.slice(0, MAX_MARKETPLACE_ERROR_DETAIL_LENGTH - 1).join("")}…`
+ : normalized;
+ }
+ }
+ } catch {
+ // Malformed or non-API responses are intentionally not exposed to the renderer.
+ }
+ }
+
+ const summary = `Marketplace request failed (HTTP ${status})`;
+ return detail ? `${summary}: ${detail}` : `${summary}.`;
+}
diff --git a/electron/extensions/extensionMarketplace.ts b/electron/extensions/extensionMarketplace.ts
index e8bc66dd..b7a38e46 100644
--- a/electron/extensions/extensionMarketplace.ts
+++ b/electron/extensions/extensionMarketplace.ts
@@ -12,7 +12,7 @@ import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
import type { ReadableStream as NodeReadableStream } from "node:stream/web";
import { app } from "electron";
-import { getErrorMessage } from "./errorUtils";
+import { formatMarketplaceHttpError, getErrorMessage } from "./errorUtils";
import { getRegisteredExtensions, installExtensionFromPath } from "./extensionLoader";
import type {
ExtensionReview,
@@ -97,7 +97,13 @@ async function marketplaceFetch(
if (!response.ok) {
const text = await response.text().catch(() => "");
- throw new Error(`Marketplace API error ${response.status}: ${text}`);
+ throw new Error(
+ formatMarketplaceHttpError({
+ status: response.status,
+ contentType: response.headers.get("content-type"),
+ body: text,
+ }),
+ );
}
return (await response.json()) as T;
diff --git a/electron/ipc/paths/binaries.test.ts b/electron/ipc/paths/binaries.test.ts
index 5b89d957..36186173 100644
--- a/electron/ipc/paths/binaries.test.ts
+++ b/electron/ipc/paths/binaries.test.ts
@@ -27,6 +27,14 @@ describe("Windows native helper path resolution", () => {
await fs.rm(tempRoot, { recursive: true, force: true });
});
+ it("resolves a requested platform tag independently of the host platform", async () => {
+ const { getNativeArchTag } = await import("./binaries");
+
+ expect(getNativeArchTag("win32")).toBe(
+ process.arch === "arm64" ? "win32-arm64" : "win32-x64",
+ );
+ });
+
it("prefers the branch-staged helper over a stale local CMake build in dev", async () => {
const buildOutputPath = path.join(
appPath,
diff --git a/electron/ipc/paths/binaries.ts b/electron/ipc/paths/binaries.ts
index 739f7df8..3e15f332 100644
--- a/electron/ipc/paths/binaries.ts
+++ b/electron/ipc/paths/binaries.ts
@@ -29,24 +29,27 @@ export function getNativeCaptureHelperSourcePath(): string {
return resolveUnpackedAppPath("electron", "native", "ScreenCaptureKitRecorder.swift");
}
-export function getNativeArchTag(): string {
- if (process.platform === "darwin") {
+export function getNativeArchTag(platform: NodeJS.Platform = process.platform): string {
+ if (platform === "darwin") {
return process.arch === "arm64" ? "darwin-arm64" : "darwin-x64";
}
- if (process.platform === "win32") {
+ if (platform === "win32") {
return process.arch === "arm64" ? "win32-arm64" : "win32-x64";
}
- if (process.platform === "linux") {
+ if (platform === "linux") {
return process.arch === "arm64" ? "linux-arm64" : "linux-x64";
}
- return `${process.platform}-${process.arch}`;
+ return `${platform}-${process.arch}`;
}
-export function getPrebundledNativeHelperPath(binaryName: string): string {
- return resolveUnpackedAppPath("electron", "native", "bin", getNativeArchTag(), binaryName);
+export function getPrebundledNativeHelperPath(
+ binaryName: string,
+ archTag = getNativeArchTag(),
+): string {
+ return resolveUnpackedAppPath("electron", "native", "bin", archTag, binaryName);
}
export function resolvePreferredWindowsNativeHelperPath(
@@ -61,7 +64,7 @@ export function resolvePreferredWindowsNativeHelperPath(
"Release",
binaryName,
);
- const prebundledPath = getPrebundledNativeHelperPath(binaryName);
+ const prebundledPath = getPrebundledNativeHelperPath(binaryName, getNativeArchTag("win32"));
if (app.isPackaged && existsSync(prebundledPath)) {
return prebundledPath;
diff --git a/electron/ipc/project/atomicSave.test.ts b/electron/ipc/project/atomicSave.test.ts
new file mode 100644
index 00000000..34646af3
--- /dev/null
+++ b/electron/ipc/project/atomicSave.test.ts
@@ -0,0 +1,112 @@
+import fs from "node:fs/promises";
+import os from "node:os";
+import path from "node:path";
+import { afterEach, beforeEach, describe, expect, it } from "vitest";
+
+import { getProjectBackupPath, writeProjectFileAtomically } from "./atomicSave";
+
+describe("writeProjectFileAtomically", () => {
+ let tempDir: string;
+ let projectPath: string;
+
+ beforeEach(async () => {
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "recordly-atomic-project-"));
+ projectPath = path.join(tempDir, "demo.recordly");
+ });
+
+ afterEach(async () => {
+ await fs.rm(tempDir, { recursive: true, force: true });
+ });
+
+ async function expectNoTemporaryArtifacts() {
+ const entries = await fs.readdir(tempDir);
+ expect(entries.filter((entry) => entry.endsWith(".tmp"))).toEqual([]);
+ }
+
+ it("commits a complete new project without creating a backup", async () => {
+ await writeProjectFileAtomically(projectPath, '{"version":1}');
+
+ await expect(fs.readFile(projectPath, "utf-8")).resolves.toBe('{"version":1}');
+ await expect(fs.access(getProjectBackupPath(projectPath))).rejects.toMatchObject({
+ code: "ENOENT",
+ });
+ await expectNoTemporaryArtifacts();
+ await expectNoTemporaryArtifacts();
+ });
+
+ it("removes a stale backup when the target has no previous generation", async () => {
+ await fs.writeFile(getProjectBackupPath(projectPath), "stale-project");
+
+ await writeProjectFileAtomically(projectPath, '{"version":1}');
+
+ await expect(fs.access(getProjectBackupPath(projectPath))).rejects.toMatchObject({
+ code: "ENOENT",
+ });
+ });
+
+ it("preserves the previous complete generation before replacement", async () => {
+ await writeProjectFileAtomically(projectPath, '{"version":1,"name":"old"}');
+ await writeProjectFileAtomically(projectPath, '{"version":1,"name":"new"}');
+
+ await expect(fs.readFile(projectPath, "utf-8")).resolves.toBe('{"version":1,"name":"new"}');
+ await expect(fs.readFile(getProjectBackupPath(projectPath), "utf-8")).resolves.toBe(
+ '{"version":1,"name":"old"}',
+ );
+ await expectNoTemporaryArtifacts();
+ });
+
+ it("keeps the active generation unchanged when backup commit fails", async () => {
+ await writeProjectFileAtomically(projectPath, '{"version":1,"name":"old"}');
+ await fs.mkdir(getProjectBackupPath(projectPath));
+
+ await expect(
+ writeProjectFileAtomically(projectPath, '{"version":1,"name":"new"}'),
+ ).rejects.toBeDefined();
+
+ await expect(fs.readFile(projectPath, "utf-8")).resolves.toBe('{"version":1,"name":"old"}');
+ await expectNoTemporaryArtifacts();
+
+ await fs.rm(getProjectBackupPath(projectPath), { recursive: true });
+ await writeProjectFileAtomically(projectPath, '{"version":1,"name":"retry"}');
+ await expect(fs.readFile(projectPath, "utf-8")).resolves.toBe(
+ '{"version":1,"name":"retry"}',
+ );
+ await expect(fs.readFile(getProjectBackupPath(projectPath), "utf-8")).resolves.toBe(
+ '{"version":1,"name":"old"}',
+ );
+ await expectNoTemporaryArtifacts();
+ });
+
+ it("serializes overlapping writes to the same project", async () => {
+ await writeProjectFileAtomically(projectPath, '{"revision":1}');
+
+ // Each call enters the queue synchronously before its first await, preserving invocation order.
+ await Promise.all([
+ writeProjectFileAtomically(projectPath, '{"revision":2}'),
+ writeProjectFileAtomically(projectPath, '{"revision":3}'),
+ ]);
+
+ await expect(fs.readFile(projectPath, "utf-8")).resolves.toBe('{"revision":3}');
+ await expect(fs.readFile(getProjectBackupPath(projectPath), "utf-8")).resolves.toBe(
+ '{"revision":2}',
+ );
+ await expectNoTemporaryArtifacts();
+ });
+
+ it.skipIf(process.platform === "win32")(
+ "preserves exact project permission bits despite the process umask",
+ async () => {
+ await fs.writeFile(projectPath, '{"revision":1}', { mode: 0o666 });
+ await fs.chmod(projectPath, 0o666);
+ const previousUmask = process.umask(0o077);
+
+ try {
+ await writeProjectFileAtomically(projectPath, '{"revision":2}');
+ } finally {
+ process.umask(previousUmask);
+ }
+
+ expect((await fs.stat(projectPath)).mode & 0o777).toBe(0o666);
+ },
+ );
+});
diff --git a/electron/ipc/project/atomicSave.ts b/electron/ipc/project/atomicSave.ts
new file mode 100644
index 00000000..d2440ffe
--- /dev/null
+++ b/electron/ipc/project/atomicSave.ts
@@ -0,0 +1,146 @@
+import { randomUUID } from "node:crypto";
+import { constants as fsConstants } from "node:fs";
+import fs from "node:fs/promises";
+import path from "node:path";
+
+const pendingWrites = new Map>();
+
+const unsupportedDirectorySyncErrors = new Set([
+ "EACCES",
+ "EINVAL",
+ "EISDIR",
+ "ENOSYS",
+ "ENOTSUP",
+ "EOPNOTSUPP",
+ "EPERM",
+]);
+
+export function getProjectBackupPath(projectPath: string): string {
+ return `${projectPath}.bak`;
+}
+
+function getQueueKey(projectPath: string): string {
+ const resolvedPath = path.resolve(projectPath);
+ return process.platform === "win32" ? resolvedPath.toLowerCase() : resolvedPath;
+}
+
+function createTemporaryPath(parentDir: string, label: string): string {
+ return path.join(parentDir, `.recordly-${label}-${process.pid}-${randomUUID()}.tmp`);
+}
+
+async function getExistingFileMode(filePath: string): Promise {
+ try {
+ return (await fs.stat(filePath)).mode & 0o777;
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
+ return undefined;
+ }
+ throw error;
+ }
+}
+
+async function writeSyncedTemporaryFile(
+ filePath: string,
+ contents: string,
+ mode?: number,
+): Promise {
+ const handle = await fs.open(filePath, "wx", mode);
+ try {
+ await handle.writeFile(contents, "utf-8");
+ if (mode !== undefined) {
+ await handle.chmod(mode);
+ }
+ await handle.sync();
+ } finally {
+ await handle.close();
+ }
+}
+
+async function syncExistingFile(filePath: string): Promise {
+ const handle = await fs.open(filePath, "r+");
+ try {
+ await handle.sync();
+ } finally {
+ await handle.close();
+ }
+}
+
+async function syncParentDirectory(parentDir: string): Promise {
+ if (process.platform === "win32") {
+ return;
+ }
+
+ try {
+ const handle = await fs.open(parentDir, "r");
+ try {
+ await handle.sync();
+ } finally {
+ await handle.close();
+ }
+ } catch (error) {
+ const code = (error as NodeJS.ErrnoException).code;
+ if (!code || !unsupportedDirectorySyncErrors.has(code)) {
+ throw error;
+ }
+ }
+}
+
+async function preservePreviousGeneration(
+ targetPath: string,
+ backupPath: string,
+ backupTemporaryPath: string,
+): Promise {
+ try {
+ await fs.copyFile(targetPath, backupTemporaryPath, fsConstants.COPYFILE_EXCL);
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
+ await fs.rm(backupPath, { force: true });
+ return;
+ }
+ throw error;
+ }
+
+ await syncExistingFile(backupTemporaryPath);
+ await fs.rename(backupTemporaryPath, backupPath);
+}
+
+async function commitProjectFile(projectPath: string, contents: string): Promise {
+ const targetPath = path.resolve(projectPath);
+ const parentDir = path.dirname(targetPath);
+ const backupPath = getProjectBackupPath(targetPath);
+ const temporaryPath = createTemporaryPath(parentDir, "project");
+ const backupTemporaryPath = createTemporaryPath(parentDir, "backup");
+ const existingMode = await getExistingFileMode(targetPath);
+
+ try {
+ await writeSyncedTemporaryFile(temporaryPath, contents, existingMode);
+ await preservePreviousGeneration(targetPath, backupPath, backupTemporaryPath);
+ await fs.rename(temporaryPath, targetPath);
+ await syncParentDirectory(parentDir);
+ } finally {
+ await Promise.all([
+ fs.rm(temporaryPath, { force: true }).catch(() => undefined),
+ fs.rm(backupTemporaryPath, { force: true }).catch(() => undefined),
+ ]);
+ }
+}
+
+export async function writeProjectFileAtomically(
+ projectPath: string,
+ contents: string,
+): Promise {
+ const queueKey = getQueueKey(projectPath);
+ const previousWrite = pendingWrites.get(queueKey) ?? Promise.resolve();
+ const currentWrite = previousWrite
+ .catch(() => undefined)
+ .then(() => commitProjectFile(projectPath, contents));
+ pendingWrites.set(queueKey, currentWrite);
+
+ try {
+ await currentWrite;
+ } finally {
+ if (pendingWrites.get(queueKey) === currentWrite) {
+ pendingWrites.delete(queueKey);
+ }
+ }
+}
diff --git a/electron/ipc/recording/storagePath.test.ts b/electron/ipc/recording/storagePath.test.ts
new file mode 100644
index 00000000..dced4f52
--- /dev/null
+++ b/electron/ipc/recording/storagePath.test.ts
@@ -0,0 +1,53 @@
+import path from "node:path";
+import { describe, expect, it } from "vitest";
+import { resolveRecordedVideoStoragePath } from "./storagePath";
+
+describe("resolveRecordedVideoStoragePath", () => {
+ const recordingsDir = path.resolve("recordings-root");
+
+ it.each([
+ "recording-0.webm",
+ "recording-1720588800000.mp4",
+ "recording-1720588800000-webcam.webm",
+ "recording-1720588800000-webcam.mp4",
+ ])("accepts an app-generated recording name: %s", (fileName) => {
+ expect(resolveRecordedVideoStoragePath(recordingsDir, fileName)).toBe(
+ path.resolve(recordingsDir, fileName),
+ );
+ });
+
+ it.each([
+ "",
+ "../recording-1.webm",
+ "..\\recording-1.webm",
+ "nested/recording-1.webm",
+ "nested\\recording-1.webm",
+ "/tmp/recording-1.webm",
+ "C:\\temp\\recording-1.webm",
+ "\\\\server\\share\\recording-1.webm",
+ "recording-1.webm:payload",
+ "recording-1.webm\n",
+ "recording-1.webm\0",
+ "recording--1.webm",
+ "recording-1.5.webm",
+ "recording-1.mov",
+ "other-1.webm",
+ "recording-1-WEBCAM.webm",
+ ])("rejects an untrusted recording name: %s", (fileName) => {
+ expect(() => resolveRecordedVideoStoragePath(recordingsDir, fileName)).toThrow(
+ "Invalid recording file name",
+ );
+ });
+
+ it.each([
+ { label: "undefined", value: undefined },
+ { label: "null", value: null },
+ { label: "number", value: 1 },
+ { label: "object", value: {} },
+ { label: "array", value: [] },
+ ])("rejects a non-string recording name: $label", ({ value }) => {
+ expect(() => resolveRecordedVideoStoragePath(recordingsDir, value)).toThrow(
+ "Invalid recording file name",
+ );
+ });
+});
diff --git a/electron/ipc/recording/storagePath.ts b/electron/ipc/recording/storagePath.ts
new file mode 100644
index 00000000..12c3484f
--- /dev/null
+++ b/electron/ipc/recording/storagePath.ts
@@ -0,0 +1,24 @@
+import path from "node:path";
+
+const RECORDED_VIDEO_FILE_NAME = /^recording-[0-9]+(?:-webcam)?\.(?:webm|mp4)$/;
+
+export function resolveRecordedVideoStoragePath(recordingsDir: string, fileName: unknown): string {
+ if (typeof fileName !== "string" || RECORDED_VIDEO_FILE_NAME.exec(fileName)?.[0] !== fileName) {
+ throw new Error("Invalid recording file name");
+ }
+
+ const resolvedRecordingsDir = path.resolve(recordingsDir);
+ const candidatePath = path.resolve(resolvedRecordingsDir, fileName);
+ const relativePath = path.relative(resolvedRecordingsDir, candidatePath);
+
+ if (
+ relativePath.length === 0 ||
+ relativePath === ".." ||
+ relativePath.startsWith(`..${path.sep}`) ||
+ path.isAbsolute(relativePath)
+ ) {
+ throw new Error("Invalid recording file name");
+ }
+
+ return candidatePath;
+}
diff --git a/electron/ipc/register/assets.ts b/electron/ipc/register/assets.ts
index a0b132ea..f18bf7b6 100644
--- a/electron/ipc/register/assets.ts
+++ b/electron/ipc/register/assets.ts
@@ -62,7 +62,7 @@ export function registerAssetHandlers() {
await fs.writeFile(thumbPath, jpegData)
})
// Keep the queue moving even if one fails
- thumbGenerationQueue = generation.catch(() => {})
+ thumbGenerationQueue = generation.catch(() => undefined)
await generation
return { success: true, data: jpegData! }
diff --git a/electron/ipc/register/project.ts b/electron/ipc/register/project.ts
index 61dbdbaa..f1fa43e2 100644
--- a/electron/ipc/register/project.ts
+++ b/electron/ipc/register/project.ts
@@ -9,6 +9,7 @@ import {
LEGACY_PROJECT_FILE_EXTENSIONS,
PROJECT_FILE_EXTENSION,
} from "../constants";
+import { getProjectBackupPath, writeProjectFileAtomically } from "../project/atomicSave";
import {
getProjectsDir,
getProjectThumbnailPath,
@@ -305,7 +306,10 @@ export function registerProjectHandlers() {
: null
if (trustedExistingProjectPath) {
- await fs.writeFile(trustedExistingProjectPath, JSON.stringify(preparedProject.projectData, null, 2), 'utf-8')
+ await writeProjectFileAtomically(
+ trustedExistingProjectPath,
+ JSON.stringify(preparedProject.projectData, null, 2),
+ )
setCurrentProjectPath(trustedExistingProjectPath)
await saveProjectThumbnail(trustedExistingProjectPath, thumbnailDataUrl)
await rememberRecentProject(trustedExistingProjectPath)
@@ -345,7 +349,10 @@ export function registerProjectHandlers() {
}
}
- await fs.writeFile(result.filePath, JSON.stringify(preparedProject.projectData, null, 2), 'utf-8')
+ await writeProjectFileAtomically(
+ result.filePath,
+ JSON.stringify(preparedProject.projectData, null, 2),
+ )
setCurrentProjectPath(result.filePath)
await saveProjectThumbnail(result.filePath, thumbnailDataUrl)
await rememberRecentProject(result.filePath)
@@ -411,7 +418,10 @@ export function registerProjectHandlers() {
return overwriteCheck
}
- await fs.writeFile(targetProjectPath, JSON.stringify(preparedProject.projectData, null, 2), 'utf-8')
+ await writeProjectFileAtomically(
+ targetProjectPath,
+ JSON.stringify(preparedProject.projectData, null, 2),
+ )
await saveProjectThumbnail(targetProjectPath, thumbnailDataUrl)
await rememberRecentProject(targetProjectPath)
@@ -422,6 +432,7 @@ export function registerProjectHandlers() {
}
})
await fs.rm(getProjectThumbnailPath(activeProjectPath), { force: true }).catch(() => undefined)
+ await fs.rm(getProjectBackupPath(activeProjectPath), { force: true }).catch(() => undefined)
const recentProjectPaths = await loadRecentProjectPaths()
const filteredRecentProjectPaths: string[] = []
diff --git a/electron/ipc/register/recording.ts b/electron/ipc/register/recording.ts
index b13453c7..06a33f84 100644
--- a/electron/ipc/register/recording.ts
+++ b/electron/ipc/register/recording.ts
@@ -68,6 +68,7 @@ import {
waitForNativeCaptureStart,
waitForNativeCaptureStop,
} from "../recording/mac";
+import { resolveRecordedVideoStoragePath } from "../recording/storagePath";
import {
attachWindowsCaptureLifecycle,
isNativeWindowsCaptureAvailable,
@@ -1747,10 +1748,10 @@ export function registerRecordingHandlers(
},
);
- ipcMain.handle("store-recorded-video", async (_, videoData: ArrayBuffer, fileName: string) => {
+ ipcMain.handle("store-recorded-video", async (_, videoData: ArrayBuffer, fileName: unknown) => {
try {
const recordingsDir = await getRecordingsDir();
- const videoPath = path.join(recordingsDir, fileName);
+ const videoPath = resolveRecordedVideoStoragePath(recordingsDir, fileName);
await fs.writeFile(videoPath, Buffer.from(videoData));
return await finalizeStoredVideo(videoPath);
} catch (error) {
diff --git a/electron/main.ts b/electron/main.ts
index ed05ffeb..38f4333f 100644
--- a/electron/main.ts
+++ b/electron/main.ts
@@ -1,6 +1,6 @@
import fs from "node:fs/promises";
import path from "node:path";
-import { fileURLToPath } from "node:url";
+import { fileURLToPath, pathToFileURL } from "node:url";
import {
app,
BrowserWindow,
@@ -11,8 +11,10 @@ import {
Notification,
nativeImage,
session,
+ shell,
systemPreferences,
Tray,
+ webContents as electronWebContents,
} from "electron";
import { RECORDINGS_DIR } from "./appPaths";
import { showCursor } from "./cursorHider";
@@ -26,7 +28,12 @@ import {
registerIpcHandlers,
} from "./ipc/handlers";
import { ensureMediaServer } from "./mediaServer";
-import { ensurePackagedRendererServer } from "./rendererServer";
+import { shouldGrantDisplayCapture, shouldGrantMediaPermission } from "./permissionPolicy";
+import { ensurePackagedRendererServer, getPackagedRendererBaseUrl } from "./rendererServer";
+import {
+ hardenWebContentsNavigation,
+ shouldHardenWebContentsType,
+} from "./navigationPolicy";
import type { UpdateToastPayload } from "./updater";
import {
checkForAppUpdates,
@@ -73,6 +80,14 @@ app.commandLine.appendSwitch("ignore-gpu-blocklist");
app.commandLine.appendSwitch("enable-unsafe-webgpu");
app.commandLine.appendSwitch("enable-gpu-rasterization");
+app.on("web-contents-created", (_event, contents) => {
+ if (!shouldHardenWebContentsType(contents.getType())) {
+ return;
+ }
+
+ hardenWebContentsNavigation(contents, (url) => shell.openExternal(url));
+});
+
function configureGpuAccelerationSwitches() {
const { useAngle, useGl, disableFeatures } = getGpuSwitches(process.platform, process.env);
if (useAngle) {
@@ -132,6 +147,30 @@ process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
? path.join(process.env.APP_ROOT, "public")
: RENDERER_DIST;
+function getTrustedCaptureDocumentBaseUrls(): string[] {
+ const trustedUrls = [pathToFileURL(path.join(RENDERER_DIST, "index.html")).href];
+
+ if (VITE_DEV_SERVER_URL) {
+ trustedUrls.push(VITE_DEV_SERVER_URL);
+ }
+
+ const packagedRendererBaseUrl = getPackagedRendererBaseUrl();
+ if (packagedRendererBaseUrl) {
+ trustedUrls.push(new URL("/", packagedRendererBaseUrl).href);
+ }
+
+ return trustedUrls;
+}
+
+function isHudWebContents(webContents: Electron.WebContents | null): boolean {
+ if (!webContents || webContents.isDestroyed()) {
+ return false;
+ }
+
+ const hudWindow = getHudOverlayWindow();
+ return Boolean(hudWindow && hudWindow.webContents === webContents);
+}
+
// Window references
let mainWindow: BrowserWindow | null = null;
let sourceSelectorWindow: BrowserWindow | null = null;
@@ -879,17 +918,47 @@ app.whenReady().then(async () => {
app.setAppUserModelId("dev.recordly.app");
}
- session.defaultSession.setPermissionCheckHandler((_webContents, permission) => {
- const allowed = ["media", "audioCapture", "microphone", "camera", "videoCapture"];
- return allowed.includes(permission);
- });
+ session.defaultSession.setPermissionCheckHandler(
+ (webContents, permission, requestingOrigin, details) => {
+ return shouldGrantMediaPermission(
+ {
+ permission,
+ isTrustedCaptureWindow: isHudWebContents(webContents),
+ isMainFrame: details.isMainFrame,
+ currentDocumentUrl: webContents?.getURL() ?? "",
+ // Electron 39 may supply the last committed document URL, including its
+ // query, in the requestingOrigin argument for media checks.
+ requestingUrl: details.requestingUrl ?? requestingOrigin,
+ securityOrigins:
+ details.securityOrigin === undefined ? [] : [details.securityOrigin],
+ },
+ getTrustedCaptureDocumentBaseUrls(),
+ );
+ },
+ );
- session.defaultSession.setPermissionRequestHandler((_webContents, permission, callback) => {
- const allowed = ["media", "audioCapture", "microphone", "camera", "videoCapture"];
- callback(allowed.includes(permission));
- });
+ session.defaultSession.setPermissionRequestHandler(
+ (webContents, permission, callback, details) => {
+ const securityOrigin = "securityOrigin" in details ? details.securityOrigin : undefined;
- session.defaultSession.setDevicePermissionHandler((_details) => true);
+ callback(
+ shouldGrantMediaPermission(
+ {
+ permission,
+ isTrustedCaptureWindow: isHudWebContents(webContents),
+ isMainFrame: details.isMainFrame,
+ currentDocumentUrl: webContents.getURL(),
+ requestingUrl: details.requestingUrl,
+ securityOrigins: securityOrigin === undefined ? [] : [securityOrigin],
+ },
+ getTrustedCaptureDocumentBaseUrls(),
+ ),
+ );
+ },
+ );
+
+ // Recordly does not use WebHID, Web Serial, or WebUSB. Do not grant devices by default.
+ session.defaultSession.setDevicePermissionHandler(() => false);
if (process.platform === "darwin") {
const cameraStatus = systemPreferences.getMediaAccessStatus("camera");
@@ -1003,8 +1072,35 @@ app.whenReady().then(async () => {
// via an unsafe cast breaks Electron's internal cursor-constraint
// propagation and causes cursor: 'never' from the renderer to be silently
// ignored by the native capture pipeline.
- session.defaultSession.setDisplayMediaRequestHandler(async (_request, callback) => {
+ session.defaultSession.setDisplayMediaRequestHandler(async (request, callback) => {
try {
+ const frame = request.frame;
+ const isLiveFrame = Boolean(frame && !frame.isDestroyed());
+ const requestingWebContents =
+ isLiveFrame && frame ? electronWebContents.fromFrame(frame) : undefined;
+ const isHudMainFrame = Boolean(
+ isLiveFrame &&
+ requestingWebContents &&
+ isHudWebContents(requestingWebContents) &&
+ frame === requestingWebContents.mainFrame,
+ );
+
+ if (
+ !shouldGrantDisplayCapture(
+ {
+ isTrustedCaptureWindow: isHudMainFrame,
+ isMainFrame: Boolean(isLiveFrame && frame?.parent === null),
+ currentDocumentUrl: isLiveFrame ? (frame?.url ?? "") : "",
+ securityOrigin: request.securityOrigin,
+ videoRequested: request.videoRequested,
+ },
+ getTrustedCaptureDocumentBaseUrls(),
+ )
+ ) {
+ callback({});
+ return;
+ }
+
const sourceId = getSelectedSourceId();
// On Linux/Wayland, calling desktopCapturer.getSources() itself
// invokes the xdg-desktop-portal picker. If we then return one of
diff --git a/electron/navigationPolicy.test.ts b/electron/navigationPolicy.test.ts
new file mode 100644
index 00000000..e021c96a
--- /dev/null
+++ b/electron/navigationPolicy.test.ts
@@ -0,0 +1,265 @@
+import { describe, expect, it, vi } from "vitest";
+import {
+ createWillNavigateHandler,
+ createWillRedirectHandler,
+ createWindowOpenHandler,
+ hardenWebContentsNavigation,
+ isInternalRendererTarget,
+ normalizeExternalHttpUrl,
+ shouldHardenWebContentsType,
+} from "./navigationPolicy";
+
+describe("normalizeExternalHttpUrl", () => {
+ it.each([
+ ["https://example.com/docs", "https://example.com/docs"],
+ ["http://127.0.0.1:3000/path?q=1", "http://127.0.0.1:3000/path?q=1"],
+ ["HTTPS://Example.COM:443/docs", "https://example.com/docs"],
+ ])("normalizes an external HTTP(S) URL: %s", (value, expected) => {
+ expect(normalizeExternalHttpUrl(value)).toBe(expected);
+ });
+
+ it.each([
+ "",
+ "not a URL",
+ "file:///tmp/recordly.html",
+ "data:text/html,hello",
+ "javascript:alert(1)",
+ "mailto:security@example.com",
+ "https://user:password@example.com/",
+ ])("rejects an unsafe external URL: %s", (value) => {
+ expect(normalizeExternalHttpUrl(value)).toBeNull();
+ });
+});
+
+describe("shouldHardenWebContentsType", () => {
+ it("selects BrowserWindow contents only", () => {
+ expect(shouldHardenWebContentsType("window")).toBe(true);
+ expect(shouldHardenWebContentsType("webview")).toBe(false);
+ expect(shouldHardenWebContentsType("offscreen")).toBe(false);
+ });
+});
+
+describe("isInternalRendererTarget", () => {
+ it.each([
+ ["http://localhost:5173/?windowType=editor", "http://localhost:5173/editor?reload=1"],
+ ["http://127.0.0.1:43123/?windowType=editor", "http://127.0.0.1:43123/assets/index.js"],
+ [
+ "file:///opt/Recordly/dist/index.html?windowType=editor",
+ "file:///opt/Recordly/dist/index.html?windowType=hud-overlay#status",
+ ],
+ ])("identifies the current renderer origin/file", (currentUrl, targetUrl) => {
+ expect(isInternalRendererTarget(currentUrl, targetUrl)).toBe(true);
+ });
+
+ it.each([
+ ["http://localhost:5173/?windowType=editor", "http://localhost.example.com:5173/"],
+ ["http://localhost:5173/", "http://localhost:5174/"],
+ ["https://recordly.example/", "http://recordly.example/"],
+ ["https://recordly.example/", "https://user:pass@recordly.example/"],
+ ["file:///opt/Recordly/dist/index.html", "file:///etc/passwd"],
+ ["file:///opt/Recordly/dist/index.html", "data:text/html,hello"],
+ ["not a URL", "https://example.com/"],
+ ])("distinguishes a target outside the current renderer", (currentUrl, targetUrl) => {
+ expect(isInternalRendererTarget(currentUrl, targetUrl)).toBe(false);
+ });
+});
+
+describe("navigation event handlers", () => {
+ it("preserves an exact renderer reload", () => {
+ const preventDefault = vi.fn();
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWillNavigateHandler(
+ () => "http://localhost:5173/editor?windowType=editor",
+ openExternal,
+ );
+
+ handler({
+ url: "http://localhost:5173/editor?windowType=editor",
+ preventDefault,
+ });
+
+ expect(preventDefault).not.toHaveBeenCalled();
+ expect(openExternal).not.toHaveBeenCalled();
+ });
+
+ it("stops same-origin renderer navigation without externalizing it", () => {
+ const preventDefault = vi.fn();
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWillNavigateHandler(
+ () => "http://localhost:5173/editor",
+ openExternal,
+ );
+
+ handler({ url: "http://localhost:5173/settings", preventDefault });
+
+ expect(preventDefault).toHaveBeenCalledOnce();
+ expect(openExternal).not.toHaveBeenCalled();
+ });
+
+ it("stops same-file query mutation without externalizing it", () => {
+ const preventDefault = vi.fn();
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWillNavigateHandler(
+ () => "file:///opt/Recordly/dist/index.html?windowType=editor",
+ openExternal,
+ );
+
+ handler({
+ url: "file:///opt/Recordly/dist/index.html?smokeExport=1",
+ preventDefault,
+ });
+
+ expect(preventDefault).toHaveBeenCalledOnce();
+ expect(openExternal).not.toHaveBeenCalled();
+ });
+
+ it("stops cross-origin navigation and opens HTTP(S) in the system browser", () => {
+ const preventDefault = vi.fn();
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWillNavigateHandler(
+ () => "http://localhost:5173/editor",
+ openExternal,
+ );
+
+ handler({ url: "https://example.com/docs", preventDefault });
+
+ expect(preventDefault).toHaveBeenCalledOnce();
+ expect(openExternal).toHaveBeenCalledWith("https://example.com/docs");
+ });
+
+ it("stops unsafe schemes without opening them externally", () => {
+ const preventDefault = vi.fn();
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWillNavigateHandler(
+ () => "file:///opt/Recordly/dist/index.html",
+ openExternal,
+ );
+
+ handler({ url: "file:///etc/passwd", preventDefault });
+
+ expect(preventDefault).toHaveBeenCalledOnce();
+ expect(openExternal).not.toHaveBeenCalled();
+ });
+
+ it("stops server redirects without externalizing the target", () => {
+ const preventDefault = vi.fn();
+ createWillRedirectHandler()({ url: "https://example.com/redirect", preventDefault });
+ expect(preventDefault).toHaveBeenCalledOnce();
+ });
+
+ it("always denies Electron child windows while preserving safe external links", () => {
+ const openExternal = vi.fn(async () => undefined);
+ const handler = createWindowOpenHandler(() => "http://localhost:5173/editor", openExternal);
+
+ expect(handler({ url: "https://example.com/docs" })).toEqual({ action: "deny" });
+ expect(handler({ url: "http://localhost:5173/settings" })).toEqual({ action: "deny" });
+ expect(handler({ url: "javascript:alert(1)" })).toEqual({ action: "deny" });
+ expect(openExternal).toHaveBeenCalledOnce();
+ expect(openExternal).toHaveBeenCalledWith("https://example.com/docs");
+ });
+
+ it("reports a system-browser failure without allowing the child window", async () => {
+ const error = new Error("browser unavailable");
+ const reportOpenError = vi.fn();
+ const handler = createWindowOpenHandler(
+ () => "http://localhost:5173/editor",
+ vi.fn(async () => {
+ throw error;
+ }),
+ reportOpenError,
+ );
+
+ expect(handler({ url: "https://example.com/docs" })).toEqual({ action: "deny" });
+ await vi.waitFor(() => {
+ expect(reportOpenError).toHaveBeenCalledWith("https://example.com/docs", error);
+ });
+ });
+
+ it("reports a synchronous browser-launch failure while still denying the child", () => {
+ const error = new Error("browser launch threw");
+ const reportOpenError = vi.fn();
+ const handler = createWindowOpenHandler(
+ () => "http://localhost:5173/editor",
+ vi.fn(() => {
+ throw error;
+ }),
+ reportOpenError,
+ );
+
+ expect(handler({ url: "https://example.com/docs" })).toEqual({ action: "deny" });
+ expect(reportOpenError).toHaveBeenCalledWith("https://example.com/docs", error);
+ });
+
+ it("attaches navigation, redirect, and window-open policies", () => {
+ const on = vi.fn();
+ const setWindowOpenHandler = vi.fn();
+ const webContents = {
+ getURL: () => "http://localhost:5173/",
+ on,
+ setWindowOpenHandler,
+ };
+
+ hardenWebContentsNavigation(
+ webContents,
+ vi.fn(async () => undefined),
+ );
+
+ expect(on).toHaveBeenCalledWith("will-navigate", expect.any(Function));
+ expect(on).toHaveBeenCalledWith("will-redirect", expect.any(Function));
+ expect(on).toHaveBeenCalledWith("did-navigate", expect.any(Function));
+ expect(setWindowOpenHandler).toHaveBeenCalledWith(expect.any(Function));
+ });
+
+ it("does not trust a renderer-mutated URL as an exact reload", () => {
+ let currentUrl = "file:///opt/Recordly/dist/index.html?windowType=editor";
+ const on = vi.fn();
+ const webContents = {
+ getURL: () => currentUrl,
+ on,
+ setWindowOpenHandler: vi.fn(),
+ };
+ const openExternal = vi.fn(async () => undefined);
+
+ hardenWebContentsNavigation(webContents, openExternal);
+
+ // history.replaceState() changes getURL() without crossing a document-navigation boundary.
+ currentUrl = "file:///opt/Recordly/dist/index.html?windowType=source-selector";
+ const willNavigate = on.mock.calls.find(([eventName]) => eventName === "will-navigate")?.[1];
+ if (typeof willNavigate !== "function") {
+ throw new Error("will-navigate handler was not registered");
+ }
+
+ const preventDefault = vi.fn();
+ willNavigate({ url: currentUrl, preventDefault });
+
+ expect(preventDefault).toHaveBeenCalledOnce();
+ expect(openExternal).not.toHaveBeenCalled();
+ });
+
+ it("trusts an exact reload after a completed document navigation", () => {
+ const on = vi.fn();
+ const webContents = {
+ getURL: () => "",
+ on,
+ setWindowOpenHandler: vi.fn(),
+ };
+
+ hardenWebContentsNavigation(
+ webContents,
+ vi.fn(async () => undefined),
+ );
+
+ const didNavigate = on.mock.calls.find(([eventName]) => eventName === "did-navigate")?.[1];
+ const willNavigate = on.mock.calls.find(([eventName]) => eventName === "will-navigate")?.[1];
+ if (typeof didNavigate !== "function" || typeof willNavigate !== "function") {
+ throw new Error("navigation handlers were not registered");
+ }
+
+ const loadedUrl = "file:///opt/Recordly/dist/index.html?windowType=editor";
+ didNavigate({}, loadedUrl);
+ const preventDefault = vi.fn();
+ willNavigate({ url: loadedUrl, preventDefault });
+
+ expect(preventDefault).not.toHaveBeenCalled();
+ });
+});
diff --git a/electron/navigationPolicy.ts b/electron/navigationPolicy.ts
new file mode 100644
index 00000000..1bc9df4e
--- /dev/null
+++ b/electron/navigationPolicy.ts
@@ -0,0 +1,151 @@
+import type { WebContents } from "electron";
+
+type OpenExternal = (url: string) => Promise;
+type ReportOpenError = (url: string, error: unknown) => void;
+
+export type NavigationEvent = {
+ url: string;
+ preventDefault: () => void;
+};
+
+export function shouldHardenWebContentsType(type: ReturnType): boolean {
+ return type === "window";
+}
+
+export function normalizeExternalHttpUrl(value: string): string | null {
+ try {
+ const url = new URL(value);
+ if (
+ (url.protocol !== "http:" && url.protocol !== "https:") ||
+ !url.hostname ||
+ url.username ||
+ url.password
+ ) {
+ return null;
+ }
+
+ return url.href;
+ } catch {
+ return null;
+ }
+}
+
+export function isInternalRendererTarget(currentValue: string, targetValue: string): boolean {
+ try {
+ const currentUrl = new URL(currentValue);
+ const targetUrl = new URL(targetValue);
+
+ if (targetUrl.username || targetUrl.password) {
+ return false;
+ }
+
+ if (
+ (currentUrl.protocol === "http:" || currentUrl.protocol === "https:") &&
+ (targetUrl.protocol === "http:" || targetUrl.protocol === "https:")
+ ) {
+ return currentUrl.origin === targetUrl.origin;
+ }
+
+ if (currentUrl.protocol === "file:" && targetUrl.protocol === "file:") {
+ return currentUrl.host === targetUrl.host && currentUrl.pathname === targetUrl.pathname;
+ }
+
+ return currentUrl.href === targetUrl.href;
+ } catch {
+ return false;
+ }
+}
+
+function isExactRendererLocation(currentValue: string, targetValue: string): boolean {
+ try {
+ const currentUrl = new URL(currentValue);
+ const targetUrl = new URL(targetValue);
+ return !targetUrl.username && !targetUrl.password && currentUrl.href === targetUrl.href;
+ } catch {
+ return false;
+ }
+}
+
+function openExternalIfSafe(
+ value: string,
+ openExternal: OpenExternal,
+ reportOpenError: ReportOpenError,
+): void {
+ const safeUrl = normalizeExternalHttpUrl(value);
+ if (!safeUrl) {
+ return;
+ }
+
+ try {
+ void openExternal(safeUrl).catch((error) => reportOpenError(safeUrl, error));
+ } catch (error) {
+ reportOpenError(safeUrl, error);
+ }
+}
+
+const defaultReportOpenError: ReportOpenError = (url, error) => {
+ console.error("[navigation-policy] Failed to open external URL", { url, error });
+};
+
+export function createWillNavigateHandler(
+ getTrustedRendererUrl: () => string,
+ openExternal: OpenExternal,
+ reportOpenError: ReportOpenError = defaultReportOpenError,
+) {
+ return (event: NavigationEvent): void => {
+ const trustedRendererUrl = getTrustedRendererUrl();
+ // Preserve an exact reload, but freeze all renderer-selected destination changes,
+ // including same-origin query mutations that can carry privileged local paths.
+ if (isExactRendererLocation(trustedRendererUrl, event.url)) {
+ return;
+ }
+
+ // The internal-target check only prevents app URLs from leaking into the system browser.
+ event.preventDefault();
+ if (isInternalRendererTarget(trustedRendererUrl, event.url)) {
+ return;
+ }
+
+ openExternalIfSafe(event.url, openExternal, reportOpenError);
+ };
+}
+
+export function createWillRedirectHandler() {
+ return (event: NavigationEvent): void => {
+ event.preventDefault();
+ };
+}
+
+export function createWindowOpenHandler(
+ getCurrentUrl: () => string,
+ openExternal: OpenExternal,
+ reportOpenError: ReportOpenError = defaultReportOpenError,
+) {
+ return (details: { url: string }) => {
+ if (!isInternalRendererTarget(getCurrentUrl(), details.url)) {
+ openExternalIfSafe(details.url, openExternal, reportOpenError);
+ }
+ return { action: "deny" as const };
+ };
+}
+
+export function hardenWebContentsNavigation(
+ webContents: Pick,
+ openExternal: OpenExternal,
+ reportOpenError: ReportOpenError = defaultReportOpenError,
+): void {
+ // Renderer history APIs mutate getURL() without a document navigation. Keep the last
+ // main-frame document URL as the reload trust boundary instead of trusting that live value.
+ let trustedRendererUrl = webContents.getURL();
+ webContents.on("did-navigate", (_event, url) => {
+ trustedRendererUrl = url;
+ });
+ webContents.on(
+ "will-navigate",
+ createWillNavigateHandler(() => trustedRendererUrl, openExternal, reportOpenError),
+ );
+ webContents.on("will-redirect", createWillRedirectHandler());
+ webContents.setWindowOpenHandler(
+ createWindowOpenHandler(() => webContents.getURL(), openExternal, reportOpenError),
+ );
+}
diff --git a/electron/permissionPolicy.test.ts b/electron/permissionPolicy.test.ts
new file mode 100644
index 00000000..45ffc82f
--- /dev/null
+++ b/electron/permissionPolicy.test.ts
@@ -0,0 +1,197 @@
+import { describe, expect, it } from "vitest";
+
+import {
+ isTrustedCaptureDocumentUrl,
+ shouldGrantDisplayCapture,
+ shouldGrantMediaPermission,
+} from "./permissionPolicy";
+
+const TRUSTED_DOCUMENT_BASE_URLS = [
+ "http://localhost:5173/",
+ "http://127.0.0.1:43127/",
+ "file:///C:/Program%20Files/Recordly/resources/app.asar/dist/index.html",
+];
+
+const DEV_HUD_URL = "http://localhost:5173/?windowType=hud-overlay";
+const PACKAGED_HUD_URL = "http://127.0.0.1:43127/?windowType=hud-overlay";
+const FILE_HUD_URL =
+ "file:///C:/Program%20Files/Recordly/resources/app.asar/dist/index.html?windowType=hud-overlay";
+
+describe("isTrustedCaptureDocumentUrl", () => {
+ it.each([
+ DEV_HUD_URL,
+ PACKAGED_HUD_URL,
+ FILE_HUD_URL,
+ `${DEV_HUD_URL}#microphone`,
+ ])("accepts a Recordly HUD document: %s", (candidateUrl) => {
+ expect(isTrustedCaptureDocumentUrl(candidateUrl, TRUSTED_DOCUMENT_BASE_URLS)).toBe(true);
+ });
+
+ it.each([
+ "http://localhost:5173/",
+ "http://localhost:5173/?windowType=editor",
+ "http://localhost:5173/?windowType=HUD-OVERLAY",
+ "http://localhost:5173/?windowType=hud-overlay&debug=1",
+ "http://localhost:5173/?windowType=hud-overlay&windowType=hud-overlay",
+ "http://localhost:5174/?windowType=hud-overlay",
+ "http://localhost.evil.test:5173/?windowType=hud-overlay",
+ "http://localhost:5173.evil.test/?windowType=hud-overlay",
+ "http://user@localhost:5173/?windowType=hud-overlay",
+ "https://localhost:5173/?windowType=hud-overlay",
+ "http://127.0.0.1:43127/nested/?windowType=hud-overlay",
+ "file:///C:/Program%20Files/Recordly/resources/app.asar/dist/other.html?windowType=hud-overlay",
+ "file:///C:/Program%20Files/Recordly/resources/app.asar/dist/index.html/child?windowType=hud-overlay",
+ "data:text/html,recordly?windowType=hud-overlay",
+ "not a url",
+ ])("rejects a non-Recordly capture document: %s", (candidateUrl) => {
+ expect(isTrustedCaptureDocumentUrl(candidateUrl, TRUSTED_DOCUMENT_BASE_URLS)).toBe(false);
+ });
+
+ it("ignores malformed trusted base URLs instead of throwing", () => {
+ expect(
+ isTrustedCaptureDocumentUrl(DEV_HUD_URL, ["not a url", ...TRUSTED_DOCUMENT_BASE_URLS]),
+ ).toBe(true);
+ });
+});
+
+describe("shouldGrantMediaPermission", () => {
+ const makeRequest = (
+ overrides: Partial[0]> = {},
+ ): Parameters[0] => ({
+ permission: "media",
+ isTrustedCaptureWindow: true,
+ isMainFrame: true,
+ currentDocumentUrl: DEV_HUD_URL,
+ requestingUrl: DEV_HUD_URL,
+ securityOrigins: ["http://localhost:5173"],
+ ...overrides,
+ });
+
+ it("grants camera or microphone media to the trusted HUD main frame", () => {
+ expect(shouldGrantMediaPermission(makeRequest(), TRUSTED_DOCUMENT_BASE_URLS)).toBe(true);
+ });
+
+ it("accepts Chromium's trailing-slash HTTP origin serialization", () => {
+ expect(
+ shouldGrantMediaPermission(
+ makeRequest({ securityOrigins: ["http://localhost:5173/"] }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ });
+
+ it("accepts the packaged loopback renderer with its exact origin", () => {
+ expect(
+ shouldGrantMediaPermission(
+ makeRequest({
+ currentDocumentUrl: PACKAGED_HUD_URL,
+ requestingUrl: PACKAGED_HUD_URL,
+ securityOrigins: ["http://127.0.0.1:43127"],
+ }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ });
+
+ it.each([
+ "null",
+ "file://",
+ "file:///",
+ ])("accepts Chromium's packaged file origin form: %s", (securityOrigin) => {
+ expect(
+ shouldGrantMediaPermission(
+ makeRequest({
+ currentDocumentUrl: FILE_HUD_URL,
+ requestingUrl: FILE_HUD_URL,
+ securityOrigins: [securityOrigin],
+ }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ });
+
+ it.each([
+ ["another permission", { permission: "display-capture" }],
+ ["another BrowserWindow", { isTrustedCaptureWindow: false }],
+ ["a subframe", { isMainFrame: false }],
+ ["an untrusted current document", { currentDocumentUrl: "https://example.com/" }],
+ ["a missing requesting document", { requestingUrl: "" }],
+ ["an untrusted requesting document", { requestingUrl: "https://example.com/" }],
+ ["a different trusted document", { requestingUrl: PACKAGED_HUD_URL }],
+ ["a mismatched origin", { securityOrigins: ["http://localhost:5174"] }],
+ ["an origin lookalike", { securityOrigins: ["http://localhost:5173.evil.test"] }],
+ ["an origin with credentials", { securityOrigins: ["http://user@localhost:5173/"] }],
+ ["an origin with a path", { securityOrigins: ["http://localhost:5173/other"] }],
+ ["an origin with a query", { securityOrigins: ["http://localhost:5173/?debug=1"] }],
+ ["a missing security origin", { securityOrigins: [] }],
+ ["an empty origin", { securityOrigins: [""] }],
+ ] as const)("denies %s", (_label, overrides) => {
+ expect(shouldGrantMediaPermission(makeRequest(overrides), TRUSTED_DOCUMENT_BASE_URLS)).toBe(
+ false,
+ );
+ });
+});
+
+describe("shouldGrantDisplayCapture", () => {
+ const makeRequest = (
+ overrides: Partial[0]> = {},
+ ): Parameters[0] => ({
+ isTrustedCaptureWindow: true,
+ isMainFrame: true,
+ currentDocumentUrl: DEV_HUD_URL,
+ securityOrigin: "http://localhost:5173",
+ videoRequested: true,
+ ...overrides,
+ });
+
+ it("grants selected-display video to the trusted HUD main frame", () => {
+ expect(shouldGrantDisplayCapture(makeRequest(), TRUSTED_DOCUMENT_BASE_URLS)).toBe(true);
+ });
+
+ it("accepts a trailing slash on the display security origin", () => {
+ expect(
+ shouldGrantDisplayCapture(
+ makeRequest({ securityOrigin: "http://localhost:5173/" }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ });
+
+ it("accepts the packaged loopback renderer with its exact origin", () => {
+ expect(
+ shouldGrantDisplayCapture(
+ makeRequest({
+ currentDocumentUrl: PACKAGED_HUD_URL,
+ securityOrigin: "http://127.0.0.1:43127",
+ }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ });
+
+ it.each(["null", "file://", "file:///"])(
+ "accepts Chromium's packaged file origin form: %s",
+ (securityOrigin) => {
+ expect(
+ shouldGrantDisplayCapture(
+ makeRequest({ currentDocumentUrl: FILE_HUD_URL, securityOrigin }),
+ TRUSTED_DOCUMENT_BASE_URLS,
+ ),
+ ).toBe(true);
+ },
+ );
+
+ it.each([
+ ["another BrowserWindow", { isTrustedCaptureWindow: false }],
+ ["a subframe", { isMainFrame: false }],
+ ["a non-Recordly document", { currentDocumentUrl: "https://example.com/" }],
+ ["a mismatched origin", { securityOrigin: "http://127.0.0.1:43127" }],
+ ["a malformed origin", { securityOrigin: "not an origin" }],
+ ["an origin with a path", { securityOrigin: "http://localhost:5173/other" }],
+ ["an audio-only request", { videoRequested: false }],
+ ] as const)("denies %s", (_label, overrides) => {
+ expect(shouldGrantDisplayCapture(makeRequest(overrides), TRUSTED_DOCUMENT_BASE_URLS)).toBe(
+ false,
+ );
+ });
+});
diff --git a/electron/permissionPolicy.ts b/electron/permissionPolicy.ts
new file mode 100644
index 00000000..0c9ea07c
--- /dev/null
+++ b/electron/permissionPolicy.ts
@@ -0,0 +1,157 @@
+const CAPTURE_WINDOW_TYPE = "hud-overlay";
+const TRUSTED_RENDERER_PROTOCOLS = new Set(["http:", "https:", "file:"]);
+const FILE_SECURITY_ORIGINS = new Set(["null", "file://", "file:///"]);
+
+export interface MediaPermissionPolicyRequest {
+ permission: string;
+ isTrustedCaptureWindow: boolean;
+ isMainFrame: boolean;
+ currentDocumentUrl: string;
+ requestingUrl: string;
+ securityOrigins: readonly string[];
+}
+
+export interface DisplayCapturePolicyRequest {
+ isTrustedCaptureWindow: boolean;
+ isMainFrame: boolean;
+ currentDocumentUrl: string;
+ securityOrigin: string;
+ videoRequested: boolean;
+}
+
+function parseUrl(value: string): URL | null {
+ try {
+ return new URL(value);
+ } catch {
+ return null;
+ }
+}
+
+function hasExactCaptureWindowQuery(url: URL): boolean {
+ const entries = [...url.searchParams.entries()];
+ return (
+ entries.length === 1 &&
+ entries[0]?.[0] === "windowType" &&
+ entries[0][1] === CAPTURE_WINDOW_TYPE
+ );
+}
+
+function isValidTrustedBaseUrl(url: URL): boolean {
+ return (
+ TRUSTED_RENDERER_PROTOCOLS.has(url.protocol) &&
+ url.username === "" &&
+ url.password === "" &&
+ url.search === "" &&
+ url.hash === ""
+ );
+}
+
+function hasSameBaseLocation(candidate: URL, trustedBase: URL): boolean {
+ return (
+ candidate.protocol === trustedBase.protocol &&
+ candidate.hostname === trustedBase.hostname &&
+ candidate.port === trustedBase.port &&
+ candidate.pathname === trustedBase.pathname
+ );
+}
+
+export function isTrustedCaptureDocumentUrl(
+ candidateUrl: string,
+ trustedDocumentBaseUrls: readonly string[],
+): boolean {
+ const candidate = parseUrl(candidateUrl);
+ if (
+ !candidate ||
+ !TRUSTED_RENDERER_PROTOCOLS.has(candidate.protocol) ||
+ candidate.username !== "" ||
+ candidate.password !== "" ||
+ !hasExactCaptureWindowQuery(candidate)
+ ) {
+ return false;
+ }
+
+ return trustedDocumentBaseUrls.some((trustedBaseUrl) => {
+ const trustedBase = parseUrl(trustedBaseUrl);
+ return Boolean(
+ trustedBase &&
+ isValidTrustedBaseUrl(trustedBase) &&
+ hasSameBaseLocation(candidate, trustedBase),
+ );
+ });
+}
+
+function isSameDocument(firstUrl: string, secondUrl: string): boolean {
+ const first = parseUrl(firstUrl);
+ const second = parseUrl(secondUrl);
+ if (!first || !second) {
+ return false;
+ }
+
+ first.hash = "";
+ second.hash = "";
+ return first.href === second.href;
+}
+
+function isSecurityOriginForDocument(securityOrigin: string, documentUrl: string): boolean {
+ const document = parseUrl(documentUrl);
+ if (!document) {
+ return false;
+ }
+
+ if (document.protocol === "file:") {
+ return FILE_SECURITY_ORIGINS.has(securityOrigin);
+ }
+
+ const origin = parseUrl(securityOrigin);
+ return Boolean(
+ origin &&
+ (origin.protocol === "http:" || origin.protocol === "https:") &&
+ origin.username === "" &&
+ origin.password === "" &&
+ origin.origin === document.origin &&
+ origin.pathname === "/" &&
+ origin.search === "" &&
+ origin.hash === "",
+ );
+}
+
+export function shouldGrantMediaPermission(
+ request: MediaPermissionPolicyRequest,
+ trustedDocumentBaseUrls: readonly string[],
+): boolean {
+ if (
+ request.permission !== "media" ||
+ !request.isTrustedCaptureWindow ||
+ !request.isMainFrame ||
+ !isTrustedCaptureDocumentUrl(request.currentDocumentUrl, trustedDocumentBaseUrls)
+ ) {
+ return false;
+ }
+
+ if (
+ !isTrustedCaptureDocumentUrl(request.requestingUrl, trustedDocumentBaseUrls) ||
+ !isSameDocument(request.currentDocumentUrl, request.requestingUrl)
+ ) {
+ return false;
+ }
+
+ return (
+ request.securityOrigins.length > 0 &&
+ request.securityOrigins.every((securityOrigin) =>
+ isSecurityOriginForDocument(securityOrigin, request.currentDocumentUrl),
+ )
+ );
+}
+
+export function shouldGrantDisplayCapture(
+ request: DisplayCapturePolicyRequest,
+ trustedDocumentBaseUrls: readonly string[],
+): boolean {
+ return (
+ request.isTrustedCaptureWindow &&
+ request.isMainFrame &&
+ request.videoRequested &&
+ isTrustedCaptureDocumentUrl(request.currentDocumentUrl, trustedDocumentBaseUrls) &&
+ isSecurityOriginForDocument(request.securityOrigin, request.currentDocumentUrl)
+ );
+}
diff --git a/package-lock.json b/package-lock.json
index a255b232..8688478b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,8 +20,6 @@
"@biomejs/biome": "2.3.13",
"@electron/rebuild": "^4.0.3",
"@fix-webm-duration/fix": "^1.0.1",
- "@pixi/filter-drop-shadow": "^5.2.0",
- "@pixi/filter-motion-blur": "^5.1.1",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -37,7 +35,6 @@
"@types/node": "^25.0.3",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
- "@types/uuid": "^10.0.0",
"@uiw/color-convert": "^2.9.2",
"@uiw/react-color-block": "^2.9.2",
"@vitejs/plugin-react": "^4.2.1",
@@ -45,14 +42,11 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dnd-timeline": "^2.2.0",
- "electron": "^39.2.7",
+ "electron": "^39.8.10",
"electron-builder": "^26.7.0",
- "electron-icon-builder": "^2.0.1",
"emoji-picker-react": "^4.16.1",
"fast-check": "^4.5.2",
- "fix-webm-duration": "^1.0.6",
"gif.js": "^0.2.0",
- "gsap": "^3.13.0",
"mediabunny": "^1.25.1",
"motion": "^12.23.24",
"mp4box": "^2.2.0",
@@ -70,11 +64,10 @@
"tailwindcss-animate": "^1.0.7",
"terser": "^5.44.1",
"typescript": "^5.2.2",
- "uuid": "^13.0.0",
"vite": "^5.1.6",
"vite-plugin-electron": "^0.28.6",
"vite-plugin-electron-renderer": "^0.14.5",
- "vitest": "^4.0.16",
+ "vitest": "^4.1.10",
"web-demuxer": "^4.0.0"
}
},
@@ -351,6 +344,7 @@
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -1417,6 +1411,40 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/@emnapi/core": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
+ "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.2",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
+ "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
+ "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@@ -1707,9 +1735,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
- "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
"cpu": [
"arm64"
],
@@ -1719,6 +1747,7 @@
"os": [
"netbsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -1741,9 +1770,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
- "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
"cpu": [
"arm64"
],
@@ -1753,6 +1782,7 @@
"os": [
"openbsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -1775,9 +1805,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
- "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
+ "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
"cpu": [
"arm64"
],
@@ -1787,6 +1817,7 @@
"os": [
"openharmony"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -2048,512 +2079,6 @@
"node": ">=16 || 14 >=14.17"
}
},
- "node_modules/@jimp/bmp": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.13.tgz",
- "integrity": "sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "bmp-js": "^0.1.0"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/core": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.13.tgz",
- "integrity": "sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "any-base": "^1.1.0",
- "buffer": "^5.2.0",
- "exif-parser": "^0.1.12",
- "file-type": "^16.5.4",
- "load-bmfont": "^1.3.1",
- "mkdirp": "^0.5.1",
- "phin": "^2.9.1",
- "pixelmatch": "^4.0.2",
- "tinycolor2": "^1.4.1"
- }
- },
- "node_modules/@jimp/core/node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.6"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
- "node_modules/@jimp/custom": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.13.tgz",
- "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/core": "^0.16.13"
- }
- },
- "node_modules/@jimp/gif": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.13.tgz",
- "integrity": "sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "gifwrap": "^0.9.2",
- "omggif": "^1.0.9"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/jpeg": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.13.tgz",
- "integrity": "sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "jpeg-js": "^0.4.2"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-blit": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.13.tgz",
- "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-blur": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.13.tgz",
- "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-circle": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.13.tgz",
- "integrity": "sha512-RNave7EFgZrb5V5EpdvJGAEHMnDAJuwv05hKscNfIYxf0kR3KhViBTDy+MoTnMlIvaKFULfwIgaZWzyhuINMzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-color": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.13.tgz",
- "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "tinycolor2": "^1.4.1"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-contain": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.13.tgz",
- "integrity": "sha512-QayTXw4tXMwU6q6acNTQrTTFTXpNRBe+MgTGMDU0lk+23PjlFCO/9sacflelG8lsp7vNHhAxFeHptDMAksEYzg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-blit": ">=0.3.5",
- "@jimp/plugin-resize": ">=0.3.5",
- "@jimp/plugin-scale": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-cover": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.13.tgz",
- "integrity": "sha512-BSsP71GTNaqWRcvkbWuIVH+zK7b3TSNebbhDkFK0fVaUTzHuKMS/mgY4hDZIEVt7Rf5FjadAYtsujHN9w0iSYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-crop": ">=0.3.5",
- "@jimp/plugin-resize": ">=0.3.5",
- "@jimp/plugin-scale": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-crop": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.13.tgz",
- "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-displace": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.13.tgz",
- "integrity": "sha512-qt9WKq8vWrcjySa9DyQ0x/RBMHQeiVjdVSY1SJsMjssPUf0pS74qorcuAkGi89biN3YoGUgPkpqECnAWnYwgGA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-dither": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.13.tgz",
- "integrity": "sha512-5/N3yJggbWQTlGZHQYJPmQXEwR52qaXjEzkp1yRBbtdaekXE3BG/suo0fqeoV/csf8ooI78sJzYmIrxNoWVtgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-fisheye": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.13.tgz",
- "integrity": "sha512-2rZmTdFbT/cF9lEZIkXCYO0TsT114Q27AX5IAo0Sju6jVQbvIk1dFUTnwLDadTo8wkJlFzGqMQ24Cs8cHWOliA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-flip": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.13.tgz",
- "integrity": "sha512-EmcgAA74FTc5u7Z+hUO/sRjWwfPPLuOQP5O64x5g4j0T12Bd29IgsYZxoutZo/rb3579+JNa/3wsSEmyVv1EpA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-rotate": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-gaussian": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.13.tgz",
- "integrity": "sha512-A1XKfGQD0iDdIiKqFYi8nZMv4dDVYdxbrmgR7y/CzUHhSYdcmoljLIIsZZM3Iks/Wa353W3vtvkWLuDbQbch1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-invert": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.13.tgz",
- "integrity": "sha512-xFMrIn7czEZbdbMzZWuaZFnlLGJDVJ82y5vlsKsXRTG2kcxRsMPXvZRWHV57nSs1YFsNqXSbrC8B98n0E32njQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-mask": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.13.tgz",
- "integrity": "sha512-wLRYKVBXql2GAYgt6FkTnCfE+q5NomM7Dlh0oIPGAoMBWDyTx0eYutRK6PlUrRK2yMHuroAJCglICTbxqGzowQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-normalize": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.13.tgz",
- "integrity": "sha512-3tfad0n9soRna4IfW9NzQdQ2Z3ijkmo21DREHbE6CGcMIxOSvfRdSvf1qQPApxjTSo8LTU4MCi/fidx/NZ0GqQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-print": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.13.tgz",
- "integrity": "sha512-0m6i3p01PGRkGAK9r53hDYrkyMq+tlhLOIbsSTmZyh6HLshUKlTB7eXskF5OpVd5ZUHoltlNc6R+ggvKIzxRFw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "load-bmfont": "^1.4.0"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-blit": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-resize": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz",
- "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-rotate": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.13.tgz",
- "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-blit": ">=0.3.5",
- "@jimp/plugin-crop": ">=0.3.5",
- "@jimp/plugin-resize": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-scale": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.13.tgz",
- "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-resize": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-shadow": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.13.tgz",
- "integrity": "sha512-nmu5VSZ9hsB1JchTKhnnCY+paRBnwzSyK5fhkhtQHHoFD5ArBQ/5wU8y6tCr7k/GQhhGq1OrixsECeMjPoc8Zw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-blur": ">=0.3.5",
- "@jimp/plugin-resize": ">=0.3.5"
- }
- },
- "node_modules/@jimp/plugin-threshold": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.13.tgz",
- "integrity": "sha512-+3zArBH0OE3Rhjm4HyAokMsZlIq5gpQec33CncyoSwxtRBM2WAhUVmCUKuBo+Lr/2/4ISoY4BWpHKhMLDix6cA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5",
- "@jimp/plugin-color": ">=0.8.0",
- "@jimp/plugin-resize": ">=0.8.0"
- }
- },
- "node_modules/@jimp/plugins": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.13.tgz",
- "integrity": "sha512-CJLdqODEhEVs4MgWCxpWL5l95sCBlkuSLz65cxEm56X5akIsn4LOlwnKoSEZioYcZUBvHhCheH67AyPTudfnQQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/plugin-blit": "^0.16.13",
- "@jimp/plugin-blur": "^0.16.13",
- "@jimp/plugin-circle": "^0.16.13",
- "@jimp/plugin-color": "^0.16.13",
- "@jimp/plugin-contain": "^0.16.13",
- "@jimp/plugin-cover": "^0.16.13",
- "@jimp/plugin-crop": "^0.16.13",
- "@jimp/plugin-displace": "^0.16.13",
- "@jimp/plugin-dither": "^0.16.13",
- "@jimp/plugin-fisheye": "^0.16.13",
- "@jimp/plugin-flip": "^0.16.13",
- "@jimp/plugin-gaussian": "^0.16.13",
- "@jimp/plugin-invert": "^0.16.13",
- "@jimp/plugin-mask": "^0.16.13",
- "@jimp/plugin-normalize": "^0.16.13",
- "@jimp/plugin-print": "^0.16.13",
- "@jimp/plugin-resize": "^0.16.13",
- "@jimp/plugin-rotate": "^0.16.13",
- "@jimp/plugin-scale": "^0.16.13",
- "@jimp/plugin-shadow": "^0.16.13",
- "@jimp/plugin-threshold": "^0.16.13",
- "timm": "^1.6.1"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/png": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.13.tgz",
- "integrity": "sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/utils": "^0.16.13",
- "pngjs": "^3.3.3"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/png/node_modules/pngjs": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
- "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/@jimp/tiff": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.13.tgz",
- "integrity": "sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "utif": "^2.0.1"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/types": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.13.tgz",
- "integrity": "sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/bmp": "^0.16.13",
- "@jimp/gif": "^0.16.13",
- "@jimp/jpeg": "^0.16.13",
- "@jimp/png": "^0.16.13",
- "@jimp/tiff": "^0.16.13",
- "timm": "^1.6.1"
- },
- "peerDependencies": {
- "@jimp/custom": ">=0.3.5"
- }
- },
- "node_modules/@jimp/utils": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.13.tgz",
- "integrity": "sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "regenerator-runtime": "^0.13.3"
- }
- },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -2693,6 +2218,25 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
+ "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.3"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2808,6 +2352,16 @@
"node": ">= 14"
}
},
+ "node_modules/@oxc-project/types": {
+ "version": "0.139.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
+ "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
"node_modules/@phosphor-icons/react": {
"version": "2.1.10",
"resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz",
@@ -2821,17 +2375,6 @@
"react-dom": ">= 16.8"
}
},
- "node_modules/@pixi/color": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.4.3.tgz",
- "integrity": "sha512-a6R+bXKeXMDcRmjYQoBIK+v2EYqxSX49wcjAY579EYM/WrFKS98nSees6lqVUcLKrcQh2DT9srJHX7XMny3voQ==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@pixi/colord": "^2.9.6"
- }
- },
"node_modules/@pixi/colord": {
"version": "2.9.6",
"resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz",
@@ -2839,160 +2382,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@pixi/constants": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-7.4.3.tgz",
- "integrity": "sha512-QGmwJUNQy/vVEHzL6VGQvnwawLZ1wceZMI8HwJAT4/I2uAzbBeFDdmCS8WsTpSWLZjF/DszDc1D8BFp4pVJ5UQ==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/@pixi/core": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/core/-/core-7.4.3.tgz",
- "integrity": "sha512-5YDs11faWgVVTL8VZtLU05/Fl47vaP5Tnsbf+y/WRR0VSW3KhRRGTBU1J3Gdc2xEWbJhUK07KGP7eSZpvtPVgA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@pixi/color": "7.4.3",
- "@pixi/constants": "7.4.3",
- "@pixi/extensions": "7.4.3",
- "@pixi/math": "7.4.3",
- "@pixi/runner": "7.4.3",
- "@pixi/settings": "7.4.3",
- "@pixi/ticker": "7.4.3",
- "@pixi/utils": "7.4.3"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/pixijs"
- }
- },
- "node_modules/@pixi/extensions": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/extensions/-/extensions-7.4.3.tgz",
- "integrity": "sha512-FhoiYkHQEDYHUE7wXhqfsTRz6KxLXjuMbSiAwnLb9uG1vAgp6q6qd6HEsf4X30YaZbLFY8a4KY6hFZWjF+4Fdw==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/@pixi/filter-drop-shadow": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@pixi/filter-drop-shadow/-/filter-drop-shadow-5.2.0.tgz",
- "integrity": "sha512-cYS2KDER7cwCu0V4VNSxTHGvzmNcEXdC9j3031YBOkUAE3+p17LMS/TAt6XeMfJV7KaPuusvXy2NFgGkv3RDbw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@pixi/filter-kawase-blur": "5.1.1"
- },
- "peerDependencies": {
- "@pixi/core": "^7.0.0-X"
- }
- },
- "node_modules/@pixi/filter-kawase-blur": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@pixi/filter-kawase-blur/-/filter-kawase-blur-5.1.1.tgz",
- "integrity": "sha512-nPnJ1ChBFP+4pgFCwC0RJgHAJCetiHcQU3INH7zCdq88cFABmVmhN+wCKRNg4H7lF1EJjaXgFDkTrTreOD/bnw==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@pixi/core": "^7.0.0-X"
- }
- },
- "node_modules/@pixi/filter-motion-blur": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@pixi/filter-motion-blur/-/filter-motion-blur-5.1.1.tgz",
- "integrity": "sha512-I94s3pW2GutjCyXiKQ/dI4Vl9JKne+Q8QgGRn1mrk0Uwg6DDO/OQI3jqv01S+SCTU3LZqhR/p8AQyxeDmOhr2w==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@pixi/core": "^7.0.0-X"
- }
- },
- "node_modules/@pixi/math": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/math/-/math-7.4.3.tgz",
- "integrity": "sha512-/uJOVhR2DOZ+zgdI6Bs/CwcXT4bNRKsS+TqX3ekRIxPCwaLra+Qdm7aDxT5cTToDzdxbKL5+rwiLu3Y1egILDw==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/@pixi/runner": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-7.4.3.tgz",
- "integrity": "sha512-TJyfp7y23u5vvRAyYhVSa7ytq0PdKSvPLXu4G3meoFh1oxTLHH6g/RIzLuxUAThPG2z7ftthuW3qWq6dRV+dhw==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/@pixi/settings": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-7.4.3.tgz",
- "integrity": "sha512-SmGK8smc0PxRB9nr0UJioEtE9hl4gvj9OedCvZx3bxBwA3omA5BmP3CyhQfN8XJ29+o2OUL01r3zAPVol4l4lA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@pixi/constants": "7.4.3",
- "@types/css-font-loading-module": "^0.0.12",
- "ismobilejs": "^1.1.0"
- }
- },
- "node_modules/@pixi/ticker": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-7.4.3.tgz",
- "integrity": "sha512-tHsAD0iOUb6QSGGw+c8cyRBvxsq/NlfzIFBZLEHhWZ+Bx4a0MmXup6I/yJDGmyPCYE+ctCcAfY13wKAzdiVFgQ==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@pixi/extensions": "7.4.3",
- "@pixi/settings": "7.4.3",
- "@pixi/utils": "7.4.3"
- }
- },
- "node_modules/@pixi/utils": {
- "version": "7.4.3",
- "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-7.4.3.tgz",
- "integrity": "sha512-NO3Y9HAn2UKS1YdxffqsPp+kDpVm8XWvkZcS/E+rBzY9VTLnNOI7cawSRm+dacdET3a8Jad3aDKEDZ0HmAqAFA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@pixi/color": "7.4.3",
- "@pixi/constants": "7.4.3",
- "@pixi/settings": "7.4.3",
- "@types/earcut": "^2.1.0",
- "earcut": "^2.2.4",
- "eventemitter3": "^4.0.0",
- "url": "^0.11.0"
- }
- },
- "node_modules/@pixi/utils/node_modules/@types/earcut": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.4.tgz",
- "integrity": "sha512-qp3m9PPz4gULB9MhjGID7wpo3gJ4bTGXm7ltNDsmOvsPduTeHp8wSW9YckBj3mljeOh4F0m2z/0JKAALRKbmLQ==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
- "node_modules/@pixi/utils/node_modules/earcut": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
- "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
- "dev": true,
- "license": "ISC",
- "peer": true
- },
- "node_modules/@pixi/utils/node_modules/eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -3943,6 +3332,263 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
+ "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
+ "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
+ "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
+ "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
+ "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
+ "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
+ "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
+ "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
+ "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
+ "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
+ "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
+ "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
+ "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "1.11.1",
+ "@emnapi/runtime": "1.11.1",
+ "@napi-rs/wasm-runtime": "^1.1.6"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
+ "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
+ "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
@@ -4291,12 +3937,16 @@
"node": ">=10"
}
},
- "node_modules/@tokenizer/token": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
- "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
+ "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
@@ -4540,13 +4190,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/verror": {
"version": "1.10.11",
"resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz",
@@ -4654,44 +4297,44 @@
}
},
"node_modules/@vitest/expect": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.16.tgz",
- "integrity": "sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz",
+ "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2",
- "@vitest/spy": "4.0.16",
- "@vitest/utils": "4.0.16",
- "chai": "^6.2.1",
- "tinyrainbow": "^3.0.3"
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/pretty-format": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.16.tgz",
- "integrity": "sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz",
+ "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tinyrainbow": "^3.0.3"
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@vitest/runner": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.16.tgz",
- "integrity": "sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz",
+ "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "4.0.16",
+ "@vitest/utils": "4.1.10",
"pathe": "^2.0.3"
},
"funding": {
@@ -4699,13 +4342,14 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.16.tgz",
- "integrity": "sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz",
+ "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.0.16",
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/utils": "4.1.10",
"magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
@@ -4714,9 +4358,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.16.tgz",
- "integrity": "sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz",
+ "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==",
"dev": true,
"license": "MIT",
"funding": {
@@ -4724,14 +4368,15 @@
}
},
"node_modules/@vitest/utils": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.16.tgz",
- "integrity": "sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz",
+ "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.0.16",
- "tinyrainbow": "^3.0.3"
+ "@vitest/pretty-format": "4.1.10",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
},
"funding": {
"url": "https://opencollective.com/vitest"
@@ -4761,19 +4406,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
- "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -4799,20 +4431,6 @@
"node": ">= 6.0.0"
}
},
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -4866,13 +4484,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/any-base": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
- "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
@@ -5231,100 +4842,6 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
- "node_modules/args": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
- "integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "camelcase": "5.0.0",
- "chalk": "2.4.2",
- "leven": "2.1.0",
- "mri": "1.1.4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/args/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/args/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/args/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/args/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/args/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/args/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/args/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/aria-hidden": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
@@ -5338,32 +4855,13 @@
"node": ">=10"
}
},
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/asn1": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
- "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safer-buffer": "~2.1.0"
- }
- },
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true,
"license": "MIT",
+ "optional": true,
"engines": {
"node": ">=0.8"
}
@@ -5461,23 +4959,6 @@
"postcss": "^8.1.0"
}
},
- "node_modules/aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
- "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws4": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
- "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -5516,16 +4997,6 @@
"baseline-browser-mapping": "dist/cli.js"
}
},
- "node_modules/bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tweetnacl": "^0.14.3"
- }
- },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -5551,13 +5022,6 @@
"readable-stream": "^3.4.0"
}
},
- "node_modules/bmp-js": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz",
- "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
@@ -5822,34 +5286,6 @@
"node": ">= 0.4"
}
},
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/camelcase": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
- "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -5899,20 +5335,10 @@
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
"license": "Apache-2.0"
},
- "node_modules/centra": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz",
- "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.6"
- }
- },
"node_modules/chai": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz",
- "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6010,16 +5436,6 @@
"url": "https://polar.sh/cva"
}
},
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -6112,16 +5528,6 @@
"node": ">=6"
}
},
- "node_modules/code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -6182,55 +5588,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "engines": [
- "node >= 0.8"
- ],
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
- "node_modules/concat-stream/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/concat-stream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/concat-stream/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -6243,7 +5600,8 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true
},
"node_modules/crc": {
"version": "3.8.0",
@@ -6299,19 +5657,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -6329,16 +5674,6 @@
}
}
},
- "node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -6429,29 +5764,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/del": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
- "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "globby": "^11.0.1",
- "graceful-fs": "^4.2.4",
- "is-glob": "^4.0.1",
- "is-path-cwd": "^2.2.0",
- "is-path-inside": "^3.0.2",
- "p-map": "^4.0.0",
- "rimraf": "^3.0.2",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -6529,19 +5841,6 @@
"node": "*"
}
},
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
@@ -6643,12 +5942,6 @@
"resize-observer-polyfill": "^1.5.1"
}
},
- "node_modules/dom-walk": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
- "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==",
- "dev": true
- },
"node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
@@ -6707,17 +6000,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/ecc-jsbn": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
- "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.1.0"
- }
- },
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
@@ -6735,9 +6017,9 @@
}
},
"node_modules/electron": {
- "version": "39.2.7",
- "resolved": "https://registry.npmjs.org/electron/-/electron-39.2.7.tgz",
- "integrity": "sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==",
+ "version": "39.8.10",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-39.8.10.tgz",
+ "integrity": "sha512-zbYtGPYUI7PzqLAzkk21Rk6j67WN0hxn0Mq/njErZo1d0HSf33is4f8ICI5fMLy5vYe0JtCtM5sYunNOaochSQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -6830,24 +6112,6 @@
"node": ">= 10.0.0"
}
},
- "node_modules/electron-icon-builder": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/electron-icon-builder/-/electron-icon-builder-2.0.1.tgz",
- "integrity": "sha512-rg9BxW2kJi3TXsMFFNXWXrwQEd5dzXmeD+w7Pj3k3z7aYRePLxE89qU4lvL/rK1X/NTY5KDn3+Dbgm1TU2dGXQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "args": "^5.0.1",
- "icon-gen": "^2.0.0",
- "jimp": "^0.16.1"
- },
- "bin": {
- "electron-icon-builder": "index.js"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
"node_modules/electron-publish": {
"version": "26.6.0",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.6.0.tgz",
@@ -7076,16 +6340,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/error-ex": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
- "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -7107,9 +6361,9 @@
}
},
"node_modules/es-module-lexer": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
- "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.0.tgz",
+ "integrity": "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==",
"dev": true,
"license": "MIT"
},
@@ -7150,13 +6404,6 @@
"license": "MIT",
"optional": true
},
- "node_modules/es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
@@ -7230,16 +6477,6 @@
"@types/estree": "^1.0.0"
}
},
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
- "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
@@ -7247,16 +6484,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.x"
- }
- },
"node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -7310,12 +6537,6 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
},
- "node_modules/exif-parser": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
- "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==",
- "dev": true
- },
"node_modules/expect-type": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
@@ -7333,13 +6554,6 @@
"dev": true,
"license": "Apache-2.0"
},
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -7481,34 +6695,6 @@
"integrity": "sha512-Dvpa9uhVMOYivhHKWLGDoa512J751qN1WZAIO+Xw4L/mrUSPxS4DApzSUDbCFE/LUq2+xYnznEahTd63AqBSpA==",
"license": "MIT"
},
- "node_modules/file-type": {
- "version": "16.5.4",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz",
- "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "readable-web-to-node-stream": "^3.0.0",
- "strtok3": "^6.2.4",
- "token-types": "^4.1.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
- }
- },
- "node_modules/file-url": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/file-url/-/file-url-2.0.2.tgz",
- "integrity": "sha512-x3989K8a1jM6vulMigE8VngH7C5nci0Ks5d9kVjUXmNF28gmiZUNujk5HjwaS8dAzN2QmUfX56riJKgN00dNRw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/filelist": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
@@ -7545,13 +6731,6 @@
"node": ">=8"
}
},
- "node_modules/fix-webm-duration": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/fix-webm-duration/-/fix-webm-duration-1.0.6.tgz",
- "integrity": "sha512-zVAqi4gE+8ywxJuAyV/rlJVX6CMtvyapEbQx6jyoeX9TMjdqAlt/FdG5d7rXSSkDVzTvS0H7CtwzHcH/vh4FPA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/flairup": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz",
@@ -7559,27 +6738,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -7597,16 +6755,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "*"
- }
- },
"node_modules/form-data": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -7798,16 +6946,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
- "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0"
- }
- },
"node_modules/gif.js": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/gif.js/-/gif.js-0.2.0.tgz",
@@ -7825,17 +6963,6 @@
"js-binary-schema-parser": "^2.0.3"
}
},
- "node_modules/gifwrap": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.4.tgz",
- "integrity": "sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "image-q": "^4.0.0",
- "omggif": "^1.0.10"
- }
- },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -7895,17 +7022,6 @@
"node": "*"
}
},
- "node_modules/global": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
- "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "min-document": "^2.19.0",
- "process": "^0.11.10"
- }
- },
"node_modules/global-agent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
@@ -7943,27 +7059,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -8009,38 +7104,6 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
- "node_modules/gsap": {
- "version": "3.13.0",
- "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.13.0.tgz",
- "integrity": "sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==",
- "dev": true,
- "license": "Standard 'no charge' license: https://gsap.com/standard-license."
- },
- "node_modules/har-schema": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
- "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/har-validator": {
- "version": "5.1.5",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
- "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
- "deprecated": "this library is no longer supported",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ajv": "^6.12.3",
- "har-schema": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -8094,20 +7157,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/hasha": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz",
- "integrity": "sha512-jZ38TU/EBiGKrmyTNNZgnvCZHNowiRI4+w/I9noMlekHTZH3KyGgvJLmhSgykeAQ9j2SYPDosM0Bg3wHfzibAQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-stream": "^1.0.1",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -8176,22 +7225,6 @@
"integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==",
"license": "MIT"
},
- "node_modules/http-signature": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
- "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "jsprim": "^1.2.2",
- "sshpk": "^1.7.0"
- },
- "engines": {
- "node": ">=0.8",
- "npm": ">=1.3.7"
- }
- },
"node_modules/http2-wrapper": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
@@ -8228,47 +7261,6 @@
"node": ">=10.17.0"
}
},
- "node_modules/icon-gen": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/icon-gen/-/icon-gen-2.1.0.tgz",
- "integrity": "sha512-rqIVvq9MJ8X7wnJW0NO8Eau/+5RWV7AH6L5vEt/U5Ajv5WefdDNDxGwJhGokyHuyBWeX7JqRMQ03tG0gAco4Eg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "commander": "^6.2.0",
- "del": "^6.0.0",
- "mkdirp": "^1.0.4",
- "pngjs": "^6.0.0",
- "svg2png": "4.1.1",
- "uuid": "^8.3.1"
- },
- "bin": {
- "icon-gen": "dist/bin/index.js"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/icon-gen/node_modules/commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/icon-gen/node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
"node_modules/iconv-corefoundation": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
@@ -8321,33 +7313,6 @@
],
"license": "BSD-3-Clause"
},
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/image-q": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz",
- "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "16.9.1"
- }
- },
- "node_modules/image-q/node_modules/@types/node": {
- "version": "16.9.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
- "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -8358,16 +7323,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -8386,16 +7341,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/invert-kv": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
- "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/ip-address": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
@@ -8406,13 +7351,6 @@
"node": ">= 12"
}
},
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -8462,13 +7400,6 @@
"node": ">=8"
}
},
- "node_modules/is-function": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
- "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -8502,43 +7433,6 @@
"node": ">=0.12.0"
}
},
- "node_modules/is-path-cwd": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
- "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -8552,20 +7446,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-utf8": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
- "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/isbinaryfile": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz",
@@ -8592,13 +7472,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@@ -8633,20 +7506,6 @@
"node": ">=10"
}
},
- "node_modules/jimp": {
- "version": "0.16.13",
- "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.13.tgz",
- "integrity": "sha512-Bxz8q7V4rnCky9A0ktTNGA9SkNFVWRHodddI/DaAWZJzF7sVUlFYKQ60y9JGqrKpi48ECA/TnfMzzc5C70VByA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.7.2",
- "@jimp/custom": "^0.16.13",
- "@jimp/plugins": "^0.16.13",
- "@jimp/types": "^0.16.13",
- "regenerator-runtime": "^0.13.3"
- }
- },
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
@@ -8657,13 +7516,6 @@
"jiti": "bin/jiti.js"
}
},
- "node_modules/jpeg-js": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
- "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
"node_modules/js-binary-schema-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
@@ -8689,13 +7541,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
- "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -8716,13 +7561,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-schema": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
- "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
- "dev": true,
- "license": "(AFL-2.1 OR BSD-3-Clause)"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -8735,7 +7573,8 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
"dev": true,
- "license": "ISC"
+ "license": "ISC",
+ "optional": true
},
"node_modules/json5": {
"version": "2.2.3",
@@ -8760,54 +7599,6 @@
"graceful-fs": "^4.1.6"
}
},
- "node_modules/jsprim": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
- "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.4.0",
- "verror": "1.10.0"
- },
- "engines": {
- "node": ">=0.6.0"
- }
- },
- "node_modules/jsprim/node_modules/extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT"
- },
- "node_modules/jsprim/node_modules/verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
- "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- }
- },
- "node_modules/kew": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz",
- "integrity": "sha512-IG6nm0+QtAMdXt9KvbgbGdvY50RSrw+U4sGZg+KlrSKPJEwVE5JVoI3d7RWfSMdBQneRheeAOj3lIjX5VL/9RQ==",
- "dev": true,
- "license": "Apache-2.0"
- },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -8818,43 +7609,271 @@
"json-buffer": "3.0.1"
}
},
- "node_modules/klaw": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
- "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
- "dev": true,
- "license": "MIT",
- "optionalDependencies": {
- "graceful-fs": "^4.1.9"
- }
- },
"node_modules/lazy-val": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
"license": "MIT"
},
- "node_modules/lcid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
- "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==",
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
"dependencies": {
- "invert-kv": "^1.0.0"
+ "detect-libc": "^2.0.3"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.32.0",
+ "lightningcss-darwin-arm64": "1.32.0",
+ "lightningcss-darwin-x64": "1.32.0",
+ "lightningcss-freebsd-x64": "1.32.0",
+ "lightningcss-linux-arm-gnueabihf": "1.32.0",
+ "lightningcss-linux-arm64-gnu": "1.32.0",
+ "lightningcss-linux-arm64-musl": "1.32.0",
+ "lightningcss-linux-x64-gnu": "1.32.0",
+ "lightningcss-linux-x64-musl": "1.32.0",
+ "lightningcss-win32-arm64-msvc": "1.32.0",
+ "lightningcss-win32-x64-msvc": "1.32.0"
}
},
- "node_modules/leven": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
- "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
+ "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
- "license": "MIT",
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
+ "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
+ "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
+ "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
+ "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
+ "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
+ "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
+ "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
+ "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
+ "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
"node_modules/lilconfig": {
@@ -8877,77 +7896,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/load-bmfont": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz",
- "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-equal": "0.0.1",
- "mime": "^1.3.4",
- "parse-bmfont-ascii": "^1.0.3",
- "parse-bmfont-binary": "^1.0.5",
- "parse-bmfont-xml": "^1.1.4",
- "phin": "^3.7.1",
- "xhr": "^2.0.1",
- "xtend": "^4.0.0"
- }
- },
- "node_modules/load-bmfont/node_modules/buffer-equal": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
- "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/load-bmfont/node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/load-bmfont/node_modules/phin": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz",
- "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "centra": "^2.7.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/load-json-file": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
- "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "strip-bom": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
@@ -9161,16 +8109,6 @@
"node": ">=4"
}
},
- "node_modules/min-document": {
- "version": "2.19.2",
- "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.2.tgz",
- "integrity": "sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dom-walk": "^0.1.0"
- }
- },
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -9306,19 +8244,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/motion": {
"version": "12.23.24",
"resolved": "https://registry.npmjs.org/motion/-/motion-12.23.24.tgz",
@@ -9373,16 +8298,6 @@
"node": ">=20.8.1"
}
},
- "node_modules/mri": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
- "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -9402,9 +8317,9 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
+ "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
"dev": true,
"funding": [
{
@@ -9446,36 +8361,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "node_modules/normalize-package-data/node_modules/hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/normalize-package-data/node_modules/semver": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
- }
- },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -9521,26 +8406,6 @@
"node": ">=8"
}
},
- "node_modules/number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/oauth-sign": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
- "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "*"
- }
- },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -9561,20 +8426,6 @@
"node": ">= 6"
}
},
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -9597,13 +8448,6 @@
],
"license": "MIT"
},
- "node_modules/omggif": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
- "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -9653,19 +8497,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/os-locale": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
- "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "lcid": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
@@ -9692,22 +8523,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -9715,63 +8530,11 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
- "node_modules/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "dev": true,
- "license": "(MIT AND Zlib)"
- },
- "node_modules/parse-bmfont-ascii": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
- "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/parse-bmfont-binary": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
- "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/parse-bmfont-xml": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz",
- "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "xml-parse-from-string": "^1.0.0",
- "xml2js": "^0.5.0"
- }
- },
"node_modules/parse-cache-control": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
"integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg=="
},
- "node_modules/parse-headers": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz",
- "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "error-ex": "^1.2.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/parse-svg-path": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
@@ -9829,16 +8592,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -9861,20 +8614,6 @@
"url": "https://github.com/sponsors/jet2jet"
}
},
- "node_modules/peek-readable": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
- "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -9882,134 +8621,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/performance-now": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/phantomjs-prebuilt": {
- "version": "2.1.16",
- "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz",
- "integrity": "sha512-PIiRzBhW85xco2fuj41FmsyuYHKjKuXWmhjy3A/Y+CMpN/63TV+s9uzfVhsUwFe0G77xWtHBG8xmXf5BqEUEuQ==",
- "deprecated": "this package is now deprecated",
- "dev": true,
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "dependencies": {
- "es6-promise": "^4.0.3",
- "extract-zip": "^1.6.5",
- "fs-extra": "^1.0.0",
- "hasha": "^2.2.0",
- "kew": "^0.7.0",
- "progress": "^1.1.8",
- "request": "^2.81.0",
- "request-progress": "^2.0.1",
- "which": "^1.2.10"
- },
- "bin": {
- "phantomjs": "bin/phantomjs"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/extract-zip": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
- "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "concat-stream": "^1.6.2",
- "debug": "^2.6.9",
- "mkdirp": "^0.5.4",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "extract-zip": "cli.js"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/fs-extra": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
- "integrity": "sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^2.1.0",
- "klaw": "^1.0.0"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/jsonfile": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
- "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
- "dev": true,
- "license": "MIT",
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.6"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/phantomjs-prebuilt/node_modules/progress": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
- "integrity": "sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/phantomjs-prebuilt/node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
- "node_modules/phin": {
- "version": "2.9.3",
- "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz",
- "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "dev": true,
- "license": "MIT"
- },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -10040,29 +8651,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pinkie": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/pirates": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
@@ -10073,29 +8661,6 @@
"node": ">= 6"
}
},
- "node_modules/pixelmatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz",
- "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "pngjs": "^3.0.0"
- },
- "bin": {
- "pixelmatch": "bin/pixelmatch"
- }
- },
- "node_modules/pixelmatch/node_modules/pngjs": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
- "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/pixi-filters": {
"version": "6.1.5",
"resolved": "https://registry.npmjs.org/pixi-filters/-/pixi-filters-6.1.5.tgz",
@@ -10148,27 +8713,10 @@
"node": ">=10.4.0"
}
},
- "node_modules/pn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
- "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/pngjs": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
- "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.13.0"
- }
- },
"node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "version": "8.5.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz",
+ "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==",
"dev": true,
"funding": [
{
@@ -10186,7 +8734,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -10368,23 +8916,6 @@
"node": "^18.17.0 || >=20.5.0"
}
},
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6.0"
- }
- },
- "node_modules/process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -10439,19 +8970,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/psl": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
- "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "punycode": "^2.3.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/lupomontero"
- }
- },
"node_modules/pump": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
@@ -10490,23 +9008,6 @@
],
"license": "MIT"
},
- "node_modules/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "peer": true,
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -10758,77 +9259,6 @@
"pify": "^2.3.0"
}
},
- "node_modules/read-pkg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
- "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "load-json-file": "^1.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "find-up": "^1.0.0",
- "read-pkg": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/read-pkg-up/node_modules/find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/read-pkg-up/node_modules/path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/read-pkg/node_modules/path-type": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
- "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -10843,65 +9273,6 @@
"node": ">= 6"
}
},
- "node_modules/readable-web-to-node-stream": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz",
- "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "readable-stream": "^4.7.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/readable-web-to-node-stream/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
- "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "abort-controller": "^3.0.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "process": "^0.11.10",
- "string_decoder": "^1.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -10915,92 +9286,6 @@
"node": ">=8.10.0"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.13.11",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
- "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/request": {
- "version": "2.88.2",
- "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
- "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
- "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~2.3.2",
- "har-validator": "~5.1.3",
- "http-signature": "~1.2.0",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "oauth-sign": "~0.9.0",
- "performance-now": "^2.1.0",
- "qs": "~6.5.2",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "~2.5.0",
- "tunnel-agent": "^0.6.0",
- "uuid": "^3.3.2"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/request-progress": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz",
- "integrity": "sha512-dxdraeZVUNEn9AvLrxkgB2k6buTlym71dJk1fk4v8j3Ou3RKNm07BcgbHdj2lLgYGfqX71F+awb1MR+tWPFJzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "throttleit": "^1.0.0"
- }
- },
- "node_modules/request/node_modules/form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/request/node_modules/qs": {
- "version": "6.5.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
- "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/request/node_modules/uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
- "dev": true,
- "license": "MIT",
- "bin": {
- "uuid": "bin/uuid"
- }
- },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -11011,13 +9296,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/resedit": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz",
@@ -11126,23 +9404,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/roarr": {
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
@@ -11162,6 +9423,47 @@
"node": ">=8.0"
}
},
+ "node_modules/rolldown": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
+ "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.139.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.1.5",
+ "@rolldown/binding-darwin-arm64": "1.1.5",
+ "@rolldown/binding-darwin-x64": "1.1.5",
+ "@rolldown/binding-freebsd-x64": "1.1.5",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
+ "@rolldown/binding-linux-arm64-gnu": "1.1.5",
+ "@rolldown/binding-linux-arm64-musl": "1.1.5",
+ "@rolldown/binding-linux-ppc64-gnu": "1.1.5",
+ "@rolldown/binding-linux-s390x-gnu": "1.1.5",
+ "@rolldown/binding-linux-x64-gnu": "1.1.5",
+ "@rolldown/binding-linux-x64-musl": "1.1.5",
+ "@rolldown/binding-openharmony-arm64": "1.1.5",
+ "@rolldown/binding-wasm32-wasi": "1.1.5",
+ "@rolldown/binding-win32-arm64-msvc": "1.1.5",
+ "@rolldown/binding-win32-x64-msvc": "1.1.5"
+ }
+ },
+ "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/rollup": {
"version": "4.52.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz",
@@ -11331,13 +9633,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -11359,86 +9654,6 @@
"node": ">=8"
}
},
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/siginfo": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
@@ -11472,16 +9687,6 @@
"node": ">=10"
}
},
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/slice-ansi": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
@@ -11566,42 +9771,6 @@
"source-map": "^0.6.0"
}
},
- "node_modules/spdx-correct": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
- "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-exceptions": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
- "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
- "dev": true,
- "license": "CC-BY-3.0"
- },
- "node_modules/spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-license-ids": {
- "version": "3.0.22",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz",
- "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==",
- "dev": true,
- "license": "CC0-1.0"
- },
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
@@ -11610,32 +9779,6 @@
"license": "BSD-3-Clause",
"optional": true
},
- "node_modules/sshpk": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
- "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asn1": "~0.2.3",
- "assert-plus": "^1.0.0",
- "bcrypt-pbkdf": "^1.0.0",
- "dashdash": "^1.12.0",
- "ecc-jsbn": "~0.1.1",
- "getpass": "^0.1.1",
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.0.2",
- "tweetnacl": "~0.14.0"
- },
- "bin": {
- "sshpk-conv": "bin/sshpk-conv",
- "sshpk-sign": "bin/sshpk-sign",
- "sshpk-verify": "bin/sshpk-verify"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -11654,9 +9797,9 @@
}
},
"node_modules/std-env": {
- "version": "3.10.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
- "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
+ "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
"dev": true,
"license": "MIT"
},
@@ -11727,19 +9870,6 @@
"node": ">=8"
}
},
- "node_modules/strip-bom": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
- "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-utf8": "^0.2.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
@@ -11749,24 +9879,6 @@
"node": ">=6"
}
},
- "node_modules/strtok3": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
- "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@tokenizer/token": "^0.3.0",
- "peek-readable": "^4.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -11870,155 +9982,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/svg2png": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/svg2png/-/svg2png-4.1.1.tgz",
- "integrity": "sha512-9tOp9Ugjlunuf1ugqkhiYboTmTaTI7p48dz5ZjNA5NQJ5xS1NLTZZ1tF8vkJOIBb/ZwxGJsKZvRWqVpo4q9z9Q==",
- "dev": true,
- "license": "WTFPL",
- "dependencies": {
- "file-url": "^2.0.0",
- "phantomjs-prebuilt": "^2.1.14",
- "pn": "^1.0.0",
- "yargs": "^6.5.0"
- },
- "bin": {
- "svg2png": "bin/svg2png-cli.js"
- }
- },
- "node_modules/svg2png/node_modules/ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/camelcase": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
- "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/cliui": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
- "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wrap-ansi": "^2.0.0"
- }
- },
- "node_modules/svg2png/node_modules/get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/svg2png/node_modules/is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "number-is-nan": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/svg2png/node_modules/y18n": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
- "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/svg2png/node_modules/yargs": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz",
- "integrity": "sha512-6/QWTdisjnu5UHUzQGst+UOEuEVwIzFVGBjq3jMTFNs5WJQsH/X6nMURSaScIdF5txylr1Ao9bvbWiKi2yXbwA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "camelcase": "^3.0.0",
- "cliui": "^3.2.0",
- "decamelize": "^1.1.1",
- "get-caller-file": "^1.0.1",
- "os-locale": "^1.4.0",
- "read-pkg-up": "^1.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^1.0.2",
- "which-module": "^1.0.0",
- "y18n": "^3.2.1",
- "yargs-parser": "^4.2.0"
- }
- },
- "node_modules/svg2png/node_modules/yargs-parser": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz",
- "integrity": "sha512-+QQWqC2xeL0N5/TE+TY6OGEqyNRM+g2/r712PDNYgiCdXYCApXf1vzfmDSLBxfGRwV+moTq/V8FnMI24JCm2Yg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "camelcase": "^3.0.0"
- }
- },
"node_modules/tailwind-merge": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
@@ -12220,23 +10183,6 @@
"node": ">=0.8"
}
},
- "node_modules/throttleit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz",
- "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/timm": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz",
- "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/tiny-async-pool": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz",
@@ -12280,13 +10226,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/tinycolor2": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
- "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/tinyexec": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
@@ -12298,14 +10237,14 @@
}
},
"node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
- "picomatch": "^4.0.3"
+ "picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
@@ -12333,9 +10272,9 @@
}
},
"node_modules/tinyglobby/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -12346,9 +10285,9 @@
}
},
"node_modules/tinyrainbow": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
- "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
+ "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -12388,38 +10327,6 @@
"node": ">=8.0"
}
},
- "node_modules/token-types": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
- "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@tokenizer/token": "^0.3.0",
- "ieee754": "^1.2.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/tough-cookie": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
- "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "psl": "^1.1.28",
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
"node_modules/truncate-utf8-bytes": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
@@ -12444,26 +10351,6 @@
"dev": true,
"license": "0BSD"
},
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
- "dev": true,
- "license": "Unlicense"
- },
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -12555,29 +10442,6 @@
"punycode": "^2.1.0"
}
},
- "node_modules/url": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz",
- "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "punycode": "^1.4.1",
- "qs": "^6.12.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/url/node_modules/punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
- "dev": true,
- "license": "MIT",
- "peer": true
- },
"node_modules/use-callback-ref": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
@@ -12630,47 +10494,12 @@
"dev": true,
"license": "(WTFPL OR MIT)"
},
- "node_modules/utif": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz",
- "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pako": "^1.0.5"
- }
- },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
- "node_modules/uuid": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
- "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
- "dev": true,
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist-node/bin/uuid"
- }
- },
- "node_modules/validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
"node_modules/verror": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
@@ -12770,31 +10599,31 @@
"license": "MIT"
},
"node_modules/vitest": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.16.tgz",
- "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
+ "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.0.16",
- "@vitest/mocker": "4.0.16",
- "@vitest/pretty-format": "4.0.16",
- "@vitest/runner": "4.0.16",
- "@vitest/snapshot": "4.0.16",
- "@vitest/spy": "4.0.16",
- "@vitest/utils": "4.0.16",
- "es-module-lexer": "^1.7.0",
- "expect-type": "^1.2.2",
+ "@vitest/expect": "4.1.10",
+ "@vitest/mocker": "4.1.10",
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/runner": "4.1.10",
+ "@vitest/snapshot": "4.1.10",
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
"magic-string": "^0.30.21",
"obug": "^2.1.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
- "std-env": "^3.10.0",
+ "std-env": "^4.0.0-rc.1",
"tinybench": "^2.9.0",
"tinyexec": "^1.0.2",
"tinyglobby": "^0.2.15",
- "tinyrainbow": "^3.0.3",
- "vite": "^6.0.0 || ^7.0.0",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
"why-is-node-running": "^2.3.0"
},
"bin": {
@@ -12810,12 +10639,15 @@
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.0.16",
- "@vitest/browser-preview": "4.0.16",
- "@vitest/browser-webdriverio": "4.0.16",
- "@vitest/ui": "4.0.16",
+ "@vitest/browser-playwright": "4.1.10",
+ "@vitest/browser-preview": "4.1.10",
+ "@vitest/browser-webdriverio": "4.1.10",
+ "@vitest/coverage-istanbul": "4.1.10",
+ "@vitest/coverage-v8": "4.1.10",
+ "@vitest/ui": "4.1.10",
"happy-dom": "*",
- "jsdom": "*"
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"@edge-runtime/vm": {
@@ -12836,6 +10668,12 @@
"@vitest/browser-webdriverio": {
"optional": true
},
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
"@vitest/ui": {
"optional": true
},
@@ -12844,13 +10682,16 @@
},
"jsdom": {
"optional": true
+ },
+ "vite": {
+ "optional": false
}
}
},
"node_modules/vitest/node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
- "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
+ "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
"cpu": [
"ppc64"
],
@@ -12860,14 +10701,15 @@
"os": [
"aix"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/android-arm": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
- "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
+ "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
"cpu": [
"arm"
],
@@ -12877,14 +10719,15 @@
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/android-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
- "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
+ "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
"cpu": [
"arm64"
],
@@ -12894,14 +10737,15 @@
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/android-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
- "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
+ "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
"cpu": [
"x64"
],
@@ -12911,14 +10755,15 @@
"os": [
"android"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
- "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
+ "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
"cpu": [
"arm64"
],
@@ -12928,14 +10773,15 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/darwin-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
- "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
+ "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
"cpu": [
"x64"
],
@@ -12945,14 +10791,15 @@
"os": [
"darwin"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
- "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
+ "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
"cpu": [
"arm64"
],
@@ -12962,14 +10809,15 @@
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
- "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
"cpu": [
"x64"
],
@@ -12979,14 +10827,15 @@
"os": [
"freebsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-arm": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
- "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
+ "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
"cpu": [
"arm"
],
@@ -12996,14 +10845,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
- "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
+ "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
"cpu": [
"arm64"
],
@@ -13013,14 +10863,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-ia32": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
- "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
+ "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
"cpu": [
"ia32"
],
@@ -13030,14 +10881,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-loong64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
- "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
+ "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
"cpu": [
"loong64"
],
@@ -13047,14 +10899,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
- "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
+ "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
"cpu": [
"mips64el"
],
@@ -13064,14 +10917,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
- "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
+ "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
"cpu": [
"ppc64"
],
@@ -13081,14 +10935,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
- "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
+ "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
"cpu": [
"riscv64"
],
@@ -13098,14 +10953,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-s390x": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
- "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
+ "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
"cpu": [
"s390x"
],
@@ -13115,14 +10971,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/linux-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
- "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
+ "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
"cpu": [
"x64"
],
@@ -13132,14 +10989,15 @@
"os": [
"linux"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
- "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
"cpu": [
"x64"
],
@@ -13149,14 +11007,15 @@
"os": [
"netbsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
- "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
+ "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
"cpu": [
"x64"
],
@@ -13166,14 +11025,15 @@
"os": [
"openbsd"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/sunos-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
- "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
+ "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
"cpu": [
"x64"
],
@@ -13183,14 +11043,15 @@
"os": [
"sunos"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/win32-arm64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
- "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
+ "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
"cpu": [
"arm64"
],
@@ -13200,14 +11061,15 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/win32-ia32": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
- "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
+ "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
"cpu": [
"ia32"
],
@@ -13217,14 +11079,15 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@esbuild/win32-x64": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
- "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
+ "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
"cpu": [
"x64"
],
@@ -13234,18 +11097,19 @@
"os": [
"win32"
],
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/vitest/node_modules/@vitest/mocker": {
- "version": "4.0.16",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.16.tgz",
- "integrity": "sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==",
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz",
+ "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.0.16",
+ "@vitest/spy": "4.1.10",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21"
},
@@ -13254,7 +11118,7 @@
},
"peerDependencies": {
"msw": "^2.4.9",
- "vite": "^6.0.0 || ^7.0.0-0"
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"msw": {
@@ -13266,12 +11130,14 @@
}
},
"node_modules/vitest/node_modules/esbuild": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
- "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
+ "version": "0.28.1",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
+ "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@@ -13279,56 +11145,38 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.2",
- "@esbuild/android-arm": "0.27.2",
- "@esbuild/android-arm64": "0.27.2",
- "@esbuild/android-x64": "0.27.2",
- "@esbuild/darwin-arm64": "0.27.2",
- "@esbuild/darwin-x64": "0.27.2",
- "@esbuild/freebsd-arm64": "0.27.2",
- "@esbuild/freebsd-x64": "0.27.2",
- "@esbuild/linux-arm": "0.27.2",
- "@esbuild/linux-arm64": "0.27.2",
- "@esbuild/linux-ia32": "0.27.2",
- "@esbuild/linux-loong64": "0.27.2",
- "@esbuild/linux-mips64el": "0.27.2",
- "@esbuild/linux-ppc64": "0.27.2",
- "@esbuild/linux-riscv64": "0.27.2",
- "@esbuild/linux-s390x": "0.27.2",
- "@esbuild/linux-x64": "0.27.2",
- "@esbuild/netbsd-arm64": "0.27.2",
- "@esbuild/netbsd-x64": "0.27.2",
- "@esbuild/openbsd-arm64": "0.27.2",
- "@esbuild/openbsd-x64": "0.27.2",
- "@esbuild/openharmony-arm64": "0.27.2",
- "@esbuild/sunos-x64": "0.27.2",
- "@esbuild/win32-arm64": "0.27.2",
- "@esbuild/win32-ia32": "0.27.2",
- "@esbuild/win32-x64": "0.27.2"
- }
- },
- "node_modules/vitest/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
+ "@esbuild/aix-ppc64": "0.28.1",
+ "@esbuild/android-arm": "0.28.1",
+ "@esbuild/android-arm64": "0.28.1",
+ "@esbuild/android-x64": "0.28.1",
+ "@esbuild/darwin-arm64": "0.28.1",
+ "@esbuild/darwin-x64": "0.28.1",
+ "@esbuild/freebsd-arm64": "0.28.1",
+ "@esbuild/freebsd-x64": "0.28.1",
+ "@esbuild/linux-arm": "0.28.1",
+ "@esbuild/linux-arm64": "0.28.1",
+ "@esbuild/linux-ia32": "0.28.1",
+ "@esbuild/linux-loong64": "0.28.1",
+ "@esbuild/linux-mips64el": "0.28.1",
+ "@esbuild/linux-ppc64": "0.28.1",
+ "@esbuild/linux-riscv64": "0.28.1",
+ "@esbuild/linux-s390x": "0.28.1",
+ "@esbuild/linux-x64": "0.28.1",
+ "@esbuild/netbsd-arm64": "0.28.1",
+ "@esbuild/netbsd-x64": "0.28.1",
+ "@esbuild/openbsd-arm64": "0.28.1",
+ "@esbuild/openbsd-x64": "0.28.1",
+ "@esbuild/openharmony-arm64": "0.28.1",
+ "@esbuild/sunos-x64": "0.28.1",
+ "@esbuild/win32-arm64": "0.28.1",
+ "@esbuild/win32-ia32": "0.28.1",
+ "@esbuild/win32-x64": "0.28.1"
}
},
"node_modules/vitest/node_modules/picomatch": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -13339,18 +11187,17 @@
}
},
"node_modules/vitest/node_modules/vite": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz",
- "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
+ "version": "8.1.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz",
+ "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "esbuild": "^0.27.0",
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3",
- "postcss": "^8.5.6",
- "rollup": "^4.43.0",
- "tinyglobby": "^0.2.15"
+ "lightningcss": "^1.32.0",
+ "picomatch": "^4.0.5",
+ "postcss": "^8.5.16",
+ "rolldown": "~1.1.4",
+ "tinyglobby": "^0.2.17"
},
"bin": {
"vite": "bin/vite.js"
@@ -13366,9 +11213,10 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.3.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
- "lightningcss": "^1.21.0",
"sass": "^1.70.0",
"sass-embedded": "^1.70.0",
"stylus": ">=0.54.8",
@@ -13381,15 +11229,18 @@
"@types/node": {
"optional": true
},
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
"jiti": {
"optional": true
},
"less": {
"optional": true
},
- "lightningcss": {
- "optional": true
- },
"sass": {
"optional": true
},
@@ -13448,13 +11299,6 @@
"node": ">= 8"
}
},
- "node_modules/which-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
- "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/why-is-node-running": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
@@ -13516,50 +11360,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/xhr": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz",
- "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "global": "~4.4.0",
- "is-function": "^1.0.1",
- "parse-headers": "^2.0.0",
- "xtend": "^4.0.0"
- }
- },
- "node_modules/xml-parse-from-string": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
- "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/xml2js": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
- "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/xml2js/node_modules/xmlbuilder": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
- "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- }
- },
"node_modules/xmlbuilder": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
@@ -13570,16 +11370,6 @@
"node": ">=8.0"
}
},
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/package.json b/package.json
index 6357c666..0014f4ed 100644
--- a/package.json
+++ b/package.json
@@ -18,9 +18,10 @@
"dev": "vite --config vite.config.ts",
"postinstall": "node scripts/postinstall.mjs",
"build": "npm run build:platform-native-helpers && tsc && vite build --config vite.config.ts && npm run normalize:electron-main-cjs && npm run smoke:electron-main-cjs && electron-builder",
- "lint": "biome check .",
- "lint:fix": "biome check --write .",
+ "lint": "biome lint .",
+ "lint:fix": "biome lint --write .",
"format": "biome format --write .",
+ "format:check": "biome format .",
"preview": "vite preview --config vite.config.ts",
"rebuild:native": "node ./node_modules/@electron/rebuild/lib/cli.js --force --only uiohook-napi",
"build:native-helpers": "node scripts/build-native-helpers.mjs",
@@ -55,8 +56,6 @@
"@biomejs/biome": "2.3.13",
"@electron/rebuild": "^4.0.3",
"@fix-webm-duration/fix": "^1.0.1",
- "@pixi/filter-drop-shadow": "^5.2.0",
- "@pixi/filter-motion-blur": "^5.1.1",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
@@ -72,7 +71,6 @@
"@types/node": "^25.0.3",
"@types/react": "^18.2.64",
"@types/react-dom": "^18.2.21",
- "@types/uuid": "^10.0.0",
"@uiw/color-convert": "^2.9.2",
"@uiw/react-color-block": "^2.9.2",
"@vitejs/plugin-react": "^4.2.1",
@@ -80,14 +78,11 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dnd-timeline": "^2.2.0",
- "electron": "^39.2.7",
+ "electron": "^39.8.10",
"electron-builder": "^26.7.0",
- "electron-icon-builder": "^2.0.1",
"emoji-picker-react": "^4.16.1",
"fast-check": "^4.5.2",
- "fix-webm-duration": "^1.0.6",
"gif.js": "^0.2.0",
- "gsap": "^3.13.0",
"mediabunny": "^1.25.1",
"motion": "^12.23.24",
"mp4box": "^2.2.0",
@@ -105,11 +100,10 @@
"tailwindcss-animate": "^1.0.7",
"terser": "^5.44.1",
"typescript": "^5.2.2",
- "uuid": "^13.0.0",
"vite": "^5.1.6",
"vite-plugin-electron": "^0.28.6",
"vite-plugin-electron-renderer": "^0.14.5",
- "vitest": "^4.0.16",
+ "vitest": "^4.1.10",
"web-demuxer": "^4.0.0"
},
"main": "dist-electron/main.cjs"
diff --git a/src/components/launch/SourceSelector.tsx b/src/components/launch/SourceSelector.tsx
index 158b53e1..baa4da59 100644
--- a/src/components/launch/SourceSelector.tsx
+++ b/src/components/launch/SourceSelector.tsx
@@ -80,7 +80,7 @@ export const SourceSelectorContent = ({
windowSources = [],
selectedSource = "Screen",
loading = false,
- onSourceSelect = () => {},
+ onSourceSelect = () => undefined,
}: Pick) => {
const t = useScopedT("launch");
const renderSourceItem = (source: DesktopSource, index: number) => {
diff --git a/src/components/launch/contexts/HudInteractionContext.tsx b/src/components/launch/contexts/HudInteractionContext.tsx
index 65a1accb..66b5159e 100644
--- a/src/components/launch/contexts/HudInteractionContext.tsx
+++ b/src/components/launch/contexts/HudInteractionContext.tsx
@@ -1,8 +1,8 @@
-import { createContext, useContext } from "react";
+import { createContext, type MouseEvent, useContext } from "react";
interface HudInteractionContextType {
onMouseEnter: () => void;
- onMouseLeave: (event: any) => void;
+ onMouseLeave: (event: MouseEvent) => void;
}
export const HudInteractionContext = createContext(null);
diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx
index 0b23fb69..c72d5df0 100644
--- a/src/components/video-editor/VideoEditor.tsx
+++ b/src/components/video-editor/VideoEditor.tsx
@@ -87,7 +87,12 @@ import {
} from "@/utils/aspectRatioUtils";
import { planClipSpeedChange } from "./clipSpeedChange";
import { ExtensionIcon } from "./ExtensionIcon";
-import { calculateMp4ExportDimensions, calculateMp4SourceDimensions } from "./exportDimensions";
+import {
+ calculateMp4ExportDimensions,
+ calculateMp4SourceDimensions,
+ type Mp4SupportProbeSnapshot,
+ shouldDebounceMp4SupportProbe,
+} from "./exportDimensions";
import { resolveSavingExportProgress } from "./exportProgressState";
import { resolveExportStartSettings } from "./exportStartSettings";
import { resolveExportStatusModel } from "./exportStatusModel";
@@ -256,6 +261,7 @@ type CancelableExporter = {
};
const EXPORT_BLOB_STREAM_CHUNK_BYTES = 16 * 1024 * 1024;
+const MP4_CROP_PROBE_DEBOUNCE_MS = 200;
async function streamExportBlobToTempFile(blob: Blob, extension: string): Promise {
if (
@@ -701,6 +707,7 @@ export default function VideoEditor() {
const pendingFreshRecordingAutoSuggestTelemetryCountRef = useRef(0);
const cropSnapshotRef = useRef(null);
const mp4SupportRequestRef = useRef(0);
+ const previousMp4SupportProbeRef = useRef(null);
const smokeExportStartedRef = useRef(false);
const projectAutosaveTimeoutRef = useRef(null);
const pendingProjectSaveDialogRef = useRef(null);
@@ -1485,15 +1492,22 @@ export default function VideoEditor() {
[gifSizePreset],
);
- const desiredMp4SourceDimensions = useMemo(
- () =>
- calculateMp4SourceDimensions(
- videoPlaybackRef.current?.video?.videoWidth || 1920,
- videoPlaybackRef.current?.video?.videoHeight || 1080,
- aspectRatio,
- ),
- [aspectRatio],
- );
+ const mp4SourceDimensions = useMemo(() => {
+ const sourceVideo = isPreviewReady ? videoPlaybackRef.current?.video : null;
+ return {
+ width: sourceVideo?.videoWidth || 1920,
+ height: sourceVideo?.videoHeight || 1080,
+ };
+ }, [isPreviewReady]);
+
+ const desiredMp4SourceDimensions = useMemo(() => {
+ return calculateMp4SourceDimensions(
+ mp4SourceDimensions.width,
+ mp4SourceDimensions.height,
+ aspectRatio,
+ cropRegion,
+ );
+ }, [aspectRatio, cropRegion, mp4SourceDimensions.height, mp4SourceDimensions.width]);
const mp4OutputDimensions = useMemo(() => {
const baseWidth = supportedMp4SourceDimensions.encoderPath
@@ -1533,21 +1547,6 @@ export default function VideoEditor() {
);
}
- setSupportedMp4SourceDimensions((current) => {
- if (
- current.width === result.width &&
- current.height === result.height &&
- current.capped === result.capped &&
- current.encoderPath?.codec === result.encoderPath?.codec &&
- current.encoderPath?.hardwareAcceleration ===
- result.encoderPath?.hardwareAcceleration
- ) {
- return current;
- }
-
- return result;
- });
-
return result;
},
[desiredMp4SourceDimensions.height, desiredMp4SourceDimensions.width],
@@ -1557,6 +1556,19 @@ export default function VideoEditor() {
let cancelled = false;
const requestId = mp4SupportRequestRef.current + 1;
mp4SupportRequestRef.current = requestId;
+ const probeSnapshot: Mp4SupportProbeSnapshot = {
+ sourceWidth: mp4SourceDimensions.width,
+ sourceHeight: mp4SourceDimensions.height,
+ targetWidth: desiredMp4SourceDimensions.width,
+ targetHeight: desiredMp4SourceDimensions.height,
+ aspectRatio,
+ frameRate: mp4FrameRate,
+ };
+ const shouldDebounce = shouldDebounceMp4SupportProbe(
+ previousMp4SupportProbeRef.current,
+ probeSnapshot,
+ );
+ previousMp4SupportProbeRef.current = probeSnapshot;
setSupportedMp4SourceDimensions({
width: desiredMp4SourceDimensions.width,
height: desiredMp4SourceDimensions.height,
@@ -1564,33 +1576,48 @@ export default function VideoEditor() {
encoderPath: null,
});
- void ensureSupportedMp4SourceDimensions(mp4FrameRate)
- .then((result) => {
- if (cancelled || requestId !== mp4SupportRequestRef.current) {
- return;
- }
- setSupportedMp4SourceDimensions(result);
- })
- .catch(() => {
- if (cancelled || requestId !== mp4SupportRequestRef.current) {
- return;
- }
- setSupportedMp4SourceDimensions({
- width: desiredMp4SourceDimensions.width,
- height: desiredMp4SourceDimensions.height,
- capped: false,
- encoderPath: null,
+ const runProbe = () => {
+ void ensureSupportedMp4SourceDimensions(mp4FrameRate)
+ .then((result) => {
+ if (cancelled || requestId !== mp4SupportRequestRef.current) {
+ return;
+ }
+ setSupportedMp4SourceDimensions(result);
+ })
+ .catch(() => {
+ if (cancelled || requestId !== mp4SupportRequestRef.current) {
+ return;
+ }
+ setSupportedMp4SourceDimensions({
+ width: desiredMp4SourceDimensions.width,
+ height: desiredMp4SourceDimensions.height,
+ capped: false,
+ encoderPath: null,
+ });
});
- });
+ };
+
+ const timeoutId = shouldDebounce
+ ? window.setTimeout(runProbe, MP4_CROP_PROBE_DEBOUNCE_MS)
+ : null;
+ if (timeoutId === null) {
+ runProbe();
+ }
return () => {
cancelled = true;
+ if (timeoutId !== null) {
+ window.clearTimeout(timeoutId);
+ }
};
}, [
+ aspectRatio,
desiredMp4SourceDimensions.height,
desiredMp4SourceDimensions.width,
ensureSupportedMp4SourceDimensions,
mp4FrameRate,
+ mp4SourceDimensions.height,
+ mp4SourceDimensions.width,
]);
// Extension-contributed standalone section pages (no parentSection)
diff --git a/src/components/video-editor/VideoPlayback.tsx b/src/components/video-editor/VideoPlayback.tsx
index 499179f3..7490f454 100644
--- a/src/components/video-editor/VideoPlayback.tsx
+++ b/src/components/video-editor/VideoPlayback.tsx
@@ -17,6 +17,10 @@ import {
enablePitchPreservingPlayback,
getMediaSyncPlaybackRate,
} from "@/lib/mediaTiming";
+import {
+ destroyPixiApplication,
+ initializePixiApplicationWithTimeout,
+} from "@/lib/pixiApplicationLifecycle";
import {
DEFAULT_WALLPAPER_PATH,
DEFAULT_WALLPAPER_RELATIVE_PATH,
@@ -169,7 +173,6 @@ import {
import { clampFocusToStage as clampFocusToStageUtil } from "./videoPlayback/focusUtils";
import {
layoutVideoContent as layoutVideoContentUtil,
- scalePreviewBorderRadius,
} from "./videoPlayback/layoutUtils";
import { updateOverlayIndicator } from "./videoPlayback/overlayUtils";
import { createVideoEventHandlers } from "./videoPlayback/videoEventHandlers";
@@ -260,30 +263,6 @@ function summarizeRendererAttempts(attempts: readonly PixiRendererAttempt[]): st
return `No supported Pixi preview renderer was available. Attempted: ${details}`;
}
-type PixiInitOptions = Parameters[0];
-
-async function initApplicationWithTimeout(
- app: Application,
- options: PixiInitOptions,
- backend: PixiPreviewBackend,
-): Promise {
- const timeoutErrorMessage = `Initialization timed out after ${PIXI_RENDERER_INIT_TIMEOUT_MS}ms for ${backend} renderer`;
- let timeoutId: ReturnType | undefined;
- const timeoutPromise = new Promise((_, reject) => {
- timeoutId = setTimeout(() => {
- reject(new Error(timeoutErrorMessage));
- }, PIXI_RENDERER_INIT_TIMEOUT_MS);
- });
-
- try {
- await Promise.race([app.init(options), timeoutPromise]);
- } finally {
- if (timeoutId !== undefined) {
- clearTimeout(timeoutId);
- }
- }
-}
-
function getCursorPositionAtTime(
telemetry: CursorTelemetryPoint[],
timeMs: number,
@@ -681,7 +660,7 @@ const VideoPlayback = forwardRef(
const initStarted =
typeof performance === "undefined" ? Date.now() : performance.now();
try {
- await initApplicationWithTimeout(
+ await initializePixiApplicationWithTimeout(
rendererApp,
{
width: container.clientWidth,
@@ -695,6 +674,7 @@ const VideoPlayback = forwardRef(
autoStart: true,
sharedTicker: false,
},
+ PIXI_RENDERER_INIT_TIMEOUT_MS,
backend,
);
const elapsed = Math.round(
@@ -723,7 +703,10 @@ const VideoPlayback = forwardRef(
`[VideoPlayback] Failed to init ${backend} renderer (${statusMessage}) after ${elapsed}ms; trying fallback.`,
error,
);
- rendererApp.destroy(true);
+ destroyPixiApplication(
+ rendererApp,
+ `${backend} preview renderer initialization`,
+ );
}
}
@@ -2127,11 +2110,7 @@ const VideoPlayback = forwardRef(
app.ticker.maxFPS = 60;
if (!mounted) {
- app.destroy(true, {
- children: true,
- texture: false,
- textureSource: false,
- });
+ destroyPixiApplication(app, "unmounted preview renderer");
return;
}
@@ -2227,13 +2206,7 @@ const VideoPlayback = forwardRef(
motionBlurFilterRef.current?.destroy();
zoomBlurFilterRef.current = null;
motionBlurFilterRef.current = null;
- if (app && app.renderer) {
- app.destroy(true, {
- children: true,
- texture: false,
- textureSource: false,
- });
- }
+ destroyPixiApplication(app, "preview renderer");
appRef.current = null;
cameraContainerRef.current = null;
videoEffectsContainerRef.current = null;
diff --git a/src/components/video-editor/audio/waveform/waveform.worker.ts b/src/components/video-editor/audio/waveform/waveform.worker.ts
index 80403a09..28e2ebd9 100644
--- a/src/components/video-editor/audio/waveform/waveform.worker.ts
+++ b/src/components/video-editor/audio/waveform/waveform.worker.ts
@@ -6,7 +6,7 @@ type WaveformWorkerRequest = {
interface WorkerContext {
onmessage: (e: MessageEvent) => void;
- postMessage: (message: any, transfer?: Transferable[]) => void;
+ postMessage: (message: unknown, transfer?: Transferable[]) => void;
}
const workerScope = self as unknown as WorkerContext;
diff --git a/src/components/video-editor/exportDimensions.test.ts b/src/components/video-editor/exportDimensions.test.ts
index 7c79f4ed..5797daae 100644
--- a/src/components/video-editor/exportDimensions.test.ts
+++ b/src/components/video-editor/exportDimensions.test.ts
@@ -1,5 +1,9 @@
import { describe, expect, it } from "vitest";
-import { calculateMp4ExportDimensions, calculateMp4SourceDimensions } from "./exportDimensions";
+import {
+ calculateMp4ExportDimensions,
+ calculateMp4SourceDimensions,
+ shouldDebounceMp4SupportProbe,
+} from "./exportDimensions";
describe("calculateMp4SourceDimensions", () => {
it("keeps native exports at the source dimensions", () => {
@@ -9,6 +13,18 @@ describe("calculateMp4SourceDimensions", () => {
});
});
+ it("uses the cropped source bounds for native exports", () => {
+ expect(
+ calculateMp4SourceDimensions(320, 180, "native", {
+ width: 1,
+ height: 0.8,
+ }),
+ ).toEqual({
+ width: 320,
+ height: 144,
+ });
+ });
+
it("uses the rotated source bounds for 9:16 original exports", () => {
expect(calculateMp4SourceDimensions(1920, 1080, "9:16")).toEqual({
width: 1080,
@@ -16,6 +32,18 @@ describe("calculateMp4SourceDimensions", () => {
});
});
+ it("ignores crop bounds for fixed-aspect exports", () => {
+ expect(
+ calculateMp4SourceDimensions(1920, 1080, "9:16", {
+ width: 0.5,
+ height: 0.5,
+ }),
+ ).toEqual({
+ width: 1080,
+ height: 1920,
+ });
+ });
+
it("uses the rotated source bounds for portrait social ratios", () => {
expect(calculateMp4SourceDimensions(1920, 1080, "4:5")).toEqual({
width: 1080,
@@ -70,3 +98,48 @@ describe("calculateMp4ExportDimensions", () => {
});
});
});
+
+describe("shouldDebounceMp4SupportProbe", () => {
+ const baseSnapshot = {
+ sourceWidth: 1920,
+ sourceHeight: 1080,
+ targetWidth: 1920,
+ targetHeight: 1080,
+ aspectRatio: "native" as const,
+ frameRate: 30 as const,
+ };
+
+ it("debounces only native crop-driven target changes", () => {
+ expect(
+ shouldDebounceMp4SupportProbe(baseSnapshot, {
+ ...baseSnapshot,
+ targetHeight: 864,
+ }),
+ ).toBe(true);
+ });
+
+ it("keeps non-crop probe changes immediate", () => {
+ expect(shouldDebounceMp4SupportProbe(null, baseSnapshot)).toBe(false);
+ expect(
+ shouldDebounceMp4SupportProbe(baseSnapshot, {
+ ...baseSnapshot,
+ frameRate: 60,
+ }),
+ ).toBe(false);
+ expect(
+ shouldDebounceMp4SupportProbe(baseSnapshot, {
+ ...baseSnapshot,
+ sourceWidth: 1280,
+ sourceHeight: 720,
+ targetWidth: 1280,
+ targetHeight: 720,
+ }),
+ ).toBe(false);
+ expect(
+ shouldDebounceMp4SupportProbe(baseSnapshot, {
+ ...baseSnapshot,
+ aspectRatio: "16:9",
+ }),
+ ).toBe(false);
+ });
+});
diff --git a/src/components/video-editor/exportDimensions.ts b/src/components/video-editor/exportDimensions.ts
index 8c36d895..2f9dcdc2 100644
--- a/src/components/video-editor/exportDimensions.ts
+++ b/src/components/video-editor/exportDimensions.ts
@@ -1,6 +1,36 @@
-import type { ExportQuality } from "@/lib/exporter";
+import type { ExportMp4FrameRate, ExportQuality } from "@/lib/exporter";
import { type AspectRatio, getAspectRatioValue } from "@/utils/aspectRatioUtils";
+export type Mp4SupportProbeSnapshot = {
+ sourceWidth: number;
+ sourceHeight: number;
+ targetWidth: number;
+ targetHeight: number;
+ aspectRatio: AspectRatio;
+ frameRate: ExportMp4FrameRate;
+};
+
+export function shouldDebounceMp4SupportProbe(
+ previous: Mp4SupportProbeSnapshot | null,
+ current: Mp4SupportProbeSnapshot,
+): boolean {
+ if (
+ !previous ||
+ current.aspectRatio !== "native" ||
+ previous.aspectRatio !== current.aspectRatio ||
+ previous.frameRate !== current.frameRate ||
+ previous.sourceWidth !== current.sourceWidth ||
+ previous.sourceHeight !== current.sourceHeight
+ ) {
+ return false;
+ }
+
+ return (
+ previous.targetWidth !== current.targetWidth ||
+ previous.targetHeight !== current.targetHeight
+ );
+}
+
function normalizeEvenDimension(value: number): number {
return Math.max(2, Math.floor(value / 2) * 2);
}
@@ -30,9 +60,15 @@ export function calculateMp4SourceDimensions(
sourceWidth: number,
sourceHeight: number,
aspectRatio: AspectRatio,
+ cropRegion?: { width: number; height: number },
): { width: number; height: number } {
- const safeSourceWidth = normalizeEvenDimension(sourceWidth);
- const safeSourceHeight = normalizeEvenDimension(sourceHeight);
+ const useCroppedBounds = aspectRatio === "native";
+ const safeSourceWidth = normalizeEvenDimension(
+ sourceWidth * (useCroppedBounds ? (cropRegion?.width ?? 1) : 1),
+ );
+ const safeSourceHeight = normalizeEvenDimension(
+ sourceHeight * (useCroppedBounds ? (cropRegion?.height ?? 1) : 1),
+ );
const sourceAspectRatio = safeSourceHeight > 0 ? safeSourceWidth / safeSourceHeight : 16 / 9;
const aspectRatioValue = getAspectRatioValue(aspectRatio, sourceAspectRatio);
diff --git a/src/components/video-editor/timeline/hooks/useTimelineSelection.ts b/src/components/video-editor/timeline/hooks/useTimelineSelection.ts
index 7681d8e5..07ee09bd 100644
--- a/src/components/video-editor/timeline/hooks/useTimelineSelection.ts
+++ b/src/components/video-editor/timeline/hooks/useTimelineSelection.ts
@@ -1,5 +1,4 @@
import { useCallback, useMemo, useState } from "react";
-import { v4 as uuidv4 } from "uuid";
import type { TimelineRegion } from "../core/timelineTypes";
interface UseTimelineSelectionParams {
@@ -56,7 +55,10 @@ export function useTimelineSelection({
if (totalMs === 0) return;
const time = Math.max(0, Math.min(currentTimeMs, totalMs));
if (keyframes.some((kf) => Math.abs(kf.time - time) < 1)) return;
- setKeyframes((prev) => [...prev, { id: uuidv4(), time }]);
+ setKeyframes((prev) => [
+ ...prev,
+ { id: globalThis.crypto.randomUUID(), time },
+ ]);
}, [currentTimeMs, totalMs, keyframes]);
const deleteSelectedKeyframe = useCallback(() => {
diff --git a/src/lib/exporter/forwardFrameSource.ts b/src/lib/exporter/forwardFrameSource.ts
index 34fbc1f2..bd1afde7 100644
--- a/src/lib/exporter/forwardFrameSource.ts
+++ b/src/lib/exporter/forwardFrameSource.ts
@@ -1,10 +1,7 @@
import { WebDemuxer } from "web-demuxer";
import { getEffectiveVideoStreamDurationSeconds } from "@/lib/mediaTiming";
+import { createFallbackDemuxerSource, resolveMediaResourceUrl } from "./localMediaSource";
import { getDecodedFrameTimelineOffsetUs } from "./streamingDecoder";
-import {
- createReadableMediaResourceFile,
- resolveMediaResourceUrl,
-} from "./localMediaSource";
const DEFAULT_MAX_DECODE_QUEUE = 12;
const DEFAULT_MAX_PENDING_FRAMES = 32;
@@ -59,7 +56,7 @@ export class ForwardFrameSource {
mediaInfo = await loadMediaInfo(resourceUrl);
} catch (error) {
console.warn(
- "[ForwardFrameSource] Direct source load failed, retrying with file fallback:",
+ "[ForwardFrameSource] Direct source load failed, retrying with a fresh media source:",
error,
);
const currentDemuxer = this.demuxer;
@@ -70,7 +67,7 @@ export class ForwardFrameSource {
// Ignore cleanup errors before fallback re-init.
}
}
- mediaInfo = await loadMediaInfo(await createReadableMediaResourceFile(videoUrl));
+ mediaInfo = await loadMediaInfo(await createFallbackDemuxerSource(videoUrl));
}
const videoStream = mediaInfo.streams.find(
diff --git a/src/lib/exporter/frameRenderer.ts b/src/lib/exporter/frameRenderer.ts
index 3fa2c1f3..018bd176 100644
--- a/src/lib/exporter/frameRenderer.ts
+++ b/src/lib/exporter/frameRenderer.ts
@@ -72,6 +72,10 @@ import {
clampMediaTimeToDuration,
getEffectiveVideoStreamDurationSeconds,
} from "@/lib/mediaTiming";
+import {
+ destroyPixiApplication,
+ initializePixiApplicationWithTimeout,
+} from "@/lib/pixiApplicationLifecycle";
import { isVideoWallpaperSource } from "@/lib/wallpapers";
import { renderAnnotations } from "./annotationRenderer";
import { renderCaptions } from "./captionRenderer";
@@ -173,30 +177,6 @@ function toErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error ?? "Unknown renderer init error");
}
-type PixiInitOptions = Parameters[0];
-
-async function initApplicationWithTimeout(
- app: Application,
- options: PixiInitOptions,
- backend: ExportRenderBackend,
-): Promise {
- const timeoutErrorMessage = `Initialization timed out after ${PIXI_RENDERER_INIT_TIMEOUT_MS}ms for ${backend} renderer`;
- let timeoutId: ReturnType | undefined;
- const timeoutPromise = new Promise((_, reject) => {
- timeoutId = setTimeout(() => {
- reject(new Error(timeoutErrorMessage));
- }, PIXI_RENDERER_INIT_TIMEOUT_MS);
- });
-
- try {
- await Promise.race([app.init(options), timeoutPromise]);
- } finally {
- if (timeoutId !== undefined) {
- clearTimeout(timeoutId);
- }
- }
-}
-
function summarizeRendererAttempts(attempts: readonly PixiRendererAttempt[]): string {
const details = attempts.map((attempt) => `${attempt.backend}: ${attempt.message}`).join(" | ");
return `No supported Pixi export backend was available. Attempted: ${details}`;
@@ -358,12 +338,13 @@ export class FrameRenderer {
const app = new Application();
const initStarted = typeof performance === "undefined" ? Date.now() : performance.now();
try {
- await initApplicationWithTimeout(
+ await initializePixiApplicationWithTimeout(
app,
{
...baseOptions,
preference: backend,
},
+ PIXI_RENDERER_INIT_TIMEOUT_MS,
backend,
);
const elapsed = Math.round(
@@ -389,7 +370,7 @@ export class FrameRenderer {
`[FrameRenderer] ${backend} renderer unavailable after ${elapsed}ms; trying next backend.`,
error,
);
- app.destroy(true);
+ destroyPixiApplication(app, `${backend} export renderer initialization`);
}
}
@@ -2587,11 +2568,7 @@ export class FrameRenderer {
}
this.backgroundSprite = null;
if (this.app) {
- this.app.destroy(true, {
- children: true,
- texture: false,
- textureSource: false,
- });
+ destroyPixiApplication(this.app, "legacy export renderer");
this.app = null;
}
this.zoomBlurFilter?.destroy();
diff --git a/src/lib/exporter/localMediaSource.test.ts b/src/lib/exporter/localMediaSource.test.ts
index 883370ed..73cbc9b8 100644
--- a/src/lib/exporter/localMediaSource.test.ts
+++ b/src/lib/exporter/localMediaSource.test.ts
@@ -1,18 +1,27 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
-import { resolveMediaElementSource } from "./localMediaSource";
+import { createFallbackDemuxerSource, resolveMediaElementSource } from "./localMediaSource";
+
+const readLocalFile = vi.fn();
+const getLocalMediaUrl = vi.fn(async (filePath: string) => ({
+ success: true,
+ url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
+}));
describe("resolveMediaElementSource", () => {
beforeEach(() => {
vi.restoreAllMocks();
+ readLocalFile.mockReset();
+ getLocalMediaUrl.mockReset();
+ getLocalMediaUrl.mockImplementation(async (filePath: string) => ({
+ success: true,
+ url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
+ }));
Object.assign(globalThis, {
window: {
electronAPI: {
- readLocalFile: vi.fn(),
- getLocalMediaUrl: vi.fn(async (filePath: string) => ({
- success: true,
- url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
- })),
+ readLocalFile,
+ getLocalMediaUrl,
},
},
});
@@ -21,20 +30,16 @@ describe("resolveMediaElementSource", () => {
it("resolves file URLs through the local media server for media elements", async () => {
const result = await resolveMediaElementSource("file:///tmp/example.mp4");
- expect((window as any).electronAPI.readLocalFile).not.toHaveBeenCalled();
- expect((window as any).electronAPI.getLocalMediaUrl).toHaveBeenCalledWith(
- "/tmp/example.mp4",
- );
+ expect(readLocalFile).not.toHaveBeenCalled();
+ expect(getLocalMediaUrl).toHaveBeenCalledWith("/tmp/example.mp4");
expect(result.src).toBe("http://127.0.0.1:4321/video?path=%2Ftmp%2Fexample.mp4");
});
it("resolves absolute local paths through the local media server without copying them into blobs", async () => {
const result = await resolveMediaElementSource("/tmp/example.wav");
- expect((window as any).electronAPI.readLocalFile).not.toHaveBeenCalled();
- expect((window as any).electronAPI.getLocalMediaUrl).toHaveBeenCalledWith(
- "/tmp/example.wav",
- );
+ expect(readLocalFile).not.toHaveBeenCalled();
+ expect(getLocalMediaUrl).toHaveBeenCalledWith("/tmp/example.wav");
expect(result.src).toBe("http://127.0.0.1:4321/video?path=%2Ftmp%2Fexample.wav");
});
@@ -43,20 +48,39 @@ describe("resolveMediaElementSource", () => {
"http://127.0.0.1:43123/video?path=%2Ftmp%2Fexample%20clip.mp4",
);
- expect((window as any).electronAPI.readLocalFile).not.toHaveBeenCalled();
- expect((window as any).electronAPI.getLocalMediaUrl).not.toHaveBeenCalled();
- expect(result.src).toBe(
- "http://127.0.0.1:43123/video?path=%2Ftmp%2Fexample%20clip.mp4",
- );
+ expect(readLocalFile).not.toHaveBeenCalled();
+ expect(getLocalMediaUrl).not.toHaveBeenCalled();
+ expect(result.src).toBe("http://127.0.0.1:43123/video?path=%2Ftmp%2Fexample%20clip.mp4");
});
it("leaves remote URLs untouched", async () => {
- const readLocalFile = vi.fn();
- (window as any).electronAPI.readLocalFile = readLocalFile;
-
const result = await resolveMediaElementSource("https://example.com/video.mp4");
expect(result.src).toBe("https://example.com/video.mp4");
expect(readLocalFile).not.toHaveBeenCalled();
});
+
+ it("keeps local demuxer fallback on the range-streamed media URL", async () => {
+ const source = await createFallbackDemuxerSource("/tmp/large-recording.mp4");
+
+ expect(source).toBe("http://127.0.0.1:4321/video?path=%2Ftmp%2Flarge-recording.mp4");
+ expect(readLocalFile).not.toHaveBeenCalled();
+ });
+
+ it("retains the readable File fallback for remote media", async () => {
+ const fetchMock = vi.fn(async () => ({
+ ok: true,
+ blob: async () => new Blob([new Uint8Array([1, 2, 3])], { type: "video/mp4" }),
+ }));
+ vi.stubGlobal("fetch", fetchMock);
+
+ try {
+ const source = await createFallbackDemuxerSource("https://example.com/video.mp4");
+
+ expect(source).toBeInstanceOf(File);
+ expect(fetchMock).toHaveBeenCalledWith("https://example.com/video.mp4");
+ } finally {
+ vi.unstubAllGlobals();
+ }
+ });
});
diff --git a/src/lib/exporter/localMediaSource.ts b/src/lib/exporter/localMediaSource.ts
index 4f5a1b57..984d959c 100644
--- a/src/lib/exporter/localMediaSource.ts
+++ b/src/lib/exporter/localMediaSource.ts
@@ -116,36 +116,29 @@ export async function resolveMediaResourceUrl(resource: string): Promise
return /^file:\/\//i.test(resource) ? resource : toFileUrl(localFilePath);
}
-export async function createReadableMediaResourceFile(resource: string): Promise {
- const localFilePath = getLocalFilePath(resource);
- const filename = (localFilePath ?? resource).split(/[\\/]/).pop()?.split("?")[0] || "media";
-
- if (localFilePath && typeof window !== "undefined" && window.electronAPI?.readLocalFile) {
- const result = await window.electronAPI.readLocalFile(localFilePath);
- if (!result.success || !result.data) {
- throw new Error(result.error || "Failed to read local media file");
- }
-
- const bytes = result.data instanceof Uint8Array ? result.data : new Uint8Array(result.data);
- const arrayBuffer = bytes.buffer.slice(
- bytes.byteOffset,
- bytes.byteOffset + bytes.byteLength,
- ) as ArrayBuffer;
- return new File([arrayBuffer], filename, { type: inferMimeType(filename) });
- }
-
+async function createReadableMediaResourceFile(resource: string): Promise {
+ const filename = resource.split(/[\\/]/).pop()?.split("?")[0] || "media";
const resourceUrl = await resolveMediaResourceUrl(resource);
const response = await fetch(resourceUrl);
if (!response.ok) {
- throw new Error(
- `Failed to load media resource: ${response.status} ${response.statusText}`,
- );
+ throw new Error(`Failed to load media resource: ${response.status} ${response.statusText}`);
}
const blob = await response.blob();
return new File([blob], filename, { type: blob.type || inferMimeType(filename) });
}
+export async function createFallbackDemuxerSource(resource: string): Promise {
+ // Local media already has a random-access transport: WebDemuxer issues bounded
+ // byte-range requests against this URL. Converting it to a File would copy the
+ // complete recording through Electron IPC and make memory use scale with file size.
+ if (getLocalFilePath(resource)) {
+ return resolveMediaResourceUrl(resource);
+ }
+
+ return createReadableMediaResourceFile(resource);
+}
+
export async function resolveMediaElementSource(resource: string): Promise<{
src: string;
revoke: () => void;
diff --git a/src/lib/exporter/modernFrameRenderer.test.ts b/src/lib/exporter/modernFrameRenderer.test.ts
index 688e51f2..612a5898 100644
--- a/src/lib/exporter/modernFrameRenderer.test.ts
+++ b/src/lib/exporter/modernFrameRenderer.test.ts
@@ -6,12 +6,21 @@ const {
destroyForwardFrameSourceMock,
getForwardFrameAtTimeMock,
initializeForwardFrameSourceMock,
+ pixiApplicationInstancesMock,
+ pixiInitializationErrorsMock,
resolveMediaElementSourceMock,
} = vi.hoisted(() => ({
cancelForwardFrameSourceMock: vi.fn(),
destroyForwardFrameSourceMock: vi.fn(async () => undefined),
getForwardFrameAtTimeMock: vi.fn(async () => null),
initializeForwardFrameSourceMock: vi.fn(async () => undefined),
+ pixiApplicationInstancesMock: [] as Array<{
+ destroy: ReturnType;
+ init: ReturnType;
+ renderer: { destroy: ReturnType };
+ stage: { destroy: ReturnType };
+ }>,
+ pixiInitializationErrorsMock: [] as Array,
resolveMediaElementSourceMock: vi.fn(async () => ({
src: "blob:background",
revoke: vi.fn(),
@@ -19,7 +28,21 @@ const {
}));
vi.mock("pixi.js", () => ({
- Application: class {},
+ Application: class {
+ destroy = vi.fn(() => {
+ throw new TypeError("this._cancelResize is not a function");
+ });
+ init = vi.fn(async () => {
+ const error = pixiInitializationErrorsMock.shift();
+ if (error) throw error;
+ });
+ renderer = { destroy: vi.fn() };
+ stage = { destroy: vi.fn() };
+
+ constructor() {
+ pixiApplicationInstancesMock.push(this);
+ }
+ },
BlurFilter: class {},
Container: class {
visible = true;
@@ -179,6 +202,36 @@ function createRenderer() {
});
}
+describe("ModernFrameRenderer Pixi lifecycle", () => {
+ it("continues to the next backend when failed-init cleanup would throw", async () => {
+ pixiApplicationInstancesMock.length = 0;
+ pixiInitializationErrorsMock.length = 0;
+ pixiInitializationErrorsMock.push(new Error("WebGPU initialization failed"), undefined);
+ vi.stubGlobal("navigator", { gpu: {} });
+
+ try {
+ const renderer = createRenderer() as unknown as {
+ config: { preferredRenderBackend?: "webgl" | "webgpu" };
+ createPixiApplication: (
+ canvas: HTMLCanvasElement,
+ ) => Promise<{ backend: "webgl" | "webgpu" }>;
+ };
+ renderer.config.preferredRenderBackend = "webgpu";
+
+ await expect(renderer.createPixiApplication({} as HTMLCanvasElement)).resolves.toMatchObject({
+ backend: "webgl",
+ });
+
+ expect(pixiApplicationInstancesMock).toHaveLength(2);
+ expect(pixiApplicationInstancesMock[0].destroy).not.toHaveBeenCalled();
+ expect(pixiApplicationInstancesMock[0].stage.destroy).toHaveBeenCalledTimes(1);
+ expect(pixiApplicationInstancesMock[0].renderer.destroy).toHaveBeenCalledTimes(1);
+ } finally {
+ vi.unstubAllGlobals();
+ }
+ });
+});
+
describe("ModernFrameRenderer blur export path", () => {
beforeEach(() => {
Object.assign(globalThis, {
diff --git a/src/lib/exporter/modernFrameRenderer.ts b/src/lib/exporter/modernFrameRenderer.ts
index 529b2109..33aad0dd 100644
--- a/src/lib/exporter/modernFrameRenderer.ts
+++ b/src/lib/exporter/modernFrameRenderer.ts
@@ -82,6 +82,10 @@ import {
clampMediaTimeToDuration,
getEffectiveVideoStreamDurationSeconds,
} from "@/lib/mediaTiming";
+import {
+ destroyPixiApplication,
+ initializePixiApplicationWithTimeout,
+} from "@/lib/pixiApplicationLifecycle";
import { isVideoWallpaperSource } from "@/lib/wallpapers";
import {
type AnnotationRenderAssets,
@@ -284,30 +288,6 @@ function isKnownRendererUnavailableError(error: unknown): boolean {
);
}
-type PixiInitOptions = Parameters[0];
-
-async function initApplicationWithTimeout(
- app: Application,
- options: PixiInitOptions,
- backend: ExportRenderBackend,
-): Promise {
- const timeoutErrorMessage = `Initialization timed out after ${PIXI_RENDERER_INIT_TIMEOUT_MS}ms for ${backend} renderer`;
- let timeoutId: ReturnType | undefined;
- const timeoutPromise = new Promise((_, reject) => {
- timeoutId = setTimeout(() => {
- reject(new Error(timeoutErrorMessage));
- }, PIXI_RENDERER_INIT_TIMEOUT_MS);
- });
-
- try {
- await Promise.race([app.init(options), timeoutPromise]);
- } finally {
- if (timeoutId !== undefined) {
- clearTimeout(timeoutId);
- }
- }
-}
-
interface RenderSnapshot {
timeMs: number;
cursorTimeMs: number;
@@ -720,12 +700,13 @@ export class FrameRenderer {
const app = new Application();
const initStarted = typeof performance === "undefined" ? Date.now() : performance.now();
try {
- await initApplicationWithTimeout(
+ await initializePixiApplicationWithTimeout(
app,
{
...baseOptions,
preference: backend,
},
+ PIXI_RENDERER_INIT_TIMEOUT_MS,
backend,
);
const elapsed = Math.round(
@@ -754,7 +735,7 @@ export class FrameRenderer {
`[FrameRenderer] ${backend} export renderer unavailable (${rendererMessage}) after ${elapsed}ms; trying next backend:`,
error,
);
- app.destroy(true);
+ destroyPixiApplication(app, `${backend} export renderer initialization`);
}
}
@@ -3921,11 +3902,7 @@ export class FrameRenderer {
this.motionBlurFilter?.destroy();
this.backgroundBlurFilter?.destroy();
- this.app?.destroy(true, {
- children: true,
- texture: false,
- textureSource: false,
- });
+ destroyPixiApplication(this.app, "Lightning export renderer");
for (const texture of texturesToDestroy) {
try {
diff --git a/src/lib/exporter/modernVideoExporter.fallback.test.ts b/src/lib/exporter/modernVideoExporter.fallback.test.ts
index 5431f7d7..e1afc68c 100644
--- a/src/lib/exporter/modernVideoExporter.fallback.test.ts
+++ b/src/lib/exporter/modernVideoExporter.fallback.test.ts
@@ -238,7 +238,7 @@ describe("ModernVideoExporter native fallback routing", () => {
expect(mocks.streamingDecoderLoadMetadata).not.toHaveBeenCalled();
}, 15_000);
- it("retries the main decode path once with a readable file-backed source", async () => {
+ it("retries the main decode path once with a fresh media source", async () => {
mocks.streamingDecoderGetEffectiveDuration.mockReturnValue(1);
mocks.streamingDecoderDecodeAll
.mockRejectedValueOnce(
@@ -277,13 +277,13 @@ describe("ModernVideoExporter native fallback routing", () => {
expect(mocks.streamingDecoderLoadMetadata.mock.calls[0]).toEqual([
"file:///recording.mp4",
{
- forceReadableFileSource: false,
+ useFallbackMediaSource: false,
},
]);
expect(mocks.streamingDecoderLoadMetadata.mock.calls[1]).toEqual([
"file:///recording.mp4",
{
- forceReadableFileSource: true,
+ useFallbackMediaSource: true,
},
]);
expect(mocks.streamingDecoderDecodeAll).toHaveBeenCalledTimes(2);
diff --git a/src/lib/exporter/modernVideoExporter.ts b/src/lib/exporter/modernVideoExporter.ts
index a1983599..c77ba964 100644
--- a/src/lib/exporter/modernVideoExporter.ts
+++ b/src/lib/exporter/modernVideoExporter.ts
@@ -288,7 +288,7 @@ type NativeStaticLayoutZoomSample = {
};
const NATIVE_EXPORT_ENGINE_NAME = "Breeze";
-const READABLE_SOURCE_RETRY_ERROR_TOKENS = [
+const MEDIA_SOURCE_RETRY_ERROR_TOKENS = [
"readavpacket",
"get_media_info",
"avfoundation",
@@ -371,11 +371,11 @@ export class ModernVideoExporter {
}
async export(): Promise {
- let preferReadableFileSource = false;
- let retriedWithReadableFileSource = false;
+ let useFallbackMediaSource = false;
+ let retriedWithFallbackMediaSource = false;
while (true) {
- let shouldRetryWithReadableFileSource = false;
+ let shouldRetryWithFallbackMediaSource = false;
try {
this.cleanup();
this.cancelled = false;
@@ -522,7 +522,7 @@ export class ModernVideoExporter {
});
stageStartedAt = this.getNowMs();
const videoInfo = await this.streamingDecoder.loadMetadata(this.config.videoUrl, {
- forceReadableFileSource: preferReadableFileSource,
+ useFallbackMediaSource,
});
this.metadataLoadTimeMs = this.getNowMs() - stageStartedAt;
const nativeAudioPlan = this.buildNativeAudioPlan(videoInfo);
@@ -892,15 +892,15 @@ export class ModernVideoExporter {
};
} catch (error) {
if (
- !preferReadableFileSource &&
- !retriedWithReadableFileSource &&
- this.shouldRetryWithReadableFileSource(error)
+ !useFallbackMediaSource &&
+ !retriedWithFallbackMediaSource &&
+ this.shouldRetryWithFallbackMediaSource(error)
) {
- retriedWithReadableFileSource = true;
- preferReadableFileSource = true;
- shouldRetryWithReadableFileSource = true;
+ retriedWithFallbackMediaSource = true;
+ useFallbackMediaSource = true;
+ shouldRetryWithFallbackMediaSource = true;
console.warn(
- "[VideoExporter] Primary decode path failed; retrying export once with a readable file-backed media source.",
+ "[VideoExporter] Primary decode path failed; retrying export once with a fresh media source.",
error,
);
} else {
@@ -921,7 +921,7 @@ export class ModernVideoExporter {
};
}
} finally {
- if (!shouldRetryWithReadableFileSource && this.totalExportStartTimeMs > 0) {
+ if (!shouldRetryWithFallbackMediaSource && this.totalExportStartTimeMs > 0) {
console.log(
`[VideoExporter] Final metrics ${JSON.stringify(this.buildExportMetrics())}`,
);
@@ -929,20 +929,18 @@ export class ModernVideoExporter {
this.cleanup();
}
- if (shouldRetryWithReadableFileSource) {
+ if (shouldRetryWithFallbackMediaSource) {
continue;
}
}
}
- private shouldRetryWithReadableFileSource(error: unknown): boolean {
+ private shouldRetryWithFallbackMediaSource(error: unknown): boolean {
const resolvedError = this.encoderError ?? error;
const message =
resolvedError instanceof Error ? resolvedError.message : String(resolvedError);
const normalizedMessage = message.toLowerCase();
- return READABLE_SOURCE_RETRY_ERROR_TOKENS.some((token) =>
- normalizedMessage.includes(token),
- );
+ return MEDIA_SOURCE_RETRY_ERROR_TOKENS.some((token) => normalizedMessage.includes(token));
}
private getPlatformLabel(): string {
diff --git a/src/lib/exporter/streamingDecoder.test.ts b/src/lib/exporter/streamingDecoder.test.ts
index de831671..7de21b5b 100644
--- a/src/lib/exporter/streamingDecoder.test.ts
+++ b/src/lib/exporter/streamingDecoder.test.ts
@@ -40,6 +40,12 @@ vi.mock("web-demuxer", () => ({
},
}));
+const mockReadLocalFile = vi.fn();
+const mockGetLocalMediaUrl = vi.fn(async (filePath: string) => ({
+ success: true,
+ url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
+}));
+
describe("StreamingVideoDecoder local media loading", () => {
beforeEach(() => {
vi.restoreAllMocks();
@@ -47,17 +53,20 @@ describe("StreamingVideoDecoder local media loading", () => {
mockDemuxerGetMediaInfo.mockClear();
mockDemuxerDestroy.mockClear();
mockDemuxerGetDecoderConfig.mockClear();
+ mockReadLocalFile.mockReset();
+ mockGetLocalMediaUrl.mockReset();
+ mockGetLocalMediaUrl.mockImplementation(async (filePath: string) => ({
+ success: true,
+ url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
+ }));
Object.assign(globalThis, {
window: {
location: {
href: "http://localhost:5173/",
},
electronAPI: {
- readLocalFile: vi.fn(),
- getLocalMediaUrl: vi.fn(async (filePath: string) => ({
- success: true,
- url: `http://127.0.0.1:4321/video?path=${encodeURIComponent(filePath)}`,
- })),
+ readLocalFile: mockReadLocalFile,
+ getLocalMediaUrl: mockGetLocalMediaUrl,
},
},
});
@@ -67,17 +76,17 @@ describe("StreamingVideoDecoder local media loading", () => {
const decoder = new StreamingVideoDecoder();
await decoder.loadMetadata("http://127.0.0.1:43123/video?path=%2Ftmp%2Fcapture.mp4");
- expect((window as any).electronAPI.readLocalFile).not.toHaveBeenCalled();
+ expect(window.electronAPI.readLocalFile).not.toHaveBeenCalled();
expect(mockDemuxerLoad).toHaveBeenCalledWith(
"http://127.0.0.1:43123/video?path=%2Ftmp%2Fcapture.mp4",
);
});
- it("normalizes absolute local paths to file URLs before loading them", async () => {
+ it("resolves absolute local paths to range-streamed media URLs", async () => {
const decoder = new StreamingVideoDecoder();
await decoder.loadMetadata("/tmp/capture.mp4");
- expect((window as any).electronAPI.getLocalMediaUrl).toHaveBeenCalledWith(
+ expect(window.electronAPI.getLocalMediaUrl).toHaveBeenCalledWith(
"/tmp/capture.mp4",
);
expect(mockDemuxerLoad).toHaveBeenCalledWith(
@@ -85,27 +94,31 @@ describe("StreamingVideoDecoder local media loading", () => {
);
});
- it("falls back to a readable File when direct loading fails", async () => {
+ it("retries the range-streamed URL when direct local loading fails", async () => {
mockDemuxerLoad.mockReset();
mockDemuxerLoad
.mockRejectedValueOnce(new Error("get_media_info failed: Failed after 3 attempts"))
.mockResolvedValueOnce(undefined);
- (window as any).electronAPI.readLocalFile = vi.fn(async () => ({
- success: true,
- data: new Uint8Array([1, 2, 3]),
- }));
-
const decoder = new StreamingVideoDecoder();
await decoder.loadMetadata("/tmp/fallback.mp4");
expect(mockDemuxerLoad).toHaveBeenNthCalledWith(
- 1,
+ 2,
"http://127.0.0.1:4321/video?path=%2Ftmp%2Ffallback.mp4",
);
- expect(mockDemuxerLoad.mock.calls[1]?.[0]).toBeInstanceOf(File);
- expect((window as any).electronAPI.readLocalFile).toHaveBeenCalledWith(
- "/tmp/fallback.mp4",
+ expect(window.electronAPI.readLocalFile).not.toHaveBeenCalled();
+ });
+
+ it("keeps an explicit local retry on the range-streamed URL", async () => {
+ const decoder = new StreamingVideoDecoder();
+ await decoder.loadMetadata("/tmp/retry.mp4", {
+ useFallbackMediaSource: true,
+ });
+
+ expect(mockDemuxerLoad).toHaveBeenCalledWith(
+ "http://127.0.0.1:4321/video?path=%2Ftmp%2Fretry.mp4",
);
+ expect(window.electronAPI.readLocalFile).not.toHaveBeenCalled();
});
});
diff --git a/src/lib/exporter/streamingDecoder.ts b/src/lib/exporter/streamingDecoder.ts
index 861d6720..004f1fec 100644
--- a/src/lib/exporter/streamingDecoder.ts
+++ b/src/lib/exporter/streamingDecoder.ts
@@ -1,7 +1,7 @@
import { WebDemuxer } from "web-demuxer";
import type { SpeedRegion, TrimRegion } from "@/components/video-editor/types";
import { getEffectiveVideoStreamDurationSeconds } from "@/lib/mediaTiming";
-import { createReadableMediaResourceFile, resolveMediaResourceUrl } from "./localMediaSource";
+import { createFallbackDemuxerSource, resolveMediaResourceUrl } from "./localMediaSource";
const DEFAULT_MAX_DECODE_QUEUE = 12;
const DEFAULT_MAX_PENDING_FRAMES = 32;
@@ -24,7 +24,7 @@ export interface DecodedVideoInfo {
}
interface StreamingVideoDecoderLoadOptions {
- forceReadableFileSource?: boolean;
+ useFallbackMediaSource?: boolean;
}
/** Decoder retains ownership of the VideoFrame and closes it after use. */
@@ -126,14 +126,14 @@ export class StreamingVideoDecoder {
};
let mediaInfo;
- if (options.forceReadableFileSource) {
- mediaInfo = await loadMediaInfo(await createReadableMediaResourceFile(videoUrl));
+ if (options.useFallbackMediaSource) {
+ mediaInfo = await loadMediaInfo(await createFallbackDemuxerSource(videoUrl));
} else {
try {
mediaInfo = await loadMediaInfo(resourceUrl);
} catch (error) {
console.warn(
- "[StreamingVideoDecoder] Direct source load failed, retrying with file fallback:",
+ "[StreamingVideoDecoder] Direct source load failed, retrying with a fresh media source:",
error,
);
const currentDemuxer = this.demuxer;
@@ -144,7 +144,7 @@ export class StreamingVideoDecoder {
// Ignore cleanup errors before fallback re-init.
}
}
- mediaInfo = await loadMediaInfo(await createReadableMediaResourceFile(videoUrl));
+ mediaInfo = await loadMediaInfo(await createFallbackDemuxerSource(videoUrl));
}
}
diff --git a/src/lib/pixiApplicationLifecycle.test.ts b/src/lib/pixiApplicationLifecycle.test.ts
new file mode 100644
index 00000000..6b576242
--- /dev/null
+++ b/src/lib/pixiApplicationLifecycle.test.ts
@@ -0,0 +1,113 @@
+import type { Application } from "pixi.js";
+import { describe, expect, it, vi } from "vitest";
+import {
+ destroyPixiApplication,
+ initializePixiApplication,
+ initializePixiApplicationWithTimeout,
+} from "./pixiApplicationLifecycle";
+
+function createApplication(init: () => Promise = async () => undefined) {
+ return {
+ init: vi.fn(init),
+ destroy: vi.fn(),
+ stage: { destroy: vi.fn() },
+ renderer: { destroy: vi.fn() },
+ } as unknown as Application;
+}
+
+describe("Pixi application lifecycle", () => {
+ it("cleans a failed initialization without running uninitialized plugins", async () => {
+ const initializationError = new Error("No available renderer");
+ const app = createApplication(async () => {
+ throw initializationError;
+ });
+ const applicationDestroy = vi.mocked(app.destroy);
+ applicationDestroy.mockImplementation(() => {
+ throw new TypeError("this._cancelResize is not a function");
+ });
+
+ await expect(initializePixiApplication(app, {})).rejects.toBe(initializationError);
+ expect(() => destroyPixiApplication(app, "test renderer init")).not.toThrow();
+
+ expect(applicationDestroy).not.toHaveBeenCalled();
+ expect(app.stage.destroy).toHaveBeenCalledWith({
+ children: true,
+ texture: false,
+ textureSource: false,
+ });
+ expect(app.renderer.destroy).toHaveBeenCalledWith({
+ removeView: true,
+ releaseGlobalResources: false,
+ });
+ });
+
+ it("destroys a successfully initialized application at most once", async () => {
+ const app = createApplication();
+
+ await initializePixiApplication(app, {});
+ destroyPixiApplication(app, "test renderer");
+ destroyPixiApplication(app, "test renderer");
+
+ expect(app.destroy).toHaveBeenCalledTimes(1);
+ expect(app.destroy).toHaveBeenCalledWith(
+ { removeView: true, releaseGlobalResources: false },
+ { children: true, texture: false, textureSource: false },
+ );
+ });
+
+ it("defers teardown until an in-flight initialization settles", async () => {
+ let finishInitialization: (() => void) | undefined;
+ const app = createApplication(
+ () =>
+ new Promise((resolve) => {
+ finishInitialization = resolve;
+ }),
+ );
+ const initialization = initializePixiApplication(app, {});
+
+ destroyPixiApplication(app, "timed-out renderer init");
+ expect(app.destroy).not.toHaveBeenCalled();
+
+ finishInitialization?.();
+ await initialization;
+
+ expect(app.destroy).toHaveBeenCalledTimes(1);
+ });
+
+ it("reports cleanup errors without throwing or retrying unsafe teardown", async () => {
+ const app = createApplication();
+ const cleanupError = new Error("renderer cleanup failed");
+ vi.mocked(app.destroy).mockImplementation(() => {
+ throw cleanupError;
+ });
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
+
+ await initializePixiApplication(app, {});
+ expect(() => destroyPixiApplication(app, "test renderer")).not.toThrow();
+ expect(() => destroyPixiApplication(app, "test renderer")).not.toThrow();
+
+ expect(app.destroy).toHaveBeenCalledTimes(1);
+ expect(warn).toHaveBeenCalledWith(
+ "[PixiApplication] Failed to clean up test renderer:",
+ cleanupError,
+ );
+ warn.mockRestore();
+ });
+
+ it("reports the backend when initialization times out", async () => {
+ vi.useFakeTimers();
+ try {
+ const app = createApplication(() => new Promise(() => undefined));
+ const initialization = initializePixiApplicationWithTimeout(app, {}, 250, "webgpu");
+ const rejection = initialization.catch((error: unknown) => error);
+
+ await vi.advanceTimersByTimeAsync(250);
+
+ await expect(rejection).resolves.toEqual(
+ new Error("Initialization timed out after 250ms for webgpu renderer"),
+ );
+ } finally {
+ vi.useRealTimers();
+ }
+ });
+});
diff --git a/src/lib/pixiApplicationLifecycle.ts b/src/lib/pixiApplicationLifecycle.ts
new file mode 100644
index 00000000..62a0f743
--- /dev/null
+++ b/src/lib/pixiApplicationLifecycle.ts
@@ -0,0 +1,108 @@
+import type { Application } from "pixi.js";
+
+type PixiInitializationState = "initializing" | "initialized" | "failed";
+type PixiInitOptions = Parameters[0];
+
+const initializationStates = new WeakMap();
+const destroyRequests = new WeakSet();
+const destroyContexts = new WeakMap();
+const completedCleanups = new WeakSet();
+
+const RENDERER_DESTROY_OPTIONS = {
+ removeView: true,
+ releaseGlobalResources: false,
+} as const;
+
+const STAGE_DESTROY_OPTIONS = {
+ children: true,
+ texture: false,
+ textureSource: false,
+} as const;
+
+function reportCleanupError(app: Application, error: unknown): void {
+ const context = destroyContexts.get(app) ?? "Pixi application";
+ console.warn(`[PixiApplication] Failed to clean up ${context}:`, error);
+}
+
+function destroyFailedApplication(app: Application): void {
+ const partialApp = app as Partial;
+
+ try {
+ partialApp.stage?.destroy(STAGE_DESTROY_OPTIONS);
+ } catch (error) {
+ reportCleanupError(app, error);
+ }
+
+ try {
+ partialApp.renderer?.destroy(RENDERER_DESTROY_OPTIONS);
+ } catch (error) {
+ reportCleanupError(app, error);
+ }
+}
+
+function completeDestroy(app: Application): void {
+ if (completedCleanups.has(app)) return;
+ completedCleanups.add(app);
+
+ if (initializationStates.get(app) !== "initialized") {
+ destroyFailedApplication(app);
+ return;
+ }
+
+ try {
+ app.destroy(RENDERER_DESTROY_OPTIONS, STAGE_DESTROY_OPTIONS);
+ } catch (error) {
+ reportCleanupError(app, error);
+ }
+}
+
+export async function initializePixiApplication(
+ app: Application,
+ options: PixiInitOptions,
+): Promise {
+ if (initializationStates.has(app) || destroyRequests.has(app)) {
+ throw new Error("Pixi application lifecycle has already started");
+ }
+
+ initializationStates.set(app, "initializing");
+ try {
+ await app.init(options);
+ initializationStates.set(app, "initialized");
+ } catch (error) {
+ initializationStates.set(app, "failed");
+ if (destroyRequests.has(app)) completeDestroy(app);
+ throw error;
+ }
+
+ if (destroyRequests.has(app)) completeDestroy(app);
+}
+
+export async function initializePixiApplicationWithTimeout(
+ app: Application,
+ options: PixiInitOptions,
+ timeoutMs: number,
+ backendLabel: string,
+): Promise {
+ let timeoutId: ReturnType | undefined;
+ const timeoutPromise = new Promise((_, reject) => {
+ timeoutId = setTimeout(() => {
+ reject(
+ new Error(`Initialization timed out after ${timeoutMs}ms for ${backendLabel} renderer`),
+ );
+ }, timeoutMs);
+ });
+
+ try {
+ await Promise.race([initializePixiApplication(app, options), timeoutPromise]);
+ } finally {
+ if (timeoutId !== undefined) clearTimeout(timeoutId);
+ }
+}
+
+export function destroyPixiApplication(app: Application | null, context: string): void {
+ if (!app || destroyRequests.has(app) || completedCleanups.has(app)) return;
+
+ destroyRequests.add(app);
+ destroyContexts.set(app, context);
+ if (initializationStates.get(app) !== "initializing") completeDestroy(app);
+}