From 491dc8357b5a2b2f07bdac21dd602796b19b1be6 Mon Sep 17 00:00:00 2001 From: Rostyslav Nihrutsa Date: Wed, 25 Feb 2026 10:43:58 +0200 Subject: [PATCH 01/20] refactor(Manifest): add raw method to manifestBuilder, add plugin and manifest option to config --- .../builders/manifest/ManifestBase.test.ts | 518 ++++++++++++++++++ src/cli/builders/manifest/ManifestBase.ts | 290 +++++++--- src/cli/builders/manifest/ManifestV2.ts | 7 +- src/cli/builders/manifest/ManifestV3.ts | 10 +- src/cli/builders/manifest/utils.test.ts | 62 ++- src/cli/builders/manifest/utils.ts | 19 +- src/cli/plugins/index.ts | 1 + src/cli/plugins/manifest.ts | 28 + src/cli/plugins/version/AbstractVersion.ts | 2 +- src/cli/resolvers/config.ts | 4 + src/types/config.ts | 16 +- src/types/manifest.ts | 6 +- 12 files changed, 866 insertions(+), 97 deletions(-) create mode 100644 src/cli/plugins/manifest.ts diff --git a/src/cli/builders/manifest/ManifestBase.test.ts b/src/cli/builders/manifest/ManifestBase.test.ts index 85e7b748..53a3c109 100644 --- a/src/cli/builders/manifest/ManifestBase.test.ts +++ b/src/cli/builders/manifest/ManifestBase.test.ts @@ -1,6 +1,482 @@ import ManifestV3 from "./ManifestV3"; +import ManifestV2 from "./ManifestV2"; import {Browser, DataCollectionPermission} from "@typing/browser"; +const unique = (arr: string[]) => Array.from(new Set(arr)).length === arr.length; + +describe("ManifestBase primitive properties", () => { + it("name", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setName("InternalName"); + builder1.raw({name: "OptionalName"}); + const manifest1: any = builder1.build(); + expect(manifest1.name).toBe("InternalName"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({name: "OptionalName"}); + const manifest2: any = builder2.build(); + expect(manifest2.name).toBe("OptionalName"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.name).toBe("__MSG_app_name__"); + }); + + it("short_name", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setShortName("Short"); + builder1.raw({short_name: "OptShort"}); + const manifest1: any = builder1.build(); + expect(manifest1.short_name).toBe("Short"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({short_name: "OptShort"}); + const manifest2: any = builder2.build(); + expect(manifest2.short_name).toBe("OptShort"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.short_name).toBeUndefined(); + }); + + it("description", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setDescription("Desc"); + builder1.raw({description: "OptDesc"}); + const manifest1: any = builder1.build(); + expect(manifest1.description).toBe("Desc"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({description: "OptDesc"}); + const manifest2: any = builder2.build(); + expect(manifest2.description).toBe("OptDesc"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.description).toBeUndefined(); + }); + + it("version", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setVersion("1.2.3"); + builder1.raw({version: "9.9.9"}); + const manifest1: any = builder1.build(); + expect(manifest1.version).toBe("1.2.3"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({version: "9.9.9"}); + const manifest2: any = builder2.build(); + expect(manifest2.version).toBe("9.9.9"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.version).toBe("0.0.0"); + }); + + it("minimum_chrome_version", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setMinimumVersion("120.0.0"); + builder1.raw({minimum_chrome_version: "100.0.0"}); + const manifest1: any = builder1.build(); + expect(manifest1.minimum_chrome_version).toBe("120.0.0"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({minimum_chrome_version: "100.0.0"}); + const manifest2: any = builder2.build(); + expect(manifest2.minimum_chrome_version).toBe("100.0.0"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.minimum_chrome_version).toBeUndefined(); + }); + + it("author", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setAuthor("AddonBone"); + const manifest1: any = builder1.build(); + expect(manifest1.author).toBe("AddonBone"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({author: "Opt"}); + const manifest2: any = builder2.build(); + expect(manifest2.author).toBe("Opt"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.author).toBeUndefined(); + }); + + it("homepage_url", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setHomepage("https://me.example"); + const manifest1: any = builder1.build(); + expect(manifest1.homepage_url).toBe("https://me.example"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({homepage_url: "https://opt.example"}); + const manifest2: any = builder2.build(); + expect(manifest2.homepage_url).toBe("https://opt.example"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.homepage_url).toBeUndefined(); + }); + + it("incognito", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setIncognito("not_allowed" as any); + const manifest1: any = builder1.build(); + expect(manifest1.incognito).toBe("not_allowed"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({incognito: "split"}); + const manifest2: any = builder2.build(); + expect(manifest2.incognito).toBe("split"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.incognito).toBeUndefined(); + }); + + it("default_locale", () => { + const builder1 = new ManifestV3(Browser.Chrome); + builder1.setLocale("en" as any); + const manifest1: any = builder1.build(); + expect(manifest1.default_locale).toBe("en"); + + const builder2 = new ManifestV3(Browser.Chrome); + builder2.raw({default_locale: "uk"}); + const manifest2: any = builder2.build(); + expect(manifest2.default_locale).toBe("uk"); + + const builder3 = new ManifestV3(Browser.Chrome); + const manifest3: any = builder3.build(); + expect(manifest3.default_locale).toBeUndefined(); + }); +}); + +describe("ManifestBase merged properties", () => { + it("commands", () => { + const builder = new ManifestV3(Browser.Chrome); + + builder.setCommands( + new Set([ + {name: "internal_command"}, + { + name: "common", + description: "Internal description", + chromeosKey: "Internal chromeosKey", + }, + ]) + ); + + builder.raw({ + commands: { + raw_command: {}, + common: { + description: "Raw description", + suggested_key: { + mac: "Raw macKey", + }, + }, + }, + }); + const commands: any = builder.build().commands; + + expect(commands.raw_command).toBeDefined(); + expect(commands.internal_command).toBeDefined(); + expect(commands.common.description).toBe("Internal description"); + expect(commands.common.suggested_key.chromeos).toBe("Internal chromeosKey"); + expect(commands.common.suggested_key.mac).toBe("Raw macKey"); + }); + + it("content_scripts", () => { + const builder = new ManifestV3(Browser.Chrome); + + builder + .setDependencies( + new Map([ + [ + "entry", + { + js: new Set(["entry.js"]), + css: new Set(["entry.css"]), + assets: new Set(["entry.png"]), + }, + ], + ]) + ) + .setContentScripts( + new Set([ + { + matches: ["https://internal.com/*"], + entry: "entry", + }, + ]) + ); + + builder.raw({ + content_scripts: [ + { + matches: ["https://raw.com/*"], + js: ["raw.js"], + css: ["raw.css"], + }, + ], + }); + + const contentScripts: any = builder.build().content_scripts; + + expect(contentScripts).toBeDefined(); + expect(contentScripts.length).toBe(2); + }); + + it("icons", () => { + const builder = new ManifestV3(Browser.Chrome); + + builder.setIcons( + new Map([ + [ + "default", + new Map([ + [16, "internal16.png"], + [24, "internal24.png"], + ]), + ], + ]) + ); + + builder.raw({icons: {16: "raw16.png", 32: "raw32.png"}}); + + const icons: any = builder.build().icons; + + expect(icons["16"]).toBe("internal16.png"); + expect(icons["24"]).toBe("internal24.png"); + expect(icons["32"]).toBe("raw32.png"); + }); + + it("permissions", () => { + const builder_v3 = new ManifestV3(Browser.Chrome); + builder_v3.appendPermissions(new Set(["storage", "activeTab"])).raw({ + permissions: ["tabs"], + host_permissions: ["https://api.example.com/*"], + }); + const manifest_v3: any = builder_v3.build(); + expect(manifest_v3.host_permissions).toEqual(expect.arrayContaining(["https://api.example.com/*"])); + expect(manifest_v3.permissions).toEqual(expect.arrayContaining(["storage", "tabs"])); + + const builder_v2 = new ManifestV2(Browser.Chrome); + builder_v2 + .addPermission("storage") + .addHostPermission("https://*.example.com/*") + .raw({ + permissions: ["tabs", "activeTab"], + host_permissions: ["https://api.example.com/*"], + }); + const manifest_v2: any = builder_v2.build(); + expect(manifest_v2.host_permissions).toBeUndefined(); + expect(manifest_v2.permissions).toEqual( + expect.arrayContaining(["storage", "tabs", "https://*.example.com/*", "https://api.example.com/*"]) + ); + }); + + it("optional_permissions", () => { + const builder_v3 = new ManifestV3(Browser.Chrome); + builder_v3 + .addPermission("storage") + .addOptionalPermission("bookmarks") + .raw({optional_permissions: ["history", "storage"]}); + const manifest_v3: any = builder_v3.build(); + expect(manifest_v3.optional_permissions).toEqual(expect.arrayContaining(["bookmarks", "history"])); + expect(manifest_v3.optional_permissions).not.toEqual(expect.arrayContaining(["storage"])); + + // MV2: optional_permissions also include optional host permissions not already in host permissions + const builder_v2 = new ManifestV2(Browser.Chrome); + builder_v2 + .addPermission("storage") + .addHostPermission("https://*.example.com/*") + .setOptionalPermissions(new Set(["bookmarks"])) + .setOptionalHostPermissions(new Set(["https://opt.example.com/*", "https://*.example.com/*"])) + .raw({optional_permissions: ["history"]}); + const manifest_v2: any = builder_v2.build(); + expect(manifest_v2.optional_permissions).toEqual( + expect.arrayContaining(["bookmarks", "history", "https://opt.example.com/*"]) + ); + expect(manifest_v2.optional_permissions).not.toEqual(expect.arrayContaining(["https://*.example.com/*"])); + }); + + it("host_permissions", () => { + const builder_v3 = new ManifestV3(Browser.Chrome); + builder_v3.addHostPermission("https://*.example.com/*").raw({host_permissions: ["https://api.example.com/*"]}); + const manifest_v3: any = builder_v3.build(); + expect(manifest_v3.host_permissions).toEqual( + expect.arrayContaining(["https://*.example.com/*", "https://api.example.com/*"]) + ); + + const builder_v2 = new ManifestV2(Browser.Chrome); + builder_v2.addHostPermission("https://*.example.com/*").raw({host_permissions: ["https://api.example.com/*"]}); + const manifest_v2: any = builder_v2.build(); + expect(manifest_v2.host_permissions).toBeUndefined(); + expect(manifest_v2.permissions).toEqual( + expect.arrayContaining(["https://*.example.com/*", "https://api.example.com/*"]) + ); + }); + + it("optional_host_permissions", () => { + const builder_v3 = new ManifestV3(Browser.Chrome); + builder_v3 + .addHostPermission("https://*.example.com/*") + .setOptionalHostPermissions(new Set(["https://opt.example.com/*", "https://*.example.com/*"])) // duplicated one should be filtered out + .raw({optional_host_permissions: ["https://raw-opt.example.com/*"]}); + const manifest_v3: any = builder_v3.build(); + expect(manifest_v3.optional_host_permissions).toEqual( + expect.arrayContaining(["https://opt.example.com/*", "https://raw-opt.example.com/*"]) + ); + expect(manifest_v3.optional_host_permissions).not.toEqual(expect.arrayContaining(["https://*.example.com/*"])); + + const builder_v2 = new ManifestV2(Browser.Chrome); + builder_v2 + .addHostPermission("https://*.example.com/*") + .setOptionalHostPermissions(new Set(["https://opt.example.com/*"])); + const manifest_v2: any = builder_v2.build(); + expect(manifest_v2.optional_host_permissions).toBeUndefined(); + expect(manifest_v2.optional_permissions).toEqual(expect.arrayContaining(["https://opt.example.com/*"])); + }); + + it("web_accessible_resources (MV3)", () => { + const builder = new ManifestV3(Browser.Chrome); + + builder + .setDependencies( + new Map([ + [ + "entry", + { + js: new Set(["entry.js"]), + css: new Set(), + assets: new Set(["img/a.png", "img/b.png"]), + }, + ], + [ + "entry2", + { + js: new Set(["entry2.js"]), + css: new Set(), + assets: new Set(["img/b.png", "img/c.png"]), + }, + ], + ]) + ) + .setContentScripts( + new Set([ + { + matches: ["https://site.com/*"], + entry: "entry", + }, + { + matches: ["https://other.com/*"], + entry: "entry2", + }, + ]) + ) + .addAccessibleResource({resources: ["img/common.png"], matches: ["https://site.com/*"]}) + .raw({ + web_accessible_resources: [ + {resources: ["img/raw.png", "img/a.png"], matches: ["https://site.com/*"]}, + {resources: ["img/onlyraw.png"], matches: ["https://other.com/*"]}, + ], + }); + + const resources: any[] = builder.build().web_accessible_resources as any[]; + expect(Array.isArray(resources)).toBe(true); + + const byMatches = (pattern: string) => resources.find(r => (r.matches || []).includes(pattern)); + + const site = byMatches("https://site.com/*"); + expect(site).toBeDefined(); + expect(site.resources).toEqual( + expect.arrayContaining([ + "img/a.png", // from deps + raw + "img/b.png", // from deps + "img/common.png", // internal + "img/raw.png", // raw only + ]) + ); + + const other = byMatches("https://other.com/*"); + expect(other).toBeDefined(); + expect(other.resources).toEqual( + expect.arrayContaining([ + "img/b.png", // from entry2 deps + "img/c.png", // from entry2 deps + "img/onlyraw.png", // raw only + ]) + ); + + // Ensure no duplicates overall within each group + expect(unique(site.resources)).toBe(true); + expect(unique(other.resources)).toBe(true); + }); + + it("web_accessible_resources (MV2)", () => { + const builder = new ManifestV2(Browser.Chrome); + + builder + .setDependencies( + new Map([ + [ + "entry", + { + js: new Set(["entry.js"]), + css: new Set(), + assets: new Set(["img/a.png", "img/b.png"]), + }, + ], + [ + "entry2", + { + js: new Set(["entry2.js"]), + css: new Set(), + assets: new Set(["img/b.png", "img/c.png"]), + }, + ], + ]) + ) + .setContentScripts( + new Set([ + {matches: ["https://site.com/*"], entry: "entry"}, + {matches: ["https://other.com/*"], entry: "entry2"}, + ]) + ) + .addAccessibleResource({resources: ["img/common.png"], matches: ["https://site.com/*"]}) + .raw({ + web_accessible_resources: [ + {resources: ["img/raw.png", "img/a.png"], matches: ["https://site.com/*"]}, + {resources: ["img/onlyraw.png"], matches: ["https://other.com/*"]}, + ], + }); + + const resources: any[] = (builder.build() as any).web_accessible_resources; + expect(Array.isArray(resources)).toBe(true); + + // MV2 flattens to unique list of strings + expect(resources).toEqual( + expect.arrayContaining([ + "img/a.png", + "img/b.png", + "img/c.png", + "img/common.png", + "img/raw.png", + "img/onlyraw.png", + ]) + ); + + // Ensure uniqueness + + expect(unique(resources)).toBe(true); + }); +}); + describe("ManifestBase mergeSpecific", () => { it("should perform a deep merge of browser specific settings", () => { const builder = new ManifestV3(Browser.Firefox); @@ -60,7 +536,49 @@ describe("ManifestBase mergeSpecific", () => { }, }); + builder.raw({ + browser_specific_settings: { + safari: { + strict_max_version: "20", + }, + }, + }); + const manifest: any = builder.build(); expect(manifest.browser_specific_settings.safari.strict_min_version).toBe("15"); + expect(manifest.browser_specific_settings.safari.strict_max_version).toBe("20"); + }); + + it("should use raw for gecko settings when specific is not set", () => { + const builder = new ManifestV3(Browser.Firefox); + + builder.raw({ + browser_specific_settings: { + gecko: { + id: "from@optional", + update_url: "https://example.com/update.json", + strict_min_version: "110.0", + strict_max_version: "119.0", + data_collection_permissions: { + required: [DataCollectionPermission.WebsiteActivity], + optional: [DataCollectionPermission.AuthenticationInfo], + }, + }, + gecko_android: { + strict_min_version: "110.0", + strict_max_version: "119.0", + }, + }, + }); + + const settings: any = builder.build().browser_specific_settings; + + expect(settings.gecko.id).toBe("from@optional"); + expect(settings.gecko.update_url).toBe("https://example.com/update.json"); + expect(settings.gecko.strict_min_version).toBe("110.0"); + expect(settings.gecko.strict_max_version).toBe("119.0"); + expect(settings.gecko.data_collection_permissions.required).toContain(DataCollectionPermission.WebsiteActivity); + expect(settings.gecko_android.strict_min_version).toBe("110.0"); + expect(settings.gecko_android.strict_max_version).toBe("119.0"); }); }); diff --git a/src/cli/builders/manifest/ManifestBase.ts b/src/cli/builders/manifest/ManifestBase.ts index 05200bbb..0d91eebb 100644 --- a/src/cli/builders/manifest/ManifestBase.ts +++ b/src/cli/builders/manifest/ManifestBase.ts @@ -20,6 +20,7 @@ import { ManifestPopup, ManifestSidebar, ManifestVersion, + OptionalManifest, } from "@typing/manifest"; import {Browser, BrowserSpecific} from "@typing/browser"; import {Language} from "@typing/locale"; @@ -40,13 +41,13 @@ export class ManifestError extends Error { } export default abstract class implements ManifestBuilder { - protected name: string = "__MSG_app_name__"; + protected name?: string; protected author?: string; protected homepage?: string; protected shortName?: string; protected description?: string; protected minimumVersion?: string; - protected version: string = "0.0.0"; + protected version?: string; protected icon?: string; protected incognito?: ManifestIncognito; protected specific?: BrowserSpecific; @@ -64,6 +65,9 @@ export default abstract class implements ManifestBuilder protected optionalHostPermissions: ManifestHostPermissions = new Set(); protected accessibleResources: ManifestAccessibleResources = new Set(); + protected raws: Set = new Set(); + protected mergedRaws: OptionalManifest | null = null; + public abstract getManifestVersion(): ManifestVersion; protected abstract buildAction(): Partial | undefined; @@ -111,7 +115,7 @@ export default abstract class implements ManifestBuilder } public setVersion(version?: string): this { - this.version = version || "0.0.0"; + this.version = version; return this; } @@ -292,43 +296,31 @@ export default abstract class implements ManifestBuilder return this; } - public setManifestAccessibleResource(accessibleResources: ManifestAccessibleResources): this { + public setAccessibleResource(accessibleResources: ManifestAccessibleResources): this { this.accessibleResources = accessibleResources; return this; } - private merge(manifest: T, ...sources: Array | undefined>): T { - sources = sources.filter(source => source !== undefined); - - if (sources.length === 0) { - return manifest; - } - - const result = {...manifest}; + public raw(manifest: OptionalManifest): this { + this.raws.add(manifest); - for (const source of sources) { - Object.assign(result, source); - } - - return result; + return this; } public build(): T { - let manifest: Manifest = { - name: this.name, - short_name: this.shortName, - description: this.description, - version: this.version, - manifest_version: this.getManifestVersion(), - minimum_chrome_version: this.minimumVersion, - author: this.author, - homepage_url: this.homepage, - incognito: this.incognito, - }; - - manifest = this.merge( - manifest, + const raws = this.buildRaws(); + + return this.merge( + this.buildName(), + this.buildShortName(), + this.buildDescription(), + this.buildVersion(), + this.buildManifestVersion(), + this.buildMinimumChromeVersion(), + this.buildAuthor(), + this.buildHomepageUrl(), + this.buildIncognito(), this.buildLocale(), this.buildIcons(), this.buildBackground(), @@ -341,16 +333,90 @@ export default abstract class implements ManifestBuilder this.buildHostPermissions(), this.buildOptionalHostPermissions(), this.buildWebAccessibleResources(), - this.buildBrowserSpecificSettings() - ); + this.buildBrowserSpecificSettings(), + raws + ) as T; + } - return manifest as T; + public get(): T { + return this.build(); } - protected buildIcons(): Partial | undefined { - if (this.icon) { - return {icons: this.getIconsByName(this.icon)}; + protected get optionalManifest(): OptionalManifest { + if (this.mergedRaws) return this.mergedRaws; + + return (this.mergedRaws = Array.from(this.raws).reduce((result, manifest) => _.merge(result, manifest), {})); + } + + private merge(...sources: Array | undefined>): T { + sources = sources.filter(source => source !== undefined); + + if (sources.length === 0) { + throw new ManifestError("No sources provided for manifest merging"); } + + const result = {} as T; + + for (const source of sources) { + Object.assign(result, source); + } + + return result; + } + + protected buildName(): Partial { + return {name: this.name || this.optionalManifest.name || "__MSG_app_name__"}; + } + + protected buildShortName(): Partial | undefined { + const shortName = this.shortName || this.optionalManifest.short_name; + return shortName ? {short_name: shortName} : undefined; + } + + protected buildDescription(): Partial | undefined { + const description = this.description || this.optionalManifest.description; + return description ? {description} : undefined; + } + + protected buildVersion(): Partial { + return {version: this.version || this.optionalManifest.version || "0.0.0"}; + } + + protected buildManifestVersion(): Partial { + return {manifest_version: this.getManifestVersion()}; + } + + protected buildMinimumChromeVersion(): Partial | undefined { + const version = this.minimumVersion || this.optionalManifest.minimum_chrome_version; + return version ? {minimum_chrome_version: version} : undefined; + } + + protected buildAuthor(): Partial | undefined { + const author = this.author || this.optionalManifest.author; + return author ? {author} : undefined; + } + + protected buildHomepageUrl(): Partial | undefined { + const homepage = this.homepage || this.optionalManifest.homepage_url; + return homepage ? {homepage_url: homepage} : undefined; + } + + protected buildIncognito(): Partial | undefined { + const incognito = this.incognito || this.optionalManifest.incognito; + return incognito !== undefined ? {incognito} : undefined; + } + + protected buildLocale(): Partial | undefined { + const defaultLocale = this.locale || this.optionalManifest.default_locale; + return defaultLocale ? {default_locale: defaultLocale} : undefined; + } + + protected buildIcons(): Partial | undefined { + const icons = { + ...this.optionalManifest.icons, + ...this.getIconsByName(this.icon), + }; + return Object.keys(icons).length ? {icons} : undefined; } protected buildBackground(): Partial | undefined { @@ -374,10 +440,11 @@ export default abstract class implements ManifestBuilder } protected buildCommands(): Partial | undefined { - if (this.commands.size > 0) { - const commands = Array.from(this.commands).reduce( - (commands, command) => { - const item = { + const internalCommands = Array.from(this.commands).reduce( + (commands, command) => { + return { + ...commands, + [command.name]: { suggested_key: { default: command?.defaultKey, windows: command?.windowsKey, @@ -389,21 +456,25 @@ export default abstract class implements ManifestBuilder command?.description || (command.name === CommandExecuteActionName ? undefined : command.name), global: command?.global, - }; + }, + }; + }, + {} as CoreManifest["commands"] + ); - return {...commands, [command.name]: item}; - }, - {} as CoreManifest["commands"] - ); + const commands = _.merge(this.optionalManifest.commands, internalCommands); - return {commands}; - } + if (Object.keys(commands).length) return {commands}; } protected buildContentScripts(): Partial | undefined { - if (this.contentScripts.size > 0) { - const contentScripts: ManifestV3["content_scripts"] = []; + const contentScripts: ManifestV3["content_scripts"] = []; + + if (this.optionalManifest.content_scripts) { + contentScripts.push(...this.optionalManifest.content_scripts); + } + if (this.contentScripts.size > 0) { for (const script of this.contentScripts.values()) { const { entry, @@ -446,13 +517,22 @@ export default abstract class implements ManifestBuilder world, }); } - - return {content_scripts: contentScripts}; } + + return contentScripts.length ? {content_scripts: contentScripts} : undefined; } protected buildSidebar(): Partial | undefined { if (!this.sidebar) { + const sidebarAction = this.optionalManifest.sidebar_action; + const sidePanel = this.optionalManifest.side_panel; + + if (SidebarAlternativeBrowsers.has(this.browser)) { + if (sidebarAction) return {sidebar_action: sidebarAction}; + } else { + if (sidePanel) return {side_panel: sidePanel}; + } + return; } @@ -469,57 +549,105 @@ export default abstract class implements ManifestBuilder : {side_panel: {...commonProps, default_path: path}}; } - protected buildLocale(): Partial | undefined { - if (this.locale) { - return {default_locale: this.locale}; - } - } - protected buildBrowserSpecificSettings(): Partial | undefined { - const settings = this.specific || {}; - const {safari, gecko, geckoAndroid} = settings; + const optionalSettings = this.optionalManifest.browser_specific_settings; + const {safari, gecko, geckoAndroid} = this.specific || {}; if (this.browser === Browser.Firefox) { - const emptyGeckoAndroid = - _.isEmpty(geckoAndroid?.strictMinVersion) && _.isEmpty(geckoAndroid?.strictMaxVersion); + const id = gecko?.id || optionalSettings?.gecko?.id; + const updateUrl = gecko?.updateUrl || optionalSettings?.gecko?.update_url; + const geckoMinVersion = gecko?.strictMinVersion || optionalSettings?.gecko?.strict_min_version; + const geckoMaxVersion = gecko?.strictMaxVersion || optionalSettings?.gecko?.strict_max_version; + const dataCollectionPermissions = _.merge( + optionalSettings?.gecko?.data_collection_permissions, + gecko?.dataCollectionPermissions + ); + + const androidMinVersion = + geckoAndroid?.strictMinVersion || optionalSettings?.gecko_android?.strict_min_version; + const androidMaxVersion = + geckoAndroid?.strictMaxVersion || optionalSettings?.gecko_android?.strict_max_version; return { browser_specific_settings: { gecko: { - id: gecko?.id, - strict_min_version: gecko?.strictMinVersion, - strict_max_version: gecko?.strictMaxVersion, - update_url: gecko?.updateUrl, - data_collection_permissions: normalizeDataCollectionPermissions( - gecko?.dataCollectionPermissions - ), + id, + update_url: updateUrl, + strict_min_version: geckoMinVersion, + strict_max_version: geckoMaxVersion, + data_collection_permissions: normalizeDataCollectionPermissions(dataCollectionPermissions), }, - gecko_android: emptyGeckoAndroid - ? undefined - : { - strict_min_version: geckoAndroid?.strictMinVersion, - strict_max_version: geckoAndroid?.strictMaxVersion, - }, + gecko_android: + _.isEmpty(androidMinVersion) && _.isEmpty(androidMaxVersion) + ? undefined + : { + strict_min_version: androidMinVersion, + strict_max_version: androidMaxVersion, + }, }, }; } else if (this.browser === Browser.Safari) { - if (_.isEmpty(safari?.strictMinVersion) && _.isEmpty(safari?.strictMaxVersion)) { + const minVersion = safari?.strictMinVersion || optionalSettings?.safari?.strict_min_version; + const maxVersion = safari?.strictMaxVersion || optionalSettings?.safari?.strict_max_version; + + if (_.isEmpty(minVersion) && _.isEmpty(maxVersion)) { return; } return { browser_specific_settings: { safari: { - strict_min_version: safari?.strictMinVersion, - strict_max_version: safari?.strictMaxVersion, + strict_min_version: minVersion, + strict_max_version: maxVersion, }, }, }; } } + protected buildRaws(): Partial | undefined { + const { + name, + short_name, + description, + version, + minimum_chrome_version, + author, + homepage_url, + incognito, + default_locale, + icons, + background, + commands, + action, + sidebar, + content_scripts, + permissions, + optional_permissions, + host_permissions, + optional_host_permissions, + web_accessible_resources, + browser_specific_settings, + ...other + } = this.optionalManifest; + + this.appendPermissions(new Set(permissions)); + this.appendOptionalPermissions(new Set(optional_permissions)); + this.appendHostPermissions(new Set(host_permissions)); + this.appendOptionalHostPermissions(new Set(optional_host_permissions)); + + this.appendAccessibleResources(new Set(web_accessible_resources)); + + return other; + } + protected hasExecuteActionCommand(): boolean { - return this.commands.size > 0 && Array.from(this.commands).some(({name}) => name === CommandExecuteActionName); + const optionalCommands = this.optionalManifest.commands; + + const inInternalCommands = + this.commands.size > 0 && Array.from(this.commands).some(({name}) => name === CommandExecuteActionName); + const inOptionalCommands = optionalCommands && Object.keys(optionalCommands).includes(CommandExecuteActionName); + return inInternalCommands || inOptionalCommands; } protected getIconsByName(name?: string): CoreManifestIcons | undefined { @@ -538,10 +666,6 @@ export default abstract class implements ManifestBuilder } } - public get(): T { - return this.build(); - } - public getWebAccessibleResources(): ManifestAccessibleResource[] { const resources: ManifestAccessibleResource[] = [...this.accessibleResources]; diff --git a/src/cli/builders/manifest/ManifestV2.ts b/src/cli/builders/manifest/ManifestV2.ts index 97e50704..b22b7f53 100644 --- a/src/cli/builders/manifest/ManifestV2.ts +++ b/src/cli/builders/manifest/ManifestV2.ts @@ -1,6 +1,6 @@ import ManifestBase from "./ManifestBase"; -import {filterHostPatterns, filterPermissionsForMV2} from "./utils"; +import {filterHostPatterns, filterOptionalPermissions, filterPermissionsForMV2} from "./utils"; import {CoreManifest, ManifestVersion} from "@typing/manifest"; import {Browser} from "@typing/browser"; @@ -77,8 +77,9 @@ export default class extends ManifestBase { } protected buildOptionalPermissions(): Partial | undefined { - const optionalPermissions: string[] = Array.from(filterPermissionsForMV2(this.optionalPermissions)).filter( - permission => !this.permissions.has(permission) + const optionalPermissions: string[] = filterOptionalPermissions( + filterPermissionsForMV2(this.optionalPermissions), + filterPermissionsForMV2(this.permissions) ); // prettier-ignore diff --git a/src/cli/builders/manifest/ManifestV3.ts b/src/cli/builders/manifest/ManifestV3.ts index 2e8c3dc1..bbf1ec17 100644 --- a/src/cli/builders/manifest/ManifestV3.ts +++ b/src/cli/builders/manifest/ManifestV3.ts @@ -1,6 +1,6 @@ import ManifestBase, {ManifestError} from "./ManifestBase"; -import {filterHostPatterns, filterPermissionsForMV3} from "./utils"; +import {filterHostPatterns, filterOptionalPermissions, filterPermissionsForMV3} from "./utils"; import {CoreManifest, ManifestAccessibleResource, ManifestVersion} from "@typing/manifest"; import {Browser} from "@typing/browser"; @@ -81,10 +81,10 @@ export default class extends ManifestBase { } protected buildOptionalPermissions(): Partial | undefined { - // prettier-ignore - const optionalPermissions = Array - .from(filterPermissionsForMV3(this.optionalPermissions)) - .filter((permission) => !this.permissions.has(permission)); + const optionalPermissions = filterOptionalPermissions( + filterPermissionsForMV3(this.optionalPermissions), + filterPermissionsForMV3(this.permissions) + ); if (optionalPermissions.length > 0) { return {optional_permissions: optionalPermissions}; diff --git a/src/cli/builders/manifest/utils.test.ts b/src/cli/builders/manifest/utils.test.ts index f5a669ff..dfd6c529 100644 --- a/src/cli/builders/manifest/utils.test.ts +++ b/src/cli/builders/manifest/utils.test.ts @@ -1,8 +1,16 @@ -import {filterHostPatterns, mergeWebAccessibleResources, normalizeDataCollectionPermissions} from "./utils"; +import { + filterHostPatterns, + filterOptionalPermissions, + mergeWebAccessibleResources, + normalizeDataCollectionPermissions, +} from "./utils"; import {DataCollectionPermission} from "@typing/browser"; import {ManifestAccessibleResource} from "@typing/manifest"; +type ManifestPermission = chrome.runtime.ManifestPermission; +type ManifestOptionalPermission = chrome.runtime.ManifestOptionalPermission; + const toSet = (arr: string[]) => new Set(arr); const setToArray = (set: Set) => Array.from(set); const sortResources = (resources: ManifestAccessibleResource[]): ManifestAccessibleResource[] => { @@ -96,6 +104,58 @@ describe("filterHostPatterns", () => { }); }); +describe("filterOptionalPermissions", () => { + test("removes permissions that are already required", () => { + const required = new Set(["storage"]); + const optional = new Set(["storage", "tabs"]); + + const result = filterOptionalPermissions(optional, required); + + expect(result).toEqual(expect.arrayContaining(["tabs"])); + expect(result).not.toEqual(expect.arrayContaining(["storage"])); + expect(result.length).toBe(1); + }); + + test("drops activeTab from optional when tabs is present in optional", () => { + const optional = new Set(["activeTab", "tabs"]); + const required = new Set(); + + const result = filterOptionalPermissions(optional, required); + + // filterPermissions removes activeTab when tabs is present in the union + expect(result).toEqual(["tabs"]); + }); + + test("drops activeTab from optional when tabs is present in required", () => { + const optional = new Set(["activeTab"]); + const required = new Set(["tabs"]); + + const result = filterOptionalPermissions(optional, required); + + // Union contains tabs and activeTab; filterPermissions removes activeTab, then diff removes tabs as required -> empty + expect(result).toEqual([]); + }); + + test("keeps activeTab when tabs is absent from both optional and required", () => { + const optional = new Set(["activeTab"]); + const required = new Set(); + + const result = filterOptionalPermissions(optional, required); + + expect(result).toEqual(["activeTab"]); + }); + + test("deduplicates and filters correctly when mixing optional and required", () => { + const optional = new Set(["tabs", "storage", "activeTab"]); + const required = new Set(["storage"]); + + const result = filterOptionalPermissions(optional, required); + + // activeTab should be removed because tabs is present; storage removed because it's required + expect(result).toEqual(["tabs"]); + }); +}); + describe("mergeWebAccessibleResources", () => { test("merge resources with same matches without duplicates", () => { const input = [ diff --git a/src/cli/builders/manifest/utils.ts b/src/cli/builders/manifest/utils.ts index b4c8e918..e0bbed79 100644 --- a/src/cli/builders/manifest/utils.ts +++ b/src/cli/builders/manifest/utils.ts @@ -13,6 +13,13 @@ type Permission = ManifestPermissions | ManifestOptionalPermissions; * @param permissions - Set of permissions to filter * @returns New set of permissions adapted for Manifest V2 */ +export const filterPermissions = (permissions: Set): Set => { + if (permissions.has("tabs" as T)) { + permissions.delete("activeTab" as T); + } + return permissions; +}; + export const filterPermissionsForMV2 = (permissions: Set): Set => { const filteredPermissions = new Set(permissions); @@ -35,7 +42,7 @@ export const filterPermissionsForMV2 = (permissions: Set(permissions: Set): Set => { @@ -53,7 +60,15 @@ export const filterPermissionsForMV3 = (permissions: Set( + optional: Set, + required: Set +): O[] => { + const allPermissions = filterPermissions(new Set([...optional, ...required])); + return _.difference(Array.from(allPermissions), Array.from(required)) as O[]; }; export const filterHostPatterns = (patterns: Set): Set => { diff --git a/src/cli/plugins/index.ts b/src/cli/plugins/index.ts index ece5e463..40f0dafd 100644 --- a/src/cli/plugins/index.ts +++ b/src/cli/plugins/index.ts @@ -4,6 +4,7 @@ export {default as pluginBackground} from "./background"; export {default as pluginContent} from "./content"; export {default as pluginDotenv} from "./dotenv"; export {default as pluginHtml} from "./html"; +export {default as pluginManifest} from "./manifest"; export {default as pluginOptimization} from "./optimization"; export {default as pluginOutput} from "./output"; export {default as pluginIcon} from "./icon"; diff --git a/src/cli/plugins/manifest.ts b/src/cli/plugins/manifest.ts new file mode 100644 index 00000000..c0c9de1d --- /dev/null +++ b/src/cli/plugins/manifest.ts @@ -0,0 +1,28 @@ +import {definePlugin} from "@main/plugin"; +import {fromRootPath} from "@cli/resolvers/path"; +import fs from "fs"; + +export default definePlugin(() => { + return { + name: "adnbn:manifest", + manifest: ({config, manifest}) => { + try { + const packagePath = fromRootPath(config, "package.json"); + + const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8")); + + packageJson.manifest && manifest.raw(packageJson.manifest); + } catch (e) {} + + const configManifest = config.manifest; + + if (typeof configManifest === "object") { + manifest.raw(configManifest); + } else if (typeof configManifest === "function") { + const result = configManifest(manifest); + + result && manifest.raw(result); + } + }, + }; +}); diff --git a/src/cli/plugins/version/AbstractVersion.ts b/src/cli/plugins/version/AbstractVersion.ts index 8fa7f021..b0576e40 100644 --- a/src/cli/plugins/version/AbstractVersion.ts +++ b/src/cli/plugins/version/AbstractVersion.ts @@ -19,6 +19,6 @@ export default abstract class AbstractVersion { return; } - return String(_.isFunction(version) ? version : version); + return String(_.isFunction(version) ? version() : version); } } diff --git a/src/cli/resolvers/config.ts b/src/cli/resolvers/config.ts index e5ce7b86..d2800b7d 100644 --- a/src/cli/resolvers/config.ts +++ b/src/cli/resolvers/config.ts @@ -14,6 +14,7 @@ import { pluginLocale, pluginMeta, pluginOffscreen, + pluginManifest, pluginOptimization, pluginOutput, pluginPage, @@ -193,6 +194,7 @@ export default async (config: OptionalConfig): Promise => { html = [], bundler = {}, env = {}, + manifest, manifestVersion = (new Set([Browser.Safari]).has(browser) ? 2 : 3) as ManifestVersion, mode = Mode.Development, analyze = false, @@ -246,6 +248,7 @@ export default async (config: OptionalConfig): Promise => { icon, incognito, specific, + manifest, manifestVersion, rootDir, outDir, @@ -326,6 +329,7 @@ export default async (config: OptionalConfig): Promise => { pluginHtml(), pluginVersion(), pluginBundler(), + pluginManifest(), ]; return { diff --git a/src/types/config.ts b/src/types/config.ts index 784525f3..ada3e2ad 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -3,7 +3,7 @@ import type {Options as HtmlOptions} from "html-rspack-tags-plugin"; import {Command, Mode} from "@typing/app"; import {Browser, BrowserSpecific} from "@typing/browser"; -import {ManifestIncognitoValue, ManifestVersion} from "@typing/manifest"; +import {ManifestIncognitoValue, ManifestVersion, ManifestBuilder, OptionalManifest} from "@typing/manifest"; import {Plugin} from "@typing/plugin"; import {Language} from "@typing/locale"; import {Awaiter} from "@typing/helpers"; @@ -171,6 +171,20 @@ export interface Config { */ incognito?: ManifestIncognitoValue | (() => ManifestIncognitoValue | undefined); + /** + * Extension manifest without the version. + * Allows customizing the manifest.json file beyond the standard fields handled by the builder. + * The structure and available APIs depend on the manifest version (v2 or v3). + * + * Accepts: + * - an object with additional manifest fields + * - a function that receives a ManifestBuilder instance and returns manifest fields + * + * Note: Some fields like name, version, and permissions are handled automatically + * by the builder and should not be included here unless you need to override them. + */ + manifest?: OptionalManifest | ((builder: ManifestBuilder) => OptionalManifest | undefined); + /** * Extension manifest version (e.g., v2 or v3). * Defines the manifest structure and available APIs. diff --git a/src/types/manifest.ts b/src/types/manifest.ts index 32751683..70fb335a 100644 --- a/src/types/manifest.ts +++ b/src/types/manifest.ts @@ -84,6 +84,8 @@ export type SafariManifest = ChromeManifest & { export type Manifest = ChromeManifest | FirefoxManifest | SafariManifest; +export type OptionalManifest = Partial>; + export interface ManifestBuilder { setName(name: string): this; @@ -156,7 +158,7 @@ export interface ManifestBuilder { appendOptionalHostPermissions(permissions: ManifestHostPermissions): this; // Web Accessible Resource - setManifestAccessibleResource(accessibleResources: ManifestAccessibleResources): this; + setAccessibleResource(accessibleResources: ManifestAccessibleResources): this; appendAccessibleResources(accessibleResources: ManifestAccessibleResources): this; @@ -166,6 +168,8 @@ export interface ManifestBuilder { // Getter get(): T; + + raw(manifest: OptionalManifest): this; } type Entry = string; From ddc543bc8d96a0d5bed45942c45679d696f61dbf Mon Sep 17 00:00:00 2001 From: Rostyslav Nihrutsa Date: Thu, 26 Feb 2026 11:34:30 +0200 Subject: [PATCH 02/20] refactor(Manifest): improve permissions and host permissions logic, improve raw manifest merging --- .../builders/manifest/ManifestBase.test.ts | 60 ++++++--- src/cli/builders/manifest/ManifestBase.ts | 116 +++++++++++++----- src/cli/builders/manifest/ManifestV2.ts | 14 +-- src/cli/builders/manifest/ManifestV3.ts | 14 +-- 4 files changed, 141 insertions(+), 63 deletions(-) diff --git a/src/cli/builders/manifest/ManifestBase.test.ts b/src/cli/builders/manifest/ManifestBase.test.ts index 53a3c109..204542c8 100644 --- a/src/cli/builders/manifest/ManifestBase.test.ts +++ b/src/cli/builders/manifest/ManifestBase.test.ts @@ -156,6 +156,26 @@ describe("ManifestBase primitive properties", () => { }); describe("ManifestBase merged properties", () => { + it("merging objects and arrays", () => { + const builder = new ManifestV3(Browser.Chrome); + + builder + .raw({permissions: ["tabs"]}) + .raw({permissions: ["storage"]}) + .raw({commands: {cmd1: {description: "First"}}}) + .raw({commands: {cmd2: {description: "Second"}}}); + + const manifest: any = builder.build(); + + expect(manifest.permissions).toEqual(expect.arrayContaining(["tabs", "storage"])); + expect(manifest.commands).toEqual( + expect.objectContaining({ + cmd1: {description: "First"}, + cmd2: {description: "Second"}, + }) + ); + }); + it("commands", () => { const builder = new ManifestV3(Browser.Chrome); @@ -551,25 +571,32 @@ describe("ManifestBase mergeSpecific", () => { it("should use raw for gecko settings when specific is not set", () => { const builder = new ManifestV3(Browser.Firefox); - - builder.raw({ - browser_specific_settings: { + builder + .setSpecific({ gecko: { - id: "from@optional", - update_url: "https://example.com/update.json", - strict_min_version: "110.0", - strict_max_version: "119.0", - data_collection_permissions: { - required: [DataCollectionPermission.WebsiteActivity], - optional: [DataCollectionPermission.AuthenticationInfo], + dataCollectionPermissions: { + required: [DataCollectionPermission.BrowsingActivity], }, }, - gecko_android: { - strict_min_version: "110.0", - strict_max_version: "119.0", + }) + .raw({ + browser_specific_settings: { + gecko: { + id: "from@optional", + update_url: "https://example.com/update.json", + strict_min_version: "110.0", + strict_max_version: "119.0", + data_collection_permissions: { + required: [DataCollectionPermission.WebsiteActivity], + optional: [DataCollectionPermission.AuthenticationInfo], + }, + }, + gecko_android: { + strict_min_version: "110.0", + strict_max_version: "119.0", + }, }, - }, - }); + }); const settings: any = builder.build().browser_specific_settings; @@ -578,6 +605,9 @@ describe("ManifestBase mergeSpecific", () => { expect(settings.gecko.strict_min_version).toBe("110.0"); expect(settings.gecko.strict_max_version).toBe("119.0"); expect(settings.gecko.data_collection_permissions.required).toContain(DataCollectionPermission.WebsiteActivity); + expect(settings.gecko.data_collection_permissions.required).toContain( + DataCollectionPermission.BrowsingActivity + ); expect(settings.gecko_android.strict_min_version).toBe("110.0"); expect(settings.gecko_android.strict_max_version).toBe("119.0"); }); diff --git a/src/cli/builders/manifest/ManifestBase.ts b/src/cli/builders/manifest/ManifestBase.ts index 0d91eebb..dd1f9afb 100644 --- a/src/cli/builders/manifest/ManifestBase.ts +++ b/src/cli/builders/manifest/ManifestBase.ts @@ -66,7 +66,7 @@ export default abstract class implements ManifestBuilder protected accessibleResources: ManifestAccessibleResources = new Set(); protected raws: Set = new Set(); - protected mergedRaws: OptionalManifest | null = null; + protected mergedRaws?: OptionalManifest; public abstract getManifestVersion(): ManifestVersion; @@ -309,8 +309,6 @@ export default abstract class implements ManifestBuilder } public build(): T { - const raws = this.buildRaws(); - return this.merge( this.buildName(), this.buildShortName(), @@ -334,7 +332,7 @@ export default abstract class implements ManifestBuilder this.buildOptionalHostPermissions(), this.buildWebAccessibleResources(), this.buildBrowserSpecificSettings(), - raws + this.buildRaw() ) as T; } @@ -342,10 +340,58 @@ export default abstract class implements ManifestBuilder return this.build(); } - protected get optionalManifest(): OptionalManifest { + protected get combinedRaws(): OptionalManifest { if (this.mergedRaws) return this.mergedRaws; - return (this.mergedRaws = Array.from(this.raws).reduce((result, manifest) => _.merge(result, manifest), {})); + this.mergedRaws = Array.from(this.raws).reduce((result, raw) => { + return _.mergeWith(result, raw, (objValue, srcValue) => { + if (Array.isArray(objValue) && Array.isArray(srcValue)) { + return objValue.concat(srcValue); + } + }); + }, {}); + + return this.mergedRaws; + } + + protected get combinedPermissions(): ManifestPermissions { + const result = new Set(this.permissions); + if (this.combinedRaws.permissions) { + for (const permission of this.combinedRaws.permissions) { + result.add(permission); + } + } + return result; + } + + protected get combinedOptionalPermissions(): ManifestOptionalPermissions { + const result = new Set(this.optionalPermissions); + if (this.combinedRaws.optional_permissions) { + for (const permission of this.combinedRaws.optional_permissions) { + result.add(permission); + } + } + return result; + } + + protected get combinedHostPermissions(): ManifestHostPermissions { + const result = new Set(this.hostPermissions); + if (this.combinedRaws.host_permissions) { + for (const permission of this.combinedRaws.host_permissions) { + result.add(permission); + } + } + return result; + } + + protected get combinedOptionalHostPermissions(): ManifestHostPermissions { + const result = new Set(this.optionalHostPermissions); + if (this.combinedRaws.optional_host_permissions) { + for (const permission of this.combinedRaws.optional_host_permissions) { + result.add(permission); + } + } + return result; } private merge(...sources: Array | undefined>): T { @@ -365,21 +411,21 @@ export default abstract class implements ManifestBuilder } protected buildName(): Partial { - return {name: this.name || this.optionalManifest.name || "__MSG_app_name__"}; + return {name: this.name || this.combinedRaws.name || "__MSG_app_name__"}; } protected buildShortName(): Partial | undefined { - const shortName = this.shortName || this.optionalManifest.short_name; + const shortName = this.shortName || this.combinedRaws.short_name; return shortName ? {short_name: shortName} : undefined; } protected buildDescription(): Partial | undefined { - const description = this.description || this.optionalManifest.description; + const description = this.description || this.combinedRaws.description; return description ? {description} : undefined; } protected buildVersion(): Partial { - return {version: this.version || this.optionalManifest.version || "0.0.0"}; + return {version: this.version || this.combinedRaws.version || "0.0.0"}; } protected buildManifestVersion(): Partial { @@ -387,33 +433,33 @@ export default abstract class implements ManifestBuilder } protected buildMinimumChromeVersion(): Partial | undefined { - const version = this.minimumVersion || this.optionalManifest.minimum_chrome_version; + const version = this.minimumVersion || this.combinedRaws.minimum_chrome_version; return version ? {minimum_chrome_version: version} : undefined; } protected buildAuthor(): Partial | undefined { - const author = this.author || this.optionalManifest.author; + const author = this.author || this.combinedRaws.author; return author ? {author} : undefined; } protected buildHomepageUrl(): Partial | undefined { - const homepage = this.homepage || this.optionalManifest.homepage_url; + const homepage = this.homepage || this.combinedRaws.homepage_url; return homepage ? {homepage_url: homepage} : undefined; } protected buildIncognito(): Partial | undefined { - const incognito = this.incognito || this.optionalManifest.incognito; + const incognito = this.incognito || this.combinedRaws.incognito; return incognito !== undefined ? {incognito} : undefined; } protected buildLocale(): Partial | undefined { - const defaultLocale = this.locale || this.optionalManifest.default_locale; + const defaultLocale = this.locale || this.combinedRaws.default_locale; return defaultLocale ? {default_locale: defaultLocale} : undefined; } protected buildIcons(): Partial | undefined { const icons = { - ...this.optionalManifest.icons, + ...this.combinedRaws.icons, ...this.getIconsByName(this.icon), }; return Object.keys(icons).length ? {icons} : undefined; @@ -462,7 +508,7 @@ export default abstract class implements ManifestBuilder {} as CoreManifest["commands"] ); - const commands = _.merge(this.optionalManifest.commands, internalCommands); + const commands = _.merge(this.combinedRaws.commands, internalCommands); if (Object.keys(commands).length) return {commands}; } @@ -470,8 +516,8 @@ export default abstract class implements ManifestBuilder protected buildContentScripts(): Partial | undefined { const contentScripts: ManifestV3["content_scripts"] = []; - if (this.optionalManifest.content_scripts) { - contentScripts.push(...this.optionalManifest.content_scripts); + if (this.combinedRaws.content_scripts) { + contentScripts.push(...this.combinedRaws.content_scripts); } if (this.contentScripts.size > 0) { @@ -524,8 +570,8 @@ export default abstract class implements ManifestBuilder protected buildSidebar(): Partial | undefined { if (!this.sidebar) { - const sidebarAction = this.optionalManifest.sidebar_action; - const sidePanel = this.optionalManifest.side_panel; + const sidebarAction = this.combinedRaws.sidebar_action; + const sidePanel = this.combinedRaws.side_panel; if (SidebarAlternativeBrowsers.has(this.browser)) { if (sidebarAction) return {sidebar_action: sidebarAction}; @@ -550,7 +596,7 @@ export default abstract class implements ManifestBuilder } protected buildBrowserSpecificSettings(): Partial | undefined { - const optionalSettings = this.optionalManifest.browser_specific_settings; + const optionalSettings = this.combinedRaws.browser_specific_settings; const {safari, gecko, geckoAndroid} = this.specific || {}; if (this.browser === Browser.Firefox) { @@ -558,9 +604,14 @@ export default abstract class implements ManifestBuilder const updateUrl = gecko?.updateUrl || optionalSettings?.gecko?.update_url; const geckoMinVersion = gecko?.strictMinVersion || optionalSettings?.gecko?.strict_min_version; const geckoMaxVersion = gecko?.strictMaxVersion || optionalSettings?.gecko?.strict_max_version; - const dataCollectionPermissions = _.merge( + const dataCollectionPermissions = _.mergeWith( optionalSettings?.gecko?.data_collection_permissions, - gecko?.dataCollectionPermissions + gecko?.dataCollectionPermissions, + (objValue, srcValue) => { + if (Array.isArray(objValue) && Array.isArray(srcValue)) { + return objValue.concat(srcValue); + } + } ); const androidMinVersion = @@ -605,7 +656,7 @@ export default abstract class implements ManifestBuilder } } - protected buildRaws(): Partial | undefined { + protected buildRaw(): Partial | undefined { const { name, short_name, @@ -629,20 +680,13 @@ export default abstract class implements ManifestBuilder web_accessible_resources, browser_specific_settings, ...other - } = this.optionalManifest; - - this.appendPermissions(new Set(permissions)); - this.appendOptionalPermissions(new Set(optional_permissions)); - this.appendHostPermissions(new Set(host_permissions)); - this.appendOptionalHostPermissions(new Set(optional_host_permissions)); - - this.appendAccessibleResources(new Set(web_accessible_resources)); + } = this.combinedRaws; return other; } protected hasExecuteActionCommand(): boolean { - const optionalCommands = this.optionalManifest.commands; + const optionalCommands = this.combinedRaws.commands; const inInternalCommands = this.commands.size > 0 && Array.from(this.commands).some(({name}) => name === CommandExecuteActionName); @@ -680,6 +724,10 @@ export default abstract class implements ManifestBuilder } } + if (this.combinedRaws.web_accessible_resources) { + resources.push(...this.combinedRaws.web_accessible_resources); + } + return mergeWebAccessibleResources(resources); } } diff --git a/src/cli/builders/manifest/ManifestV2.ts b/src/cli/builders/manifest/ManifestV2.ts index b22b7f53..8ca5f814 100644 --- a/src/cli/builders/manifest/ManifestV2.ts +++ b/src/cli/builders/manifest/ManifestV2.ts @@ -65,10 +65,10 @@ export default class extends ManifestBase { } protected buildPermissions(): Partial | undefined { - const permissions: string[] = Array.from(filterPermissionsForMV2(this.permissions)); + const permissions: string[] = Array.from(filterPermissionsForMV2(this.combinedPermissions)); - if (this.hostPermissions.size > 0) { - permissions.push(...filterHostPatterns(this.hostPermissions)); + if (this.combinedHostPermissions.size > 0) { + permissions.push(...filterHostPatterns(this.combinedHostPermissions)); } if (permissions.length > 0) { @@ -78,14 +78,14 @@ export default class extends ManifestBase { protected buildOptionalPermissions(): Partial | undefined { const optionalPermissions: string[] = filterOptionalPermissions( - filterPermissionsForMV2(this.optionalPermissions), - filterPermissionsForMV2(this.permissions) + filterPermissionsForMV2(this.combinedOptionalPermissions), + filterPermissionsForMV2(this.combinedPermissions) ); // prettier-ignore const optionalHostPermissions: string[] = Array - .from(filterHostPatterns(new Set([...this.hostPermissions, ...this.optionalHostPermissions]))) - .filter((permission) => !this.hostPermissions.has(permission)); + .from(filterHostPatterns(new Set([...this.combinedHostPermissions, ...this.combinedOptionalHostPermissions]))) + .filter((permission) => !this.combinedHostPermissions.has(permission)); if (optionalHostPermissions.length > 0) { optionalPermissions.push(...optionalHostPermissions); diff --git a/src/cli/builders/manifest/ManifestV3.ts b/src/cli/builders/manifest/ManifestV3.ts index bbf1ec17..c8bdccbb 100644 --- a/src/cli/builders/manifest/ManifestV3.ts +++ b/src/cli/builders/manifest/ManifestV3.ts @@ -73,7 +73,7 @@ export default class extends ManifestBase { } protected buildPermissions(): Partial | undefined { - const permissions = Array.from(filterPermissionsForMV3(this.permissions)); + const permissions = Array.from(filterPermissionsForMV3(this.combinedPermissions)); if (permissions.length > 0) { return {permissions}; @@ -82,8 +82,8 @@ export default class extends ManifestBase { protected buildOptionalPermissions(): Partial | undefined { const optionalPermissions = filterOptionalPermissions( - filterPermissionsForMV3(this.optionalPermissions), - filterPermissionsForMV3(this.permissions) + filterPermissionsForMV3(this.combinedOptionalPermissions), + filterPermissionsForMV3(this.combinedPermissions) ); if (optionalPermissions.length > 0) { @@ -92,16 +92,16 @@ export default class extends ManifestBase { } protected buildHostPermissions(): Partial | undefined { - if (this.hostPermissions.size > 0) { - return {host_permissions: [...filterHostPatterns(this.hostPermissions)]}; + if (this.combinedHostPermissions.size > 0) { + return {host_permissions: [...filterHostPatterns(this.combinedHostPermissions)]}; } } protected buildOptionalHostPermissions(): Partial | undefined { // prettier-ignore const optionalHostPermissions = Array - .from(filterHostPatterns(new Set([...this.hostPermissions, ...this.optionalHostPermissions]))) - .filter((permission) => !this.hostPermissions.has(permission)); + .from(filterHostPatterns(new Set([...this.combinedHostPermissions, ...this.combinedOptionalHostPermissions]))) + .filter((permission) => !this.combinedHostPermissions.has(permission)); if (optionalHostPermissions.length > 0) { return {optional_host_permissions: optionalHostPermissions}; From 83db7c1979da8f91230c7be3381ad812edcf9db4 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Thu, 26 Feb 2026 23:01:03 +0200 Subject: [PATCH 03/20] refactor(manifest): streamline `combined*` methods for readability and maintainability --- src/cli/builders/manifest/ManifestBase.ts | 108 +++++++++++----------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/src/cli/builders/manifest/ManifestBase.ts b/src/cli/builders/manifest/ManifestBase.ts index dd1f9afb..7fb58066 100644 --- a/src/cli/builders/manifest/ManifestBase.ts +++ b/src/cli/builders/manifest/ManifestBase.ts @@ -82,6 +82,62 @@ export default abstract class implements ManifestBuilder protected abstract buildWebAccessibleResources(): Partial | undefined; + protected get combinedRaws(): OptionalManifest { + return this.mergedRaws ??= Array.from(this.raws).reduce((result, raw) => { + return _.mergeWith(result, raw, (objValue, srcValue) => { + if (Array.isArray(objValue) && Array.isArray(srcValue)) { + return objValue.concat(srcValue); + } + }); + }, {}); + } + + protected get combinedPermissions(): ManifestPermissions { + const result = new Set(this.permissions); + + if (this.combinedRaws.permissions) { + for (const permission of this.combinedRaws.permissions) { + result.add(permission); + } + } + + return result; + } + + protected get combinedOptionalPermissions(): ManifestOptionalPermissions { + const result = new Set(this.optionalPermissions); + + if (this.combinedRaws.optional_permissions) { + for (const permission of this.combinedRaws.optional_permissions) { + result.add(permission); + } + } + + return result; + } + + protected get combinedHostPermissions(): ManifestHostPermissions { + const result = new Set(this.hostPermissions); + + if (this.combinedRaws.host_permissions) { + for (const permission of this.combinedRaws.host_permissions) { + result.add(permission); + } + } + + return result; + } + + protected get combinedOptionalHostPermissions(): ManifestHostPermissions { + const result = new Set(this.optionalHostPermissions); + if (this.combinedRaws.optional_host_permissions) { + for (const permission of this.combinedRaws.optional_host_permissions) { + result.add(permission); + } + } + return result; + } + protected constructor(protected readonly browser: Browser = Browser.Chrome) {} public setAuthor(author?: string): this { @@ -340,59 +396,7 @@ export default abstract class implements ManifestBuilder return this.build(); } - protected get combinedRaws(): OptionalManifest { - if (this.mergedRaws) return this.mergedRaws; - - this.mergedRaws = Array.from(this.raws).reduce((result, raw) => { - return _.mergeWith(result, raw, (objValue, srcValue) => { - if (Array.isArray(objValue) && Array.isArray(srcValue)) { - return objValue.concat(srcValue); - } - }); - }, {}); - - return this.mergedRaws; - } - - protected get combinedPermissions(): ManifestPermissions { - const result = new Set(this.permissions); - if (this.combinedRaws.permissions) { - for (const permission of this.combinedRaws.permissions) { - result.add(permission); - } - } - return result; - } - - protected get combinedOptionalPermissions(): ManifestOptionalPermissions { - const result = new Set(this.optionalPermissions); - if (this.combinedRaws.optional_permissions) { - for (const permission of this.combinedRaws.optional_permissions) { - result.add(permission); - } - } - return result; - } - - protected get combinedHostPermissions(): ManifestHostPermissions { - const result = new Set(this.hostPermissions); - if (this.combinedRaws.host_permissions) { - for (const permission of this.combinedRaws.host_permissions) { - result.add(permission); - } - } - return result; - } - protected get combinedOptionalHostPermissions(): ManifestHostPermissions { - const result = new Set(this.optionalHostPermissions); - if (this.combinedRaws.optional_host_permissions) { - for (const permission of this.combinedRaws.optional_host_permissions) { - result.add(permission); - } - } - return result; - } private merge(...sources: Array | undefined>): T { sources = sources.filter(source => source !== undefined); From 78698181e38d46bf5c7600b0a1cd7ec660e4517f Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:57:45 +0200 Subject: [PATCH 04/20] chore: simplify documentation for `EntrypointOptions` by removing redundant notes --- src/cli/builders/manifest/ManifestBase.ts | 6 ++---- src/types/entrypoint.ts | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cli/builders/manifest/ManifestBase.ts b/src/cli/builders/manifest/ManifestBase.ts index 7fb58066..ed3fabdb 100644 --- a/src/cli/builders/manifest/ManifestBase.ts +++ b/src/cli/builders/manifest/ManifestBase.ts @@ -83,13 +83,13 @@ export default abstract class implements ManifestBuilder protected abstract buildWebAccessibleResources(): Partial | undefined; protected get combinedRaws(): OptionalManifest { - return this.mergedRaws ??= Array.from(this.raws).reduce((result, raw) => { + return (this.mergedRaws ??= Array.from(this.raws).reduce((result, raw) => { return _.mergeWith(result, raw, (objValue, srcValue) => { if (Array.isArray(objValue) && Array.isArray(srcValue)) { return objValue.concat(srcValue); } }); - }, {}); + }, {})); } protected get combinedPermissions(): ManifestPermissions { @@ -396,8 +396,6 @@ export default abstract class implements ManifestBuilder return this.build(); } - - private merge(...sources: Array | undefined>): T { sources = sources.filter(source => source !== undefined); diff --git a/src/types/entrypoint.ts b/src/types/entrypoint.ts index feaaa4dd..a9755ba5 100644 --- a/src/types/entrypoint.ts +++ b/src/types/entrypoint.ts @@ -20,15 +20,14 @@ export enum EntrypointType { export interface EntrypointOptions { /** * List of target browsers to include this entrypoint in. Defaults to being included in all - * builds. Cannot be used with `exclude`. You must choose one of the two options. + * builds. * * @default undefined */ includeBrowser?: `${Browser}`[] | Browser[]; /** - * List of target browsers to exclude this entrypoint from. Cannot be used with `include`. You - * must choose one of the two options. + * List of target browsers to exclude this entrypoint from. * * @default undefined */ @@ -36,15 +35,13 @@ export interface EntrypointOptions { /** * List of target apps to include this entrypoint in. Defaults to being included in all builds. - * Cannot be used with `excludeApp`. You must choose one of the two options. * * @default undefined */ excludeApp?: string[]; /** - * List of target apps to exclude this entrypoint from. Cannot be used with `includeApp`. You - * must choose one of the two options. + * List of target apps to exclude this entrypoint from. * * @default undefined */ From 9c1dbcf71ab99b70718694511c67814a800892bf Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:15:24 +0300 Subject: [PATCH 05/20] refactor(finder): improve sorting logic and enhance priority handling --- src/cli/entrypoint/finder/AbstractFinder.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cli/entrypoint/finder/AbstractFinder.ts b/src/cli/entrypoint/finder/AbstractFinder.ts index b587f5ea..25dc2319 100644 --- a/src/cli/entrypoint/finder/AbstractFinder.ts +++ b/src/cli/entrypoint/finder/AbstractFinder.ts @@ -57,7 +57,7 @@ export default abstract class implements EntrypointFinder { return priorityA - priorityB; } - return a.file.length - b.file.length; + return this.sortKey(a).localeCompare(this.sortKey(b)); }); return (this._files = new Set(files)); @@ -134,6 +134,12 @@ export default abstract class implements EntrypointFinder { } protected priority(file: EntrypointFile): number { - return _.findIndex(this.priorityDirectories, dir => file.file.includes(dir)); + const priority = _.findIndex(this.priorityDirectories, dir => file.file.includes(dir)); + + return priority >= 0 ? priority : this.priorityDirectories.length; + } + + protected sortKey(file: EntrypointFile): string { + return toPosixPath(file.import || file.file); } } From 4ae0c7b0df98256557d2c765485427734ea0af1a Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:28:01 +0300 Subject: [PATCH 06/20] refactor(finder): restructure file collection logic to support grouped and root entrypoints --- .../finder/AbstractEntrypointFinder.test.ts | 135 ++++++++++++++++++ .../finder/AbstractEntrypointFinder.ts | 41 +++--- 2 files changed, 159 insertions(+), 17 deletions(-) create mode 100644 src/cli/entrypoint/finder/AbstractEntrypointFinder.test.ts diff --git a/src/cli/entrypoint/finder/AbstractEntrypointFinder.test.ts b/src/cli/entrypoint/finder/AbstractEntrypointFinder.test.ts new file mode 100644 index 00000000..19ca6a51 --- /dev/null +++ b/src/cli/entrypoint/finder/AbstractEntrypointFinder.test.ts @@ -0,0 +1,135 @@ +import fs from "fs"; +import os from "os"; +import path from "path"; + +import AbstractEntrypointFinder from "./AbstractEntrypointFinder"; + +import {ReadonlyConfig} from "@typing/config"; +import {EntrypointFile, EntrypointOptions, EntrypointParser, EntrypointType} from "@typing/entrypoint"; + +class TestFinder extends AbstractEntrypointFinder { + public constructor() { + super({ + app: "app", + appsDir: "apps", + appSrcDir: ".", + debug: false, + rootDir: ".", + sharedDir: "shared", + srcDir: "src", + } as ReadonlyConfig); + } + + public type(): EntrypointType { + return EntrypointType.Background; + } + + public scan(directory: string): Set { + return this.findFiles(directory); + } + + protected getParser(): EntrypointParser { + return { + options: () => ({}), + contract: () => undefined, + }; + } +} + +const createTempDir = (): string => { + return fs.mkdtempSync(path.join(os.tmpdir(), "adnbn-entrypoint-finder-")); +}; + +const touch = (file: string): void => { + fs.mkdirSync(path.dirname(file), {recursive: true}); + fs.writeFileSync(file, "export {};\n"); +}; + +const relativeFiles = (root: string, files: Set): string[] => { + return Array.from(files, ({file}) => path.relative(root, file)).sort(); +}; + +describe("AbstractEntrypointFinder", () => { + test("uses grouped entrypoint directory instead of root-level entrypoint files", () => { + const root = createTempDir(); + + try { + touch(path.join(root, "background.ts")); + touch(path.join(root, "analytics.background.ts")); + touch(path.join(root, "backgrounds", "main.background.ts")); + touch(path.join(root, "backgrounds", "sync.background", "index.ts")); + + const files = new TestFinder().scan(root); + + expect(relativeFiles(root, files)).toEqual([ + "backgrounds/main.background.ts", + "backgrounds/sync.background/index.ts", + ]); + } finally { + fs.rmSync(root, {force: true, recursive: true}); + } + }); + + test("uses root-level entrypoint files when grouped directory has no entrypoints", () => { + const root = createTempDir(); + + try { + fs.mkdirSync(path.join(root, "backgrounds"), {recursive: true}); + touch(path.join(root, "background.ts")); + touch(path.join(root, "analytics.background.ts")); + + const files = new TestFinder().scan(root); + + expect(relativeFiles(root, files)).toEqual(["analytics.background.ts", "background.ts"]); + } finally { + fs.rmSync(root, {force: true, recursive: true}); + } + }); + + test("uses singular entrypoint directory when grouped and root-level entrypoints are missing", () => { + const root = createTempDir(); + + try { + touch(path.join(root, "background", "index.ts")); + + const files = new TestFinder().scan(root); + + expect(relativeFiles(root, files)).toEqual(["background/index.ts"]); + } finally { + fs.rmSync(root, {force: true, recursive: true}); + } + }); + + test("uses grouped entrypoint directory instead of singular entrypoint directory", () => { + const root = createTempDir(); + + try { + touch(path.join(root, "backgrounds", "main.background.ts")); + touch(path.join(root, "background", "index.ts")); + + const files = new TestFinder().scan(root); + + expect(relativeFiles(root, files)).toEqual(["backgrounds/main.background.ts"]); + } finally { + fs.rmSync(root, {force: true, recursive: true}); + } + }); + + test("uses root-level entrypoint directories when grouped directory is missing", () => { + const root = createTempDir(); + + try { + touch(path.join(root, "analytics.background", "index.ts")); + touch(path.join(root, "tracking.background", "index.ts")); + + const files = new TestFinder().scan(root); + + expect(relativeFiles(root, files)).toEqual([ + "analytics.background/index.ts", + "tracking.background/index.ts", + ]); + } finally { + fs.rmSync(root, {force: true, recursive: true}); + } + }); +}); diff --git a/src/cli/entrypoint/finder/AbstractEntrypointFinder.ts b/src/cli/entrypoint/finder/AbstractEntrypointFinder.ts index 1dfd1bac..6d0f1d07 100644 --- a/src/cli/entrypoint/finder/AbstractEntrypointFinder.ts +++ b/src/cli/entrypoint/finder/AbstractEntrypointFinder.ts @@ -60,9 +60,10 @@ export default abstract class extends AbstractOptio const entrypoint = this.type(); const entrypointPluralize = pluralize(entrypoint); - const files: EntrypointFile[] = []; + const rootFiles: EntrypointFile[] = []; + const groupedFiles: EntrypointFile[] = []; - const finder = (dir: string): void => { + const collect = (dir: string, files: EntrypointFile[], collectGrouped: boolean): void => { let entries: Dirent[]; try { @@ -97,8 +98,8 @@ export default abstract class extends AbstractOptio } } } - } else if (entry.name === entrypointPluralize) { - finder(fullPath); + } else if (collectGrouped && entry.name === entrypointPluralize) { + collect(fullPath, groupedFiles, false); } } else if (entry.isFile() && this.isValidFilename(entry.name)) { files.push(this.file(fullPath)); @@ -106,25 +107,31 @@ export default abstract class extends AbstractOptio } }; - finder(directory); + collect(directory, rootFiles, true); - if (files.length === 0) { - try { - directory = path.join(directory, entrypoint); + if (groupedFiles.length > 0) { + return new Set(groupedFiles); + } - const stat = fs.statSync(directory); + if (rootFiles.length > 0) { + return new Set(rootFiles); + } - if (stat.isDirectory()) { - finder(directory); - } - } catch (e) { - if (this.config.debug) { - console.log("Error reading entrypoint directory:", directory); - } + try { + directory = path.join(directory, entrypoint); + + const stat = fs.statSync(directory); + + if (stat.isDirectory()) { + collect(directory, rootFiles, false); + } + } catch (e) { + if (this.config.debug) { + console.log("Error reading entrypoint directory:", directory); } } - return new Set(files); + return new Set(rootFiles); } protected isValidFilename(filename: string): boolean { From 0ff5c346623e5a1a402b08fcae9dc5c02b7abedf Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Thu, 30 Apr 2026 21:12:24 +0300 Subject: [PATCH 07/20] feat(config): add `shared` option for configurable shared source layer - Introduced `shared` option to configure shared directories as `false`, `true`, or a custom string. - Added tests to validate behavior for all `shared` option cases. - Updated type definitions to document the new `shared` configuration. --- src/cli/resolvers/config.test.ts | 84 ++++++++++++++++++++++++++++++++ src/cli/resolvers/config.ts | 18 +++++-- src/types/config.ts | 13 ++++- 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/cli/resolvers/config.test.ts diff --git a/src/cli/resolvers/config.test.ts b/src/cli/resolvers/config.test.ts new file mode 100644 index 00000000..93351020 --- /dev/null +++ b/src/cli/resolvers/config.test.ts @@ -0,0 +1,84 @@ +jest.mock("../plugins", () => { + const plugin = (name: string) => () => ({name}); + + return { + pluginAsset: plugin("asset"), + pluginBackground: plugin("background"), + pluginBundler: plugin("bundler"), + pluginContent: plugin("content"), + pluginDotenv: plugin("dotenv"), + pluginHtml: plugin("html"), + pluginIcon: plugin("icon"), + pluginLocale: plugin("locale"), + pluginManifest: plugin("manifest"), + pluginMeta: plugin("meta"), + pluginOffscreen: plugin("offscreen"), + pluginOptimization: plugin("optimization"), + pluginOutput: plugin("output"), + pluginPage: plugin("page"), + pluginPopup: plugin("popup"), + pluginPublic: plugin("public"), + pluginReact: plugin("react"), + pluginSidebar: plugin("sidebar"), + pluginStyle: plugin("style"), + pluginTypescript: plugin("typescript"), + pluginVersion: plugin("version"), + pluginView: plugin("view"), + }; +}); + +jest.mock("c12", () => ({ + loadConfig: jest.fn(), +})); + +import {loadConfig} from "c12"; + +import resolveConfig from "./config"; + +const mockedLoadConfig = jest.mocked(loadConfig); + +describe("config resolver", () => { + beforeEach(() => { + mockedLoadConfig.mockResolvedValue({config: {}}); + }); + + test("uses source directory as shared layer by default", async () => { + const config = await resolveConfig({configFile: "package.json"}); + + expect(config.shared).toBe(false); + expect(config.sharedDir).toBe("."); + }); + + test("uses default shared directory when shared is true", async () => { + const config = await resolveConfig({ + configFile: "package.json", + shared: true, + }); + + expect(config.shared).toBe(true); + expect(config.sharedDir).toBe("shared"); + }); + + test("uses custom shared directory when shared is a string", async () => { + const config = await resolveConfig({ + configFile: "package.json", + shared: "common", + }); + + expect(config.shared).toBe("common"); + expect(config.sharedDir).toBe("common"); + }); + + test("normalizes shared directory after loading user config", async () => { + mockedLoadConfig.mockResolvedValue({ + config: { + shared: true, + }, + }); + + const config = await resolveConfig({configFile: "package.json"}); + + expect(config.shared).toBe(true); + expect(config.sharedDir).toBe("shared"); + }); +}); diff --git a/src/cli/resolvers/config.ts b/src/cli/resolvers/config.ts index d2800b7d..fea043ef 100644 --- a/src/cli/resolvers/config.ts +++ b/src/cli/resolvers/config.ts @@ -177,10 +177,10 @@ export default async (config: OptionalConfig): Promise => { lang = Language.English, incognito, specific, + shared = false, rootDir = ".", outDir = "dist", srcDir = "src", - sharedDir = "shared", appsDir = "apps", appSrcDir = ".", localeDir = "locales", @@ -250,10 +250,11 @@ export default async (config: OptionalConfig): Promise => { specific, manifest, manifestVersion, + shared, rootDir, outDir, srcDir, - sharedDir, + sharedDir: _.isString(shared) ? shared : shared ? "shared" : ".", appsDir, appSrcDir, jsDir, @@ -298,7 +299,18 @@ export default async (config: OptionalConfig): Promise => { const {plugins: userPlugins = [], ...userConfig} = await getUserConfig(resolvedConfig); - resolvedConfig = validateConfig({...resolvedConfig, ...userConfig}); + resolvedConfig = { + ...resolvedConfig, + ...userConfig, + }; + + resolvedConfig.sharedDir = _.isString(resolvedConfig.shared) + ? resolvedConfig.shared + : resolvedConfig.shared + ? "shared" + : "."; + + resolvedConfig = validateConfig(resolvedConfig); vars = {...vars, ...loadDotenv(resolvedConfig)}; diff --git a/src/types/config.ts b/src/types/config.ts index ada3e2ad..dcd79751 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -197,6 +197,17 @@ export interface Config { */ lang?: string | Language; + /** + * Shared source layer configuration. + * + * - `false` uses the source directory itself as the shared layer. + * - `true` uses the default `shared` directory. + * - a string uses a custom shared directory name. + * + * @default false + */ + shared: boolean | string; + /** * Path to the directory with source files for building. * This is the base directory relative to which other paths are defined. @@ -714,7 +725,7 @@ export interface Config { } export type OptionalConfig = Partial; -export type UserConfig = Omit; +export type UserConfig = Omit; export type ReadonlyConfig = Readonly; export type UserConfigCallback = (config: ReadonlyConfig) => UserConfig; From c0e9464ff21fa428de2343b758e4184651ec6d89 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Fri, 1 May 2026 00:21:11 +0300 Subject: [PATCH 08/20] refactor(command): enhance shortcut key validation and add tests for CommandParser - Refined shortcut key validation, supporting media and platform-specific keys. - Added stricter global shortcut constraints and error messaging improvements. - Introduced comprehensive tests to ensure robust validation logic. --- .../entrypoint/parser/CommandParser.test.ts | 113 ++++++++++++++++++ src/cli/entrypoint/parser/CommandParser.ts | 35 +++++- 2 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 src/cli/entrypoint/parser/CommandParser.test.ts diff --git a/src/cli/entrypoint/parser/CommandParser.test.ts b/src/cli/entrypoint/parser/CommandParser.test.ts new file mode 100644 index 00000000..79e09023 --- /dev/null +++ b/src/cli/entrypoint/parser/CommandParser.test.ts @@ -0,0 +1,113 @@ +import fs from "fs"; +import os from "os"; +import path from "path"; + +import CommandParser from "./CommandParser"; + +import type {ReadonlyConfig} from "@typing/config"; + +jest.mock("../file/resolvers", () => { + class TsResolver { + public static make(): TsResolver { + return new TsResolver(); + } + + public get matchPath(): {(_path: string): string | undefined} { + return () => undefined; + } + } + + class ImportResolver { + public setBaseDir(): this { + return this; + } + + public get(importPath: string): string { + return importPath; + } + } + + return {ImportResolver, TsResolver}; +}); + +const rootDir = path.resolve(__dirname, "../../../.."); + +const parse = (source: string) => { + const directory = fs.mkdtempSync(path.join(os.tmpdir(), "adnbn-command-parser-")); + const file = path.join(directory, "test.command.ts"); + + fs.writeFileSync(file, source); + + return new CommandParser({rootDir} as ReadonlyConfig).options({file, import: file}); +}; + +const parseError = (source: string): Error => { + try { + parse(source); + } catch (error) { + return error as Error; + } + + throw new Error("Expected command parser to throw"); +}; + +const command = (options: string) => ` +import {defineCommand} from "adnbn"; + +export default defineCommand({ + ${options}, + execute() {}, +}); +`; + +describe("CommandParser", () => { + test("accepts browser command shortcuts", () => { + const options = parse( + command(` + defaultKey: "Ctrl+Shift+Y", + windowsKey: "Alt+Shift+U", + linuxKey: "Ctrl+F12", + chromeosKey: "MediaPlayPause" + `) + ); + + expect(options.defaultKey).toBe("Ctrl+Shift+Y"); + expect(options.windowsKey).toBe("Alt+Shift+U"); + expect(options.linuxKey).toBe("Ctrl+F12"); + expect(options.chromeosKey).toBe("MediaPlayPause"); + }); + + test("accepts macOS-specific command modifiers only for macKey", () => { + const options = parse( + command(` + defaultKey: "Ctrl+Shift+Y", + macKey: "Command+Shift+P" + `) + ); + + expect(options.macKey).toBe("Command+Shift+P"); + + expect(() => parse(command(`defaultKey: "Command+Shift+P"`))).toThrow("Invalid shortcut key"); + expect(() => parse(command(`linuxKey: "Option+Shift+U"`))).toThrow("Invalid shortcut key"); + }); + + test("rejects modifiers with media keys", () => { + expect(() => parse(command(`defaultKey: "Ctrl+MediaPlayPause"`))).toThrow("Invalid shortcut key"); + }); + + test("includes file path when no suggested key is defined", () => { + const error = parseError(command(`name: "missing-key"`)); + + expect(error.message).toContain("At least one suggested key must be defined"); + expect(error.message).toContain("test.command.ts"); + }); + + test("requires Chrome global command shortcuts to use Ctrl+Shift+[0..9]", () => { + expect(parse(command(`global: true, defaultKey: "Ctrl+Shift+5"`)).defaultKey).toBe("Ctrl+Shift+5"); + + const error = parseError(command(`global: true, defaultKey: "Ctrl+Shift+Y"`)); + + expect(error.message).toContain("must use Ctrl+Shift+[0..9]"); + expect(error.message).toContain("test.command.ts"); + }); +}); diff --git a/src/cli/entrypoint/parser/CommandParser.ts b/src/cli/entrypoint/parser/CommandParser.ts index bb85dc26..2a44c96a 100644 --- a/src/cli/entrypoint/parser/CommandParser.ts +++ b/src/cli/entrypoint/parser/CommandParser.ts @@ -13,11 +13,24 @@ export default class extends BackgroundParser { } protected schema(): typeof this.CommonPropertiesSchema { + const key = + "(?:[A-Z0-9]|F(?:[1-9]|1[0-2])|Comma|Period|Home|End|PageUp|PageDown|Space|Insert|Delete|Up|Down|Left|Right)"; + const mediaKey = "(?:MediaNextTrack|MediaPlayPause|MediaPrevTrack|MediaStop)"; + const shortcutMessage = + "Invalid shortcut key, expected format like: Ctrl+Shift+K, Alt+Shift+U, or MediaPlayPause"; + const macShortcutMessage = + "Invalid mac shortcut key, expected format like: Command+Shift+P, MacCtrl+K, Option+Shift+U, or MediaPlayPause"; + const ShortcutKeySchema = z + .string() + .regex(new RegExp(`^(?:(?:Ctrl|Alt)(?:\\+Shift)?\\+${key}|${mediaKey})$`), shortcutMessage) + .optional(); + + const MacShortcutKeySchema = z .string() .regex( - /^(Ctrl|Command|MacCtrl|Alt|Option)(\+Shift)?\+[A-Z0-9]$/, - "Invalid shortcut key, expected format like: Ctrl+Shift+K or Command+Shift+P" + new RegExp(`^(?:(?:Ctrl|Alt|Command|MacCtrl|Option)(?:\\+Shift)?\\+${key}|${mediaKey})$`), + macShortcutMessage ) .optional(); @@ -27,7 +40,7 @@ export default class extends BackgroundParser { global: z.boolean().optional(), defaultKey: ShortcutKeySchema, windowsKey: ShortcutKeySchema, - macKey: ShortcutKeySchema, + macKey: MacShortcutKeySchema, chromeosKey: ShortcutKeySchema, linuxKey: ShortcutKeySchema, }); @@ -37,7 +50,21 @@ export default class extends BackgroundParser { const {defaultKey, windowsKey, macKey, chromeosKey, linuxKey, ...options} = super.options(file); if (!defaultKey && !windowsKey && !macKey && !chromeosKey && !linuxKey) { - throw new Error("Invalid command options: At least one suggested key must be defined"); + throw new Error( + `Invalid command options in "${file.file}": At least one suggested key must be defined` + ); + } + + if (options.global) { + const globalShortcut = /^Ctrl\+Shift\+[0-9]$/; + const keys = {defaultKey, windowsKey, macKey, chromeosKey, linuxKey}; + const invalidKey = Object.entries(keys).find(([, key]) => key && !globalShortcut.test(key)); + + if (invalidKey) { + throw new Error( + `Invalid command options in "${file.file}": Global command shortcut "${invalidKey[1]}" in "${invalidKey[0]}" must use Ctrl+Shift+[0..9]` + ); + } } return { From c02a4ddb06d8639817b44ed2924cc1f82539ae83 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Fri, 1 May 2026 00:28:47 +0300 Subject: [PATCH 09/20] fix(command): simplify error message for invalid command key options --- src/cli/entrypoint/parser/CommandParser.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cli/entrypoint/parser/CommandParser.ts b/src/cli/entrypoint/parser/CommandParser.ts index 2a44c96a..fdaf8fbe 100644 --- a/src/cli/entrypoint/parser/CommandParser.ts +++ b/src/cli/entrypoint/parser/CommandParser.ts @@ -50,9 +50,7 @@ export default class extends BackgroundParser { const {defaultKey, windowsKey, macKey, chromeosKey, linuxKey, ...options} = super.options(file); if (!defaultKey && !windowsKey && !macKey && !chromeosKey && !linuxKey) { - throw new Error( - `Invalid command options in "${file.file}": At least one suggested key must be defined` - ); + throw new Error(`Invalid command options in "${file.file}": At least one suggested key must be defined`); } if (options.global) { From 7864487f8fde6d37282047fc19dde2f5d964e825 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 2 May 2026 16:21:50 +0300 Subject: [PATCH 10/20] perf(build): enable separate TypeScript declaration file generation --- package-lock.json | 4762 +++++++++++++++++++++++-------------------- package.json | 10 +- tsconfig.build.json | 20 + tsup.config.ts | 2 +- 4 files changed, 2523 insertions(+), 2271 deletions(-) create mode 100644 tsconfig.build.json diff --git a/package-lock.json b/package-lock.json index c4f7b477..493756ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,6 +79,7 @@ "prettier": "^3.6.2", "release-it": "^19.2.3", "ts-node": "^1.7.1", + "tsc-alias": "^1.8.17", "tsup": "^8.5.0", "tsx": "^4.19.2", "uglify-js": "^3.19.3", @@ -165,23 +166,23 @@ "license": "MIT" }, "node_modules/@asamuzakjp/css-color": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.1.tgz", - "integrity": "sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", + "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.4", - "@csstools/css-color-parser": "^3.1.0", - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4", - "lru-cache": "^11.2.4" + "@csstools/css-calc": "^3.0.0", + "@csstools/css-color-parser": "^4.0.1", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.2.5" } }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -189,9 +190,9 @@ } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.7.tgz", - "integrity": "sha512-8CO/UQ4tzDd7ula+/CVimJIVWez99UJlbMyIgk8xOnhAVPKLnBZmUFYVgugS441v2ZqUq5EnSh6B0Ua0liSFAA==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -199,13 +200,13 @@ "bidi-js": "^1.0.3", "css-tree": "^3.1.0", "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.5" + "lru-cache": "^11.2.6" } }, "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -234,9 +235,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -296,9 +297,9 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.0.tgz", - "integrity": "sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==", + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.0", @@ -349,9 +350,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz", + "integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -359,7 +360,7 @@ "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/traverse": "^7.29.0", "semver": "^6.3.1" }, "engines": { @@ -405,9 +406,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", @@ -582,22 +583,22 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -655,6 +656,22 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", @@ -1872,18 +1889,19 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", - "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.3.tgz", + "integrity": "sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.29.0", + "@babel/compat-data": "^7.29.3", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", @@ -2018,9 +2036,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "dev": true, "license": "MIT", "engines": { @@ -2108,17 +2126,17 @@ "license": "MIT" }, "node_modules/@commitlint/cli": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.4.1.tgz", - "integrity": "sha512-uuFKKpc7OtQM+6SRqT+a4kV818o1pS+uvv/gsRhyX7g4x495jg+Q7P0+O9VNGyLXBYP0syksS7gMRDJKcekr6A==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.3.tgz", + "integrity": "sha512-OJdL0EXWD5y9LPa0nr/geOwzaS8BsdaybKkcloB0JgsguGxNv2R+hC2FTPqrAcprg35zF33KOQerY0x8W1aesA==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/format": "^20.4.0", - "@commitlint/lint": "^20.4.1", - "@commitlint/load": "^20.4.0", - "@commitlint/read": "^20.4.0", - "@commitlint/types": "^20.4.0", + "@commitlint/format": "^20.5.0", + "@commitlint/lint": "^20.5.3", + "@commitlint/load": "^20.5.3", + "@commitlint/read": "^20.5.0", + "@commitlint/types": "^20.5.0", "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, @@ -2130,27 +2148,27 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.4.1.tgz", - "integrity": "sha512-0YUvIeBtpi86XriqrR+TCULVFiyYTIOEPjK7tTRMxjcBm1qlzb+kz7IF2WxL6Fq5DaundG8VO37BNgMkMTBwqA==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.3.tgz", + "integrity": "sha512-j34Qqeaa152chJgz2ysyk0BCpHenJn1lV0Rx0VXf8k3ccQcED+48EZrzMvo9jLmJUyBrrBwvu89I+2er4gW7QQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", - "conventional-changelog-conventionalcommits": "^9.1.0" + "@commitlint/types": "^20.5.0", + "conventional-changelog-conventionalcommits": "^9.2.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/config-validator": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.4.0.tgz", - "integrity": "sha512-zShmKTF+sqyNOfAE0vKcqnpvVpG0YX8F9G/ZIQHI2CoKyK+PSdladXMSns400aZ5/QZs+0fN75B//3Q5CHw++w==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.5.0.tgz", + "integrity": "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", + "@commitlint/types": "^20.5.0", "ajv": "^8.11.0" }, "engines": { @@ -2158,18 +2176,14 @@ } }, "node_modules/@commitlint/ensure": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.4.1.tgz", - "integrity": "sha512-WLQqaFx1pBooiVvBrA1YfJNFqZF8wS/YGOtr5RzApDbV9tQ52qT5VkTsY65hFTnXhW8PcDfZLaknfJTmPejmlw==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.3.tgz", + "integrity": "sha512-4i4AgNvH62owG9MwSiWKrle7HGNpBHHdLnWFIp5fTsHUYe5kRuh15t08L/0pdbbrRk8JKXQxxN4hZQcn+szkrw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" + "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0" }, "engines": { "node": ">=v18" @@ -2186,13 +2200,13 @@ } }, "node_modules/@commitlint/format": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.4.0.tgz", - "integrity": "sha512-i3ki3WR0rgolFVX6r64poBHXM1t8qlFel1G1eCBvVgntE3fCJitmzSvH5JD/KVJN/snz6TfaX2CLdON7+s4WVQ==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.5.0.tgz", + "integrity": "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", + "@commitlint/types": "^20.5.0", "picocolors": "^1.1.1" }, "engines": { @@ -2200,13 +2214,13 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.4.1.tgz", - "integrity": "sha512-In5EO4JR1lNsAv1oOBBO24V9ND1IqdAJDKZiEpdfjDl2HMasAcT7oA+5BKONv1pRoLG380DGPE2W2RIcUwdgLA==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.5.0.tgz", + "integrity": "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", + "@commitlint/types": "^20.5.0", "semver": "^7.6.0" }, "engines": { @@ -2214,36 +2228,36 @@ } }, "node_modules/@commitlint/lint": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.4.1.tgz", - "integrity": "sha512-g94LrGl/c6UhuhDQqNqU232aslLEN2vzc7MPfQTHzwzM4GHNnEAwVWWnh0zX8S5YXecuLXDwbCsoGwmpAgPWKA==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.3.tgz", + "integrity": "sha512-M7JbWBNr2gXKaPc4i/KipsuW1gkDHpj35KPjWtKy3Z+2AQw5wu1gBi1LIO0uoaij67CqY4K8PxPZSGens4evCw==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^20.4.1", - "@commitlint/parse": "^20.4.1", - "@commitlint/rules": "^20.4.1", - "@commitlint/types": "^20.4.0" + "@commitlint/is-ignored": "^20.5.0", + "@commitlint/parse": "^20.5.0", + "@commitlint/rules": "^20.5.3", + "@commitlint/types": "^20.5.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.4.0.tgz", - "integrity": "sha512-Dauup/GfjwffBXRJUdlX/YRKfSVXsXZLnINXKz0VZkXdKDcaEILAi9oflHGbfydonJnJAbXEbF3nXPm9rm3G6A==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.3.tgz", + "integrity": "sha512-1FDZWuKyu98Myb8i7Tp31jPU2rZpOwAdYRyJcy2KoGg7Xk2A+bgHN8smhMaaNSNkmE8fwt53BokywZq8Gv/5XQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^20.4.0", + "@commitlint/config-validator": "^20.5.0", "@commitlint/execute-rule": "^20.0.0", - "@commitlint/resolve-extends": "^20.4.0", - "@commitlint/types": "^20.4.0", - "cosmiconfig": "^9.0.0", + "@commitlint/resolve-extends": "^20.5.3", + "@commitlint/types": "^20.5.0", + "cosmiconfig": "^9.0.1", "cosmiconfig-typescript-loader": "^6.1.0", + "es-toolkit": "^1.46.0", "is-plain-obj": "^4.1.0", - "lodash.mergewith": "^4.6.2", "picocolors": "^1.1.1" }, "engines": { @@ -2251,9 +2265,9 @@ } }, "node_modules/@commitlint/message": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.0.tgz", - "integrity": "sha512-B5lGtvHgiLAIsK5nLINzVW0bN5hXv+EW35sKhYHE8F7V9Uz1fR4tx3wt7mobA5UNhZKUNgB/+ldVMQE6IHZRyA==", + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.4.3.tgz", + "integrity": "sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==", "dev": true, "license": "MIT", "engines": { @@ -2261,30 +2275,30 @@ } }, "node_modules/@commitlint/parse": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.4.1.tgz", - "integrity": "sha512-XNtZjeRcFuAfUnhYrCY02+mpxwY4OmnvD3ETbVPs25xJFFz1nRo/25nHj+5eM+zTeRFvWFwD4GXWU2JEtoK1/w==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.5.0.tgz", + "integrity": "sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/types": "^20.4.0", - "conventional-changelog-angular": "^8.1.0", - "conventional-commits-parser": "^6.2.1" + "@commitlint/types": "^20.5.0", + "conventional-changelog-angular": "^8.2.0", + "conventional-commits-parser": "^6.3.0" }, "engines": { "node": ">=v18" } }, "node_modules/@commitlint/read": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.4.0.tgz", - "integrity": "sha512-QfpFn6/I240ySEGv7YWqho4vxqtPpx40FS7kZZDjUJ+eHxu3azfhy7fFb5XzfTqVNp1hNoI3tEmiEPbDB44+cg==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.5.0.tgz", + "integrity": "sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/top-level": "^20.4.0", - "@commitlint/types": "^20.4.0", - "git-raw-commits": "^4.0.0", + "@commitlint/top-level": "^20.4.3", + "@commitlint/types": "^20.5.0", + "git-raw-commits": "^5.0.0", "minimist": "^1.2.8", "tinyexec": "^1.0.0" }, @@ -2293,17 +2307,17 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.4.0.tgz", - "integrity": "sha512-ay1KM8q0t+/OnlpqXJ+7gEFQNlUtSU5Gxr8GEwnVf2TPN3+ywc5DzL3JCxmpucqxfHBTFwfRMXxPRRnR5Ki20g==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.3.tgz", + "integrity": "sha512-+ogW9v/u9JqpvAgTrLra/YTFo0KkjU6iNblF89pPsj4NebNc+DAWctsludwezI8YnsjBmfHpApSwcXprN/f/ew==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/config-validator": "^20.4.0", - "@commitlint/types": "^20.4.0", - "global-directory": "^4.0.1", + "@commitlint/config-validator": "^20.5.0", + "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0", + "global-directory": "^5.0.0", "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0" }, "engines": { @@ -2311,16 +2325,16 @@ } }, "node_modules/@commitlint/rules": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.4.1.tgz", - "integrity": "sha512-WtqypKEPbQEuJwJS4aKs0OoJRBKz1HXPBC9wRtzVNH68FLhPWzxXlF09hpUXM9zdYTpm4vAdoTGkWiBgQ/vL0g==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.3.tgz", + "integrity": "sha512-MPlMnb9D3wbszYMp+1hPtuhtPJndRo6I6yfkZVA4+jR8w7Kqp0u2u/Y+gzbaItx5Lltq5rw7FSZQWJMoXUC4NQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^20.4.1", - "@commitlint/message": "^20.4.0", + "@commitlint/ensure": "^20.5.3", + "@commitlint/message": "^20.4.3", "@commitlint/to-lines": "^20.0.0", - "@commitlint/types": "^20.4.0" + "@commitlint/types": "^20.5.0" }, "engines": { "node": ">=v18" @@ -2337,9 +2351,9 @@ } }, "node_modules/@commitlint/top-level": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.0.tgz", - "integrity": "sha512-NDzq8Q6jmFaIIBC/GG6n1OQEaHdmaAAYdrZRlMgW6glYWGZ+IeuXmiymDvQNXPc82mVxq2KiE3RVpcs+1OeDeA==", + "version": "20.4.3", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.4.3.tgz", + "integrity": "sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2350,13 +2364,13 @@ } }, "node_modules/@commitlint/types": { - "version": "20.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.4.0.tgz", - "integrity": "sha512-aO5l99BQJ0X34ft8b0h7QFkQlqxC6e7ZPVmBKz13xM9O8obDaM1Cld4sQlJDXXU/VFuUzQ30mVtHjVz74TuStw==", + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.5.0.tgz", + "integrity": "sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA==", "dev": true, "license": "MIT", "dependencies": { - "conventional-commits-parser": "^6.2.1", + "conventional-commits-parser": "^6.3.0", "picocolors": "^1.1.1" }, "engines": { @@ -2364,14 +2378,14 @@ } }, "node_modules/@conventional-changelog/git-client": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.5.1.tgz", - "integrity": "sha512-lAw7iA5oTPWOLjiweb7DlGEMDEvzqzLLa6aWOly2FSZ64IwLE8T458rC+o+WvI31Doz6joM7X2DoNog7mX8r4A==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.7.0.tgz", + "integrity": "sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==", "dev": true, "license": "MIT", "dependencies": { "@simple-libs/child-process-utils": "^1.0.0", - "@simple-libs/stream-utils": "^1.1.0", + "@simple-libs/stream-utils": "^1.2.0", "semver": "^7.5.2" }, "engines": { @@ -2379,7 +2393,7 @@ }, "peerDependencies": { "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.1.0" + "conventional-commits-parser": "^6.4.0" }, "peerDependenciesMeta": { "conventional-commits-filter": { @@ -2394,10 +2408,8 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -2409,19 +2421,17 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@csstools/color-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", - "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", "dev": true, "funding": [ { @@ -2435,13 +2445,13 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz", + "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==", "dev": true, "funding": [ { @@ -2455,17 +2465,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", - "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.0.tgz", + "integrity": "sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==", "dev": true, "funding": [ { @@ -2479,21 +2489,21 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.0" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -2507,16 +2517,16 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.26.tgz", - "integrity": "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz", + "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==", "dev": true, "funding": [ { @@ -2528,12 +2538,20 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT-0" + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -2547,7 +2565,7 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@discoveryjs/json-ext": { @@ -2560,20 +2578,20 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "license": "MIT", "optional": true, "dependencies": { @@ -2581,9 +2599,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "license": "MIT", "optional": true, "dependencies": { @@ -3032,9 +3050,9 @@ } }, "node_modules/@exodus/bytes": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.11.0.tgz", - "integrity": "sha512-wO3vd8nsEHdumsXrjGO/v4p6irbg7hy9kvIeR6i2AwylZSk4HJdWgL0FNaVquW1+AweJcdvU1IEpuIWk/WaPnA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", "dev": true, "license": "MIT", "engines": { @@ -3412,27 +3430,6 @@ } } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", - "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3475,9 +3472,9 @@ } }, "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", "dev": true, "license": "MIT", "engines": { @@ -3485,17 +3482,17 @@ } }, "node_modules/@jest/console": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", - "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz", + "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -3531,19 +3528,19 @@ } }, "node_modules/@jest/console/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -3552,27 +3549,27 @@ } }, "node_modules/@jest/console/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/console/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -3583,9 +3580,9 @@ } }, "node_modules/@jest/console/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3615,39 +3612,38 @@ } }, "node_modules/@jest/core": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", - "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz", + "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", + "@jest/console": "30.3.0", "@jest/pattern": "30.0.1", - "@jest/reporters": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/reporters": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.2.0", - "jest-config": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", + "jest-changed-files": "30.3.0", + "jest-config": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-resolve-dependencies": "30.2.0", - "jest-runner": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "jest-watcher": "30.2.0", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "jest-resolve": "30.3.0", + "jest-resolve-dependencies": "30.3.0", + "jest-runner": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", + "jest-watcher": "30.3.0", + "pretty-format": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -3694,43 +3690,40 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, + "extraneous": true, "license": "BSD-3-Clause", - "optional": true, - "peer": true, "engines": { "node": ">=0.3.1" } }, "node_modules/@jest/core/node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", + "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", + "@jest/test-sequencer": "30.3.0", + "@jest/types": "30.3.0", + "babel-jest": "30.3.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", + "jest-circus": "30.3.0", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", + "jest-environment-node": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", + "jest-resolve": "30.3.0", + "jest-runner": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "parse-json": "^5.2.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3755,19 +3748,19 @@ } }, "node_modules/@jest/core/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -3776,27 +3769,27 @@ } }, "node_modules/@jest/core/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/core/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -3807,9 +3800,9 @@ } }, "node_modules/@jest/core/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3838,14 +3831,25 @@ "node": ">=8" } }, + "node_modules/@jest/core/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@jest/core/node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -3888,31 +3892,29 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=6" } }, "node_modules/@jest/create-cache-key-function": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-30.2.0.tgz", - "integrity": "sha512-44F4l4Enf+MirJN8X/NhdGkl71k5rBYiwdVlo4HxOwbu0sHV8QKrGEedb1VUU4K3W7fBKE0HGfbn7eZm0Ti3zg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-30.3.0.tgz", + "integrity": "sha512-hTupmOWylzeyqbMNeSNi7ZDprpjrcroAOOG+qCEW66st3+Z5RnYHVYkUt+zjIcLmrTUi2lPY79hJz8mB3L2oXQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0" + "@jest/types": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz", + "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==", "dev": true, "license": "MIT", "engines": { @@ -3920,35 +3922,35 @@ } }, "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz", + "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0" + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/environment-jsdom-abstract": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.2.0.tgz", - "integrity": "sha512-kazxw2L9IPuZpQ0mEt9lu9Z98SqR74xcagANmMBU16X0lS23yPc0+S6hGLUz8kVRlomZEs/5S/Zlpqwf5yu6OQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.3.0.tgz", + "integrity": "sha512-0hNFs5N6We3DMCwobzI0ydhkY10sT1tZSC0AAiy+0g2Dt/qEWgrcV5BrMxPczhe41cxW4qm6X+jqZaUdpZIajA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/jsdom": "^21.1.7", "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -3964,27 +3966,27 @@ } }, "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/environment-jsdom-abstract/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -3995,14 +3997,14 @@ } }, "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "expect": "30.3.0", + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4037,9 +4039,9 @@ } }, "node_modules/@jest/expect/node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { @@ -4063,69 +4065,69 @@ } }, "node_modules/@jest/expect/node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4134,27 +4136,27 @@ } }, "node_modules/@jest/expect/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -4165,9 +4167,9 @@ } }, "node_modules/@jest/expect/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4197,18 +4199,18 @@ } }, "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz", + "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", + "@jest/types": "30.3.0", + "@sinonjs/fake-timers": "^15.0.0", "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4243,19 +4245,19 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4264,27 +4266,27 @@ } }, "node_modules/@jest/fake-timers/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/fake-timers/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -4295,9 +4297,9 @@ } }, "node_modules/@jest/fake-timers/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4337,16 +4339,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz", + "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/types": "30.3.0", + "jest-mock": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -4367,32 +4369,32 @@ } }, "node_modules/@jest/reporters": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", - "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz", + "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", "collect-v8-coverage": "^1.0.2", "exit-x": "^0.2.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -4438,19 +4440,19 @@ } }, "node_modules/@jest/reporters/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -4459,27 +4461,27 @@ } }, "node_modules/@jest/reporters/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/reporters/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -4490,9 +4492,9 @@ } }, "node_modules/@jest/reporters/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4535,13 +4537,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz", + "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -4566,14 +4568,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", - "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz", + "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/types": "30.3.0", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -4582,15 +4584,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", - "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz", + "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", + "@jest/test-result": "30.3.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "slash": "^3.0.0" }, "engines": { @@ -4608,24 +4610,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz", + "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", "pirates": "^4.0.7", "slash": "^3.0.0", "write-file-atomic": "^5.0.1" @@ -4635,27 +4636,27 @@ } }, "node_modules/@jest/transform/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/transform/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -4676,9 +4677,9 @@ } }, "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz", + "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==", "dev": true, "license": "MIT", "dependencies": { @@ -4767,9 +4768,9 @@ } }, "node_modules/@jsonjoy.com/buffers": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.65.0.tgz", - "integrity": "sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4799,13 +4800,13 @@ } }, "node_modules/@jsonjoy.com/fs-core": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.10.tgz", - "integrity": "sha512-PyAEA/3cnHhsGcdY+AmIU+ZPqTuZkDhCXQ2wkXypdLitSpd6d5Ivxhnq4wa2ETRWFVJGabYynBWxIijOswSmOw==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", "thingies": "^2.5.0" }, "engines": { @@ -4820,14 +4821,14 @@ } }, "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.10.tgz", - "integrity": "sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", "thingies": "^2.5.0" }, "engines": { @@ -4842,16 +4843,16 @@ } }, "node_modules/@jsonjoy.com/fs-node": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.10.tgz", - "integrity": "sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", "glob-to-regex.js": "^1.0.0", "thingies": "^2.5.0" }, @@ -4867,9 +4868,9 @@ } }, "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.10.tgz", - "integrity": "sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4883,14 +4884,14 @@ } }, "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.10.tgz", - "integrity": "sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10" + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" }, "engines": { "node": ">=10.0" @@ -4904,12 +4905,12 @@ } }, "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.10.tgz", - "integrity": "sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10" + "@jsonjoy.com/fs-node-builtins": "4.57.2" }, "engines": { "node": ">=10.0" @@ -4923,12 +4924,12 @@ } }, "node_modules/@jsonjoy.com/fs-print": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.10.tgz", - "integrity": "sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.57.2", "tree-dump": "^1.1.0" }, "engines": { @@ -4943,13 +4944,13 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.10.tgz", - "integrity": "sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.57.2", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, @@ -4965,9 +4966,9 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.65.0.tgz", - "integrity": "sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4981,9 +4982,9 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.65.0.tgz", - "integrity": "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4997,16 +4998,16 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.65.0.tgz", - "integrity": "sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/base64": "17.65.0", - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0", - "@jsonjoy.com/json-pointer": "17.65.0", - "@jsonjoy.com/util": "17.65.0", + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", "hyperdyperid": "^1.2.0", "thingies": "^2.5.0", "tree-dump": "^1.1.0" @@ -5023,12 +5024,12 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.65.0.tgz", - "integrity": "sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/util": "17.65.0" + "@jsonjoy.com/util": "17.67.0" }, "engines": { "node": ">=10.0" @@ -5042,13 +5043,13 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.65.0.tgz", - "integrity": "sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0" + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" }, "engines": { "node": ">=10.0" @@ -5166,93 +5167,42 @@ "license": "MIT" }, "node_modules/@microsoft/api-extractor": { - "version": "7.56.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.56.0.tgz", - "integrity": "sha512-H0V69QG5jIb9Ayx35NVBv2lOgFSS3q+Eab2oyGEy0POL3ovYPST+rCNPbwYoczOZXNG8IKjWUmmAMxmDTsXlQA==", + "version": "7.58.7", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.58.7.tgz", + "integrity": "sha512-yK6OycD46gIzLRpj6ueVUWPk1ACSpkN1LBo05gY1qPTylbWyUCanXfH7+VgkI5LJrJoRSQR5F04XuCffCXLOBw==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/api-extractor-model": "7.32.2", + "@microsoft/api-extractor-model": "7.33.8", "@microsoft/tsdoc": "~0.16.0", - "@microsoft/tsdoc-config": "~0.18.0", - "@rushstack/node-core-library": "5.19.1", - "@rushstack/rig-package": "0.6.0", - "@rushstack/terminal": "0.21.0", - "@rushstack/ts-command-line": "5.1.7", + "@microsoft/tsdoc-config": "~0.18.1", + "@rushstack/node-core-library": "5.23.1", + "@rushstack/rig-package": "0.7.3", + "@rushstack/terminal": "0.24.0", + "@rushstack/ts-command-line": "5.3.9", "diff": "~8.0.2", - "lodash": "~4.17.15", - "minimatch": "10.0.3", + "minimatch": "10.2.3", "resolve": "~1.22.1", - "semver": "~7.5.4", + "semver": "~7.7.4", "source-map": "~0.6.1", - "typescript": "5.8.2" + "typescript": "5.9.3" }, "bin": { "api-extractor": "bin/api-extractor" } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.32.2.tgz", - "integrity": "sha512-Ussc25rAalc+4JJs9HNQE7TuO9y6jpYQX9nWD1DhqUzYPBr3Lr7O9intf+ZY8kD5HnIqeIRJX7ccCT0QyBy2Ww==", + "version": "7.33.8", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.8.tgz", + "integrity": "sha512-aIcoQggPyer3B6Ze3usz0YWC/oBwUHfRH5ETUsr+oT2BRA6SfTJl7IKPcPZkX4UR+PohowzW4uMxsvjrn8vm+w==", "dev": true, "license": "MIT", "dependencies": { "@microsoft/tsdoc": "~0.16.0", - "@microsoft/tsdoc-config": "~0.18.0", - "@rushstack/node-core-library": "5.19.1" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "@microsoft/tsdoc-config": "~0.18.1", + "@rushstack/node-core-library": "5.23.1" } }, - "node_modules/@microsoft/api-extractor/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/@microsoft/tsdoc": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", @@ -5261,29 +5211,29 @@ "license": "MIT" }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.18.0.tgz", - "integrity": "sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.18.1.tgz", + "integrity": "sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==", "dev": true, "license": "MIT", "dependencies": { "@microsoft/tsdoc": "0.16.0", - "ajv": "~8.12.0", + "ajv": "~8.18.0", "jju": "~1.4.0", "resolve": "~1.22.2" } }, "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -5433,9 +5383,9 @@ } }, "node_modules/@octokit/endpoint": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz", - "integrity": "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", + "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", "dev": true, "license": "MIT", "dependencies": { @@ -5514,16 +5464,17 @@ } }, "node_modules/@octokit/request": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz", - "integrity": "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.8.tgz", + "integrity": "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/endpoint": "^11.0.2", + "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "fast-content-type-parse": "^3.0.0", + "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" }, "engines": { @@ -5866,9 +5817,9 @@ } }, "node_modules/@parcel/watcher/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "optional": true, "engines": { @@ -5912,19 +5863,19 @@ "license": "MIT" }, "node_modules/@release-it/conventional-changelog": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@release-it/conventional-changelog/-/conventional-changelog-10.0.4.tgz", - "integrity": "sha512-pU1JkAZBHVk9u0O9CZcaLsqSZHWu0s9WNIFVUq0M9r/WlLpJvrCiSH2OCLo5XyOnWacdMvBjijm+kl6m36SdrA==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@release-it/conventional-changelog/-/conventional-changelog-10.0.6.tgz", + "integrity": "sha512-aUb0IkcsBTMcOH5PPQ9Jv9lEOOVu2+rSgkE1ny+dzsTziQm2BhDRAtaFK/dw/HflthuXMWrqhhyfJhAV1AOEPQ==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/git-client": "^2.5.1", + "@conventional-changelog/git-client": "^2.6.0", "concat-stream": "^2.0.0", - "conventional-changelog": "^7.1.1", - "conventional-changelog-angular": "^8.1.0", - "conventional-changelog-conventionalcommits": "^9.1.0", + "conventional-changelog": "^7.2.0", + "conventional-changelog-angular": "^8.3.0", + "conventional-changelog-conventionalcommits": "^9.3.0", "conventional-recommended-bump": "^11.2.0", - "semver": "^7.7.3" + "semver": "^7.7.4" }, "engines": { "node": "^20.12.0 || >=22.0.0" @@ -5934,9 +5885,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", "cpu": [ "arm" ], @@ -5948,9 +5899,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", "cpu": [ "arm64" ], @@ -5962,9 +5913,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", "cpu": [ "arm64" ], @@ -5976,9 +5927,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", "cpu": [ "x64" ], @@ -5990,9 +5941,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", "cpu": [ "arm64" ], @@ -6004,9 +5955,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", "cpu": [ "x64" ], @@ -6018,9 +5969,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", "cpu": [ "arm" ], @@ -6032,9 +5983,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", "cpu": [ "arm" ], @@ -6046,9 +5997,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", "cpu": [ "arm64" ], @@ -6060,9 +6011,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", "cpu": [ "arm64" ], @@ -6074,9 +6025,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", "cpu": [ "loong64" ], @@ -6088,9 +6039,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", "cpu": [ "loong64" ], @@ -6102,9 +6053,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", "cpu": [ "ppc64" ], @@ -6116,9 +6067,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", "cpu": [ "ppc64" ], @@ -6130,9 +6081,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", "cpu": [ "riscv64" ], @@ -6144,9 +6095,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", "cpu": [ "riscv64" ], @@ -6158,9 +6109,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", "cpu": [ "s390x" ], @@ -6172,9 +6123,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", "cpu": [ "x64" ], @@ -6186,9 +6137,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", "cpu": [ "x64" ], @@ -6200,9 +6151,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", "cpu": [ "x64" ], @@ -6214,9 +6165,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", "cpu": [ "arm64" ], @@ -6228,9 +6179,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", "cpu": [ "arm64" ], @@ -6242,9 +6193,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", "cpu": [ "ia32" ], @@ -6256,9 +6207,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", "cpu": [ "x64" ], @@ -6270,9 +6221,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", "cpu": [ "x64" ], @@ -6305,55 +6256,55 @@ } }, "node_modules/@rsdoctor/client": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/client/-/client-1.5.1.tgz", - "integrity": "sha512-dtvg4cXN90tvzabBXBWVIsdXrs6Lpt5K6vXU1nu4qKQ5EDg241rT5C9W8EpnErgONJDDaqDhkUAk48zwpDba5A==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/client/-/client-1.5.9.tgz", + "integrity": "sha512-obu4fXxU5fwWyV1rcmMsbHTkzvjkw15EH+F7v0K3pGOz0GiOFpZl8bsweLEmroMz3NU4xYDJElJfogW0ILk/uw==", "license": "MIT" }, "node_modules/@rsdoctor/core": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/core/-/core-1.5.1.tgz", - "integrity": "sha512-wcUQ4Ab3l8qKE+8dnvEkr62qZKi3y8NW38U7VnkHKh6NJNS5+bX5mfEt8fDsDNkt6BxlM9G3QgC542K0SF3biQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/core/-/core-1.5.9.tgz", + "integrity": "sha512-f2hqXYrheNCOyJlZfe0RY/ccMvrusqah6/DQFtT1GUcohamYQBWehE4HhijEAQLAL6VoL87qVKxt58ovaoEs4w==", "license": "MIT", "dependencies": { "@rsbuild/plugin-check-syntax": "1.6.1", - "@rsdoctor/graph": "1.5.1", - "@rsdoctor/sdk": "1.5.1", - "@rsdoctor/types": "1.5.1", - "@rsdoctor/utils": "1.5.1", + "@rsdoctor/graph": "1.5.9", + "@rsdoctor/sdk": "1.5.9", + "@rsdoctor/types": "1.5.9", + "@rsdoctor/utils": "1.5.9", + "@rspack/resolver": "0.2.8", "browserslist-load-config": "^1.0.1", - "enhanced-resolve": "5.12.0", - "es-toolkit": "^1.43.0", + "es-toolkit": "^1.45.1", "filesize": "^10.1.6", "fs-extra": "^11.1.1", - "semver": "^7.7.3", + "semver": "^7.7.4", "source-map": "^0.7.6" } }, "node_modules/@rsdoctor/graph": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/graph/-/graph-1.5.1.tgz", - "integrity": "sha512-qPu9aavP/oBSVsYZ2S+mMPoYKiET76jq9kKPRayDx1lRO8mjS/brW+4vG0dPUSl6dY5YfDTW4V1YLPH1C3CGAg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/graph/-/graph-1.5.9.tgz", + "integrity": "sha512-gu9/+ZfKyHnVc3Rt19p2vd+zu1/ftSH/DdenfVjYv8qgmdRXZXX1A6tuyM0JAYxKXn9Zo89BVA6sUloF7BSbIQ==", "license": "MIT", "dependencies": { - "@rsdoctor/types": "1.5.1", - "@rsdoctor/utils": "1.5.1", - "es-toolkit": "^1.43.0", + "@rsdoctor/types": "1.5.9", + "@rsdoctor/utils": "1.5.9", + "es-toolkit": "^1.45.1", "path-browserify": "1.0.1", "source-map": "^0.7.6" } }, "node_modules/@rsdoctor/rspack-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/rspack-plugin/-/rspack-plugin-1.5.1.tgz", - "integrity": "sha512-tRJhItttGM3AEi/JdBYwCaXhfgZz2FCPoeZoQfW4R/XlZjO54U2FY+uNzxxFHEWDHQeK2Yiqnc7oOCq2dT1HpQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/rspack-plugin/-/rspack-plugin-1.5.9.tgz", + "integrity": "sha512-SgzjuoRGQ6cYM1001IdXD//MrizePimIdyeZqyp4p+NpYG3LwLzCKUFtT+Ef7qOAt9lOBYcF8oCMIpSh5Xk+xg==", "license": "MIT", "dependencies": { - "@rsdoctor/core": "1.5.1", - "@rsdoctor/graph": "1.5.1", - "@rsdoctor/sdk": "1.5.1", - "@rsdoctor/types": "1.5.1", - "@rsdoctor/utils": "1.5.1" + "@rsdoctor/core": "1.5.9", + "@rsdoctor/graph": "1.5.9", + "@rsdoctor/sdk": "1.5.9", + "@rsdoctor/types": "1.5.9", + "@rsdoctor/utils": "1.5.9" }, "peerDependencies": { "@rspack/core": "*" @@ -6365,29 +6316,30 @@ } }, "node_modules/@rsdoctor/sdk": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/sdk/-/sdk-1.5.1.tgz", - "integrity": "sha512-iQxN0Qd9iDu887gNAL8egSFIYI81g+mWMX90660AK1REmQOBfQogIxnfV0DcRMEeufVb/HrEEAUvHR1UdLwqMw==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/sdk/-/sdk-1.5.9.tgz", + "integrity": "sha512-aE3tO6EecnrPdV/Jfn8dGGqZGZ5kg9Ta8ULoVbuMo9dOOnNxYq122S0EGATqROorAsfahd8QSMV7YxznoIqP+w==", "license": "MIT", "dependencies": { - "@rsdoctor/client": "1.5.1", - "@rsdoctor/graph": "1.5.1", - "@rsdoctor/types": "1.5.1", - "@rsdoctor/utils": "1.5.1", + "@rsdoctor/client": "1.5.9", + "@rsdoctor/graph": "1.5.9", + "@rsdoctor/types": "1.5.9", + "@rsdoctor/utils": "1.5.9", + "launch-editor": "^2.13.2", "safer-buffer": "2.1.2", "socket.io": "4.8.1", - "tapable": "2.2.3" + "tapable": "2.3.2" } }, "node_modules/@rsdoctor/types": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/types/-/types-1.5.1.tgz", - "integrity": "sha512-NUdbUbhl8JLRDz36HfhYyHkjx5BlVkY4sMXWOy5ZGEfXDNvRLgbD4OLnQZWJpmVU4NADYTau0rKzhN9RIDoe4g==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/types/-/types-1.5.9.tgz", + "integrity": "sha512-kjxWEocZWLiNhCaVBQDfPMn8USIf+UyFm21VhxwM0cekW5pZKPwTFE6hTzHH8aWCWtGwApzzLXPBQqZoWYUXlQ==", "license": "MIT", "dependencies": { "@types/connect": "3.4.38", "@types/estree": "1.0.5", - "@types/tapable": "2.2.7", + "@types/tapable": "2.3.0", "source-map": "^0.7.6" }, "peerDependencies": { @@ -6404,17 +6356,17 @@ } }, "node_modules/@rsdoctor/utils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@rsdoctor/utils/-/utils-1.5.1.tgz", - "integrity": "sha512-Lcpq2+n3aiT77UePb9gB63OLuZmA/vE3xt5If7hkeIi4XR6i/dS2VDTmu+jt4QbPsESXp628tjEH2IvFTAEs7g==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@rsdoctor/utils/-/utils-1.5.9.tgz", + "integrity": "sha512-e1Fii9zdtNCyYwsCZLKo5gkfBgZmkRkBpieSAcdworgdlhAA+UTxCVg1q6/Ozz8QQcUbj9AfP0do9ja633vfvw==", "license": "MIT", "dependencies": { "@babel/code-frame": "7.26.2", - "@rsdoctor/types": "1.5.1", + "@rsdoctor/types": "1.5.9", "@types/estree": "1.0.5", "acorn": "^8.10.0", "acorn-import-attributes": "^1.9.5", - "acorn-walk": "8.3.4", + "acorn-walk": "8.3.5", "deep-eql": "4.1.4", "envinfo": "7.21.0", "fs-extra": "^11.1.1", @@ -6422,32 +6374,32 @@ "json-stream-stringify": "3.0.1", "lines-and-columns": "2.0.4", "picocolors": "^1.1.1", - "rslog": "^1.2.11", + "rslog": "^1.3.2", "strip-ansi": "^6.0.1" } }, "node_modules/@rspack/binding": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.7.5.tgz", - "integrity": "sha512-tlZfDHfGu765FBL3hIyjrr8slJZztv7rCM+KIczZS7UlJQDl1+WsDKUe/+E1Fw9SlmorLWK40+y3rLTHmMrN2A==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.7.11.tgz", + "integrity": "sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q==", "license": "MIT", "optionalDependencies": { - "@rspack/binding-darwin-arm64": "1.7.5", - "@rspack/binding-darwin-x64": "1.7.5", - "@rspack/binding-linux-arm64-gnu": "1.7.5", - "@rspack/binding-linux-arm64-musl": "1.7.5", - "@rspack/binding-linux-x64-gnu": "1.7.5", - "@rspack/binding-linux-x64-musl": "1.7.5", - "@rspack/binding-wasm32-wasi": "1.7.5", - "@rspack/binding-win32-arm64-msvc": "1.7.5", - "@rspack/binding-win32-ia32-msvc": "1.7.5", - "@rspack/binding-win32-x64-msvc": "1.7.5" + "@rspack/binding-darwin-arm64": "1.7.11", + "@rspack/binding-darwin-x64": "1.7.11", + "@rspack/binding-linux-arm64-gnu": "1.7.11", + "@rspack/binding-linux-arm64-musl": "1.7.11", + "@rspack/binding-linux-x64-gnu": "1.7.11", + "@rspack/binding-linux-x64-musl": "1.7.11", + "@rspack/binding-wasm32-wasi": "1.7.11", + "@rspack/binding-win32-arm64-msvc": "1.7.11", + "@rspack/binding-win32-ia32-msvc": "1.7.11", + "@rspack/binding-win32-x64-msvc": "1.7.11" } }, "node_modules/@rspack/binding-darwin-arm64": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.5.tgz", - "integrity": "sha512-dg2/IrF+g498NUt654N8LFWfIiUsHlTankWieE1S3GWEQM6jweeRbNuu1Py1nWIUsjR2yQtv7ziia7c9Q8UTaQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.11.tgz", + "integrity": "sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig==", "cpu": [ "arm64" ], @@ -6458,9 +6410,9 @@ ] }, "node_modules/@rspack/binding-darwin-x64": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.5.tgz", - "integrity": "sha512-RQJX4boQJUu3lo1yiN344+y8W6iSO08ARXIZqFPg66coOgfX1lhsXQSRJGQEQG4PAcYuC0GmrYFzErliifbc1Q==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.11.tgz", + "integrity": "sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA==", "cpu": [ "x64" ], @@ -6471,9 +6423,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-gnu": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.5.tgz", - "integrity": "sha512-R7CO1crkJQLIQpJQzf+6DMHjvcvH/VxsatS5CG897IIT2aAfBeQuQAO+ERJko/UwSZam2K8Rxjuopcu5A2jsTQ==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.11.tgz", + "integrity": "sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA==", "cpu": [ "arm64" ], @@ -6484,9 +6436,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-musl": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.5.tgz", - "integrity": "sha512-moDVFD06ISZi+wCIjJLzQSr8WO8paViacSHk+rOKQxwKI96cPoC4JFkz0+ibT2uks4i2ecs4Op48orsoguiXxw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.11.tgz", + "integrity": "sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw==", "cpu": [ "arm64" ], @@ -6497,9 +6449,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-gnu": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.5.tgz", - "integrity": "sha512-LGtdsdhtA5IxdMptj2NDVEbuZF4aqM99BVn3saHp92A4Fn20mW9UtQ+19PtaOFdbQBUN1GcP+cosrJ1wY56hOg==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.11.tgz", + "integrity": "sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ==", "cpu": [ "x64" ], @@ -6510,9 +6462,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-musl": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.5.tgz", - "integrity": "sha512-V1HTvuj0XF/e4Xnixqf7FrxdCtTkYqn26EKwH7ExUFuVBh4SsLGr29EK5SOXBG0xdy5TSEUokMup7cuONPb3Hw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.11.tgz", + "integrity": "sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg==", "cpu": [ "x64" ], @@ -6523,9 +6475,9 @@ ] }, "node_modules/@rspack/binding-wasm32-wasi": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.5.tgz", - "integrity": "sha512-rGNHrk2QuLFfwOTib91skuLh2aMYeTP4lgM4zanDhtt95DLDlwioETFY7FzY1WmS+Z3qnEyrgQIRp8osy0NKTw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.11.tgz", + "integrity": "sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ==", "cpu": [ "wasm32" ], @@ -6536,9 +6488,9 @@ } }, "node_modules/@rspack/binding-win32-arm64-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.5.tgz", - "integrity": "sha512-eLyD9URS9M2pYa7sPICu9S0OuDAMnnGfuqrZYlrtgnEOEgimaG39gX6ENLwHvlNulaVMMFTNbDnS/2MELZ7r7g==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.11.tgz", + "integrity": "sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA==", "cpu": [ "arm64" ], @@ -6549,9 +6501,9 @@ ] }, "node_modules/@rspack/binding-win32-ia32-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.5.tgz", - "integrity": "sha512-ZT4eC8hHWzweA6S4Tl2c/z/fvhbU7Wnh+l76z+qmDy8wuA8uNrHgIb1mHLPli/wsqcjmIy8rDO9gkIBitg5I+w==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.11.tgz", + "integrity": "sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw==", "cpu": [ "ia32" ], @@ -6562,9 +6514,9 @@ ] }, "node_modules/@rspack/binding-win32-x64-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.5.tgz", - "integrity": "sha512-a2j10QS3dZvW+gdu+FXteAkChxsK2g9BRUOmpt13w22LkiGrdmOkMQyDWRgJNxUGJTlqIUqtXxs72nTTlzo2Sw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.11.tgz", + "integrity": "sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q==", "cpu": [ "x64" ], @@ -6575,9 +6527,9 @@ ] }, "node_modules/@rspack/cli": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/cli/-/cli-1.7.5.tgz", - "integrity": "sha512-z4JqxYiEb4iDbJa2Y232qmMbVEwh7c3DTZ52DQpFHDcOxxh9C7DNZTFpz5TPsv15IYxTXnC8M/wJ7gqfaU3W1g==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/cli/-/cli-1.7.11.tgz", + "integrity": "sha512-vUnflkq4F654wTEpCd+L4RYVbet8L2lNqLMmAGIZvoZddlXm4Duvg+eqcFE9iF8plAjFflRcU7DhB7WZa76pwg==", "license": "MIT", "dependencies": { "@discoveryjs/json-ext": "^0.5.7", @@ -6593,13 +6545,13 @@ } }, "node_modules/@rspack/core": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.7.5.tgz", - "integrity": "sha512-W1ChLhjBxGg6y4AHjEVjhcww/FZJ2O9obR0EOlYcfrfQGojCAUMeQjbmaF2sse5g5m0vSCaPtNYkycZ0qVRk1A==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.7.11.tgz", + "integrity": "sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew==", "license": "MIT", "dependencies": { "@module-federation/runtime-tools": "0.22.0", - "@rspack/binding": "1.7.5", + "@rspack/binding": "1.7.11", "@rspack/lite-tapable": "1.1.0" }, "engines": { @@ -6639,88 +6591,221 @@ "integrity": "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==", "license": "MIT" }, - "node_modules/@rushstack/node-core-library": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.19.1.tgz", - "integrity": "sha512-ESpb2Tajlatgbmzzukg6zyAhH+sICqJR2CNXNhXcEbz6UGCQfrKCtkxOpJTftWc8RGouroHG0Nud1SJAszvpmA==", - "dev": true, + "node_modules/@rspack/resolver": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver/-/resolver-0.2.8.tgz", + "integrity": "sha512-FBWqdHhzS8mcf/WN4Ktzr7EaeaN+hsxbN98EweegX3924beZuY6H70CSFWCv1fIHAieCUv/9XCjKggHvhCsLwA==", "license": "MIT", - "dependencies": { - "ajv": "~8.13.0", - "ajv-draft-04": "~1.0.0", - "ajv-formats": "~3.0.1", - "fs-extra": "~11.3.0", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } + "optionalDependencies": { + "@rspack/resolver-binding-darwin-arm64": "0.2.8", + "@rspack/resolver-binding-darwin-x64": "0.2.8", + "@rspack/resolver-binding-linux-arm64-gnu": "0.2.8", + "@rspack/resolver-binding-linux-arm64-musl": "0.2.8", + "@rspack/resolver-binding-linux-x64-gnu": "0.2.8", + "@rspack/resolver-binding-linux-x64-musl": "0.2.8", + "@rspack/resolver-binding-wasm32-wasi": "0.2.8", + "@rspack/resolver-binding-win32-arm64-msvc": "0.2.8", + "@rspack/resolver-binding-win32-ia32-msvc": "0.2.8", + "@rspack/resolver-binding-win32-x64-msvc": "0.2.8" + } + }, + "node_modules/@rspack/resolver-binding-darwin-arm64": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-0.2.8.tgz", + "integrity": "sha512-nTnK17kmxXEvR+WpOIZPSIzUFYeWCHoffgU9tvOLOwuTBH41kWnSQXXWu+AiMVwvJ6wdRO6Vo30hPhlXEG7Pyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@rushstack/node-core-library/node_modules/ajv": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", - "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", - "dev": true, + "node_modules/@rspack/resolver-binding-darwin-x64": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-0.2.8.tgz", + "integrity": "sha512-Aqr4TK2rA6XVYUOmM5YCtYyCMZhOIR53P4cOGgGARg99A7OuMBMzUL4r1n0M0Fx35v6/sSx1OBe+odHmPxksEg==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@rushstack/node-core-library/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "node_modules/@rspack/resolver-binding-linux-arm64-gnu": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-0.2.8.tgz", + "integrity": "sha512-wGvkxm2G4mNTztslaOzLzx5JuySQSy5DcOWEZxHcjJJzp5L3ODbYLK18HtUc6cvmaVOmjaGrrYPrqJJ0hHTVFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/resolver-binding-linux-arm64-musl": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-0.2.8.tgz", + "integrity": "sha512-EqRJ9zLQsLAvyDKJKVZ45BSqRIMS12f5HtJdy3KkAHU14ZmsGv8e5IKkwUZN5CNBRad8xVlOMMx3dOfF4whJzg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/resolver-binding-linux-x64-gnu": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-0.2.8.tgz", + "integrity": "sha512-eXbeotNCTntL4/+mxJRVCxK63YeWzTfp0F3POeHJFSs6Nt0f2J/mZNFlasJmd6xm7zvE80h/HWOwbwjRBLcElA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/resolver-binding-linux-x64-musl": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-0.2.8.tgz", + "integrity": "sha512-KWFHlOWGkT+eMngoUgPGXrDi+rU04VCh9jyk0U6Ot2RTWvhGxwKykjmLS+CWZI/EBrzr9A6g2U3jzKTMNz9oCw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/resolver-binding-wasm32-wasi": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-0.2.8.tgz", + "integrity": "sha512-I6GIhgICFViE88jejIV74oiiWHnpLpQ5ogaZM1ozM9KDnfqcHoX0IVEyrIh5KqA8iLDyhuoFSW+Hf0qN7VTBBQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, "engines": { - "node": ">=10" + "node": ">=14.0.0" + } + }, + "node_modules/@rspack/resolver-binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@rushstack/node-core-library/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@rspack/resolver-binding-win32-arm64-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-0.2.8.tgz", + "integrity": "sha512-ZXCt3qUfDAEbtc2sHpvxM7lNFZM+DxfblgXUIl3Jy6BuEZbHe1i6z+t9c34ayHoGTVbVSNCtaYuG/MaWdSnPHw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/resolver-binding-win32-ia32-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-0.2.8.tgz", + "integrity": "sha512-2LRymjDK8MpUERD8CL0PPae5y2crU5TAg4T4EzpeL5jLARVq6izsEruiWzB6Y+D15vUYlvmgs2370GXVSB861w==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/resolver-binding-win32-x64-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@rspack/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-0.2.8.tgz", + "integrity": "sha512-hzRpfbtvv4M4EVrKKIAaHDs5wT8lVcbSUjtwPs5u4IeLEix45nQPQ6ZQjmE4lIH0GP/3L3XQhZroYmTcH/xdsQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rushstack/node-core-library": { + "version": "5.23.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.23.1.tgz", + "integrity": "sha512-wlKmIKIYCKuCASbITvOxLZXepPbwXvrv7S6ig6XNWFchSyhL/E2txmVXspHY49Wu2dzf7nI27a2k/yV5BA3EiA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" + "ajv": "~8.18.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", + "fs-extra": "~11.3.0", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.7.4" }, - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "@types/node": "*" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@rushstack/node-core-library/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, "node_modules/@rushstack/problem-matcher": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@rushstack/problem-matcher/-/problem-matcher-0.1.1.tgz", - "integrity": "sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@rushstack/problem-matcher/-/problem-matcher-0.2.1.tgz", + "integrity": "sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6733,25 +6818,25 @@ } }, "node_modules/@rushstack/rig-package": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.6.0.tgz", - "integrity": "sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.7.3.tgz", + "integrity": "sha512-aAA518n6wxxjCfnTAOjQnm7ngNE0FVHxHAw2pxKlIhxrMn0XQjGcXKF0oKWpjBgJOmsaJpVob/v+zr3zxgPWuA==", "dev": true, "license": "MIT", "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" + "jju": "~1.4.0", + "resolve": "~1.22.1" } }, "node_modules/@rushstack/terminal": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.21.0.tgz", - "integrity": "sha512-cLaI4HwCNYmknM5ns4G+drqdEB6q3dCPV423+d3TZeBusYSSm09+nR7CnhzJMjJqeRcdMAaLnrA4M/3xDz4R3w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.24.0.tgz", + "integrity": "sha512-8ZQS4MMaGsv27EXCBiH7WMPkRZrffeDoIevs6z9TM5dzqiY6+Hn4evfK/G+gvgBTjfvfkHIZPQQmalmI2sM4TQ==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/node-core-library": "5.19.1", - "@rushstack/problem-matcher": "0.1.1", + "@rushstack/node-core-library": "5.23.1", + "@rushstack/problem-matcher": "0.2.1", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -6764,27 +6849,26 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.1.7.tgz", - "integrity": "sha512-Ugwl6flarZcL2nqH5IXFYk3UR3mBVDsVFlCQW/Oaqidvdb/5Ota6b/Z3JXWIdqV3rOR2/JrYoAHanWF5rgenXA==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.9.tgz", + "integrity": "sha512-GIHqU+sRGQ3LGWAZu1O+9Yh++qwtyNIIGuNbcWHJjBTm2qRez0cwINUHZ+pQLR8UuzZDcMajrDaNbUYoaL/XtQ==", "dev": true, "license": "MIT", "dependencies": { - "@rushstack/terminal": "0.21.0", + "@rushstack/terminal": "0.24.0", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" } }, "node_modules/@simple-libs/child-process-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.1.tgz", - "integrity": "sha512-3nWd8irxvDI6v856wpPCHZ+08iQR0oHTZfzAZmnbsLzf+Sf1odraP6uKOHDZToXq3RPRV/LbqGVlSCogm9cJjg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", + "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", "dev": true, "license": "MIT", "dependencies": { - "@simple-libs/stream-utils": "^1.1.0", - "@types/node": "^22.0.0" + "@simple-libs/stream-utils": "^1.2.0" }, "engines": { "node": ">=18" @@ -6793,15 +6877,25 @@ "url": "https://ko-fi.com/dangreen" } }, - "node_modules/@simple-libs/stream-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.1.0.tgz", - "integrity": "sha512-6rsHTjodIn/t90lv5snQjRPVtOosM7Vp0AKdrObymq45ojlgVwnpAqdc+0OBBrpEiy31zZ6/TKeIVqV1HwvnuQ==", + "node_modules/@simple-libs/hosted-git-info": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@simple-libs/hosted-git-info/-/hosted-git-info-1.0.2.tgz", + "integrity": "sha512-aAmGQdMH+ZinytKuA2832u0ATeOFNYNk4meBEXtB5xaPotUgggYNhq5tYU/v17wEbmTW5P9iHNqNrFyrhnqBAg==", "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "^22.0.0" + "engines": { + "node": ">=18" }, + "funding": { + "url": "https://ko-fi.com/dangreen" + } + }, + "node_modules/@simple-libs/stream-utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", + "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -6810,9 +6904,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.34.48", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", - "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "version": "0.34.49", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz", + "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==", "dev": true, "license": "MIT" }, @@ -6850,9 +6944,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "version": "15.3.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.3.2.tgz", + "integrity": "sha512-mrn35Jl2pCpns+mE3HaZa1yPN5EYCRgiMI+135COjr2hr8Cls9DXqIZ57vZe2cz7y2XVSq92tcs6kGQcT1J8Rw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7193,15 +7287,15 @@ } }, "node_modules/@swc/core": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.11.tgz", - "integrity": "sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.32.tgz", + "integrity": "sha512-/eWL0n43D64QWEUHLtTE+jDqjkJhyidjkDhv6f0uJohOUAhywxQ9wXYp845DNNds0JpCdI4Uo0a9bl+vbXf+ew==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.25" + "@swc/types": "^0.1.26" }, "engines": { "node": ">=10" @@ -7211,16 +7305,18 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.15.11", - "@swc/core-darwin-x64": "1.15.11", - "@swc/core-linux-arm-gnueabihf": "1.15.11", - "@swc/core-linux-arm64-gnu": "1.15.11", - "@swc/core-linux-arm64-musl": "1.15.11", - "@swc/core-linux-x64-gnu": "1.15.11", - "@swc/core-linux-x64-musl": "1.15.11", - "@swc/core-win32-arm64-msvc": "1.15.11", - "@swc/core-win32-ia32-msvc": "1.15.11", - "@swc/core-win32-x64-msvc": "1.15.11" + "@swc/core-darwin-arm64": "1.15.32", + "@swc/core-darwin-x64": "1.15.32", + "@swc/core-linux-arm-gnueabihf": "1.15.32", + "@swc/core-linux-arm64-gnu": "1.15.32", + "@swc/core-linux-arm64-musl": "1.15.32", + "@swc/core-linux-ppc64-gnu": "1.15.32", + "@swc/core-linux-s390x-gnu": "1.15.32", + "@swc/core-linux-x64-gnu": "1.15.32", + "@swc/core-linux-x64-musl": "1.15.32", + "@swc/core-win32-arm64-msvc": "1.15.32", + "@swc/core-win32-ia32-msvc": "1.15.32", + "@swc/core-win32-x64-msvc": "1.15.32" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -7232,9 +7328,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.11.tgz", - "integrity": "sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.32.tgz", + "integrity": "sha512-/YWMvJDPu+AAwuUsM2G+DNQ/7zhodURGzdQyewEqcvgklAdDHs3LwQmLLnyn6SJl8DT8UOxkbzK+D1PmPeelRg==", "cpu": [ "arm64" ], @@ -7249,9 +7345,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.11.tgz", - "integrity": "sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.32.tgz", + "integrity": "sha512-KOTXJXdAhWL+hZ77MYP3z+4pcMFaQhQ74yqyN1uz093q0YnbxpqMtYpPISbYvMHzVRNNx5kN+9RZAXEaadhWVA==", "cpu": [ "x64" ], @@ -7266,9 +7362,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.11.tgz", - "integrity": "sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.32.tgz", + "integrity": "sha512-oOoxLweljlc0A4X8ybsgxV7cVaYTwBOg2iMDJcFR3Sr48C+lsv9VzSmqdK/IVIXF4W4GjLc3VqTAdSMXlfVLuQ==", "cpu": [ "arm" ], @@ -7283,9 +7379,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.11.tgz", - "integrity": "sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.32.tgz", + "integrity": "sha512-oDzEkdl6D6BAWdMtU5KGO7y3HR5fJcvByNLyEk9+ugj8nP5Ovb7P4kBcStBXc4MPExFGQryehiINMlmY8HlclA==", "cpu": [ "arm64" ], @@ -7300,9 +7396,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.11.tgz", - "integrity": "sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.32.tgz", + "integrity": "sha512-omcqjoZP/b8D8PuczVoRwJieC6ibj7qIxTftNYokz4/aSmKFHvsd7nIFfPk5ZvtzncbH4AY7+Dkr/Lp2gWxYeA==", "cpu": [ "arm64" ], @@ -7316,10 +7412,44 @@ "node": ">=10" } }, + "node_modules/@swc/core-linux-ppc64-gnu": { + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.32.tgz", + "integrity": "sha512-KGkTMyz/Tbn3PBNu0AVZ4GTDFKnICrYcTiNPZq8DrvK42pnFsf3GNDrIG9E5AtQlTmC0YigkWKmu0eMcfTrmgA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-s390x-gnu": { + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.32.tgz", + "integrity": "sha512-G3Aa4tVS/3OGZBkoNIwUF9F6RAy+Osb4GOlo62SinLmDiErz/ykmM7KH0wkz6l9kM8jJq1HyAM6atJTUEbBk7g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.11.tgz", - "integrity": "sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.32.tgz", + "integrity": "sha512-ERsjfGcj6CBmj3vJnGDO8m8rTvw6RqMcWo1dogOtNx3/+/0+NNpJiXDobJrr1GwInI/BHAEkvSFIH6d2LqPcUQ==", "cpu": [ "x64" ], @@ -7334,9 +7464,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.11.tgz", - "integrity": "sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.32.tgz", + "integrity": "sha512-N4Ggahe/8SUbTX50P6EdhbW9YWcgbZVb52R4cq6MK+zsoMjRq7rGvV5ztA05QnbaCYqMYx8rTY7KAIA3Crdo4Q==", "cpu": [ "x64" ], @@ -7351,9 +7481,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.11.tgz", - "integrity": "sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.32.tgz", + "integrity": "sha512-01yN0o9jvo8xBTP12aPK2wW8b41jmOlGbDDlAnoynotc4pO6xA0zby9f1z6j++qXDpGBttLySq1omgVrlQKYcw==", "cpu": [ "arm64" ], @@ -7368,9 +7498,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.11.tgz", - "integrity": "sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.32.tgz", + "integrity": "sha512-fLagI9XZYNpTcmlqAcp3KBtmj7E19WCmYD80Jxj1Kn5tGNa7yxNLd3NNdWxuZGUPl5iC0/KqZru7g08gF6Fsrw==", "cpu": [ "ia32" ], @@ -7385,9 +7515,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.11.tgz", - "integrity": "sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw==", + "version": "1.15.32", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.32.tgz", + "integrity": "sha512-gbc2bQ/T2CiR+w0OvcVKwLOFAcPZBvmWmolbwpg1E8UrpeC03DGtyMUApOHNXNYWA3SHFrYXCQtosrcMza1YFg==", "cpu": [ "x64" ], @@ -7427,9 +7557,9 @@ } }, "node_modules/@swc/types": { - "version": "0.1.25", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", - "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.26.tgz", + "integrity": "sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7519,50 +7649,33 @@ "dev": true, "license": "MIT" }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "license": "ISC", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", @@ -7654,9 +7767,9 @@ } }, "node_modules/@types/chrome": { - "version": "0.1.36", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.36.tgz", - "integrity": "sha512-BvHbuyGttYXnGt5Gpwa4769KIinKHY1iLjlAPrrMBS2GI9m/XNMPtdsq0NgQalyuUdxvlMN/0OyGw0shFVIoUQ==", + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.40.tgz", + "integrity": "sha512-UnfyRAe8ORu9HSuTH0EqyOEUin3JrWW9Nl/gDXezNfTUrfIoxw+WRZgKOxGz0t5BnjbfXBnS2eCYfW2PxH1wcA==", "license": "MIT", "dependencies": { "@types/filesystem": "*", @@ -7898,9 +8011,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==", + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "dev": true, "license": "MIT" }, @@ -7911,9 +8024,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.8.tgz", - "integrity": "sha512-ebO/Yl+EAvVe8DnMfi+iaAyIqYdK0q/q0y0rw82INWEKJOBe6b/P3YWE8NW7oOlF/nXFNrHwhARrN/hdgDkraA==", + "version": "22.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", + "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -7950,9 +8063,9 @@ "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", "license": "MIT" }, "node_modules/@types/range-parser": { @@ -7962,9 +8075,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.11", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.11.tgz", - "integrity": "sha512-tORuanb01iEzWvMGVGv2ZDhYZVeRMrw453DCSAIn/5yvcSVnMoUMTyf33nQJLahYEnv9xqrTNbgz4qY5EfSh0g==", + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "devOptional": true, "license": "MIT", "dependencies": { @@ -8050,12 +8163,12 @@ "license": "MIT" }, "node_modules/@types/tapable": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-2.2.7.tgz", - "integrity": "sha512-D6QzACV9vNX3r8HQQNTOnpG+Bv1rko+yEA82wKs3O9CQ5+XW7HI7TED17/UE7+5dIxyxZIWTxKbsBeF6uKFCwA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-oMnbAXeVo+KUnje3hzdORXUbfnzTfqD0H92mLl19NE5hFqH9Q4ktq+xehNSxcNeeLm1COopYwa0zeP6Iz+oIXg==", "license": "MIT", "dependencies": { - "tapable": "^2.2.0" + "tapable": "^2.3.0" } }, "node_modules/@types/tough-cookie": { @@ -8590,9 +8703,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -8624,9 +8737,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "license": "MIT", "dependencies": { "acorn": "^8.11.0" @@ -8646,9 +8759,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -8796,10 +8909,8 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/argparse": { "version": "1.0.10", @@ -8834,6 +8945,16 @@ "dev": true, "license": "MIT" }, + "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/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -8874,16 +8995,16 @@ "license": "MIT" }, "node_modules/babel-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", - "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz", + "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.2.0", + "@jest/transform": "30.3.0", "@types/babel__core": "^7.20.5", "babel-plugin-istanbul": "^7.0.1", - "babel-preset-jest": "30.2.0", + "babel-preset-jest": "30.3.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "slash": "^3.0.0" @@ -8926,9 +9047,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", - "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz", + "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==", "dev": true, "license": "MIT", "dependencies": { @@ -8939,13 +9060,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", - "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -8962,12 +9083,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", - "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" }, "peerDependencies": { @@ -8975,12 +9096,12 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", - "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -9014,13 +9135,13 @@ } }, "node_modules/babel-preset-jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", - "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz", + "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "30.2.0", + "babel-plugin-jest-hoist": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0" }, "engines": { @@ -9031,10 +9152,13 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/base64id": { "version": "2.0.0", @@ -9046,18 +9170,21 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", + "version": "2.10.25", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.25.tgz", + "integrity": "sha512-QO/VHsXCQdnzADMfmkeOPvHdIAkoB7i0/rGjINPJEetLx75hNttVWGQ/jycHUDP9zZ9rupbm60WRxcwViB0MiA==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/basic-ftp": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", - "integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "dev": true, "license": "MIT", "engines": { @@ -9109,9 +9236,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -9122,7 +9249,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -9159,6 +9286,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -9176,13 +9318,15 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -9198,9 +9342,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "funding": [ { "type": "opencollective", @@ -9217,11 +9361,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -9305,23 +9449,23 @@ } }, "node_modules/c12": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.3.tgz", - "integrity": "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.4.tgz", + "integrity": "sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==", "license": "MIT", "dependencies": { "chokidar": "^5.0.0", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^17.2.3", + "confbox": "^0.2.4", + "defu": "^6.1.6", + "dotenv": "^17.3.1", "exsolve": "^1.0.8", - "giget": "^2.0.0", + "giget": "^3.2.0", "jiti": "^2.6.1", "ohash": "^2.0.11", "pathe": "^2.0.3", - "perfect-debounce": "^2.0.0", + "perfect-debounce": "^2.1.0", "pkg-types": "^2.3.0", - "rc9": "^2.1.2" + "rc9": "^3.0.1" }, "peerDependencies": { "magicast": "*" @@ -9348,9 +9492,9 @@ } }, "node_modules/c12/node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -9432,9 +9576,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001767", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz", - "integrity": "sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==", + "version": "1.0.30001791", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz", + "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==", "funding": [ { "type": "opencollective", @@ -9552,6 +9696,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, "license": "MIT", "dependencies": { "consola": "^3.2.3" @@ -9806,9 +9951,9 @@ } }, "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", "license": "MIT" }, "node_modules/connect-history-api-fallback": { @@ -9851,17 +9996,18 @@ } }, "node_modules/conventional-changelog": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-7.1.1.tgz", - "integrity": "sha512-rlqa8Lgh8YzT3Akruk05DR79j5gN9NCglHtJZwpi6vxVeaoagz+84UAtKQj/sT+RsfGaZkt3cdFCjcN6yjr5sw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-7.2.0.tgz", + "integrity": "sha512-BEdgG+vPl53EVlTTk9sZ96aagFp0AQ5pw/ggiQMy2SClLbTo1r0l+8dSg79gkLOO5DS1Lswuhp5fWn6RwE+ivg==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/git-client": "^2.5.1", + "@conventional-changelog/git-client": "^2.6.0", + "@simple-libs/hosted-git-info": "^1.0.2", "@types/normalize-package-data": "^2.4.4", "conventional-changelog-preset-loader": "^5.0.0", - "conventional-changelog-writer": "^8.2.0", - "conventional-commits-parser": "^6.2.0", + "conventional-changelog-writer": "^8.3.0", + "conventional-commits-parser": "^6.3.0", "fd-package-json": "^2.0.0", "meow": "^13.0.0", "normalize-package-data": "^7.0.0" @@ -9874,9 +10020,9 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.1.0.tgz", - "integrity": "sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", + "integrity": "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==", "dev": true, "license": "ISC", "dependencies": { @@ -9887,9 +10033,9 @@ } }, "node_modules/conventional-changelog-conventionalcommits": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.1.0.tgz", - "integrity": "sha512-MnbEysR8wWa8dAEvbj5xcBgJKQlX/m0lhS8DsyAAWDHdfs2faDJxTgzRYlRYpXSe7UiKrIIlB4TrBKU9q9DgkA==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.1.tgz", + "integrity": "sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw==", "dev": true, "license": "ISC", "dependencies": { @@ -9910,12 +10056,13 @@ } }, "node_modules/conventional-changelog-writer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.2.0.tgz", - "integrity": "sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.4.0.tgz", + "integrity": "sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==", "dev": true, "license": "MIT", "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", "conventional-commits-filter": "^5.0.0", "handlebars": "^4.7.7", "meow": "^13.0.0", @@ -9939,12 +10086,13 @@ } }, "node_modules/conventional-commits-parser": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.2.1.tgz", - "integrity": "sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.4.0.tgz", + "integrity": "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==", "dev": true, "license": "MIT", "dependencies": { + "@simple-libs/stream-utils": "^1.2.0", "meow": "^13.0.0" }, "bin": { @@ -9996,9 +10144,9 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "license": "MIT", "dependencies": { "browserslist": "^4.28.1" @@ -10032,9 +10180,9 @@ } }, "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10059,13 +10207,13 @@ } }, "node_modules/cosmiconfig-typescript-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", - "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", + "integrity": "sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==", "dev": true, "license": "MIT", "dependencies": { - "jiti": "^2.6.1" + "jiti": "2.6.1" }, "engines": { "node": ">=v18" @@ -10080,10 +10228,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/cross-env": { "version": "7.0.3", @@ -10120,9 +10266,9 @@ } }, "node_modules/css-loader": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.3.tgz", - "integrity": "sha512-frbERmjT0UC5lMheWpJmMilnt9GEhbZJN/heUb7/zaJYeIzj5St9HvDcfshzzOqbsS+rYpMk++2SD3vGETDSyA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz", + "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==", "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", @@ -10142,7 +10288,7 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "webpack": "^5.27.0" }, "peerDependenciesMeta": { @@ -10171,14 +10317,14 @@ } }, "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" @@ -10265,9 +10411,9 @@ } }, "node_modules/cssstyle/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -10281,19 +10427,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/dargs": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", - "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", @@ -10365,9 +10498,9 @@ "license": "MIT" }, "node_modules/dedent": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", - "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -10441,9 +10574,9 @@ } }, "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", "license": "MIT" }, "node_modules/degenerator": { @@ -10522,9 +10655,9 @@ "license": "MIT" }, "node_modules/diff": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10541,6 +10674,29 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "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/dir-glob/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/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -10679,9 +10835,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "version": "1.5.349", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz", + "integrity": "sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==", "license": "ISC" }, "node_modules/emittery": { @@ -10723,13 +10879,14 @@ } }, "node_modules/engine.io": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", - "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.7.tgz", + "integrity": "sha512-DgOngfDKM2EviOH3Mr9m7ks1q8roetLy/IMmYthAYzbpInMbYc/GS+fWFA3rl1gvwKVsQrVV61fo5emD1y3OJQ==", "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", @@ -10773,18 +10930,33 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", + "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" } }, + "node_modules/enhanced-resolve/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -10847,9 +11019,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "license": "MIT", "peer": true }, @@ -10866,9 +11038,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.44.0.tgz", - "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", + "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", "license": "MIT", "workspaces": [ "docs", @@ -11460,9 +11632,9 @@ } }, "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==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -11498,9 +11670,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -11554,9 +11726,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", "dev": true, "license": "MIT", "engines": { @@ -11639,9 +11811,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.1.tgz", - "integrity": "sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", "dev": true, "license": "MIT", "dependencies": { @@ -11673,51 +11845,29 @@ "license": "MIT" }, "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-3.2.0.tgz", + "integrity": "sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==", "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" - }, "bin": { "giget": "dist/cli.mjs" } }, "node_modules/git-raw-commits": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", - "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", + "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==", "dev": true, "license": "MIT", "dependencies": { - "dargs": "^8.0.0", - "meow": "^12.0.1", - "split2": "^4.0.0" + "@conventional-changelog/git-client": "^2.6.0", + "meow": "^13.0.0" }, "bin": { - "git-raw-commits": "cli.mjs" + "git-raw-commits": "src/cli.js" }, "engines": { - "node": ">=16" - } - }, - "node_modules/git-raw-commits/node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, "node_modules/git-up": { @@ -11742,17 +11892,17 @@ } }, "node_modules/glob": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz", - "integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.1.2", - "minipass": "^7.1.2", - "path-scurry": "^2.0.0" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -11793,32 +11943,17 @@ "license": "BSD-2-Clause", "peer": true }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", - "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz", + "integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==", "dev": true, "license": "MIT", "dependencies": { - "ini": "4.1.1" + "ini": "6.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11885,9 +12020,9 @@ "license": "MIT" }, "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11961,9 +12096,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -12076,10 +12211,26 @@ } } }, + "node_modules/html-rspack-tags-plugin/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/html-rspack-tags-plugin/node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/html-rspack-tags-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -12313,9 +12464,9 @@ } }, "node_modules/immutable": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", - "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "license": "MIT" }, "node_modules/import-fresh": { @@ -12411,13 +12562,13 @@ "license": "ISC" }, "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/inquirer": { @@ -12448,9 +12599,9 @@ } }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "dev": true, "license": "MIT", "engines": { @@ -12587,9 +12738,9 @@ } }, "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz", + "integrity": "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==", "license": "MIT", "engines": { "node": ">=16" @@ -12693,9 +12844,9 @@ "license": "MIT" }, "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -12831,16 +12982,16 @@ } }, "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz", + "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/types": "30.3.0", "import-local": "^3.2.0", - "jest-cli": "30.2.0" + "jest-cli": "30.3.0" }, "bin": { "jest": "bin/jest.js" @@ -12858,14 +13009,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz", + "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0" }, "engines": { @@ -12873,27 +13024,27 @@ } }, "node_modules/jest-changed-files/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-changed-files/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -12904,29 +13055,29 @@ } }, "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz", + "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/expect": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-each": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-runtime": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "p-limit": "^3.1.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -12964,51 +13115,51 @@ } }, "node_modules/jest-circus/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -13017,27 +13168,27 @@ } }, "node_modules/jest-circus/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-circus/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13048,9 +13199,9 @@ } }, "node_modules/jest-circus/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13080,21 +13231,21 @@ } }, "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz", + "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/core": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-config": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "yargs": "^17.7.2" }, "bin": { @@ -13129,43 +13280,40 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, + "extraneous": true, "license": "BSD-3-Clause", - "optional": true, - "peer": true, "engines": { "node": ">=0.3.1" } }, "node_modules/jest-cli/node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", + "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", + "@jest/test-sequencer": "30.3.0", + "@jest/types": "30.3.0", + "babel-jest": "30.3.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", + "jest-circus": "30.3.0", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", + "jest-environment-node": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", + "jest-resolve": "30.3.0", + "jest-runner": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "parse-json": "^5.2.0", - "pretty-format": "30.2.0", + "pretty-format": "30.3.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -13190,27 +13338,27 @@ } }, "node_modules/jest-cli/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-cli/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13221,9 +13369,9 @@ } }, "node_modules/jest-cli/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13252,14 +13400,25 @@ "node": ">=8" } }, + "node_modules/jest-cli/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jest-cli/node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -13302,10 +13461,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "extraneous": true, "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=6" } @@ -13395,17 +13552,17 @@ } }, "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz", + "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" + "jest-util": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13425,27 +13582,27 @@ } }, "node_modules/jest-each/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-each/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13456,9 +13613,9 @@ } }, "node_modules/jest-each/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13478,16 +13635,14 @@ "license": "MIT" }, "node_modules/jest-environment-jsdom": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.2.0.tgz", - "integrity": "sha512-zbBTiqr2Vl78pKp/laGBREYzbZx9ZtqPjOK4++lL4BNDhxRnahg51HtoDrk9/VjIy9IthNEWdKVd7H5bqBhiWQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.3.0.tgz", + "integrity": "sha512-RLEOJy6ip1lpw0yqJ8tB3i88FC7VBz7i00Zvl2qF71IdxjS98gC9/0SPWYIBVXHm5hgCYK0PAlSlnHGGy9RoMg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/environment-jsdom-abstract": "30.2.0", - "@types/jsdom": "^21.1.7", - "@types/node": "*", + "@jest/environment": "30.3.0", + "@jest/environment-jsdom-abstract": "30.3.0", "jsdom": "^26.1.0" }, "engines": { @@ -13503,46 +13658,46 @@ } }, "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz", + "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "jest-mock": "30.3.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13563,21 +13718,21 @@ } }, "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz", + "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", + "jest-util": "30.3.0", + "jest-worker": "30.3.0", + "picomatch": "^4.0.3", "walker": "^1.0.8" }, "engines": { @@ -13588,27 +13743,27 @@ } }, "node_modules/jest-haste-map/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-haste-map/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13619,14 +13774,14 @@ } }, "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz", + "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -13646,9 +13801,9 @@ } }, "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13843,42 +13998,42 @@ } }, "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz", + "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", - "jest-util": "30.2.0" + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-mock/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-mock/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13917,18 +14072,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz", + "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", + "jest-haste-map": "30.3.0", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", + "jest-util": "30.3.0", + "jest-validate": "30.3.0", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -13937,41 +14092,41 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz", + "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==", "dev": true, "license": "MIT", "dependencies": { "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "jest-snapshot": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-resolve/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-resolve/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -13992,32 +14147,32 @@ } }, "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz", + "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/console": "30.3.0", + "@jest/environment": "30.3.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", + "jest-environment-node": "30.3.0", + "jest-haste-map": "30.3.0", + "jest-leak-detector": "30.3.0", + "jest-message-util": "30.3.0", + "jest-resolve": "30.3.0", + "jest-runtime": "30.3.0", + "jest-util": "30.3.0", + "jest-watcher": "30.3.0", + "jest-worker": "30.3.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -14054,19 +14209,19 @@ } }, "node_modules/jest-runner/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -14075,27 +14230,27 @@ } }, "node_modules/jest-runner/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -14106,9 +14261,9 @@ } }, "node_modules/jest-runner/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14138,32 +14293,32 @@ } }, "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz", + "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", + "@jest/environment": "30.3.0", + "@jest/fake-timers": "30.3.0", + "@jest/globals": "30.3.0", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", + "glob": "^10.5.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", + "jest-haste-map": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", + "jest-resolve": "30.3.0", + "jest-snapshot": "30.3.0", + "jest-util": "30.3.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -14200,19 +14355,19 @@ } }, "node_modules/jest-runtime/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -14221,27 +14376,27 @@ } }, "node_modules/jest-runtime/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runtime/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -14252,9 +14407,9 @@ } }, "node_modules/jest-runtime/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14284,9 +14439,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz", + "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14295,20 +14450,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", + "@jest/snapshot-utils": "30.3.0", + "@jest/transform": "30.3.0", + "@jest/types": "30.3.0", "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.2.0", + "expect": "30.3.0", "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", + "jest-diff": "30.3.0", + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-util": "30.3.0", + "pretty-format": "30.3.0", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -14332,9 +14487,9 @@ } }, "node_modules/jest-snapshot/node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz", + "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==", "dev": true, "license": "MIT", "dependencies": { @@ -14358,69 +14513,69 @@ } }, "node_modules/jest-snapshot/node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz", + "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", + "@jest/expect-utils": "30.3.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "jest-matcher-utils": "30.3.0", + "jest-message-util": "30.3.0", + "jest-mock": "30.3.0", + "jest-util": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz", + "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", + "@jest/diff-sequences": "30.3.0", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz", + "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" + "jest-diff": "30.3.0", + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz", + "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", + "picomatch": "^4.0.3", + "pretty-format": "30.3.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -14429,27 +14584,27 @@ } }, "node_modules/jest-snapshot/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-snapshot/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -14460,9 +14615,9 @@ } }, "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14564,18 +14719,18 @@ } }, "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz", + "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.2.0" + "pretty-format": "30.3.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -14595,9 +14750,9 @@ } }, "node_modules/jest-validate/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz", + "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14617,19 +14772,19 @@ "license": "MIT" }, "node_modules/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz", + "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", + "@jest/test-result": "30.3.0", + "@jest/types": "30.3.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "string-length": "^4.0.2" }, "engines": { @@ -14637,27 +14792,27 @@ } }, "node_modules/jest-watcher/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-watcher/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -14668,22 +14823,22 @@ } }, "node_modules/jest-webextension-mock": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jest-webextension-mock/-/jest-webextension-mock-4.0.0.tgz", - "integrity": "sha512-s6q0z6dEa632MUa6334kStxY2BL86B8vntd9OsvBdOpqYX9BzY6ictX6akXlMyo9YGjDXqwmXdeyrtjXWDH07A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jest-webextension-mock/-/jest-webextension-mock-4.1.1.tgz", + "integrity": "sha512-smCGBtl+5MpjKnJhyjCeaL/ZtdUa0T41tbHsEdb1nY3UEVogbYvehVw2MuMSvysFD3wNv4iYSIEgAwnR3H0YIw==", "dev": true, "license": "ISC" }, "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz", + "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", + "jest-util": "30.3.0", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -14692,27 +14847,27 @@ } }, "node_modules/jest-worker/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "version": "30.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz", + "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", + "@jest/types": "30.3.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-worker/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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -14813,26 +14968,26 @@ } }, "node_modules/jsdom/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=20.19.0" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/jsdom/node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" + "entities": "^8.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -14869,14 +15024,21 @@ "license": "MIT" }, "node_modules/json-stringify-deterministic": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/json-stringify-deterministic/-/json-stringify-deterministic-1.0.12.tgz", - "integrity": "sha512-q3PN0lbUdv0pmurkBNdJH3pfFvOTL/Zp0lquqpvcjfKzt6Y0j49EPHAmVHCAS4Ceq/Y+PejWTzyiVpoY71+D6g==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/json-stringify-deterministic/-/json-stringify-deterministic-1.0.13.tgz", + "integrity": "sha512-Gm2hkhXlhD69QplkQGmY30S8Ps5noSFzruJKbgmD/nkYIXimS/Q0P1YIbJkWe2nbWDIzERmtp+hWGzC3Vk3bZg==", "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/json-with-bigint": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz", + "integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -14897,9 +15059,9 @@ "license": "MIT" }, "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -14918,9 +15080,9 @@ } }, "node_modules/launch-editor": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", - "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz", + "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==", "license": "MIT", "dependencies": { "picocolors": "^1.1.1", @@ -14970,9 +15132,9 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "license": "MIT", "peer": true, "engines": { @@ -15016,13 +15178,6 @@ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.capitalize": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", @@ -15057,13 +15212,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -15071,27 +15219,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", @@ -15099,13 +15226,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, "node_modules/log-symbols": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", @@ -15218,9 +15338,9 @@ } }, "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, "license": "CC0-1.0" }, @@ -15234,19 +15354,19 @@ } }, "node_modules/memfs": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.10.tgz", - "integrity": "sha512-eLvzyrwqLHnLYalJP7YZ3wBe79MXktMdfQbvMrVD80K+NhrIukCVBvgP30zTJYEEDh9hZ/ep9z0KOdD7FSHo7w==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-to-fsa": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -15393,9 +15513,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", - "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", @@ -15455,16 +15575,15 @@ "license": "ISC" }, "node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "dev": true, - "license": "ISC", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz", + "integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==", + "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -15480,10 +15599,10 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -15502,16 +15621,16 @@ } }, "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", - "ufo": "^1.6.1" + "ufo": "^1.6.3" } }, "node_modules/mlly/node_modules/confbox": { @@ -15571,6 +15690,20 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/mylas": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.14.tgz", + "integrity": "sha512-BzQguy9W9NJgoVn2mRWzbFrFWWztGCcng2QI9+41frfk+Athwgx3qhqhvStz7ExeUUu7Kzw427sNzHpEZNINog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -15584,9 +15717,9 @@ } }, "node_modules/nanoid": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", - "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz", + "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==", "funding": [ { "type": "github", @@ -15640,9 +15773,9 @@ "license": "MIT" }, "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", "dev": true, "license": "MIT", "engines": { @@ -15699,12 +15832,13 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true, "license": "MIT" }, "node_modules/node-forge": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", - "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -15718,9 +15852,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", "license": "MIT" }, "node_modules/normalize-package-data": { @@ -15773,14 +15907,15 @@ } }, "node_modules/nypm": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.4.tgz", - "integrity": "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw==", + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.6.tgz", + "integrity": "sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q==", + "dev": true, "license": "MIT", "dependencies": { - "citty": "^0.2.0", + "citty": "^0.2.2", "pathe": "^2.0.3", - "tinyexec": "^1.0.2" + "tinyexec": "^1.1.1" }, "bin": { "nypm": "dist/cli.mjs" @@ -15790,9 +15925,10 @@ } }, "node_modules/nypm/node_modules/citty": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.0.tgz", - "integrity": "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", + "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", + "dev": true, "license": "MIT" }, "node_modules/object-assign": { @@ -15943,13 +16079,13 @@ } }, "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -16209,34 +16345,34 @@ "license": "MIT" }, "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", + "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/path-type": { @@ -16271,9 +16407,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -16316,16 +16452,29 @@ } }, "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", "license": "MIT", "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", + "confbox": "^0.2.4", + "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -16336,9 +16485,9 @@ } }, "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.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz", + "integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==", "funding": [ { "type": "opencollective", @@ -16485,9 +16634,9 @@ "license": "MIT" }, "node_modules/postcss/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.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -16503,9 +16652,9 @@ } }, "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { @@ -16647,9 +16796,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -16661,6 +16810,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16682,16 +16841,6 @@ ], "license": "MIT" }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -16729,19 +16878,19 @@ } }, "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-3.0.1.tgz", + "integrity": "sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==", "license": "MIT", "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" + "defu": "^6.1.6", + "destr": "^2.0.5" } }, "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", + "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", "license": "MIT", "peer": true, "engines": { @@ -16749,16 +16898,16 @@ } }, "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", + "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", "license": "MIT", "peer": true, "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.4" + "react": "^19.2.5" } }, "node_modules/react-is": { @@ -16850,64 +16999,178 @@ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "license": "MIT" }, - "node_modules/regjsparser": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", - "license": "BSD-2-Clause", + "node_modules/regjsparser": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", + "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/release-it": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-19.2.4.tgz", + "integrity": "sha512-BwaJwQYUIIAKuDYvpqQTSoy0U7zIy6cHyEjih/aNaFICphGahia4cjDANuFXb7gVZ51hIK9W0io6fjNQWXqICg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/webpro" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/webpro" + } + ], + "license": "MIT", + "dependencies": { + "@nodeutils/defaults-deep": "1.1.0", + "@octokit/rest": "22.0.1", + "@phun-ky/typeof": "2.0.3", + "async-retry": "1.3.3", + "c12": "3.3.3", + "ci-info": "^4.3.1", + "eta": "4.5.0", + "git-url-parse": "16.1.0", + "inquirer": "12.11.1", + "issue-parser": "7.0.1", + "lodash.merge": "4.6.2", + "mime-types": "3.0.2", + "new-github-release-url": "2.0.0", + "open": "10.2.0", + "ora": "9.0.0", + "os-name": "6.1.0", + "proxy-agent": "6.5.0", + "semver": "7.7.3", + "tinyglobby": "0.2.15", + "undici": "6.23.0", + "url-join": "5.0.0", + "wildcard-match": "5.1.4", + "yargs-parser": "21.1.1" + }, + "bin": { + "release-it": "bin/release-it.js" + }, + "engines": { + "node": "^20.12.0 || >=22.0.0" + } + }, + "node_modules/release-it/node_modules/c12": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.3.tgz", + "integrity": "sha512-750hTRvgBy5kcMNPdh95Qo+XUBeGo8C7nsKSmedDmaQI+E0r82DwHeM6vBewDe4rGFbnxoa4V9pw+sPh5+Iz8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^17.2.3", + "exsolve": "^1.0.8", + "giget": "^2.0.0", + "jiti": "^2.6.1", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "*" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/release-it/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/release-it/node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/release-it/node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "dev": true, + "license": "MIT", "dependencies": { - "jsesc": "~3.1.0" + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" }, "bin": { - "regjsparser": "bin/parser" + "giget": "dist/cli.mjs" } }, - "node_modules/release-it": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-19.2.4.tgz", - "integrity": "sha512-BwaJwQYUIIAKuDYvpqQTSoy0U7zIy6cHyEjih/aNaFICphGahia4cjDANuFXb7gVZ51hIK9W0io6fjNQWXqICg==", + "node_modules/release-it/node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/webpro" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/webpro" - } - ], "license": "MIT", "dependencies": { - "@nodeutils/defaults-deep": "1.1.0", - "@octokit/rest": "22.0.1", - "@phun-ky/typeof": "2.0.3", - "async-retry": "1.3.3", - "c12": "3.3.3", - "ci-info": "^4.3.1", - "eta": "4.5.0", - "git-url-parse": "16.1.0", - "inquirer": "12.11.1", - "issue-parser": "7.0.1", - "lodash.merge": "4.6.2", - "mime-types": "3.0.2", - "new-github-release-url": "2.0.0", - "open": "10.2.0", - "ora": "9.0.0", - "os-name": "6.1.0", - "proxy-agent": "6.5.0", - "semver": "7.7.3", - "tinyglobby": "0.2.15", - "undici": "6.23.0", - "url-join": "5.0.0", - "wildcard-match": "5.1.4", - "yargs-parser": "21.1.1" + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/release-it/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/release-it/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", "bin": { - "release-it": "bin/release-it.js" + "semver": "bin/semver.js" }, "engines": { - "node": "^20.12.0 || >=22.0.0" + "node": ">=10" } }, "node_modules/require-directory": { @@ -16936,11 +17199,12 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", "dependencies": { + "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" @@ -17055,9 +17319,9 @@ } }, "node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17071,31 +17335,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", "fsevents": "~2.3.2" } }, @@ -17204,13 +17468,13 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.97.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", - "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "version": "1.99.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz", + "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -17224,9 +17488,9 @@ } }, "node_modules/sass-loader": { - "version": "16.0.6", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", - "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.7.tgz", + "integrity": "sha512-w6q+fRHourZ+e+xA1kcsF27iGM6jdB8teexYCfdUw0sYgcDNeZESnDNT9sUmmPm3ooziwUJXGwZJSTF3kOdBfA==", "license": "MIT", "dependencies": { "neo-async": "^2.6.2" @@ -17239,7 +17503,7 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", @@ -17291,6 +17555,15 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -17330,9 +17603,9 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -17380,9 +17653,9 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -17430,16 +17703,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve-index": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", @@ -17620,13 +17883,13 @@ } }, "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==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -17777,9 +18040,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", @@ -17818,13 +18081,13 @@ } }, "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz", + "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==", "dev": true, "license": "MIT", "dependencies": { - "ip-address": "^10.0.1", + "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -17922,9 +18185,9 @@ } }, "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==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, @@ -17958,16 +18221,6 @@ "wbuf": "^1.7.3" } }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -18044,14 +18297,14 @@ } }, "node_modules/string-width": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", - "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", "dev": true, "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { "node": ">=20" @@ -18074,13 +18327,13 @@ } }, "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -18135,16 +18388,13 @@ } }, "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, "node_modules/sucrase": { @@ -18221,18 +18471,18 @@ "license": "MIT" }, "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", "license": "MIT", "dependencies": { - "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", - "picocolors": "^1.0.0" + "picocolors": "^1.0.0", + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo" @@ -18288,9 +18538,9 @@ } }, "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz", + "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==", "license": "MIT", "engines": { "node": ">=6" @@ -18301,9 +18551,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.46.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz", + "integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==", "license": "BSD-2-Clause", "peer": true, "dependencies": { @@ -18320,16 +18570,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==", "license": "MIT", "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -18436,46 +18685,20 @@ } }, "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.2.tgz", + "integrity": "sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==", "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", - "minimatch": "^9.0.4" + "minimatch": "^10.2.2" }, "engines": { "node": ">=18" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -18500,9 +18723,9 @@ } }, "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", "license": "MIT", "engines": { "node": ">=10.18" @@ -18522,9 +18745,10 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.2.tgz", + "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -18566,9 +18790,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.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -18579,22 +18803,22 @@ } }, "node_modules/tldts": { - "version": "7.0.22", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.22.tgz", - "integrity": "sha512-nqpKFC53CgopKPjT6Wfb6tpIcZXHcI6G37hesvikhx0EmUGPkZrujRyAjgnmp1SHNgpQfKVanZ+KfpANFt2Hxw==", + "version": "7.0.30", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.30.tgz", + "integrity": "sha512-ELrFxuqsDdHUwoh0XxDbxuLD3Wnz49Z57IFvTtvWy1hJdcMZjXLIuonjilCiWHlT2GbE4Wlv1wKVTzDFnXH1aw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.22" + "tldts-core": "^7.0.30" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.22", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.22.tgz", - "integrity": "sha512-KgbTDC5wzlL6j/x6np6wCnDSMUq4kucHNm00KXPbfNzmllCmtmvtykJHfmgdHntwIeupW04y8s1N/43S1PkQDw==", + "version": "7.0.30", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.30.tgz", + "integrity": "sha512-uiHN8PIB1VmWyS98eZYja4xzlYqeFZVjb4OuYlJQnZAuJhMw4PbKQOKgHKhBdJR3FE/t5mUQ1Kd80++B+qhD1Q==", "dev": true, "license": "MIT" }, @@ -18636,9 +18860,9 @@ } }, "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -18818,6 +19042,79 @@ "node": ">=0.8.0" } }, + "node_modules/tsc-alias": { + "version": "1.8.17", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.17.tgz", + "integrity": "sha512-EIduCZHqbNwPm8BZYfq1aD7BQ697A4h6uSGMOFQfYGoQwfrYFTKwYfy9Bv42YxHkduVBcn9Zx0DkX111DKskyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "get-tsconfig": "^4.10.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + }, + "engines": { + "node": ">=16.20.2" + } + }, + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/tsc-alias/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/tsc-alias/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/tsc-alias/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/tsconfig": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", @@ -18880,16 +19177,6 @@ "node": ">=0.10.0" } }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -18950,9 +19237,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ "ppc64" ], @@ -18967,9 +19254,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ "arm" ], @@ -18984,9 +19271,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ "arm64" ], @@ -19001,9 +19288,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ "x64" ], @@ -19018,9 +19305,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], @@ -19035,9 +19322,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], @@ -19052,9 +19339,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], @@ -19069,9 +19356,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], @@ -19086,9 +19373,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ "arm" ], @@ -19103,9 +19390,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], @@ -19120,9 +19407,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], @@ -19137,9 +19424,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ "loong64" ], @@ -19154,9 +19441,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", "cpu": [ "mips64el" ], @@ -19171,9 +19458,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", "cpu": [ "ppc64" ], @@ -19188,9 +19475,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", "cpu": [ "riscv64" ], @@ -19205,9 +19492,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", "cpu": [ "s390x" ], @@ -19222,9 +19509,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -19239,9 +19526,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", "cpu": [ "arm64" ], @@ -19256,9 +19543,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", "cpu": [ "x64" ], @@ -19273,9 +19560,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", "cpu": [ "arm64" ], @@ -19290,9 +19577,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", "cpu": [ "x64" ], @@ -19307,9 +19594,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", "cpu": [ "arm64" ], @@ -19324,9 +19611,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", "cpu": [ "x64" ], @@ -19341,9 +19628,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", "cpu": [ "arm64" ], @@ -19358,9 +19645,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", "cpu": [ "ia32" ], @@ -19375,9 +19662,9 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", "cpu": [ "x64" ], @@ -19408,9 +19695,9 @@ } }, "node_modules/tsup/node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -19421,32 +19708,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "node_modules/tsup/node_modules/readdirp": { @@ -19491,9 +19778,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ "ppc64" ], @@ -19508,9 +19795,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ "arm" ], @@ -19525,9 +19812,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ "arm64" ], @@ -19542,9 +19829,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ "x64" ], @@ -19559,9 +19846,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], @@ -19576,9 +19863,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], @@ -19593,9 +19880,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], @@ -19610,9 +19897,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], @@ -19627,9 +19914,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ "arm" ], @@ -19644,9 +19931,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], @@ -19661,9 +19948,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], @@ -19678,9 +19965,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ "loong64" ], @@ -19695,9 +19982,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", "cpu": [ "mips64el" ], @@ -19712,9 +19999,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", "cpu": [ "ppc64" ], @@ -19729,9 +20016,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", "cpu": [ "riscv64" ], @@ -19746,9 +20033,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", "cpu": [ "s390x" ], @@ -19763,9 +20050,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -19780,9 +20067,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", "cpu": [ "arm64" ], @@ -19797,9 +20084,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", "cpu": [ "x64" ], @@ -19814,9 +20101,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", "cpu": [ "arm64" ], @@ -19831,9 +20118,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", "cpu": [ "x64" ], @@ -19848,9 +20135,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", "cpu": [ "arm64" ], @@ -19865,9 +20152,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", "cpu": [ "x64" ], @@ -19882,9 +20169,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", "cpu": [ "arm64" ], @@ -19899,9 +20186,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", "cpu": [ "ia32" ], @@ -19916,9 +20203,9 @@ } }, "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", "cpu": [ "x64" ], @@ -19933,9 +20220,9 @@ } }, "node_modules/tsx/node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -19946,32 +20233,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "node_modules/type-detect": { @@ -20050,9 +20337,9 @@ } }, "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", "dev": true, "license": "MIT" }, @@ -20289,6 +20576,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -20298,10 +20586,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "extraneous": true, + "license": "MIT" }, "node_modules/v8-to-istanbul": { "version": "9.3.0", @@ -20417,9 +20703,9 @@ } }, "node_modules/webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", + "version": "5.106.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", + "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", "license": "MIT", "peer": true, "dependencies": { @@ -20429,25 +20715,24 @@ "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", + "enhanced-resolve": "^5.20.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", + "terser-webpack-plugin": "^5.3.17", "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" + "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" @@ -20703,9 +20988,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", + "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", "license": "MIT", "peer": true, "engines": { @@ -20737,43 +21022,6 @@ } } }, - "node_modules/webpack/node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "license": "MIT", - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "peer": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/webpack/node_modules/schema-utils": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", @@ -20794,20 +21042,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack/node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -21109,9 +21343,9 @@ } }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index f330ae74..d32bc8af 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "version": "0.5.7", "description": "Addon Bone - Cross-browser web extension framework with shared code base", "homepage": "https://addonbone.com", + "author": "Anjey Tsibylskij (https://github.com/atldays)", "license": "MIT", "repository": { "type": "git", @@ -27,10 +28,6 @@ "opera", "safari" ], - "author": "Addon Stack ", - "contributors": [ - "Anjey Tsibylskij (https://github.com/atldays)" - ], "module": "./dist/index.js", "types": "./dist/index.d.ts", "files": [ @@ -104,7 +101,7 @@ "prepare": "husky", "preinstall": "npm run check:node-version", "prepublishOnly": "npm run build", - "build": "cross-env NODE_OPTIONS=--max-old-space-size=15046 tsup && node ./scripts/copy-dts.js", + "build": "tsup && tsc -p tsconfig.build.json && node ./scripts/copy-dts.js && tsc-alias -p tsconfig.build.json -f -fe .js", "format": "prettier --write .", "typecheck": "tsc -p tsconfig.json --noEmit", "check:node-version": "node ./scripts/check-node-version.js", @@ -157,7 +154,6 @@ "zod": "^3.24.2" }, "devDependencies": { - "glob": "^13.0.1", "@commitlint/cli": "^20.1.0", "@commitlint/config-conventional": "^20.0.0", "@microsoft/api-extractor": "^7.53.1", @@ -181,6 +177,7 @@ "esbuild-fix-imports-plugin": "^1.0.22", "esbuild-plugin-raw": "^0.3.0", "fs-extra": "^11.3.0", + "glob": "^13.0.1", "globby": "^14.1.0", "husky": "^9.1.7", "jest": "^30.2.0", @@ -189,6 +186,7 @@ "prettier": "^3.6.2", "release-it": "^19.2.3", "ts-node": "^1.7.1", + "tsc-alias": "^1.8.17", "tsup": "^8.5.0", "tsx": "^4.19.2", "uglify-js": "^3.19.3", diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..cb069b0a --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": false, + "rootDir": "./src", + "outDir": "./dist", + "sourceMap": false + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "**/*.test.ts", + "**/tests/**/*.ts", + "dist", + "src/cli/entrypoint/file/fixtures/**" + ] +} diff --git a/tsup.config.ts b/tsup.config.ts index aee3c82c..adcdaa01 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -73,7 +73,7 @@ export default defineConfig([ outDir: "dist", target: "node14", clean: true, - dts: true, + dts: false, sourcemap: true, // @ts-ignore esbuildPlugins: [fixVirtualIndexImportPlugin(), fixImportsPlugin()], From 1afe794eefe30def474bbb0afe6861c938889f86 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 2 May 2026 16:22:11 +0300 Subject: [PATCH 11/20] chore(tsconfig): reformat include list and update exclude patterns --- tsconfig.build.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tsconfig.build.json b/tsconfig.build.json index cb069b0a..8c581ebc 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -8,9 +8,7 @@ "outDir": "./dist", "sourceMap": false }, - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "exclude": [ "**/*.test.ts", "**/tests/**/*.ts", From 1d5f3cd99127f09b62a9cac9595c9f988ffa8c74 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Fri, 8 May 2026 21:39:32 +0300 Subject: [PATCH 12/20] fix(parsers): exclude `this` parameter from signature generation - Updated `SignatureBuilder` to filter out `this` parameters in method signatures. - Adjusted tests in `ExpressionFile` to reflect changes in method return type. - Refined type usage and formatting in service definition for consistency. --- .../entrypoint/file/ExpressionFile.test.ts | 2 +- .../file/parsers/SignatureBuilder.ts | 28 ++++++++++--------- .../literal-with-define-init-object.ts | 8 +++--- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/cli/entrypoint/file/ExpressionFile.test.ts b/src/cli/entrypoint/file/ExpressionFile.test.ts index 7971c710..3d2e9c2e 100644 --- a/src/cli/entrypoint/file/ExpressionFile.test.ts +++ b/src/cli/entrypoint/file/ExpressionFile.test.ts @@ -311,7 +311,7 @@ describe("ExpressionFile", () => { ); const type = ExpressionFile.make(filename).setDefinition("defineService").setProperty("init").getType(); - expect(type).toBe("{ ping(): Promise; }"); + expect(type).toBe("{ ping(): Promise; }"); }); }); }); diff --git a/src/cli/entrypoint/file/parsers/SignatureBuilder.ts b/src/cli/entrypoint/file/parsers/SignatureBuilder.ts index 2f57c162..084f072a 100644 --- a/src/cli/entrypoint/file/parsers/SignatureBuilder.ts +++ b/src/cli/entrypoint/file/parsers/SignatureBuilder.ts @@ -34,19 +34,21 @@ export default class SignatureBuilder { : new Map(); // parameters - const params: ParameterSignature[] = ("parameters" in method ? method.parameters : []).map(p => { - const name = ts.isIdentifier(p.name) ? p.name.text : p.name.getText(); - - // Use JSDoc type if available, otherwise use TypeScript type - const tsType = p.type ? this.typeResolver.resolveTypeNode(p.type) : "any"; - const jsDocType = jsDocParamTypes.get(name); - const type = jsDocType || tsType; - - // Remove spaces in object types to match expected format - const formattedType = type.replace(/\{\s+/g, "{").replace(/\s+\}/g, "}"); - const optional = p.questionToken !== undefined || p.initializer !== undefined; - return {name, type: formattedType, optional}; - }); + const params: ParameterSignature[] = ("parameters" in method ? method.parameters : []) + .filter(p => p.name.getText() !== "this") + .map(p => { + const name = ts.isIdentifier(p.name) ? p.name.text : p.name.getText(); + + // Use JSDoc type if available, otherwise use TypeScript type + const tsType = p.type ? this.typeResolver.resolveTypeNode(p.type) : "any"; + const jsDocType = jsDocParamTypes.get(name); + const type = jsDocType || tsType; + + // Remove spaces in object types to match expected format + const formattedType = type.replace(/\{\s+/g, "{").replace(/\s+\}/g, "}"); + const optional = p.questionToken !== undefined || p.initializer !== undefined; + return {name, type: formattedType, optional}; + }); // Get JSDoc type parameters if available, otherwise use TypeScript type parameters let typeParams: string[] = []; diff --git a/src/cli/entrypoint/file/tests/fixtures/expression/object-exports/with-init-methods/literal-with-define-init-object.ts b/src/cli/entrypoint/file/tests/fixtures/expression/object-exports/with-init-methods/literal-with-define-init-object.ts index 517a7cfd..102fe2f9 100644 --- a/src/cli/entrypoint/file/tests/fixtures/expression/object-exports/with-init-methods/literal-with-define-init-object.ts +++ b/src/cli/entrypoint/file/tests/fixtures/expression/object-exports/with-init-methods/literal-with-define-init-object.ts @@ -1,12 +1,12 @@ import {defineService} from "adnbn"; -import {MessageSenderAware} from "adnbn/message"; +import type {MessageSenderAware} from "adnbn/message"; export default defineService({ init() { return { - async ping(): Promise { - console.log('pong'); + async ping(this: MessageSenderAware): Promise { + return this.$sender?.tab?.id; } } as MessageSenderAware; } -}); \ No newline at end of file +}); From 6acda7daf7d26ab39643667991af5d5d61d2ffbb Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Fri, 8 May 2026 22:01:34 +0300 Subject: [PATCH 13/20] fix(parsers): correct regex patterns for object type formatting in `SignatureBuilder` --- src/cli/entrypoint/file/parsers/SignatureBuilder.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cli/entrypoint/file/parsers/SignatureBuilder.ts b/src/cli/entrypoint/file/parsers/SignatureBuilder.ts index 084f072a..cbe031f7 100644 --- a/src/cli/entrypoint/file/parsers/SignatureBuilder.ts +++ b/src/cli/entrypoint/file/parsers/SignatureBuilder.ts @@ -45,7 +45,7 @@ export default class SignatureBuilder { const type = jsDocType || tsType; // Remove spaces in object types to match expected format - const formattedType = type.replace(/\{\s+/g, "{").replace(/\s+\}/g, "}"); + const formattedType = type.replace(/{\s+/g, "{").replace(/\s+}/g, "}"); const optional = p.questionToken !== undefined || p.initializer !== undefined; return {name, type: formattedType, optional}; }); @@ -80,7 +80,7 @@ export default class SignatureBuilder { const returnType = jsDocReturnType || tsReturnType; // Remove spaces in object types to match expected format - const formattedReturnType = returnType.replace(/\{\s+/g, "{").replace(/\s+\}/g, "}"); + const formattedReturnType = returnType.replace(/{\s+/g, "{").replace(/\s+}/g, "}"); return { kind: "method", @@ -121,7 +121,7 @@ export default class SignatureBuilder { let paramType = p.type; if (paramType.includes("@param")) { // This is a parameter with JSDoc comments, extract just the type - const match = paramType.match(/\{([^}]+)\}/); + const match = paramType.match(/{([^}]+)}/); if (match) { paramType = match[1]; } From 2e095daadc23b6f1cea17dca6c3b8c6ba8ac365c Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Fri, 8 May 2026 22:02:03 +0300 Subject: [PATCH 14/20] chore(manifest): remove redundant comment in URL match validation logic --- src/cli/builders/manifest/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/builders/manifest/utils.ts b/src/cli/builders/manifest/utils.ts index e0bbed79..d02d32a2 100644 --- a/src/cli/builders/manifest/utils.ts +++ b/src/cli/builders/manifest/utils.ts @@ -218,7 +218,7 @@ export const mergeWebAccessibleResources = (resources: ManifestAccessibleResourc if (entry.matches.includes("") || entry.matches.includes("*://*/*")) { for (const other of result) { if (other === entry) continue; - // збігаються усі крім resources → можна чистити resources + if ( _.isEqual(other.matches, entry.matches) || other.useDynamicUrl !== entry.useDynamicUrl || From db39da29e7d66d41fa422e48c3c2a258d698089a Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 9 May 2026 00:16:04 +0300 Subject: [PATCH 15/20] feat(offscreen): add lifecycle tests and improve iframe readiness handling - Added tests to validate iframe lifecycle, including creation, readiness, and removal. - Improved offscreen iframe readiness by waiting for a specific "ready" message. - Updated timeout handling for iframe readiness and added error messaging. --- .codex/skills/offscreen/SKILL.md | 95 +++++++++ .codex/skills/offscreen/agents/openai.yaml | 4 + .mailmap | 2 - package-lock.json | 237 +++------------------ package.json | 4 +- src/entry/offscreen/Builder.ts | 12 +- src/main/offscreen.ts | 2 +- src/offscreen/OffscreenBridge.test.ts | 203 ++++++++++++++++++ src/offscreen/OffscreenBridge.ts | 81 ++++++- src/offscreen/providers/Offscreen.test.ts | 200 +++++++++++++++-- src/offscreen/providers/ProxyOffscreen.ts | 91 +++++--- src/relay/providers/Relay.test.ts | 54 +++-- src/transport/RegisterTransport.test.ts | 126 +++++++++++ src/transport/RegisterTransport.ts | 35 ++- src/types/message.ts | 4 +- src/types/offscreen.ts | 1 + tests/jest.modules.setup.ts | 10 +- tests/jest.relay.setup.ts | 25 ++- 18 files changed, 855 insertions(+), 331 deletions(-) create mode 100644 .codex/skills/offscreen/SKILL.md create mode 100644 .codex/skills/offscreen/agents/openai.yaml delete mode 100644 .mailmap create mode 100644 src/offscreen/OffscreenBridge.test.ts create mode 100644 src/transport/RegisterTransport.test.ts diff --git a/.codex/skills/offscreen/SKILL.md b/.codex/skills/offscreen/SKILL.md new file mode 100644 index 00000000..3eb72168 --- /dev/null +++ b/.codex/skills/offscreen/SKILL.md @@ -0,0 +1,95 @@ +--- +name: offscreen +description: Project guidance for addon-bone offscreen transport work. Use when changing or reviewing ProxyOffscreen scheduling, OffscreenBridge Firefox iframe fallback, request-scoped $sender transport context, SignatureBuilder transport signatures, or related offscreen/service/relay tests in /Users/anjeytsibylskij/Documents/AddonStack/addon-bone. +--- + +# Addon Bone Offscreen Transport + +## Core Map + +Use the real checkout as source of truth. Start with these files: + +- `src/offscreen/providers/ProxyOffscreen.ts` for Chrome MV3 offscreen lifecycle and Web Locks scheduling. +- `src/offscreen/OffscreenBridge.ts` and `src/entry/offscreen/Builder.ts` for Firefox iframe fallback readiness. +- `src/transport/RegisterTransport.ts` and `src/types/message.ts` for request-scoped `$sender`. +- `src/cli/entrypoint/file/parsers/SignatureBuilder.ts` for generated transport method signatures. +- `src/offscreen/providers/Offscreen.test.ts`, `src/offscreen/OffscreenBridge.test.ts`, `src/transport/RegisterTransport.test.ts`, and `src/relay/providers/Relay.test.ts` for behavior contracts. + +## Offscreen Scheduling + +Keep orchestration in `ProxyOffscreen`, not in `@addon-core/browser`. The browser package is utility-only: direct API access, simple helpers, and no locks or side effects. + +Chrome MV3 offscreen scheduling uses two Web Locks: + +- Gate lock: serializes lifecycle decisions so multiple contexts cannot race through `hasOffscreenPath()` and `createOffscreen()`. +- Active lock: shared while same-URL calls are executing, exclusive while switching URL/closing/creating offscreen. + +Preserve the intended behavior: + +- Same offscreen URL calls may run in parallel. +- Different offscreen URL calls must wait until active calls finish before closing/recreating the document. +- Release active locks in `finally` around message calls and lifecycle creation paths. +- `acquireLock()` intentionally keeps the Web Lock callback pending and exposes its resolver as a manual release function. +- Do not reintroduce singleton URL state in `ProxyOffscreen`; different proxy instances may legitimately target different offscreen URLs. + +Content scripts cannot rely on `chrome.runtime.getContexts`; direct offscreen lifecycle checks from content script fail in Chrome. Treat content-script offscreen lifecycle as a separate design problem, not as a small bug in `ProxyOffscreen`. + +## Firefox Bridge + +Firefox uses background page plus iframe fallback, not native `chrome.offscreen`. `OffscreenBridge.createOffscreen()` must mean "the iframe offscreen transport is ready", not merely "the iframe loaded". + +Preserve this handshake: + +- `OffscreenBridge` creates or reuses the iframe. +- The offscreen entry builder sets `OffscreenGlobalAccess` early only to mark offscreen scope. Do not use it as readiness. +- After `transport.build()` and optional `view.build()`, the builder calls `ready()`. +- `ready()` posts `{ type: OffscreenBridgeReadyMessageType }` to `window.parent` only when running inside an iframe. +- `OffscreenBridge` resolves creation after receiving that `postMessage` from the exact iframe `contentWindow` and same `location.origin`. + +Do not fall back to `iframe.onload` as the readiness signal. It races with listener registration and can produce "Receiving end does not exist" in Firefox. + +`framesReady` is a `Map>` for in-flight readiness promises by URL. It deduplicates concurrent `create()` calls for the same iframe URL and must be cleaned up in `finally` after success or failure. `data-ready="true"` is DOM state recovery for an existing ready iframe after the in-flight promise has been removed. + +On bridge failure paths, reject with an `Error`, not `undefined`. `iframe.onerror` should remove the iframe and reject with a load error. Ready timeout should use `readyTimeout`, remove the iframe, and reject with a timeout error so the next attempt starts from a clean iframe. + +## Sender Context + +`$sender` is a framework-reserved runtime property for service/offscreen transport methods. It is request-scoped and exposed through a `Proxy` in `RegisterTransport.withSender()`. + +Preserve these rules: + +- Do not mutate the real registered instance with `$sender`. +- Do not add `_sender` aliases. +- Use `Reflect.get(target, property, receiver)` for normal property reads. +- Invoke methods with `property.apply(context, args)` so `this.$sender` works. +- Parallel calls on the same instance must each observe their own sender. + +Developer-facing usage: + +```ts +import type {MessageSenderAware} from "adnbn/message"; + +export default () => ({ + async ping(this: MessageSenderAware) { + return this.$sender?.tab?.id; + }, +}); +``` + +Generated transport types must not include the TypeScript `this` parameter. `SignatureBuilder.getMethodSignature()` filters parameters where `p.name.getText() === "this"`. + +## Testing And Validation + +Use focused tests first, then broader validation when touching shared transport behavior: + +```bash +npm run typecheck +npm run test:offscreen -- --runInBand --detectOpenHandles +npm test -- src/transport/RegisterTransport.test.ts --runInBand --detectOpenHandles +npm run test:entrypoint -- --runInBand --detectOpenHandles +npm test -- --runInBand --detectOpenHandles +npm run build +npm run build --prefix addon +``` + +For manual addon checks, use `addon/src/shared/background.ts` and `addon/src/shared/popup.tsx` patterns. Background/popup sender identity usually appears through `sender.url` and `sender.origin`; `sender.tab.url` is not expected for extension pages. diff --git a/.codex/skills/offscreen/agents/openai.yaml b/.codex/skills/offscreen/agents/openai.yaml new file mode 100644 index 00000000..c2116444 --- /dev/null +++ b/.codex/skills/offscreen/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Offscreen" + short_description: "Offscreen transport project guide." + default_prompt: "Use $offscreen to change or review addon-bone offscreen transport behavior." diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 2f327b19..00000000 --- a/.mailmap +++ /dev/null @@ -1,2 +0,0 @@ -Addon Stack <191148085+addon-stack@users.noreply.github.com> -Addon Stack \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 493756ea..418c0e8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,9 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@addon-core/browser": "^0.2.1", + "@addon-core/browser": "^0.6.0", "@addon-core/inject-script": "^0.3.1", - "@addon-core/storage": "^0.4.0", + "@addon-core/storage": "^0.6.0", "@rsdoctor/rspack-plugin": "^1.5.1", "@rspack/cli": "^1.7.5", "@rspack/core": "^1.7.5", @@ -115,9 +115,9 @@ "license": "MIT" }, "node_modules/@addon-core/browser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@addon-core/browser/-/browser-0.2.3.tgz", - "integrity": "sha512-q0wIKy682I8WxssCB5YmKzZzx1kD1wXur5ddCFD9zupZGmY7k+F7+w3gPh983oCGLDpTEk72s19cUfdQppIXGg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@addon-core/browser/-/browser-0.6.0.tgz", + "integrity": "sha512-nMnv+q6ObOAaAfiAdgTVmbQddw4pUIume4/AK7n+mUqPrGPtjFsrd06/xjH23n4YLHkxB5ousCXSOeh3XnSc0w==", "license": "MIT", "peerDependencies": { "@types/chrome": "*" @@ -133,13 +133,22 @@ "nanoid": "^5.1.5" } }, + "node_modules/@addon-core/inject-script/node_modules/@addon-core/browser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@addon-core/browser/-/browser-0.2.3.tgz", + "integrity": "sha512-q0wIKy682I8WxssCB5YmKzZzx1kD1wXur5ddCFD9zupZGmY7k+F7+w3gPh983oCGLDpTEk72s19cUfdQppIXGg==", + "license": "MIT", + "peerDependencies": { + "@types/chrome": "*" + } + }, "node_modules/@addon-core/storage": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@addon-core/storage/-/storage-0.4.0.tgz", - "integrity": "sha512-BTsqMr18n2xvLNa7qtzzyhkzbAqV+bpy2Qh1nRoszzl+IxPPdTZvnasWKYTkllisAfj/ktFHcXnUWT6ukORqDQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@addon-core/storage/-/storage-0.6.0.tgz", + "integrity": "sha512-N483T9Guk+8T1BJEDeOmuXRuzyC26+d57yf5egUJh7bQiOmz+9vftBWBMjKkhbnV23Vk6RI+vSA3EkMmG23SQw==", "license": "MIT", "dependencies": { - "@addon-core/browser": "^0.2.1", + "@addon-core/browser": "^0.5.0", "dequal": "^2.0.3" }, "peerDependencies": { @@ -158,6 +167,15 @@ } } }, + "node_modules/@addon-core/storage/node_modules/@addon-core/browser": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@addon-core/browser/-/browser-0.5.0.tgz", + "integrity": "sha512-xFi/dFcJYNblW+esBkJ2D5ind6Yydcj3yJnwVocILjDuV1oyxD9Qlh+K3FJnRprwdlqhxeo/E06KFoS6lWSO+g==", + "license": "MIT", + "peerDependencies": { + "@types/chrome": "*" + } + }, "node_modules/@adobe/css-tools": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", @@ -2404,30 +2422,6 @@ } } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -3686,16 +3680,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/core/node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/@jest/core/node_modules/jest-config": { "version": "30.3.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", @@ -3844,60 +3828,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/core/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/@jest/create-cache-key-function": { "version": "30.3.0", "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-30.3.0.tgz", @@ -7649,34 +7579,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "extraneous": true, - "license": "MIT" - }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -8905,13 +8807,6 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "extraneous": true, - "license": "MIT" - }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -10224,13 +10119,6 @@ "typescript": ">=5" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "extraneous": true, - "license": "MIT" - }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -13276,16 +13164,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-cli/node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/jest-cli/node_modules/jest-config": { "version": "30.3.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz", @@ -13413,60 +13291,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-cli/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -20582,13 +20406,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "extraneous": true, - "license": "MIT" - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", diff --git a/package.json b/package.json index d32bc8af..28b71e07 100644 --- a/package.json +++ b/package.json @@ -120,9 +120,9 @@ "release:preview": "release-it --no-github.release --no-npm.publish --no-git.tag --ci" }, "dependencies": { - "@addon-core/browser": "^0.2.1", + "@addon-core/browser": "^0.6.0", "@addon-core/inject-script": "^0.3.1", - "@addon-core/storage": "^0.4.0", + "@addon-core/storage": "^0.6.0", "@rsdoctor/rspack-plugin": "^1.5.1", "@rspack/cli": "^1.7.5", "@rspack/core": "^1.7.5", diff --git a/src/entry/offscreen/Builder.ts b/src/entry/offscreen/Builder.ts index c3f49480..6425631e 100644 --- a/src/entry/offscreen/Builder.ts +++ b/src/entry/offscreen/Builder.ts @@ -2,7 +2,7 @@ import TransportBuilder from "./TransportBuilder"; import Builder from "../core/Builder"; -import {OffscreenGlobalAccess, OffscreenUnresolvedDefinition} from "@typing/offscreen"; +import {OffscreenBridgeReadyMessageType, OffscreenGlobalAccess, OffscreenUnresolvedDefinition} from "@typing/offscreen"; import {TransportType} from "@typing/transport"; import {ViewBuilder} from "@typing/view"; @@ -30,10 +30,20 @@ export default class extends Builder { await this._transport.build(); await this._view?.build(); + + this.ready(); } public async destroy(): Promise { await this._transport.destroy(); await this._view?.destroy(); } + + private ready(): void { + if (window.parent === window) { + return; + } + + window.parent.postMessage({type: OffscreenBridgeReadyMessageType}, location.origin); + } } diff --git a/src/main/offscreen.ts b/src/main/offscreen.ts index c9dafa90..a43e5a05 100644 --- a/src/main/offscreen.ts +++ b/src/main/offscreen.ts @@ -40,5 +40,5 @@ export const getOffscreen = ; + +const parameters = { + reasons: ["TESTING" as const], + url: "offscreen.html", + justification: "for testing", +}; + +const wait = () => new Promise(resolve => setTimeout(resolve)); +const dispatchReady = (iframe: HTMLIFrameElement) => { + window.dispatchEvent( + new MessageEvent("message", { + data: {type: OffscreenBridgeReadyMessageType}, + origin: location.origin, + source: iframe.contentWindow, + }) + ); +}; + +describe("OffscreenBridge", () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.restoreAllMocks(); + + document.body.innerHTML = ""; + mockedIsBackground.mockReturnValue(true); + + (OffscreenBridge as any).instance = undefined; + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test("creates an iframe in background context", async () => { + const bridge = new OffscreenBridge(); + const creation = bridge.create(parameters); + const iframe = document.querySelector("iframe"); + + expect(iframe).not.toBeNull(); + expect(iframe?.getAttribute("src")).toBe(parameters.url); + + dispatchReady(iframe!); + + await expect(creation).resolves.toBeUndefined(); + }); + + test("waits for ready message instead of iframe load", async () => { + const bridge = new OffscreenBridge(); + const creation = bridge.create(parameters); + const iframe = document.querySelector("iframe"); + let resolved = false; + + creation.then(() => { + resolved = true; + }); + + iframe!.dispatchEvent(new Event("load")); + await wait(); + + expect(resolved).toBe(false); + + dispatchReady(iframe!); + + await expect(creation).resolves.toBeUndefined(); + expect(resolved).toBe(true); + }); + + test("sends creation request through message outside background context", async () => { + mockedIsBackground.mockReturnValue(false); + + const send = jest.spyOn(Message.prototype, "send").mockResolvedValue(undefined); + const bridge = new OffscreenBridge(); + + await expect(bridge.create(parameters)).resolves.toBeUndefined(); + + expect(send).toHaveBeenCalledWith("offscreen-background", parameters); + expect(document.querySelector("iframe")).toBeNull(); + }); + + test("uses a singleton instance for static createOffscreen", async () => { + const create = jest.spyOn(OffscreenBridge.prototype, "create").mockResolvedValue(undefined); + + await OffscreenBridge.createOffscreen(parameters); + await OffscreenBridge.createOffscreen(parameters); + + expect(create).toHaveBeenCalledTimes(2); + expect(create.mock.instances[0]).toBe(create.mock.instances[1]); + expect(create).toHaveBeenNthCalledWith(1, parameters); + expect(create).toHaveBeenNthCalledWith(2, parameters); + }); + + test("waits for an in-flight iframe creation when the same URL is requested again", async () => { + const bridge = new OffscreenBridge(); + const first = bridge.create(parameters); + const second = bridge.create(parameters); + + const iframe = document.querySelector("iframe"); + let secondResolved = false; + + second.then(() => { + secondResolved = true; + }); + + await wait(); + + expect(document.querySelectorAll("iframe")).toHaveLength(1); + expect(iframe).not.toBeNull(); + expect(secondResolved).toBe(false); + + dispatchReady(iframe!); + + await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]); + expect(secondResolved).toBe(true); + }); + + test("creates independent iframes for different URLs", async () => { + const bridge = new OffscreenBridge(); + const otherParameters = {...parameters, url: "other-offscreen.html"}; + + const first = bridge.create(parameters); + const second = bridge.create(otherParameters); + const frames = document.querySelectorAll("iframe"); + + expect(frames).toHaveLength(2); + expect(frames[0].getAttribute("src")).toBe(parameters.url); + expect(frames[1].getAttribute("src")).toBe(otherParameters.url); + + dispatchReady(frames[0]); + dispatchReady(frames[1]); + + await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]); + }); + + test("reuses an already ready iframe for the same URL", async () => { + const bridge = new OffscreenBridge(); + + const first = bridge.create(parameters); + const iframe = document.querySelector("iframe"); + + dispatchReady(iframe!); + + await first; + await expect(bridge.create(parameters)).resolves.toBeUndefined(); + + expect(document.querySelectorAll("iframe")).toHaveLength(1); + }); + + test("rejects and removes the iframe when creation fails", async () => { + const bridge = new OffscreenBridge(); + + const first = bridge.create(parameters); + const iframe = document.querySelector("iframe"); + + iframe!.dispatchEvent(new Event("error")); + + await expect(first).rejects.toThrow(`Offscreen iframe failed to load: ${parameters.url}`); + expect(document.querySelector("iframe")).toBeNull(); + + const second = bridge.create(parameters); + const nextIframe = document.querySelector("iframe"); + + expect(nextIframe).not.toBeNull(); + expect(nextIframe).not.toBe(iframe); + + dispatchReady(nextIframe!); + + await expect(second).resolves.toBeUndefined(); + }); + + test("removes the iframe when ready message times out", async () => { + jest.useFakeTimers(); + + const bridge = new OffscreenBridge(); + + const first = bridge.create(parameters); + const iframe = document.querySelector("iframe"); + const rejection = expect(first).rejects.toThrow(`Offscreen iframe "${parameters.url}" was not ready in time.`); + + jest.runOnlyPendingTimers(); + + await rejection; + expect(document.querySelector("iframe")).toBeNull(); + + const second = bridge.create(parameters); + const nextIframe = document.querySelector("iframe"); + + expect(nextIframe).not.toBeNull(); + expect(nextIframe).not.toBe(iframe); + + dispatchReady(nextIframe!); + + await expect(second).resolves.toBeUndefined(); + }); +}); diff --git a/src/offscreen/OffscreenBridge.ts b/src/offscreen/OffscreenBridge.ts index f6bd8d68..5e09b29d 100644 --- a/src/offscreen/OffscreenBridge.ts +++ b/src/offscreen/OffscreenBridge.ts @@ -2,6 +2,8 @@ import {isBackground} from "@addon-core/browser"; import {Message} from "@message/providers"; +import {OffscreenBridgeReadyMessageType} from "@typing/offscreen"; + type CreateParameters = chrome.offscreen.CreateParameters; export default class OffscreenBridge { @@ -9,6 +11,10 @@ export default class OffscreenBridge { protected readonly message = new Message(); + protected readonly readyTimeout = 10000; + + private readonly framesReady: Map> = new Map(); + private static instance?: OffscreenBridge; public static getInstance(): OffscreenBridge { @@ -30,20 +36,79 @@ export default class OffscreenBridge { } protected apply({url}: CreateParameters): Promise { + const ready = this.framesReady.get(url); + + if (ready) { + return ready; + } + + const existing = this.getFrame(url); + + if (existing?.dataset.ready === "true") { + return Promise.resolve(); + } + + const creation = this.createFrame(url, existing).finally(() => { + this.framesReady.delete(url); + }); + + this.framesReady.set(url, creation); + + return creation; + } + + private createFrame(url: string, existing?: HTMLIFrameElement): Promise { return new Promise((resolve, reject) => { - if (document.querySelector(`iframe[src="${url}"]`)) { + const iframe = existing ?? document.createElement("iframe"); + + const cleanup = () => { + clearTimeout(timeout); + window.removeEventListener("message", listener); + iframe.onerror = null; + }; + + const listener = (event: MessageEvent) => { + if (event.source !== iframe.contentWindow) { + return; + } + + if (event.origin !== location.origin) { + return; + } + + if (event.data?.type !== OffscreenBridgeReadyMessageType) { + return; + } + + iframe.dataset.ready = "true"; + + cleanup(); resolve(); + }; - return; - } + const timeout = setTimeout(() => { + cleanup(); + iframe.remove(); + + reject(new Error(`Offscreen iframe "${url}" was not ready in time.`)); + }, this.readyTimeout); - const iframe = document.createElement("iframe"); + iframe.onerror = () => { + cleanup(); + iframe.remove(); + reject(new Error(`Offscreen iframe failed to load: ${url}`)); + }; - iframe.src = url; - iframe.onload = () => resolve(); - iframe.onerror = () => reject(); + window.addEventListener("message", listener); - document.body.appendChild(iframe); + if (!existing) { + iframe.src = url; + document.body.appendChild(iframe); + } }); } + + private getFrame(url: string): HTMLIFrameElement | undefined { + return Array.from(document.querySelectorAll("iframe")).find(iframe => iframe.getAttribute("src") === url); + } } diff --git a/src/offscreen/providers/Offscreen.test.ts b/src/offscreen/providers/Offscreen.test.ts index 39e9dcba..1cba4515 100644 --- a/src/offscreen/providers/Offscreen.test.ts +++ b/src/offscreen/providers/Offscreen.test.ts @@ -1,7 +1,7 @@ -import {closeOffscreen, createOffscreen, hasOffscreen} from "@addon-core/browser"; +import {closeOffscreen, createOffscreen, hasOffscreen, hasOffscreenPath} from "@addon-core/browser"; import {isOffscreen} from "@offscreen/utils"; -import {getBrowser} from "@main/env"; +import {isBrowser} from "@main/env"; import MessageManager from "@message/MessageManager"; @@ -11,14 +11,136 @@ import OffscreenManager from "../OffscreenManager"; import {DeepAsyncProxy} from "@typing/helpers"; import {MessageTypeSeparator} from "@typing/message"; -import {Browser} from "@typing/browser"; jest.mock("@offscreen/utils", () => ({isOffscreen: jest.fn()})); -jest.mock("@main/env", () => ({getBrowser: jest.fn()})); +jest.mock("@main/env", () => ({isBrowser: jest.fn()})); + +const mockedCloseOffscreen = closeOffscreen as jest.MockedFunction; +const mockedCreateOffscreen = createOffscreen as jest.MockedFunction; +const mockedHasOffscreen = hasOffscreen as jest.MockedFunction; +const mockedHasOffscreenPath = hasOffscreenPath as jest.MockedFunction; +const mockedIsBrowser = isBrowser as unknown as jest.Mock; +const mockedIsOffscreen = isOffscreen as jest.MockedFunction; + +type MockLockMode = "exclusive" | "shared"; +type MockLockOptions = {mode: MockLockMode}; +type MockLockCallback = () => unknown | Promise; + +type LockTask = { + mode: MockLockMode; + callback: MockLockCallback; + resolve: (value: unknown) => void; + reject: (error: unknown) => void; +}; + +class MockLockManager { + private readonly queues = new Map(); + + private readonly states = new Map(); + + public request(name: string, options: MockLockOptions, callback: MockLockCallback): Promise { + return new Promise((resolve, reject) => { + const queue = this.queues.get(name) ?? []; + queue.push({mode: options.mode, callback, resolve, reject}); + this.queues.set(name, queue); + this.drain(name); + }); + } + + private state(name: string): {shared: number; exclusive: boolean} { + const state = this.states.get(name) ?? {shared: 0, exclusive: false}; + + this.states.set(name, state); + + return state; + } + + private drain(name: string): void { + const queue = this.queues.get(name); + const state = this.state(name); + + if (!queue?.length || state.exclusive) { + return; + } + + const task = queue[0]; + + if (task.mode === "exclusive") { + if (state.shared > 0) { + return; + } + + queue.shift(); + state.exclusive = true; + this.run(name, task); + + return; + } + + while (queue[0]?.mode === "shared" && !state.exclusive) { + const sharedTask = queue.shift()!; + + state.shared++; + this.run(name, sharedTask); + } + } + + private run(name: string, task: LockTask): void { + Promise.resolve() + .then(task.callback) + .then(task.resolve, task.reject) + .finally(() => { + const state = this.state(name); + + if (task.mode === "exclusive") { + state.exclusive = false; + } else { + state.shared--; + } + + this.drain(name); + }); + } +} + +let existingOffscreenPath: string | undefined; +let blockedResolvers: Array<() => void> = []; +let blockedStarted = 0; + +const wait = (timeout = 0) => new Promise(resolve => setTimeout(resolve, timeout)); +const waitForBlockedCalls = async (count: number): Promise => { + for (let attempt = 0; attempt < 10; attempt++) { + if (blockedStarted >= count) { + return; + } + + await wait(); + } + + throw new Error(`Expected ${count} blocked offscreen calls to start, got ${blockedStarted}`); +}; beforeEach(async () => { jest.clearAllMocks(); + existingOffscreenPath = parameters.url; + blockedResolvers = []; + blockedStarted = 0; + + Object.defineProperty(navigator, "locks", { + configurable: true, + value: new MockLockManager(), + }); + + mockedHasOffscreen.mockImplementation(async () => existingOffscreenPath !== undefined); + mockedHasOffscreenPath.mockImplementation(async (path: string) => existingOffscreenPath === path); + mockedCloseOffscreen.mockImplementation(async () => { + existingOffscreenPath = undefined; + }); + mockedCreateOffscreen.mockImplementation(async (offscreenParameters: chrome.offscreen.CreateParameters) => { + existingOffscreenPath = offscreenParameters.url; + }); + OffscreenManager.getInstance().clear(); MessageManager.getInstance().clear(); @@ -30,6 +152,13 @@ const MatchService = { asyncSum: (a: number, b: number): Promise => { return new Promise(resolve => setTimeout(() => resolve(a + b), 100)); }, + blockedSum: (a: number, b: number): Promise => { + blockedStarted++; + + return new Promise(resolve => { + blockedResolvers.push(() => resolve(a + b)); + }); + }, one: 1, obj: { concat: (a: string, b: string): string => a + " " + b, @@ -49,13 +178,12 @@ const parameters = { describe("ProxyOffscreen", () => { beforeEach(async () => { - (isOffscreen as jest.Mock).mockReturnValue(false); - (hasOffscreen as jest.Mock).mockReturnValue(true); - (getBrowser as jest.Mock).mockReturnValue(Browser.Chrome); + mockedIsOffscreen.mockReturnValue(false); + mockedIsBrowser.mockReturnValue(false); }); test("throws an error when get() is called in offscreen context", async () => { - (isOffscreen as jest.Mock).mockReturnValue(true); + mockedIsOffscreen.mockReturnValue(true); const proxy = new ProxyOffscreen(offscreenName, parameters); @@ -139,14 +267,13 @@ describe("ProxyOffscreen", () => { test("does not recreate offscreen when URL hasn't changed", async () => { jest.clearAllMocks(); - (hasOffscreen as jest.Mock).mockReturnValue(false); + existingOffscreenPath = undefined; const proxyInstance = new ProxyOffscreen(offscreenName, parameters); const offscreen = proxyInstance.get(); await offscreen.sum(1, 2); - (hasOffscreen as jest.Mock).mockReturnValue(true); await offscreen.sum(3, 4); expect(createOffscreen).toHaveBeenCalledTimes(1); @@ -155,13 +282,12 @@ describe("ProxyOffscreen", () => { test("recreates offscreen when URL changes", async () => { jest.clearAllMocks(); - (hasOffscreen as jest.Mock).mockReturnValue(false); + existingOffscreenPath = undefined; const proxyInstance1 = new ProxyOffscreen(offscreenName, parameters); const offscreen1 = proxyInstance1.get(); await offscreen1.sum(1, 2); - (hasOffscreen as jest.Mock).mockReturnValue(true); const differentParams = {...parameters, url: "different-offscreen.html"}; const proxyInstance2 = new ProxyOffscreen( offscreenName, @@ -173,15 +299,61 @@ describe("ProxyOffscreen", () => { expect(createOffscreen).toHaveBeenCalledTimes(2); expect(closeOffscreen).toHaveBeenCalledTimes(1); }); + + test("runs same URL calls in parallel without recreating offscreen", async () => { + const proxyInstance = new ProxyOffscreen(offscreenName, parameters); + const offscreen = proxyInstance.get(); + + const first = offscreen.blockedSum(1, 2); + const second = offscreen.blockedSum(3, 4); + + await waitForBlockedCalls(2); + + blockedResolvers.forEach(resolve => resolve()); + + await expect(Promise.all([first, second])).resolves.toEqual([3, 7]); + + expect(createOffscreen).toHaveBeenCalledTimes(0); + expect(closeOffscreen).toHaveBeenCalledTimes(0); + }); + + test("waits for active calls before switching to a different URL", async () => { + const proxyInstance1 = new ProxyOffscreen(offscreenName, parameters); + const offscreen1 = proxyInstance1.get(); + const first = offscreen1.blockedSum(1, 2); + + await waitForBlockedCalls(1); + + const differentParams = {...parameters, url: "different-offscreen.html"}; + const proxyInstance2 = new ProxyOffscreen( + offscreenName, + differentParams + ); + const offscreen2 = proxyInstance2.get(); + const second = offscreen2.sum(3, 4); + + await wait(); + + expect(createOffscreen).toHaveBeenCalledTimes(0); + expect(closeOffscreen).toHaveBeenCalledTimes(0); + + blockedResolvers[0](); + + await expect(first).resolves.toBe(3); + await expect(second).resolves.toBe(7); + + expect(closeOffscreen).toHaveBeenCalledTimes(1); + expect(createOffscreen).toHaveBeenCalledWith(differentParams); + }); }); describe("RegisterOffscreen", () => { beforeEach(async () => { - (isOffscreen as jest.Mock).mockReturnValue(true); + mockedIsOffscreen.mockReturnValue(true); }); test("throws an error when get() is called outside offscreen context", async () => { - (isOffscreen as jest.Mock).mockReturnValue(false); + mockedIsOffscreen.mockReturnValue(false); const proxy = new RegisterOffscreen(offscreenName, () => MatchService); diff --git a/src/offscreen/providers/ProxyOffscreen.ts b/src/offscreen/providers/ProxyOffscreen.ts index 7737cb14..7cada995 100644 --- a/src/offscreen/providers/ProxyOffscreen.ts +++ b/src/offscreen/providers/ProxyOffscreen.ts @@ -1,8 +1,6 @@ -import {closeOffscreen, createOffscreen, hasOffscreen, isManifestVersion3} from "@addon-core/browser"; +import {closeOffscreen, createOffscreen, hasOffscreen, hasOffscreenPath, isManifestVersion3} from "@addon-core/browser"; -import {getBrowser} from "@main/env"; - -import {__t} from "@locale/helpers"; +import {isBrowser} from "@main/env"; import ProxyTransport from "@transport/ProxyTransport"; @@ -17,6 +15,10 @@ import {DeepAsyncProxy} from "@typing/helpers"; import {TransportDictionary, TransportManager, TransportMessage, TransportName} from "@typing/transport"; type CreateParameters = chrome.offscreen.CreateParameters; +type ReleaseLock = () => void; + +const GateLockName = "adnbn:offscreen:gate"; +const ActiveLockName = "adnbn:offscreen:active"; export default class ProxyOffscreen< N extends TransportName, @@ -24,17 +26,6 @@ export default class ProxyOffscreen< > extends ProxyTransport { protected message: TransportMessage; - private url?: string; - - private static instance?: ProxyOffscreen; - - public static getInstance>( - name: N, - parameters: CreateParameters - ): ProxyOffscreen { - return (this.instance ??= new ProxyOffscreen(name, parameters)); - } - constructor( name: N, private parameters: CreateParameters @@ -49,28 +40,62 @@ export default class ProxyOffscreen< } protected async apply(args: any[], path?: string): Promise { - const parameters: CreateParameters = { - ...this.parameters, - justification: __t(this.parameters.justification), - }; - - if (!isManifestVersion3() || getBrowser() === Browser.Firefox) { - await OffscreenBridge.createOffscreen(parameters); - } else { - const exists = await hasOffscreen(); - - if (!exists || this.url !== parameters.url) { - if (exists) { - await closeOffscreen(); - } + if (!isManifestVersion3() || isBrowser(Browser.Firefox)) { + await OffscreenBridge.createOffscreen(this.parameters); + + return this.message.send({path, args}); + } - await createOffscreen(parameters); + const release = await this.acquire(this.parameters); - this.url = parameters.url; - } + try { + return await this.message.send({path, args}); + } finally { + release(); } + } + + private async acquire(parameters: CreateParameters): Promise { + return navigator.locks.request(GateLockName, {mode: "exclusive"}, async () => { + if (await hasOffscreenPath(parameters.url)) { + return this.acquireLock(ActiveLockName, {mode: "shared"}); + } + + const releaseActive = await this.acquireLock(ActiveLockName, {mode: "exclusive"}); + + try { + if (!(await hasOffscreenPath(parameters.url))) { + if (await hasOffscreen()) { + await closeOffscreen(); + } + + await createOffscreen(parameters); + } + } finally { + releaseActive(); + } + + return this.acquireLock(ActiveLockName, {mode: "shared"}); + }); + } + + private async acquireLock(name: string, options: LockOptions): Promise { + let releaseLock!: ReleaseLock; + + // Keep the Web Lock callback pending and expose its resolver as a manual release function. + const lockHeld = new Promise(resolve => { + releaseLock = resolve; + }); + + return new Promise((resolve, reject) => { + navigator.locks + .request(name, options, async () => { + resolve(releaseLock); - return this.message.send({path, args}); + await lockHeld; + }) + .catch(reject); + }); } public get(): T { diff --git a/src/relay/providers/Relay.test.ts b/src/relay/providers/Relay.test.ts index d5cf04cc..274953f9 100644 --- a/src/relay/providers/Relay.test.ts +++ b/src/relay/providers/Relay.test.ts @@ -41,6 +41,12 @@ const options: RelayOptions = { method: RelayMethod.Scripting, }; +const expectScriptInjection = (expected: Partial>) => { + const [injection] = (chrome.scripting.executeScript as jest.Mock).mock.calls.at(-1); + + expect(injection).toEqual(expect.objectContaining(expected)); +}; + describe("ProxyRelay", () => { beforeEach(async () => { (isRelayContext as jest.Mock).mockReturnValue(false); @@ -69,13 +75,11 @@ describe("ProxyRelay", () => { expect(chrome.scripting.executeScript).toHaveBeenCalledTimes(1); - expect(chrome.scripting.executeScript).toHaveBeenCalledWith( - expect.objectContaining({ - target: {tabId: 1}, - func: expect.any(Function), - args: [relayName, "sum", [1, 2], RelayGlobalKey], - }) - ); + expectScriptInjection({ + target: {tabId: 1}, + func: expect.any(Function), + args: [relayName, "sum", [1, 2], RelayGlobalKey], + }); }); test("accesses primitive value as method on the relay object", async () => { @@ -85,35 +89,29 @@ describe("ProxyRelay", () => { }).get(); expect(await relay.one()).toBe(1); - expect(chrome.scripting.executeScript).toHaveBeenCalledWith( - expect.objectContaining({ - target: {tabId: 1, frameIds: [2]}, - func: expect.any(Function), - args: [relayName, "one", [], RelayGlobalKey], - }) - ); + expectScriptInjection({ + target: {tabId: 1, frameIds: [2]}, + func: expect.any(Function), + args: [relayName, "one", [], RelayGlobalKey], + }); }); test("accesses nested method or property ", async () => { const relay = new ProxyRelay(relayName, options, 1).get(); expect(await relay.obj.concat("Hello", "world")).toBe("Hello world"); - expect(chrome.scripting.executeScript).toHaveBeenCalledWith( - expect.objectContaining({ - target: {tabId: 1}, - func: expect.any(Function), - args: [relayName, "obj.concat", ["Hello", "world"], RelayGlobalKey], - }) - ); + expectScriptInjection({ + target: {tabId: 1}, + func: expect.any(Function), + args: [relayName, "obj.concat", ["Hello", "world"], RelayGlobalKey], + }); expect(await relay.obj.zero()).toBe(0); - expect(chrome.scripting.executeScript).toHaveBeenCalledWith( - expect.objectContaining({ - target: {tabId: 1}, - func: expect.any(Function), - args: [relayName, "obj.zero", [], RelayGlobalKey], - }) - ); + expectScriptInjection({ + target: {tabId: 1}, + func: expect.any(Function), + args: [relayName, "obj.zero", [], RelayGlobalKey], + }); }); test("calls async method on proxy and returns resolved value", async () => { diff --git a/src/transport/RegisterTransport.test.ts b/src/transport/RegisterTransport.test.ts new file mode 100644 index 00000000..22493aa8 --- /dev/null +++ b/src/transport/RegisterTransport.test.ts @@ -0,0 +1,126 @@ +import RegisterTransport from "./RegisterTransport"; +import TransportManager from "./TransportManager"; + +import {MessageSenderProperty, type MessageSender, type MessageSenderAware} from "@typing/message"; +import type {TransportMessage, TransportMessageData} from "@typing/transport"; + +class TestManager extends TransportManager {} + +class TestMessage implements TransportMessage { + private handler?: (data: TransportMessageData, sender: MessageSender) => any; + + public send(): void {} + + public watch(handler: (data: TransportMessageData, sender: MessageSender) => any): void { + this.handler = handler; + } + + public dispatch(data: TransportMessageData, sender: MessageSender): Promise { + if (!this.handler) { + throw new Error("Handler is not registered"); + } + + return Promise.resolve(this.handler(data, sender)); + } +} + +class TestRegister extends RegisterTransport<"test", T> { + constructor( + init: () => T, + private readonly transportMessage: TestMessage, + private readonly transportManager: TestManager + ) { + super("test", init); + } + + protected message(): TransportMessage { + return this.transportMessage; + } + + protected manager(): TestManager { + return this.transportManager; + } +} + +const createSender = (url: string, tabId = 1): MessageSender => ({ + url, + tab: {id: tabId} as chrome.tabs.Tab, +}); + +const wait = () => new Promise(resolve => setTimeout(resolve)); + +describe("RegisterTransport", () => { + let manager: TestManager; + let message: TestMessage; + + beforeEach(() => { + manager = new TestManager(); + message = new TestMessage(); + }); + + test("exposes sender on the call-scoped execution context", async () => { + const instance = new TestRegister( + () => ({ + getSenderTabId(this: MessageSenderAware): number | undefined { + return this.$sender?.tab?.id; + }, + }), + message, + manager + ).register(); + + await expect( + message.dispatch({path: "getSenderTabId", args: []}, createSender("https://example.com", 42)) + ).resolves.toBe(42); + + expect(Object.hasOwn(instance, MessageSenderProperty)).toBe(false); + }); + + test("exposes sender to nested transport methods", async () => { + new TestRegister( + () => ({ + nested: { + getSenderUrl(this: MessageSenderAware): string | undefined { + return this.$sender?.url; + }, + }, + }), + message, + manager + ).register(); + + await expect( + message.dispatch({path: "nested.getSenderUrl", args: []}, createSender("https://nested.test")) + ).resolves.toBe("https://nested.test"); + }); + + test("keeps sender isolated between parallel calls", async () => { + const releases: Array<() => void> = []; + + const instance = new TestRegister( + () => ({ + async getSenderAfterWait(this: MessageSenderAware): Promise { + await new Promise(resolve => { + releases.push(resolve); + }); + + return this.$sender?.url; + }, + }), + message, + manager + ).register(); + + const first = message.dispatch({path: "getSenderAfterWait", args: []}, createSender("https://first.test")); + const second = message.dispatch({path: "getSenderAfterWait", args: []}, createSender("https://second.test")); + + await wait(); + + expect(releases).toHaveLength(2); + + releases.forEach(resolve => resolve()); + + await expect(Promise.all([first, second])).resolves.toEqual(["https://first.test", "https://second.test"]); + expect(Object.hasOwn(instance, MessageSenderProperty)).toBe(false); + }); +}); diff --git a/src/transport/RegisterTransport.ts b/src/transport/RegisterTransport.ts index 91920177..1de665b6 100644 --- a/src/transport/RegisterTransport.ts +++ b/src/transport/RegisterTransport.ts @@ -31,9 +31,9 @@ export default abstract class< this.message().watch(async ({path, args}, sender) => { try { - this.injectSender(instance, sender); + const context = this.withSender(instance, sender); - const property = path == null ? instance : get(instance, path); + const property = path == null ? context : get(context, path); if (property === undefined) { throw new Error(`Property not found at path "${path}" in "${this.name}"`); @@ -42,19 +42,15 @@ export default abstract class< let result: any; if (typeof property === "function") { - result = await property.apply(instance, args); + result = await property.apply(context, args); } else { result = property; } - this.clearSender(instance); - return result; } catch (error) { console.error(`Error during message handler registration for transport "${this.name}"`, error); - this.clearSender(instance); - throw error; } }); @@ -62,22 +58,15 @@ export default abstract class< return instance; } - private injectSender(instance: T, sender: MessageSender): void { - if (!Object.getOwnPropertyDescriptor(instance, MessageSenderProperty)) { - Object.defineProperty(instance, MessageSenderProperty, { - configurable: true, - enumerable: false, - writable: true, - value: undefined, - }); - } - - (instance as any)[MessageSenderProperty] = sender; - } + private withSender(instance: T, sender: MessageSender): T { + return new Proxy(instance, { + get(target, property, receiver) { + if (property === MessageSenderProperty) { + return sender; + } - private clearSender(instance: T): void { - if (Object.getOwnPropertyDescriptor(instance, MessageSenderProperty)) { - (instance as any)[MessageSenderProperty] = undefined; - } + return Reflect.get(target, property, receiver); + }, + }); } } diff --git a/src/types/message.ts b/src/types/message.ts index 0799caa3..4aa79b15 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -2,7 +2,7 @@ export const MessageGlobalKey = "adnbnMessage"; export const MessageTypeSeparator = ":"; -export const MessageSenderProperty = "_sender"; +export const MessageSenderProperty = "$sender"; export type MessageSender = chrome.runtime.MessageSender; @@ -13,7 +13,7 @@ export interface MessageDictionary { } export interface MessageSenderAware { - [MessageSenderProperty]?: MessageSender; + readonly [MessageSenderProperty]?: MessageSender; } export type MessageType = Extract; diff --git a/src/types/offscreen.ts b/src/types/offscreen.ts index 07df0e6c..ceeda780 100644 --- a/src/types/offscreen.ts +++ b/src/types/offscreen.ts @@ -4,6 +4,7 @@ import {Awaiter} from "@typing/helpers"; export const OffscreenGlobalKey = "adnbnOffscreen"; export const OffscreenGlobalAccess = "adnbnOffscreenAccess"; +export const OffscreenBridgeReadyMessageType = "adnbn:offscreen:ready"; export enum OffscreenReason { /** A reason used for testing purposes only. */ diff --git a/tests/jest.modules.setup.ts b/tests/jest.modules.setup.ts index eb8e66c8..ea8af8df 100644 --- a/tests/jest.modules.setup.ts +++ b/tests/jest.modules.setup.ts @@ -6,16 +6,24 @@ jest.mock("@addon-core/browser", () => ({ isAvailableScripting: jest.fn(), browser: jest.fn(() => chrome), + isBackground: jest.fn(() => false), isManifestVersion3: jest.fn(() => true), hasOffscreen: jest.fn(), + getOffscreenContext: jest.fn(), + getOffscreenUrl: jest.fn(), + getOffscreenPath: jest.fn(), + hasOffscreenUrl: jest.fn(), + hasOffscreenPath: jest.fn(), closeOffscreen: jest.fn(), createOffscreen: jest.fn(), containsPermissions: jest.fn(() => true), requestPermissions: jest.fn(() => true), - executeScript: chrome.scripting.executeScript, + executeScript: (...args: Parameters) => { + return chrome.scripting.executeScript(...args); + }, sendMessage: (msg: any) => { return new Promise(resolve => { diff --git a/tests/jest.relay.setup.ts b/tests/jest.relay.setup.ts index 86b2a63d..116cda62 100644 --- a/tests/jest.relay.setup.ts +++ b/tests/jest.relay.setup.ts @@ -1,13 +1,26 @@ import {RelayGlobalKey} from "../src/types/relay"; +const resolveScriptingResult = async ({ + args, +}: chrome.scripting.ScriptInjection): Promise => { + const [name, path, callArgs] = args || []; + const relay = (globalThis as any)[RelayGlobalKey].get(name); + const target = path?.split(".").reduce((acc: any, key: string) => acc?.[key], relay); + const result = typeof target === "function" ? await target(...callArgs) : target; + + return [{result}]; +}; + chrome.scripting = { ...chrome.scripting, - executeScript: jest.fn().mockImplementation(async ({args}) => { - const [name, path, callArgs] = args; - const relay = (globalThis as any)[RelayGlobalKey].get(name); - const target = path?.split(".").reduce((acc: any, key: string) => acc?.[key], relay); - const result = typeof target === "function" ? await target(...callArgs) : target; - return [{result}]; + executeScript: jest.fn().mockImplementation((injection, callback) => { + const result = resolveScriptingResult(injection); + + if (callback) { + result.then(callback); + } + + return result; }), }; From 209be45ad7c1681d05fb18c466049320829f4513 Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 9 May 2026 00:33:25 +0300 Subject: [PATCH 16/20] chore(deps): bump lodash to v4.18.1 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 418c0e8b..7600a718 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "html-rspack-tags-plugin": "^0.0.3", "js-yaml": "^4.1.1", "json-stringify-deterministic": "^1.0.12", - "lodash": "4.17.23", + "lodash": "4.18.1", "mini-css-extract-plugin": "^2.9.2", "nanoid": "^5.1.4", "pluralize": "^8.0.0", @@ -14997,9 +14997,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.capitalize": { diff --git a/package.json b/package.json index 28b71e07..ad41035a 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "html-rspack-tags-plugin": "^0.0.3", "js-yaml": "^4.1.1", "json-stringify-deterministic": "^1.0.12", - "lodash": "4.17.23", + "lodash": "4.18.1", "mini-css-extract-plugin": "^2.9.2", "nanoid": "^5.1.4", "pluralize": "^8.0.0", From 409bf0bee800e62a4c23b657e1822a918f8f951a Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 9 May 2026 00:38:46 +0300 Subject: [PATCH 17/20] chore(deps): update `ts-node` to v10.9.2 and clean up outdated dependencies --- package-lock.json | 383 ++++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 119 insertions(+), 266 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7600a718..e2ced19d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,7 +78,7 @@ "jest-webextension-mock": "^4.0.0", "prettier": "^3.6.2", "release-it": "^19.2.3", - "ts-node": "^1.7.1", + "ts-node": "10.9.2", "tsc-alias": "^1.8.17", "tsup": "^8.5.0", "tsx": "^4.19.2", @@ -2422,6 +2422,30 @@ } } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", @@ -7579,6 +7603,34 @@ "dev": true, "license": "MIT" }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -8807,6 +8859,13 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -8850,16 +8909,6 @@ "node": ">=8" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -10119,6 +10168,13 @@ "typescript": ">=5" } }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -11939,29 +11995,6 @@ "node": ">=0.10.0" } }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/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/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -12724,13 +12757,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/is-wsl": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", @@ -15431,19 +15457,6 @@ "node": ">=16 || 14 >=14.17" } }, - "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/mlly": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", @@ -16242,16 +16255,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "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/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -18211,16 +18214,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sucrase": { "version": "3.35.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", @@ -18743,129 +18736,59 @@ "license": "Apache-2.0" }, "node_modules/ts-node": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-1.7.3.tgz", - "integrity": "sha512-0cBHoPtPIuQwquwXS9ljhJ2PowFdrJDKQSyWIYjUjW5L8RG0Y5cWnDX4aeWO0WDhGl+J+tkXaO4H+Zl9cgogWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.0", - "chalk": "^1.1.1", - "diff": "^3.1.0", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "pinkie": "^2.0.4", - "source-map-support": "^0.4.0", - "tsconfig": "^5.0.2", - "v8flags": "^2.0.11", - "xtend": "^4.0.0", - "yn": "^1.2.0" + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, "bin": { - "ts-node": "dist/bin.js" - } - }, - "node_modules/ts-node/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/ts-node/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ts-node/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "node_modules/ts-node/node_modules/diff": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", - "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, - "node_modules/ts-node/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/ts-node/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ts-node/node_modules/source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "^0.5.6" - } - }, - "node_modules/ts-node/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/ts-node/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/tsc-alias": { "version": "1.8.17", "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.17.tgz", @@ -18939,19 +18862,6 @@ "node": ">=8" } }, - "node_modules/tsconfig": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", - "integrity": "sha512-Cq65A3kVp6BbsUgg9DRHafaGmbMb9EhAc7fjWvudNWKjkbWrt43FnrtZt6awshH1R0ocfF2Z0uxock3lVqEgOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.3.0", - "parse-json": "^2.2.0", - "strip-bom": "^2.0.0", - "strip-json-comments": "^2.0.0" - } - }, "node_modules/tsconfig-paths": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", @@ -18975,32 +18885,6 @@ "node": ">=4" } }, - "node_modules/tsconfig/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/tsconfig/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/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -20358,19 +20242,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==", - "dev": true, - "license": "MIT", - "bin": { - "user-home": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -20406,6 +20277,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -20421,18 +20299,6 @@ "node": ">=10.12.0" } }, - "node_modules/v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==", - "dev": true, - "dependencies": { - "user-home": "^1.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, "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", @@ -21212,16 +21078,6 @@ "dev": true, "license": "MIT" }, - "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", @@ -21283,16 +21139,13 @@ } }, "node_modules/yn": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-1.3.0.tgz", - "integrity": "sha512-cUr+6jz1CH+E9wIGgFW5lyMMOHLbCe/UCOVqV/TTnf5XMe0NBC3TS7pR9ZpDsb84iCWKBd6ETPRBqQjssDKsIA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/yocto-queue": { diff --git a/package.json b/package.json index ad41035a..9e556838 100644 --- a/package.json +++ b/package.json @@ -185,7 +185,7 @@ "jest-webextension-mock": "^4.0.0", "prettier": "^3.6.2", "release-it": "^19.2.3", - "ts-node": "^1.7.1", + "ts-node": "10.9.2", "tsc-alias": "^1.8.17", "tsup": "^8.5.0", "tsx": "^4.19.2", From 31c2407e9c3f9484ca46e5a75cfb13af4f02a35f Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Sat, 9 May 2026 00:49:09 +0300 Subject: [PATCH 18/20] chore(docs): remove projects skills --- .codex/skills/offscreen/SKILL.md | 95 ---------------------- .codex/skills/offscreen/agents/openai.yaml | 4 - .gitignore | 2 + 3 files changed, 2 insertions(+), 99 deletions(-) delete mode 100644 .codex/skills/offscreen/SKILL.md delete mode 100644 .codex/skills/offscreen/agents/openai.yaml diff --git a/.codex/skills/offscreen/SKILL.md b/.codex/skills/offscreen/SKILL.md deleted file mode 100644 index 3eb72168..00000000 --- a/.codex/skills/offscreen/SKILL.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: offscreen -description: Project guidance for addon-bone offscreen transport work. Use when changing or reviewing ProxyOffscreen scheduling, OffscreenBridge Firefox iframe fallback, request-scoped $sender transport context, SignatureBuilder transport signatures, or related offscreen/service/relay tests in /Users/anjeytsibylskij/Documents/AddonStack/addon-bone. ---- - -# Addon Bone Offscreen Transport - -## Core Map - -Use the real checkout as source of truth. Start with these files: - -- `src/offscreen/providers/ProxyOffscreen.ts` for Chrome MV3 offscreen lifecycle and Web Locks scheduling. -- `src/offscreen/OffscreenBridge.ts` and `src/entry/offscreen/Builder.ts` for Firefox iframe fallback readiness. -- `src/transport/RegisterTransport.ts` and `src/types/message.ts` for request-scoped `$sender`. -- `src/cli/entrypoint/file/parsers/SignatureBuilder.ts` for generated transport method signatures. -- `src/offscreen/providers/Offscreen.test.ts`, `src/offscreen/OffscreenBridge.test.ts`, `src/transport/RegisterTransport.test.ts`, and `src/relay/providers/Relay.test.ts` for behavior contracts. - -## Offscreen Scheduling - -Keep orchestration in `ProxyOffscreen`, not in `@addon-core/browser`. The browser package is utility-only: direct API access, simple helpers, and no locks or side effects. - -Chrome MV3 offscreen scheduling uses two Web Locks: - -- Gate lock: serializes lifecycle decisions so multiple contexts cannot race through `hasOffscreenPath()` and `createOffscreen()`. -- Active lock: shared while same-URL calls are executing, exclusive while switching URL/closing/creating offscreen. - -Preserve the intended behavior: - -- Same offscreen URL calls may run in parallel. -- Different offscreen URL calls must wait until active calls finish before closing/recreating the document. -- Release active locks in `finally` around message calls and lifecycle creation paths. -- `acquireLock()` intentionally keeps the Web Lock callback pending and exposes its resolver as a manual release function. -- Do not reintroduce singleton URL state in `ProxyOffscreen`; different proxy instances may legitimately target different offscreen URLs. - -Content scripts cannot rely on `chrome.runtime.getContexts`; direct offscreen lifecycle checks from content script fail in Chrome. Treat content-script offscreen lifecycle as a separate design problem, not as a small bug in `ProxyOffscreen`. - -## Firefox Bridge - -Firefox uses background page plus iframe fallback, not native `chrome.offscreen`. `OffscreenBridge.createOffscreen()` must mean "the iframe offscreen transport is ready", not merely "the iframe loaded". - -Preserve this handshake: - -- `OffscreenBridge` creates or reuses the iframe. -- The offscreen entry builder sets `OffscreenGlobalAccess` early only to mark offscreen scope. Do not use it as readiness. -- After `transport.build()` and optional `view.build()`, the builder calls `ready()`. -- `ready()` posts `{ type: OffscreenBridgeReadyMessageType }` to `window.parent` only when running inside an iframe. -- `OffscreenBridge` resolves creation after receiving that `postMessage` from the exact iframe `contentWindow` and same `location.origin`. - -Do not fall back to `iframe.onload` as the readiness signal. It races with listener registration and can produce "Receiving end does not exist" in Firefox. - -`framesReady` is a `Map>` for in-flight readiness promises by URL. It deduplicates concurrent `create()` calls for the same iframe URL and must be cleaned up in `finally` after success or failure. `data-ready="true"` is DOM state recovery for an existing ready iframe after the in-flight promise has been removed. - -On bridge failure paths, reject with an `Error`, not `undefined`. `iframe.onerror` should remove the iframe and reject with a load error. Ready timeout should use `readyTimeout`, remove the iframe, and reject with a timeout error so the next attempt starts from a clean iframe. - -## Sender Context - -`$sender` is a framework-reserved runtime property for service/offscreen transport methods. It is request-scoped and exposed through a `Proxy` in `RegisterTransport.withSender()`. - -Preserve these rules: - -- Do not mutate the real registered instance with `$sender`. -- Do not add `_sender` aliases. -- Use `Reflect.get(target, property, receiver)` for normal property reads. -- Invoke methods with `property.apply(context, args)` so `this.$sender` works. -- Parallel calls on the same instance must each observe their own sender. - -Developer-facing usage: - -```ts -import type {MessageSenderAware} from "adnbn/message"; - -export default () => ({ - async ping(this: MessageSenderAware) { - return this.$sender?.tab?.id; - }, -}); -``` - -Generated transport types must not include the TypeScript `this` parameter. `SignatureBuilder.getMethodSignature()` filters parameters where `p.name.getText() === "this"`. - -## Testing And Validation - -Use focused tests first, then broader validation when touching shared transport behavior: - -```bash -npm run typecheck -npm run test:offscreen -- --runInBand --detectOpenHandles -npm test -- src/transport/RegisterTransport.test.ts --runInBand --detectOpenHandles -npm run test:entrypoint -- --runInBand --detectOpenHandles -npm test -- --runInBand --detectOpenHandles -npm run build -npm run build --prefix addon -``` - -For manual addon checks, use `addon/src/shared/background.ts` and `addon/src/shared/popup.tsx` patterns. Background/popup sender identity usually appears through `sender.url` and `sender.origin`; `sender.tab.url` is not expected for extension pages. diff --git a/.codex/skills/offscreen/agents/openai.yaml b/.codex/skills/offscreen/agents/openai.yaml deleted file mode 100644 index c2116444..00000000 --- a/.codex/skills/offscreen/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -interface: - display_name: "Offscreen" - short_description: "Offscreen transport project guide." - default_prompt: "Use $offscreen to change or review addon-bone offscreen transport behavior." diff --git a/.gitignore b/.gitignore index fdbed48d..30f71a36 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ .env .env.* .idea +.codex +.claude .output addon *.log From d3b05a67d77a29987139f7ee984760269eaefd0a Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Mon, 11 May 2026 20:37:20 +0300 Subject: [PATCH 19/20] fix(locale): validate locale contract and tighten substitutions - resolve config.lang to a concrete Language before plugins run - validate locale structure against the default language contract - allow missing keys in secondary locales and warn about extra keys - generate locale keys and types from the default language only - trim runtime substitution placeholders to match generated types - make substitution arguments strict in TypeScript - fix manifest plain name, shortName and description handling - replace locale helpers with t, choice, key and resolve - preserve empty-string values in custom and dynamic locales - add locale validator, manifest, runtime and type-level tests --- src/cli/builders/locale/LocaleBuilder.test.ts | 115 +++++++++++ src/cli/builders/locale/LocaleBuilder.ts | 2 +- .../locale/LocaleStructureValidator.test.ts | 117 ++++++++++++ .../locale/LocaleStructureValidator.ts | 76 ++++++++ src/cli/builders/locale/index.ts | 3 +- .../entrypoint/finder/LocaleFinder.test.ts | 180 ++++++++++++++++++ src/cli/entrypoint/finder/LocaleFinder.ts | 41 ++-- .../locale/default-missing/locales/fr.yaml | 2 + .../fixtures/locale/extra-key/locales/en.yaml | 2 + .../fixtures/locale/extra-key/locales/fr.yaml | 3 + .../fixtures/locale/json/locales/en.json | 5 + .../fixtures/locale/partial/locales/en.yaml | 3 + .../fixtures/locale/partial/locales/fr.yaml | 2 + .../locale/plural-mismatch/locales/en.yaml | 4 + .../locale/plural-mismatch/locales/fr.yaml | 2 + .../substitution-mismatch/locales/en.yaml | 2 + .../substitution-mismatch/locales/fr.yaml | 2 + .../tests/fixtures/locale/yml/locales/en.yml | 2 + .../plugins/locale/declaration/locale.d.ts | 72 +++++-- src/cli/plugins/locale/index.test.ts | 135 +++++++++++++ src/cli/plugins/locale/index.ts | 105 +++++----- .../tests/fixtures/manifest/locales/en.yaml | 4 + .../tests/fixtures/manifest/locales/fr.yaml | 4 + src/cli/resolvers/config.test.ts | 32 ++++ src/cli/resolvers/config.ts | 19 +- src/cli/virtual/command.ts | 4 +- src/cli/virtual/view.ts | 4 +- src/cli/virtual/virtual.d.ts | 2 +- src/locale/LocaleTypes.test.ts | 117 ++++++++++++ src/locale/adapters/react/LocaleProvider.tsx | 10 +- src/locale/adapters/react/context.ts | 17 +- src/locale/helpers.ts | 104 ++++++---- src/locale/index.ts | 4 +- src/locale/providers/AbstractLocale.ts | 28 +-- src/locale/providers/CustomLocale.test.ts | 19 +- src/locale/providers/CustomLocale.ts | 8 +- src/locale/providers/DynamicLocale.test.ts | 30 +++ src/locale/providers/DynamicLocale.ts | 9 +- src/locale/providers/NativeLocale.ts | 12 +- src/main/popup.ts | 4 +- src/main/sidebar.ts | 4 +- src/types/config.ts | 7 +- src/types/locale.ts | 40 ++-- 43 files changed, 1163 insertions(+), 194 deletions(-) create mode 100644 src/cli/builders/locale/LocaleBuilder.test.ts create mode 100644 src/cli/builders/locale/LocaleStructureValidator.test.ts create mode 100644 src/cli/builders/locale/LocaleStructureValidator.ts create mode 100644 src/cli/entrypoint/finder/LocaleFinder.test.ts create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/default-missing/locales/fr.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/en.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/fr.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/json/locales/en.json create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/en.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/fr.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/en.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/fr.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/en.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/fr.yaml create mode 100644 src/cli/entrypoint/finder/tests/fixtures/locale/yml/locales/en.yml create mode 100644 src/cli/plugins/locale/index.test.ts create mode 100644 src/cli/plugins/locale/tests/fixtures/manifest/locales/en.yaml create mode 100644 src/cli/plugins/locale/tests/fixtures/manifest/locales/fr.yaml create mode 100644 src/locale/LocaleTypes.test.ts create mode 100644 src/locale/providers/DynamicLocale.test.ts diff --git a/src/cli/builders/locale/LocaleBuilder.test.ts b/src/cli/builders/locale/LocaleBuilder.test.ts new file mode 100644 index 00000000..00adfcb0 --- /dev/null +++ b/src/cli/builders/locale/LocaleBuilder.test.ts @@ -0,0 +1,115 @@ +import LocaleBuilder from "./LocaleBuilder"; + +import {Language, LocaleCustomKeyForLanguage, LocaleValuesSeparator} from "@typing/locale"; +import {Browser} from "@typing/browser"; + +const makeValidator = () => ({ + isValid: jest.fn(), + validate: jest.fn(), +}); + +describe("LocaleBuilder", () => { + test("returns the builder language", () => { + expect(new LocaleBuilder(Browser.Chrome, Language.French).lang()).toBe(Language.French); + }); + + test("flattens nested data, stringifies values and injects the language marker", () => { + const builder = new LocaleBuilder(Browser.Chrome, Language.English).merge({ + app: { + name: "My App", + version: 2, + items: ["one", 2], + }, + }); + + expect(Object.fromEntries(builder.get())).toEqual({ + "app.name": "My App", + "app.version": "2", + "app.items": ["one", "2"].join(LocaleValuesSeparator), + [LocaleCustomKeyForLanguage]: Language.English, + }); + }); + + test("lets later merged data override earlier values and clears cached items", () => { + const builder = new LocaleBuilder(Browser.Chrome, Language.English).merge({ + title: "Before", + }); + + const first = builder.get(); + + builder.merge({ + title: "After", + }); + + const second = builder.get(); + + expect(second).not.toBe(first); + expect(second.get("title")).toBe("After"); + }); + + test("returns locale keys from converted items", () => { + const builder = new LocaleBuilder(Browser.Chrome, Language.English).merge({ + app: { + name: "My App", + }, + }); + + expect(builder.keys()).toEqual(new Set(["app.name", LocaleCustomKeyForLanguage])); + }); + + test("normalizes substitution names in locale structure", () => { + const builder = new LocaleBuilder(Browser.Chrome, Language.English).merge({ + greeting: "Hello {{ name }} {{name}} {{ count }}", + cars: ["{{count}} car", "{{count}} cars"], + }); + + expect(builder.structure().greeting.substitutions).toEqual(["count", "name"]); + expect(builder.structure().cars).toEqual({ + plural: true, + substitutions: ["count"], + }); + }); + + test("builds browser messages and validates before output", () => { + const validator = makeValidator(); + const builder = new LocaleBuilder(Browser.Chrome, Language.English).setValidator(validator).merge({ + app: { + name: "My App", + }, + }); + + expect(builder.build()).toEqual({ + app_name: { + message: "My App", + }, + [LocaleCustomKeyForLanguage]: { + message: Language.English, + }, + }); + + expect(validator.validate).toHaveBeenCalledWith(builder); + }); + + test("throws validation errors when validator is not set", () => { + const builder = new LocaleBuilder(Browser.Chrome, Language.English); + + expect(() => builder.validate()).toThrow("Locale for chrome:en - Validator is not set"); + expect(builder.isValid()).toBe(false); + }); + + test("reports validation status from configured validator", () => { + const passingValidator = makeValidator(); + const failingValidator = makeValidator(); + + failingValidator.validate.mockImplementation(() => { + throw new Error("Invalid locale"); + }); + + const passing = new LocaleBuilder(Browser.Chrome, Language.English).setValidator(passingValidator); + const failing = new LocaleBuilder(Browser.Chrome, Language.English).setValidator(failingValidator); + + expect(passing.validate()).toBe(passing); + expect(passing.isValid()).toBe(true); + expect(failing.isValid()).toBe(false); + }); +}); diff --git a/src/cli/builders/locale/LocaleBuilder.ts b/src/cli/builders/locale/LocaleBuilder.ts index 8365fc48..ffed7aea 100644 --- a/src/cli/builders/locale/LocaleBuilder.ts +++ b/src/cli/builders/locale/LocaleBuilder.ts @@ -84,7 +84,7 @@ export default class LocaleBuilder implements LocaleBuilderContract { substitutions.push(match[1].trim()); } - return substitutions; + return _.uniq(substitutions.filter(Boolean)).sort(); }; return this.get() diff --git a/src/cli/builders/locale/LocaleStructureValidator.test.ts b/src/cli/builders/locale/LocaleStructureValidator.test.ts new file mode 100644 index 00000000..697e2b97 --- /dev/null +++ b/src/cli/builders/locale/LocaleStructureValidator.test.ts @@ -0,0 +1,117 @@ +import LocaleBuilder from "./LocaleBuilder"; +import LocaleStructureValidator from "./LocaleStructureValidator"; + +import {Language, LocaleBuilders, LocaleData} from "@typing/locale"; +import {Browser} from "@typing/browser"; + +const makeBuilder = (lang: Language, data: LocaleData): LocaleBuilder => { + return new LocaleBuilder(Browser.Chrome, lang).merge(data); +}; + +const makeBuilders = (items: Array<[Language, LocaleData]>): LocaleBuilders => { + return new Map(items.map(([lang, data]) => [lang, makeBuilder(lang, data)])); +}; + +describe("LocaleStructureValidator", () => { + let consoleWarnSpy: jest.SpyInstance; + + beforeEach(() => { + consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(); + }); + + afterEach(() => { + consoleWarnSpy.mockRestore(); + }); + + test("allows non-default locales to omit default locale keys", () => { + const builders = makeBuilders([ + [ + Language.English, + { + app: { + name: "My App", + greeting: "Hello {{name}}", + }, + }, + ], + [ + Language.French, + { + app: { + name: "Mon App", + }, + }, + ], + ]); + + const validator = new LocaleStructureValidator(Language.English); + + expect(validator.validate(builders)).toBe(validator); + expect(validator.isValid(builders)).toBe(true); + }); + + test("rejects missing default locale", () => { + const builders = makeBuilders([ + [ + Language.French, + { + app: { + name: "Mon App", + }, + }, + ], + ]); + + expect(() => new LocaleStructureValidator(Language.English).validate(builders)).toThrow( + 'Default locale "en" not found in available translations. Available languages: fr' + ); + }); + + test("warns about keys outside the default locale contract", () => { + const builders = makeBuilders([ + [Language.English, {app: {name: "My App"}}], + [Language.French, {app: {name: "Mon App", extra: "Extra"}}], + ]); + + const validator = new LocaleStructureValidator(Language.English); + + expect(validator.validate(builders)).toBe(validator); + expect(consoleWarnSpy).toHaveBeenCalledWith( + 'Locale "fr" contains unknown key "app.extra" not found in default locale "en"' + ); + expect(validator.isValid(builders)).toBe(true); + }); + + test("rejects substitution mismatch against the default locale contract", () => { + const builders = makeBuilders([ + [Language.English, {app: {greeting: "Hello {{ name }}"}}], + [Language.French, {app: {greeting: "Bonjour {{firstName}}"}}], + ]); + + const validator = new LocaleStructureValidator(Language.English); + + expect(() => validator.validate(builders)).toThrow( + 'Locale "fr" key "app.greeting" substitutions [firstName] must match default locale "en" substitutions [name]' + ); + expect(validator.isValid(builders)).toBe(false); + }); + + test("rejects plural mismatch against the default locale contract", () => { + const builders = makeBuilders([ + [Language.English, {app: {cars: ["car", "cars"]}}], + [Language.French, {app: {cars: "voiture"}}], + ]); + + expect(() => new LocaleStructureValidator(Language.English).validate(builders)).toThrow( + 'Locale "fr" key "app.cars" must be plural like default locale "en"' + ); + }); + + test("allows empty builder collection", () => { + const builders: LocaleBuilders = new Map(); + const validator = new LocaleStructureValidator(Language.English); + + expect(validator.validate(builders)).toBe(validator); + expect(validator.isValid(builders)).toBe(true); + }); +}); diff --git a/src/cli/builders/locale/LocaleStructureValidator.ts b/src/cli/builders/locale/LocaleStructureValidator.ts new file mode 100644 index 00000000..d556417b --- /dev/null +++ b/src/cli/builders/locale/LocaleStructureValidator.ts @@ -0,0 +1,76 @@ +import _ from "lodash"; + +import {Language, LocaleBuilder, LocaleBuilders, LocaleContractValidator} from "@typing/locale"; + +export default class implements LocaleContractValidator { + constructor(protected readonly defaultLanguage: Language) {} + + public isValid(builders: LocaleBuilders): boolean { + try { + this.validate(builders); + + return true; + } catch { + return false; + } + } + + public validate(builders: LocaleBuilders): this { + const defaultBuilder = this.getDefaultBuilder(builders); + + if (!defaultBuilder) { + return this; + } + + const defaultStructure = defaultBuilder.structure(); + + for (const [language, builder] of builders.entries()) { + if (language === this.defaultLanguage) { + continue; + } + + const structure = builder.structure(); + + for (const [key, locale] of Object.entries(structure)) { + const expected = defaultStructure[key]; + + if (!expected) { + console.warn( + `Locale "${language}" contains unknown key "${key}" not found in default locale "${this.defaultLanguage}"` + ); + continue; + } + + if (expected.plural !== locale.plural) { + throw new Error( + `Locale "${language}" key "${key}" must be ${expected.plural ? "plural" : "non-plural"} like default locale "${this.defaultLanguage}"` + ); + } + + if (!_.isEqual(expected.substitutions, locale.substitutions)) { + throw new Error( + `Locale "${language}" key "${key}" substitutions [${locale.substitutions.join(", ")}] must match default locale "${this.defaultLanguage}" substitutions [${expected.substitutions.join(", ")}]` + ); + } + } + } + + return this; + } + + public getDefaultBuilder(builders: LocaleBuilders): LocaleBuilder | undefined { + if (builders.size === 0) { + return undefined; + } + + const builder = builders.get(this.defaultLanguage); + + if (!builder) { + throw new Error( + `Default locale "${this.defaultLanguage}" not found in available translations. Available languages: ${[...builders.keys()].join(", ")}` + ); + } + + return builder; + } +} diff --git a/src/cli/builders/locale/index.ts b/src/cli/builders/locale/index.ts index 25211538..cfa4cfe7 100644 --- a/src/cli/builders/locale/index.ts +++ b/src/cli/builders/locale/index.ts @@ -2,6 +2,7 @@ import LocaleBuilder from "./LocaleBuilder"; import LocaleValidator from "./LocaleValidator"; import OperaLocaleValidator from "./OperaLocaleValidator"; import FirefoxLocaleValidator from "./FirefoxLocaleValidator"; +import LocaleStructureValidator from "./LocaleStructureValidator"; import {extractLocaleKey} from "@locale/utils"; @@ -9,7 +10,7 @@ import {Language, LocaleBuilder as LocaleBuilderContract} from "@typing/locale"; import {ReadonlyConfig} from "@typing/config"; import {Browser} from "@typing/browser"; -export {LocaleBuilder, LocaleValidator, OperaLocaleValidator, FirefoxLocaleValidator}; +export {LocaleBuilder, LocaleValidator, OperaLocaleValidator, FirefoxLocaleValidator, LocaleStructureValidator}; export default (language: Language, config: ReadonlyConfig): LocaleBuilderContract => { const {browser, name, shortName, description, lang} = config; diff --git a/src/cli/entrypoint/finder/LocaleFinder.test.ts b/src/cli/entrypoint/finder/LocaleFinder.test.ts new file mode 100644 index 00000000..c7fa539c --- /dev/null +++ b/src/cli/entrypoint/finder/LocaleFinder.test.ts @@ -0,0 +1,180 @@ +import path from "path"; + +import LocaleFinder from "./LocaleFinder"; + +import {ReadonlyConfig} from "@typing/config"; +import {Command} from "@typing/app"; +import {Browser} from "@typing/browser"; +import {Language} from "@typing/locale"; + +const fixtures = path.resolve(__dirname, "tests", "fixtures", "locale"); + +class TestLocaleFinder extends LocaleFinder { + public languageFromFilename(filename: string): Language { + return this.getLanguageFromFilename(filename); + } +} + +const makeFinder = (fixture: string, config: Partial = {}): TestLocaleFinder => { + const root = path.join(fixtures, fixture); + + return new TestLocaleFinder({ + app: "app", + appSrcDir: ".", + appsDir: "apps", + browser: Browser.Chrome, + command: Command.Build, + lang: Language.English, + localeDir: "locales", + mergeLocales: true, + mode: "production", + plugins: [ + { + name: root, + locale: true, + }, + ], + rootDir: root, + sharedDir: "shared", + srcDir: "src", + ...config, + } as ReadonlyConfig); +}; + +describe("LocaleFinder", () => { + test("reports locale finder configuration", () => { + const finder = makeFinder("partial", { + localeDir: "translations", + mergeLocales: false, + }); + + expect(finder.getDirectory()).toBe("translations"); + expect(finder.canMerge()).toBe(false); + expect(finder.getNames().has(Language.English)).toBe(true); + expect(finder.isValidExtension("yaml")).toBe(true); + expect(finder.isValidExtension("yml")).toBe(true); + expect(finder.isValidExtension("json")).toBe(true); + expect(finder.isValidExtension("txt")).toBe(false); + expect(finder.isValidName("en")).toBe(true); + expect(finder.isValidName("en.chrome")).toBe(true); + expect(finder.isValidName("missing")).toBe(false); + }); + + test("falls back to the default locale directory", () => { + expect(makeFinder("partial", {localeDir: undefined}).getDirectory()).toBe("locales"); + }); + + test("memoizes the plugin finder", () => { + const finder = makeFinder("partial"); + + expect(finder.plugin()).toBe(finder.plugin()); + }); + + test("resolves languages from plain and browser-specific locale filenames", () => { + const finder = makeFinder("partial"); + + expect(finder.languageFromFilename("en.yaml")).toBe(Language.English); + expect(finder.languageFromFilename("fr.chrome.json")).toBe(Language.French); + expect(() => finder.languageFromFilename("missing.yaml")).toThrow("Invalid locale filename: missing.yaml"); + }); + + test("allows non-default locales to omit default locale keys", async () => { + await expect(makeFinder("partial").structure()).resolves.toMatchObject({ + "app.greeting": { + plural: false, + substitutions: ["name"], + }, + }); + }); + + test("reads locale builders, languages, keys and default structure", async () => { + const finder = makeFinder("partial"); + + await expect(finder.languages()).resolves.toEqual(new Set([Language.English, Language.French])); + await expect(finder.keys()).resolves.toEqual(new Set(["app.name", "app.greeting", "locale"])); + await expect(finder.structure()).resolves.toMatchObject({ + "app.name": { + plural: false, + substitutions: [], + }, + "app.greeting": { + plural: false, + substitutions: ["name"], + }, + }); + }); + + test("parses json locale files", async () => { + await expect(makeFinder("json").keys()).resolves.toEqual(new Set(["app.name", "locale"])); + }); + + test("parses yml locale files", async () => { + await expect(makeFinder("yml").keys()).resolves.toEqual(new Set(["app.name", "locale"])); + }); + + test("reports whether locale files are empty", async () => { + await expect(makeFinder("empty").empty()).resolves.toBe(true); + await expect(makeFinder("partial").empty()).resolves.toBe(false); + }); + + test("returns empty locale data when no locale files exist", async () => { + const finder = makeFinder("empty"); + + await expect(finder.languages()).resolves.toEqual(new Set()); + await expect(finder.keys()).resolves.toEqual(new Set()); + await expect(finder.structure()).resolves.toEqual({}); + }); + + test("caches builders until clear is called", async () => { + const finder = makeFinder("partial"); + + const first = await finder.builders(); + + expect(await finder.builders()).toBe(first); + expect(await finder.clear().builders()).not.toBe(first); + }); + + test("reads languages, keys and structure without validating non-default locale structure", async () => { + const finder = makeFinder("substitution-mismatch"); + + await expect(finder.languages()).resolves.toEqual(new Set([Language.English, Language.French])); + await expect(finder.keys()).resolves.toEqual(new Set(["app.greeting", "locale"])); + await expect(finder.structure()).resolves.toMatchObject({ + "app.greeting": { + plural: false, + substitutions: ["name"], + }, + }); + }); + + test("requires configured default locale to exist when translations are present", async () => { + await expect(makeFinder("default-missing").validate()).rejects.toThrow( + 'Default locale "en" not found in available translations. Available languages: fr' + ); + }); + + test("warns about keys outside the default locale contract", async () => { + const consoleWarnSpy = jest.spyOn(console, "warn").mockImplementation(); + + try { + await expect(makeFinder("extra-key").validate()).resolves.toBeInstanceOf(LocaleFinder); + expect(consoleWarnSpy).toHaveBeenCalledWith( + 'Locale "fr" contains unknown key "app.extra" not found in default locale "en"' + ); + } finally { + consoleWarnSpy.mockRestore(); + } + }); + + test("rejects substitution mismatch against the default locale contract", async () => { + await expect(makeFinder("substitution-mismatch").validate()).rejects.toThrow( + 'Locale "fr" key "app.greeting" substitutions [firstName] must match default locale "en" substitutions [name]' + ); + }); + + test("rejects plural mismatch against the default locale contract", async () => { + await expect(makeFinder("plural-mismatch").validate()).rejects.toThrow( + 'Locale "fr" key "app.cars" must be plural like default locale "en"' + ); + }); +}); diff --git a/src/cli/entrypoint/finder/LocaleFinder.ts b/src/cli/entrypoint/finder/LocaleFinder.ts index e5367bd6..b94f67c0 100644 --- a/src/cli/entrypoint/finder/LocaleFinder.ts +++ b/src/cli/entrypoint/finder/LocaleFinder.ts @@ -6,25 +6,27 @@ import yaml from "js-yaml"; import AbstractAssetFinder from "./AbstractAssetFinder"; import AssetPluginFinder from "./AssetPluginFinder"; -import localeFactory from "@cli/builders/locale"; +import localeFactory, {LocaleStructureValidator} from "@cli/builders/locale"; import {isFileExtension} from "@cli/utils/path"; import {ReadonlyConfig} from "@typing/config"; import { Language, LanguageCodes, - LocaleBuilder, + LocaleBuilders, LocaleData, LocaleFileExtensions, LocaleKeys, LocaleStructure, } from "@typing/locale"; -export type LocaleBuilders = Map; +export type {LocaleBuilders} from "@typing/locale"; export default class extends AbstractAssetFinder { protected _plugin?: AssetPluginFinder; protected _builders?: LocaleBuilders; + protected _validator?: LocaleStructureValidator; + protected _validated = false; public constructor(config: ReadonlyConfig) { super(config); @@ -85,6 +87,10 @@ export default class extends AbstractAssetFinder { .value(); } + protected getValidator(): LocaleStructureValidator { + return (this._validator ??= new LocaleStructureValidator(this.config.lang)); + } + protected getLanguageFromFilename(filename: string): Language { let {name} = path.parse(filename); @@ -100,25 +106,34 @@ export default class extends AbstractAssetFinder { } public async builders(): Promise { - return (this._builders ??= await this.getBuilders()); + if (this._builders) { + return this._builders; + } + + return (this._builders = await this.getBuilders()); + } + + public async validate(): Promise { + if (!this._validated) { + this.getValidator().validate(await this.builders()); + this._validated = true; + } + + return this; } public async keys(): Promise { const builders = await this.builders(); + const builder = this.getValidator().getDefaultBuilder(builders); - const keys = builders.values().reduce((keys, builder) => { - return keys.concat(...builder.keys()); - }, [] as string[]); - - return new Set(keys); + return builder?.keys() ?? new Set(); } public async structure(): Promise { const builders = await this.builders(); + const builder = this.getValidator().getDefaultBuilder(builders); - return builders.values().reduce((structure, builder) => { - return _.merge(structure, builder.structure()); - }, {} as LocaleStructure); + return builder?.structure() ?? {}; } public async languages(): Promise> { @@ -135,6 +150,8 @@ export default class extends AbstractAssetFinder { this.plugin().clear(); this._builders = undefined; + this._validator = undefined; + this._validated = false; return super.clear(); } diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/default-missing/locales/fr.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/default-missing/locales/fr.yaml new file mode 100644 index 00000000..eb4797c2 --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/default-missing/locales/fr.yaml @@ -0,0 +1,2 @@ +app: + name: Mon App diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/en.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/en.yaml new file mode 100644 index 00000000..0b39a1ad --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/en.yaml @@ -0,0 +1,2 @@ +app: + name: My App diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/fr.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/fr.yaml new file mode 100644 index 00000000..32be724e --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/extra-key/locales/fr.yaml @@ -0,0 +1,3 @@ +app: + name: Mon App + extra: Extra diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/json/locales/en.json b/src/cli/entrypoint/finder/tests/fixtures/locale/json/locales/en.json new file mode 100644 index 00000000..be0d909c --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/json/locales/en.json @@ -0,0 +1,5 @@ +{ + "app": { + "name": "My App" + } +} diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/en.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/en.yaml new file mode 100644 index 00000000..79ee2880 --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/en.yaml @@ -0,0 +1,3 @@ +app: + name: My App + greeting: Hello {{name}} diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/fr.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/fr.yaml new file mode 100644 index 00000000..eb4797c2 --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/partial/locales/fr.yaml @@ -0,0 +1,2 @@ +app: + name: Mon App diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/en.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/en.yaml new file mode 100644 index 00000000..4cce302b --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/en.yaml @@ -0,0 +1,4 @@ +app: + cars: + - car + - cars diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/fr.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/fr.yaml new file mode 100644 index 00000000..cd37fcfb --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/plural-mismatch/locales/fr.yaml @@ -0,0 +1,2 @@ +app: + cars: voiture diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/en.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/en.yaml new file mode 100644 index 00000000..9807db7c --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/en.yaml @@ -0,0 +1,2 @@ +app: + greeting: Hello {{ name }} diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/fr.yaml b/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/fr.yaml new file mode 100644 index 00000000..d632e23e --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/substitution-mismatch/locales/fr.yaml @@ -0,0 +1,2 @@ +app: + greeting: Bonjour {{firstName}} diff --git a/src/cli/entrypoint/finder/tests/fixtures/locale/yml/locales/en.yml b/src/cli/entrypoint/finder/tests/fixtures/locale/yml/locales/en.yml new file mode 100644 index 00000000..0b39a1ad --- /dev/null +++ b/src/cli/entrypoint/finder/tests/fixtures/locale/yml/locales/en.yml @@ -0,0 +1,2 @@ +app: + name: My App diff --git a/src/cli/plugins/locale/declaration/locale.d.ts b/src/cli/plugins/locale/declaration/locale.d.ts index 29b4ae9d..acd8ca13 100644 --- a/src/cli/plugins/locale/declaration/locale.d.ts +++ b/src/cli/plugins/locale/declaration/locale.d.ts @@ -5,25 +5,75 @@ import { type LocalePluralKeys, type LocaleProvider, type LocaleDynamicProvider, - type LocaleSubstitutionsFor, + type LocaleSubstitutionArgs, } from ":package/locale"; declare module ":package/locale" { // prettier-ignore export interface GeneratedNativeStructure {} - export function _>( + /** + * Translates a non-plural locale key. + * + * Substitutions are type-checked from the generated locale structure: + * keys without placeholders do not accept substitutions, while keys with + * placeholders require all declared substitution values. + * + * @example + * ```ts + * t("app.name"); + * t("app.greeting", {name: "Alice"}); + * ``` + */ + export function t>( key: K, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; - export function _c>( + /** + * Translates a plural locale key using the provided count. + * + * Substitutions are type-checked from the generated locale structure: + * keys without placeholders do not accept substitutions, while keys with + * placeholders require all declared substitution values. + * + * @example + * ```ts + * choice("cart.items", count, {count}); + * ``` + */ + export function choice>( key: K, count: number, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; - export function __(key: keyof GeneratedNativeStructure & string): string; + /** + * Converts a locale key to a browser message reference. + * + * This is useful for browser-managed extension fields that expect + * `__MSG_name__` references instead of already translated text. + * + * @example + * ```ts + * key("app.name"); // "__MSG_app_name__" + * ``` + */ + export function key(value: keyof GeneratedNativeStructure & string): string; + + /** + * Resolves a string that may contain a locale marker. + * + * When the input contains a locale marker, the marker is extracted and translated. + * Plain strings are returned unchanged. + * + * @example + * ```ts + * resolve("@app.name"); + * resolve("Plain title"); + * ``` + */ + export function resolve(input: string): string; export declare class NativeLocale implements LocaleProvider { lang(): Language; @@ -35,14 +85,14 @@ declare module ":package/locale" { // non-plural keys trans>( key: K, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; // plural keys choice>( key: K, count: number, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; } @@ -61,15 +111,15 @@ declare module ":package/locale/react" { isRtl: boolean; - _>( + t>( key: K, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; choice>( key: K, count: number, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string; change(lang: Language): void; diff --git a/src/cli/plugins/locale/index.test.ts b/src/cli/plugins/locale/index.test.ts new file mode 100644 index 00000000..f5d2dcd0 --- /dev/null +++ b/src/cli/plugins/locale/index.test.ts @@ -0,0 +1,135 @@ +import path from "path"; + +import localePlugin from "./index"; + +import ManifestV3 from "@cli/builders/manifest/ManifestV3"; + +import {Command, Mode} from "@typing/app"; +import {Browser} from "@typing/browser"; +import {Language} from "@typing/locale"; +import {ReadonlyConfig} from "@typing/config"; + +const fixtures = path.resolve(__dirname, "tests/fixtures"); + +const localeFixture = (name: string): Partial => { + const root = path.join(fixtures, name); + + return { + rootDir: root, + plugins: [ + { + name: root, + locale: true, + }, + ], + }; +}; + +const makeConfig = (config: Partial = {}): ReadonlyConfig => + ({ + app: "sample-app", + appSrcDir: ".", + appsDir: "apps", + browser: Browser.Chrome, + command: Command.Build, + description: undefined, + lang: Language.English, + localeDir: "locales", + manifestVersion: 3, + mode: Mode.Production, + name: undefined, + plugins: [], + rootDir: ".", + sharedDir: "shared", + shortName: undefined, + srcDir: "src", + ...config, + }) as ReadonlyConfig; + +const runManifest = async (config: Partial): Promise => { + const plugin = localePlugin(); + const resolvedConfig = makeConfig(config); + const manifest = new ManifestV3(resolvedConfig.browser); + + await plugin.startup?.({config: resolvedConfig}); + await plugin.manifest?.({config: resolvedConfig, manifest}); + + return manifest; +}; + +describe("locale plugin manifest", () => { + test("uses plain name, short name and description when locale files are missing", async () => { + const manifest = await runManifest({ + name: "Plain Name", + shortName: "Plain Short", + description: "Plain Description", + }); + + expect(manifest.build()).toMatchObject({ + name: "Plain Name", + short_name: "Plain Short", + description: "Plain Description", + }); + }); + + test("rejects locale keys when locale files are missing", async () => { + await expect( + runManifest({ + name: "@app.name", + }) + ).rejects.toThrow('Locale name key "app.name" provided but no translations were found'); + }); + + test("uses browser message references for locale keys when translations exist", async () => { + const manifest = await runManifest({ + ...localeFixture("manifest"), + name: "@app.name", + shortName: "@app.short_name", + description: "@app.description", + }); + + expect(manifest.build()).toMatchObject({ + name: "__MSG_app_name__", + short_name: "__MSG_app_short_name__", + description: "__MSG_app_description__", + default_locale: Language.English, + }); + }); + + test("uses translated short name for Opera and Edge", async () => { + const manifest = await runManifest({ + browser: Browser.Opera, + ...localeFixture("manifest"), + name: "@app.name", + shortName: "@app.short_name", + }); + + expect(manifest.build()).toMatchObject({ + name: "__MSG_app_name__", + short_name: "Short", + }); + }); + + test("rejects configured language that is not available in translations", async () => { + await expect( + runManifest({ + ...localeFixture("manifest"), + lang: Language.German, + name: "@app.name", + }) + ).rejects.toThrow('Language "de" not found in available translations. Available languages: en, fr'); + }); + + test("supports mixed plain and localized manifest fields", async () => { + const manifest = await runManifest({ + ...localeFixture("manifest"), + name: "Plain Name", + description: "@app.description", + }); + + expect(manifest.build()).toMatchObject({ + name: "Plain Name", + description: "__MSG_app_description__", + }); + }); +}); diff --git a/src/cli/plugins/locale/index.ts b/src/cli/plugins/locale/index.ts index 48f98def..39603a7e 100644 --- a/src/cli/plugins/locale/index.ts +++ b/src/cli/plugins/locale/index.ts @@ -11,7 +11,6 @@ import {LocaleDeclaration} from "./declaration"; import {Command} from "@typing/app"; import {Browser} from "@typing/browser"; -import {Language, LanguageCodes} from "@typing/locale"; export default definePlugin(() => { let locale: Locale; @@ -25,6 +24,8 @@ export default definePlugin(() => { }, locale: () => locale.files(), bundler: async ({config}) => { + await locale.validate(); + declaration.structure(await locale.structure()).build(); const plugin = new GenerateJsonPlugin(await locale.json()); @@ -33,6 +34,8 @@ export default definePlugin(() => { plugin.watch(async () => { locale.clear(); + await locale.validate(); + declaration.structure(await locale.structure()).build(); return await locale.json(); @@ -50,81 +53,73 @@ export default definePlugin(() => { } satisfies RspackConfig; }, manifest: async ({config, manifest}) => { - const {lang, name, shortName, description, browser} = config; - - let language: Language = Language.English; - - if (lang) { - if (LanguageCodes.has(lang)) { - language = lang as Language; - } else { - throw new Error(`Invalid language "${lang}" provided by config`); - } - - const availableLanguages = await locale.languages(); + const {lang: language, name, shortName, description, browser} = config; + const availableLanguages = await locale.languages(); + const builders = await locale.builders(); + const hasLocales = builders.size > 0; - if (availableLanguages.size > 0 && !availableLanguages.has(language)) { - throw new Error( - `Language "${language}" not found in available translations. Available languages: ${[...availableLanguages].join(", ")}` - ); - } + if (availableLanguages.size > 0 && !availableLanguages.has(language)) { + throw new Error( + `Language "${language}" not found in available translations. Available languages: ${[...availableLanguages].join(", ")}` + ); } - const builders = await locale.builders(); - const keys = await locale.keys(); + await locale.validate(); - manifest.setLocale(builders.size > 0 ? language : undefined); + const keys = await locale.keys(); - if (builders.size > 0) { - if (shortName) { - let manifestShortName: string | undefined = modifyLocaleMessageKey(shortName); + const assertLocaleKey = (value: string, label: string): void => { + const key = extractLocaleKey(value); - const shortNameKey = extractLocaleKey(shortName); + if (!key) { + return; + } - if (shortNameKey) { - if (!keys.has(shortNameKey)) { - throw new Error(`Locale short name key "${shortNameKey}" not found in translation`); - } + if (!hasLocales) { + throw new Error(`Locale ${label} key "${key}" provided but no translations were found`); + } - /** Opera/Edge do not support localization in manifest's short_name field */ - if (browser === Browser.Opera || browser === Browser.Edge) { - const instance = builders.get(language); + if (!keys.has(key)) { + throw new Error(`Locale ${label} key "${key}" not found in translation`); + } + }; - if (!instance) { - throw new Error(`Locale not found for "${language}"`); - } + manifest.setLocale(hasLocales ? language : undefined); - manifestShortName = instance.get().get(shortNameKey); - } - } + if (shortName) { + let manifestShortName = modifyLocaleMessageKey(shortName) ?? shortName; + const shortNameKey = extractLocaleKey(shortName); - manifest.setShortName(manifestShortName); - } + assertLocaleKey(shortName, "short name"); - if (description) { - const descriptionKey = extractLocaleKey(description); + /** Opera/Edge do not support localization in manifest's short_name field */ + if (shortNameKey && (browser === Browser.Opera || browser === Browser.Edge)) { + const instance = builders.get(language); - if (descriptionKey && !keys.has(descriptionKey)) { - throw new Error(`Locale description key "${descriptionKey}" not found in translation`); + if (!instance) { + throw new Error(`Locale not found for "${language}"`); } - manifest.setDescription(modifyLocaleMessageKey(description)); + manifestShortName = instance.get().get(shortNameKey) ?? manifestShortName; } - if (name) { - const nameKey = extractLocaleKey(name); + manifest.setShortName(manifestShortName); + } - if (nameKey && !keys.has(nameKey)) { - throw new Error(`Locale name key "${nameKey}" not found in translation`); - } + if (description) { + assertLocaleKey(description, "description"); + manifest.setDescription(modifyLocaleMessageKey(description)); + } - const manifestName = modifyLocaleMessageKey(name); + if (name) { + assertLocaleKey(name, "name"); - if (manifestName) { - manifest.setName(manifestName); + const manifestName = modifyLocaleMessageKey(name); - return; - } + if (manifestName) { + manifest.setName(manifestName); + + return; } } diff --git a/src/cli/plugins/locale/tests/fixtures/manifest/locales/en.yaml b/src/cli/plugins/locale/tests/fixtures/manifest/locales/en.yaml new file mode 100644 index 00000000..6a3b0380 --- /dev/null +++ b/src/cli/plugins/locale/tests/fixtures/manifest/locales/en.yaml @@ -0,0 +1,4 @@ +app: + name: My App + short_name: Short + description: My app description diff --git a/src/cli/plugins/locale/tests/fixtures/manifest/locales/fr.yaml b/src/cli/plugins/locale/tests/fixtures/manifest/locales/fr.yaml new file mode 100644 index 00000000..07b23454 --- /dev/null +++ b/src/cli/plugins/locale/tests/fixtures/manifest/locales/fr.yaml @@ -0,0 +1,4 @@ +app: + name: Mon App + short_name: Court + description: Description de mon app diff --git a/src/cli/resolvers/config.test.ts b/src/cli/resolvers/config.test.ts index 93351020..d7f36c2f 100644 --- a/src/cli/resolvers/config.test.ts +++ b/src/cli/resolvers/config.test.ts @@ -35,6 +35,8 @@ import {loadConfig} from "c12"; import resolveConfig from "./config"; +import {Language} from "@typing/locale"; + const mockedLoadConfig = jest.mocked(loadConfig); describe("config resolver", () => { @@ -49,6 +51,36 @@ describe("config resolver", () => { expect(config.sharedDir).toBe("."); }); + test("uses English as the default language", async () => { + const config = await resolveConfig({configFile: "package.json"}); + + expect(config.lang).toBe(Language.English); + }); + + test("normalizes language from user config", async () => { + mockedLoadConfig.mockResolvedValue({ + config: { + lang: "fr", + }, + }); + + const config = await resolveConfig({configFile: "package.json"}); + + expect(config.lang).toBe(Language.French); + }); + + test("throws a clear error for invalid language config", async () => { + mockedLoadConfig.mockResolvedValue({ + config: { + lang: "missing", + }, + }); + + await expect(resolveConfig({configFile: "package.json"})).rejects.toThrow( + 'Invalid language "missing" provided by config' + ); + }); + test("uses default shared directory when shared is true", async () => { const config = await resolveConfig({ configFile: "package.json", diff --git a/src/cli/resolvers/config.ts b/src/cli/resolvers/config.ts index fea043ef..6fd739a5 100644 --- a/src/cli/resolvers/config.ts +++ b/src/cli/resolvers/config.ts @@ -35,9 +35,21 @@ import {Command, Mode} from "@typing/app"; import {Browser} from "@typing/browser"; import {Plugin} from "@typing/plugin"; import {ManifestVersion} from "@typing/manifest"; -import {Language} from "@typing/locale"; +import {Language, LanguageCodes} from "@typing/locale"; import {DefaultIconGroupName} from "@typing/icon"; +const resolveLanguage = (lang?: `${Language}` | Language): Language => { + if (!lang) { + return Language.English; + } + + if (LanguageCodes.has(lang)) { + return lang as Language; + } + + throw new Error(`Invalid language "${lang}" provided by config`); +}; + const getUserConfig = async (config: ReadonlyConfig): Promise => { const configFilePath = getConfigFile(config); @@ -244,7 +256,7 @@ export default async (config: OptionalConfig): Promise => { minimumVersion, author, homepage, - lang, + lang: resolveLanguage(lang), icon, incognito, specific, @@ -297,11 +309,12 @@ export default async (config: OptionalConfig): Promise => { let vars = loadDotenv(resolvedConfig); - const {plugins: userPlugins = [], ...userConfig} = await getUserConfig(resolvedConfig); + const {plugins: userPlugins = [], lang: userLang, ...userConfig} = await getUserConfig(resolvedConfig); resolvedConfig = { ...resolvedConfig, ...userConfig, + lang: resolveLanguage(userLang ?? resolvedConfig.lang), }; resolvedConfig.sharedDir = _.isString(resolvedConfig.shared) diff --git a/src/cli/virtual/command.ts b/src/cli/virtual/command.ts index 2b600fe3..e22c820e 100644 --- a/src/cli/virtual/command.ts +++ b/src/cli/virtual/command.ts @@ -1,5 +1,5 @@ import type {CommandUnresolvedDefinition} from "adnbn"; -import {__t} from "adnbn/locale"; +import {resolve} from "adnbn/locale"; import command, {isValidCommandDefinition, isValidCommandExecuteFunction} from "adnbn/entry/command"; import * as module from "virtual:command-entrypoint"; @@ -22,7 +22,7 @@ try { command({ name, execute, - description: description ? __t(description) : undefined, + description: description ? resolve(description) : undefined, ...options, }); } catch (e) { diff --git a/src/cli/virtual/view.ts b/src/cli/virtual/view.ts index 3c69e37c..09229f69 100644 --- a/src/cli/virtual/view.ts +++ b/src/cli/virtual/view.ts @@ -1,5 +1,5 @@ import type {ViewDefinition, ViewOptions} from "adnbn"; -import {__t} from "adnbn/locale"; +import {resolve} from "adnbn/locale"; import {isViewDefinition, isValidViewDefinitionRenderValue} from "adnbn/entry/view"; import view from "virtual:view-framework"; @@ -19,7 +19,7 @@ try { const {title, ...options} = definition; - view({title: title ? __t(title) : undefined, ...options}); + view({title: title ? resolve(title) : undefined, ...options}); } catch (e) { console.error("The view crashed on startup:", e); } diff --git a/src/cli/virtual/virtual.d.ts b/src/cli/virtual/virtual.d.ts index 37be4f3d..9f9ac9cf 100644 --- a/src/cli/virtual/virtual.d.ts +++ b/src/cli/virtual/virtual.d.ts @@ -131,7 +131,7 @@ declare module "adnbn/transport" { } declare module "adnbn/locale" { - export function __t(value: string): string; + export function resolve(value: string): string; } declare module "adnbn/entry/background" { diff --git a/src/locale/LocaleTypes.test.ts b/src/locale/LocaleTypes.test.ts new file mode 100644 index 00000000..9cc2c1cd --- /dev/null +++ b/src/locale/LocaleTypes.test.ts @@ -0,0 +1,117 @@ +import path from "path"; +import ts from "typescript"; + +const typecheck = (source: string): string[] => { + const filename = path.join(__dirname, "__locale-type-test.ts"); + const options: ts.CompilerOptions = { + module: ts.ModuleKind.ESNext, + moduleResolution: ts.ModuleResolutionKind.Bundler, + noEmit: true, + skipLibCheck: true, + strict: true, + target: ts.ScriptTarget.ESNext, + types: [], + }; + + const host = ts.createCompilerHost(options); + const getSourceFile = host.getSourceFile.bind(host); + const readFile = host.readFile.bind(host); + const fileExists = host.fileExists.bind(host); + + host.getSourceFile = (file, languageVersion, onError, shouldCreateNewSourceFile) => { + if (file === filename) { + return ts.createSourceFile(file, source, languageVersion, true); + } + + return getSourceFile(file, languageVersion, onError, shouldCreateNewSourceFile); + }; + + host.readFile = file => (file === filename ? source : readFile(file)); + host.fileExists = file => file === filename || fileExists(file); + + const program = ts.createProgram([filename], options, host); + + return ts + .getPreEmitDiagnostics(program) + .filter(diagnostic => diagnostic.file?.fileName === filename) + .map(diagnostic => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")); +}; + +const prelude = ` +import type {LocaleNonPluralKeys, LocalePluralKeys, LocaleSubstitutionArgs} from "../types/locale"; + +interface Structure { + "app.name": {plural: false; substitutions: []}; + "app.greeting": {plural: false; substitutions: ["name"]}; + "app.cars": {plural: true; substitutions: ["count"]}; +} + +declare function trans>( + key: K, + ...args: LocaleSubstitutionArgs +): string; + +declare function choice>( + key: K, + count: number, + ...args: LocaleSubstitutionArgs +): string; +`; + +describe("locale types", () => { + test("accept valid locale calls", () => { + expect( + typecheck(` +${prelude} + +trans("app.name"); +trans("app.greeting", {name: "Alice"}); +choice("app.cars", 2, {count: 2}); +`) + ).toEqual([]); + }); + + test("reject substitutions for keys without placeholders", () => { + const diagnostics = typecheck(` +${prelude} + +trans("app.name", {name: "Alice"}); +`).join("\n"); + + expect(diagnostics).toMatch("Expected 1 arguments, but got 2."); + }); + + test("require all substitutions for keys with placeholders", () => { + const diagnostics = typecheck(` +${prelude} + +trans("app.greeting"); +trans("app.greeting", {}); +`).join("\n"); + + expect(diagnostics).toMatch("Expected 2 arguments, but got 1."); + expect(diagnostics).toMatch("Property 'name' is missing"); + }); + + test("reject unknown substitution keys", () => { + const diagnostics = typecheck(` +${prelude} + +trans("app.greeting", {name: "Alice", extra: "bad"}); +`).join("\n"); + + expect(diagnostics).toMatch("'extra' does not exist"); + }); + + test("keeps plural and non-plural locale keys separate", () => { + const diagnostics = typecheck(` +${prelude} + +trans("app.cars", {count: 2}); +choice("app.greeting", 1, {name: "Alice"}); +`).join("\n"); + + expect(diagnostics).toMatch("Argument of type '\"app.cars\"' is not assignable"); + expect(diagnostics).toMatch("Argument of type '\"app.greeting\"' is not assignable"); + }); +}); diff --git a/src/locale/adapters/react/LocaleProvider.tsx b/src/locale/adapters/react/LocaleProvider.tsx index c5713e2a..3f15a85c 100644 --- a/src/locale/adapters/react/LocaleProvider.tsx +++ b/src/locale/adapters/react/LocaleProvider.tsx @@ -18,12 +18,12 @@ const LocaleProvider = ({children, storage, container = "html"}: PropsWithChildr const [lang, setLang] = useState(locale.lang()); - const _: LocaleContract["_"] = useCallback((key, substitutions): string => { - return locale.trans(key, substitutions); + const t: LocaleContract["t"] = useCallback((key, ...args): string => { + return locale.trans(key, ...args); }, []); - const choice: LocaleContract["choice"] = useCallback((key, count, substitutions): string => { - return locale.choice(key, count, substitutions); + const choice: LocaleContract["choice"] = useCallback((key, count, ...args): string => { + return locale.choice(key, count, ...args); }, []); const change: LocaleContract["change"] = useCallback((lang): void => { @@ -61,7 +61,7 @@ const LocaleProvider = ({children, storage, container = "html"}: PropsWithChildr return ( { +export interface LocaleContract { lang: Language; dir: LocaleDir; isRtl: boolean; - _>(key: K, substitutions?: LocaleSubstitutionsFor): string; + t>(key: K, ...args: LocaleSubstitutionArgs): string; - choice>(key: K, count: number, substitutions?: LocaleSubstitutionsFor): string; + choice>(key: K, count: number, ...args: LocaleSubstitutionArgs): string; change(lang: Language): void; } @@ -29,7 +22,7 @@ export const DefaultLocale: LocaleContract = { lang: Language.English, isRtl: false, dir: LocaleDir.LeftToRight, - _(key: string): string { + t(key: string): string { return key as string; }, choice(key: string): string { diff --git a/src/locale/helpers.ts b/src/locale/helpers.ts index cde5d181..a198f15f 100644 --- a/src/locale/helpers.ts +++ b/src/locale/helpers.ts @@ -1,74 +1,102 @@ import {LocaleNativeStructure, NativeLocale} from "@locale/providers"; import {convertLocaleMessageKey, extractLocaleKey} from "@locale/utils"; -import {LocaleNonPluralKeys, LocalePluralKeys, LocaleSubstitutionsFor} from "@typing/locale"; +import {LocaleNonPluralKeys, LocalePluralKeys, LocaleSubstitutionArgs} from "@typing/locale"; /** - * Translates a given locale key into the corresponding localized string. + * Translates a non-plural locale key. * - * @template K - A type representing the non-plural keys of the locale structure. - * @param {K} key - The locale key to be translated. - * @param {LocaleSubstitutionsFor} [substitutions] - Optional substitutions to be applied - * within the localized string. These are typically placeholders replaced with dynamic values. - * @returns {string} - The translated string for the given key, with substitutions applied if provided. + * Substitutions are type-checked from the generated locale structure: + * keys without placeholders do not accept substitutions, while keys with + * placeholders require all declared substitution values. + * + * @example + * ```ts + * t("app.name"); + * t("app.greeting", {name: "Alice"}); + * ``` + * + * @param key - The locale key to translate. + * @param args + * @returns The translated string. */ -export const _ = >( +export const t = >( key: K, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string => { - return NativeLocale.getInstance().trans(key, substitutions); + return NativeLocale.getInstance().trans(key, ...args); }; /** - * Translates a given locale key into the corresponding localized string - * based on a specific count for pluralization. + * Translates a plural locale key using the provided count. + * + * Substitutions are type-checked from the generated locale structure: + * keys without placeholders do not accept substitutions, while keys with + * placeholders require all declared substitution values. * - * @template K - A type representing the non-plural keys of the locale structure. - * @param {K} key - The locale key to be translated. - * @param {number} count - The count used to determine the pluralization form. - * @param {LocaleSubstitutionsFor} [substitutions] - Optional substitutions to be applied - * within the localized string. These are typically placeholders replaced with dynamic values. - * @returns {string} - The translated string for the given key, adjusted for pluralization and with substitutions applied if provided. + * @example + * ```ts + * choice("cart.items", count, {count}); + * ``` + * + * @param key - The locale key to translate. + * @param count - The count used to select the plural form. + * @param args + * @returns The translated string. */ -export const _c = >( +export const choice = >( key: K, count: number, - substitutions?: LocaleSubstitutionsFor + ...args: LocaleSubstitutionArgs ): string => { - return NativeLocale.getInstance().choice(key, count, substitutions); + return NativeLocale.getInstance().choice(key, count, ...args); }; /** - * Converts a locale key into a standardized format and logs a warning if the key is not found - * in the current language's locale keys. + * Converts a locale key to a browser message reference. + * + * This is useful for browser-managed extension fields that expect + * `__MSG_name__` references instead of already translated text. * - * @param {Extract} key - The locale key to be converted. - * This key must be a string and exist within the `LocaleNativeStructure`. - * @returns {string} - The converted locale message key. + * A warning is logged when the key does not exist in the generated locale keys. + * + * @example + * ```ts + * key("app.name"); // "__MSG_app_name__" + * ``` + * + * @param value - The locale key to convert. + * @returns The browser message reference. */ -export const __ = (key: keyof LocaleNativeStructure & string): string => { +export const key = (value: keyof LocaleNativeStructure & string): string => { const locale = NativeLocale.getInstance(); - if (!locale.keys().has(key)) { - console.warn(`Locale key "${key}" not found in "${locale.lang()}" language.`); + if (!locale.keys().has(value)) { + console.warn(`Locale key "${value}" not found in "${locale.lang()}" language.`); } - return convertLocaleMessageKey(key); + return convertLocaleMessageKey(value); }; /** - * Attempts to extract a locale key from the provided string and translates it - * into the corresponding localized string. If no locale key can be extracted, - * the original string is returned. + * Resolves a string that may contain a locale marker. + * + * When the input contains a locale marker, the marker is extracted and translated. + * Plain strings are returned unchanged. + * + * @example + * ```ts + * resolve("@app.name"); + * resolve("Plain title"); + * ``` * - * @param {string} input - The input string from which a locale key is to be extracted. - * @returns {string} - The translated string if a locale key is successfully extracted, - * or the original string if no locale key is found. + * @param input - A plain string or a marked locale key string. + * @returns The translated text when a marker is found, otherwise the original input. */ -export const __t = (input: string): string => { +export const resolve = (input: string): string => { const localeKey = extractLocaleKey(input); if (localeKey) { - return _(localeKey as LocaleNonPluralKeys); + return t(localeKey as LocaleNonPluralKeys); } return input; diff --git a/src/locale/index.ts b/src/locale/index.ts index 8fc11347..19d6d8d9 100644 --- a/src/locale/index.ts +++ b/src/locale/index.ts @@ -9,7 +9,9 @@ export { type LocaleProvider, type LocaleDynamicProvider, type LocaleKeys, - type LocaleSubstitutionsFor, + type LocaleSubstitutionArgs, + type LocaleSubstitutionKeys, + type LocaleSubstitutionValue, type LocaleNonPluralKeys, type LocalePluralKeys, } from "@typing/locale"; diff --git a/src/locale/providers/AbstractLocale.ts b/src/locale/providers/AbstractLocale.ts index 718fe8fa..f21987a4 100644 --- a/src/locale/providers/AbstractLocale.ts +++ b/src/locale/providers/AbstractLocale.ts @@ -4,11 +4,12 @@ import { LocalePluralKeys, LocaleProvider, LocaleStructure, - LocaleSubstitutionsFor, + LocaleSubstitutionArgs, + LocaleSubstitutionValue, LocaleValuesSeparator, } from "@typing/locale"; -export default abstract class implements LocaleProvider { +export default abstract class implements LocaleProvider { public abstract lang(): Language; public abstract keys(): Set; @@ -17,15 +18,14 @@ export default abstract class implements LocaleProvid protected abstract value(key: keyof S & string): string | undefined; - public trans>(key: K, substitutions?: LocaleSubstitutionsFor): string { + public trans>(key: K, ...args: LocaleSubstitutionArgs): string { + const [substitutions] = args; + return this.get(key, substitutions); } - public choice>( - key: K, - count: number, - substitutions?: LocaleSubstitutionsFor - ): string { + public choice>(key: K, count: number, ...args: LocaleSubstitutionArgs): string { + const [substitutions] = args; const parts = this.get(key, substitutions).split(LocaleValuesSeparator); const idx = this.getPluralIndex(count); @@ -33,7 +33,7 @@ export default abstract class implements LocaleProvid return parts[idx] ?? parts[0] ?? (key as string); } - public get(key: K, substitutions?: LocaleSubstitutionsFor): string { + public get(key: K, substitutions?: Record): string { const template = this.value(key); if (template === undefined) { @@ -44,15 +44,17 @@ export default abstract class implements LocaleProvid if (substitutions) { return template.replace(/{{(.*?)}}/g, (_, placeholder: string) => { - if (placeholder in substitutions) { - return substitutions[placeholder]!.toString(); + const substitution = placeholder.trim(); + + if (substitution in substitutions) { + return substitutions[substitution]!.toString(); } console.warn( - `Locale substitution "${placeholder}" not found for key "${key}" in "${this.lang()}" language.` + `Locale substitution "${substitution}" not found for key "${key}" in "${this.lang()}" language.` ); - return placeholder; + return substitution; }); } diff --git a/src/locale/providers/CustomLocale.test.ts b/src/locale/providers/CustomLocale.test.ts index 27a94ae0..cc9cb147 100644 --- a/src/locale/providers/CustomLocale.test.ts +++ b/src/locale/providers/CustomLocale.test.ts @@ -6,6 +6,7 @@ describe("CustomLocale", () => { const mockMessages = { title: "Adnbn", greeting: "Hello {{name}}", + spacedGreeting: "Hello {{ name }}", empty: "", }; @@ -49,6 +50,10 @@ describe("CustomLocale", () => { expect(locale.trans("greeting" as never, {name: "Alice"})).toBe("Hello Alice"); }); + test("returned the correct message with spaced substitutions", () => { + expect(locale.trans("spacedGreeting" as never, {name: "Alice"})).toBe("Hello Alice"); + }); + test("returned placeholder name if substitution is missing", () => { expect(locale.trans("greeting" as never, {firstName: "Alice"})).toBe("Hello name"); }); @@ -58,9 +63,9 @@ describe("CustomLocale", () => { expect(consoleWarnSpy).toHaveBeenCalledWith('Locale key "test" not found in "en" language.'); }); - test("returned key instead value if message is empty", () => { - expect(locale.trans("empty" as never)).toBe("empty"); - expect(consoleWarnSpy).toHaveBeenCalledWith('Locale key "empty" not found in "en" language.'); + test("returned empty value if message is empty", () => { + expect(locale.trans("empty" as never)).toBe(""); + expect(consoleWarnSpy).not.toHaveBeenCalled(); }); }); @@ -120,11 +125,11 @@ describe("CustomLocale", () => { }); }); - test("languages with 3 plural forms - Croatian, Russian, Serbian, Ukrainian", () => { - const arr = ["машина", "машини", "машин"]; + test("languages with 3 plural forms - Russian", () => { + const arr = ["машина", "машины", "машин"]; const messages = {[key]: arr.join(LocaleValuesSeparator)}; - locale.setLang(Language.Ukrainian).setData(messages); + locale.setLang(Language.Russian).setData(messages); // Last number 1 but not 11 [1, 21, 31, 101].forEach(item => { @@ -266,7 +271,7 @@ describe("CustomLocale", () => { // For only 2 expect(locale.choice(key, 2)).toBe(arr[2]); - // last two numbers 3<= and >=10 + // last two numbers 3<= and >=10 [3, 4, 5, 10, 106, 107, 108, 110].forEach(item => { expect(locale.choice(key, item)).toBe(arr[3]); }); diff --git a/src/locale/providers/CustomLocale.ts b/src/locale/providers/CustomLocale.ts index 16b0f377..390b341c 100644 --- a/src/locale/providers/CustomLocale.ts +++ b/src/locale/providers/CustomLocale.ts @@ -6,7 +6,7 @@ import {Language, LocaleStructure} from "@typing/locale"; export type CustomLocaleData = Record; -export default class extends AbstractLocale { +export default class extends AbstractLocale { constructor( protected language: Language = Language.English, protected data: CustomLocaleData = {} @@ -30,8 +30,8 @@ export default class extends Abstra return this.language; } - public keys(): Set { - return new Set(Object.keys(this.data)); + public keys(): Set { + return new Set(Object.keys(this.data)) as Set; } public languages(): Set { @@ -41,7 +41,7 @@ export default class extends Abstra protected value(key: string): string | undefined { const value = this.data[convertLocaleKey(key)]; - if (!value || value.length === 0) { + if (value === undefined) { return undefined; } diff --git a/src/locale/providers/DynamicLocale.test.ts b/src/locale/providers/DynamicLocale.test.ts new file mode 100644 index 00000000..aa533890 --- /dev/null +++ b/src/locale/providers/DynamicLocale.test.ts @@ -0,0 +1,30 @@ +jest.mock("@addon-core/browser", () => ({ + getI18nMessage: jest.fn(() => "en"), +})); + +import DynamicLocale from "./DynamicLocale"; +import CustomLocale, {CustomLocaleData} from "./CustomLocale"; + +import {Language} from "@typing/locale"; + +interface Structure { + empty: {plural: false; substitutions: []}; +} + +class TestDynamicLocale extends DynamicLocale { + public setLocale(lang: Language, data: CustomLocaleData): this { + this.locale = new CustomLocale(lang, data); + + return this; + } +} + +describe("DynamicLocale", () => { + test("does not fall back to native locale when dynamic value is empty", () => { + const locale = new TestDynamicLocale(false).setLocale(Language.French, { + empty: "", + }); + + expect(locale.trans("empty")).toBe(""); + }); +}); diff --git a/src/locale/providers/DynamicLocale.ts b/src/locale/providers/DynamicLocale.ts index 5e9581f4..ee2b3092 100644 --- a/src/locale/providers/DynamicLocale.ts +++ b/src/locale/providers/DynamicLocale.ts @@ -7,7 +7,10 @@ import CustomLocale, {CustomLocaleData} from "./CustomLocale"; import {Language, LanguageCodes, LocaleDynamicProvider, LocaleMessages} from "@typing/locale"; -export default class extends NativeLocale implements LocaleDynamicProvider { +export default class + extends NativeLocale + implements LocaleDynamicProvider +{ protected cache = new Map(); protected locale?: CustomLocale; @@ -93,8 +96,8 @@ export default class extends NativeLocale imple return this.locale?.lang() || super.lang(); } - protected value(key: Extract): string | undefined { - return this.locale?.get(key) || super.value(key); + protected value(key: Extract): string | undefined { + return this.locale?.get(key) ?? super.value(key); } protected async fetch(lang: Language): Promise { diff --git a/src/locale/providers/NativeLocale.ts b/src/locale/providers/NativeLocale.ts index f74f440d..7f05c408 100644 --- a/src/locale/providers/NativeLocale.ts +++ b/src/locale/providers/NativeLocale.ts @@ -8,10 +8,10 @@ import {Language, LocaleCustomKeyForLanguage, LocaleProvider, LocaleStructure} f export interface LocaleNativeStructure extends LocaleStructure {} -export default class NativeLocale extends AbstractLocale { +export default class NativeLocale extends AbstractLocale { private static instance?: LocaleProvider; - public static getInstance(): LocaleProvider { + public static getInstance(): LocaleProvider { return (NativeLocale.instance ??= new NativeLocale()); } @@ -50,14 +50,14 @@ export default class NativeLocale extends AbstractLocale return this.language; } - public keys(): Set { + public keys(): Set { try { // @ts-expect-error: __ADNBN_LOCALE_KEYS__ is a virtual variable generated by the bundler `src/cli/plugins/locale/index.ts` - return new Set(__ADNBN_LOCALE_KEYS__); + return new Set(__ADNBN_LOCALE_KEYS__) as Set; } catch (e) { console.error("[NativeLocale] Failed to access locale keys. Ensure the bundler plugin is active.", e); - return new Set(); + return new Set(); } } @@ -72,7 +72,7 @@ export default class NativeLocale extends AbstractLocale } } - protected value(key: Extract): string | undefined { + protected value(key: Extract): string | undefined { const value = getI18nMessage(convertLocaleKey(key)); if (!value || value.length === 0) { diff --git a/src/main/popup.ts b/src/main/popup.ts index a310d9e3..541a5533 100644 --- a/src/main/popup.ts +++ b/src/main/popup.ts @@ -1,6 +1,6 @@ import {setActionPopup, setActionTitle} from "@addon-core/browser"; -import {__t} from "@locale/helpers"; +import {resolve} from "@locale/helpers"; import {changeActionIcon} from "./icon"; @@ -52,7 +52,7 @@ export const changePopup = async (alias: PopupAlias, tab?: number | Tab): Promis await setActionPopup(path, tab); if (title) { - await setActionTitle(__t(title), tab); + await setActionTitle(resolve(title), tab); } if (icon) { diff --git a/src/main/sidebar.ts b/src/main/sidebar.ts index b7738675..ec6ef02b 100644 --- a/src/main/sidebar.ts +++ b/src/main/sidebar.ts @@ -1,6 +1,6 @@ import {setSidebarPath, setSidebarTitle} from "@addon-core/browser"; -import {__t} from "@locale/helpers"; +import {resolve} from "@locale/helpers"; import type {SidebarDefinition} from "@typing/sidebar"; import type {ManifestSidebar} from "@typing/manifest"; @@ -50,6 +50,6 @@ export const changeSidebar = async (alias: SidebarAlias, tab?: number | Tab): Pr await setSidebarPath(path, tab); if (title) { - await setSidebarTitle(__t(title), tab); + await setSidebarTitle(resolve(title), tab); } }; diff --git a/src/types/config.ts b/src/types/config.ts index dcd79751..104db621 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -195,7 +195,7 @@ export interface Config { * Default locale for the extension. * @example "en" */ - lang?: string | Language; + lang: Language; /** * Shared source layer configuration. @@ -724,7 +724,10 @@ export interface Config { cssIdentName: string; } -export type OptionalConfig = Partial; +export type OptionalConfig = Omit, "lang"> & { + lang?: Language | `${Language}`; +}; + export type UserConfig = Omit; export type ReadonlyConfig = Readonly; diff --git a/src/types/locale.ts b/src/types/locale.ts index f6065463..b1e47572 100644 --- a/src/types/locale.ts +++ b/src/types/locale.ts @@ -77,7 +77,7 @@ export const LanguageCodes: ReadonlySet = new Set(Object.values(Language export const LocaleFileExtensions: ReadonlySet = new Set(["yaml", "yml", "json"]); -export type LocaleValue = string | number | string[] | number[]; +export type LocaleValue = string | number | Array; export type LocaleData = { [key: string]: LocaleValue | LocaleData; @@ -111,12 +111,20 @@ export interface LocaleBuilder { validate(): this; } +export type LocaleBuilders = Map; + export interface LocaleValidator { isValid(locale: LocaleBuilder): boolean; validate(locale: LocaleBuilder): this; } +export interface LocaleContractValidator { + isValid(builders: LocaleBuilders): boolean; + + validate(builders: LocaleBuilders): this; +} + export interface LocaleFutures { plural: boolean; substitutions: readonly string[]; @@ -126,23 +134,33 @@ export interface LocaleStructure { [key: string]: LocaleFutures; } -export type LocaleNonPluralKeys = { +export type LocaleNonPluralKeys = { [K in keyof T]: T[K] extends {plural: false} ? K : never; }[keyof T] & string; -export type LocalePluralKeys = { +export type LocalePluralKeys = { [K in keyof T]: T[K] extends {plural: true} ? K : never; }[keyof T] & string; -export type LocaleSubstitutionsFor = T[K] extends { - substitutions: readonly (infer U)[]; -} - ? Partial> +export type LocaleSubstitutionValue = string | number; + +export type LocaleSubstitutionKeys = T[K] extends {substitutions: readonly (infer U)[]} + ? U & string : never; -export interface LocaleProvider { +export type LocaleSubstitutionsFor = [LocaleSubstitutionKeys] extends [never] + ? never + : Record, LocaleSubstitutionValue>; + +export type LocaleSubstitutionArgs = string extends keyof T + ? [substitutions?: Record] + : [LocaleSubstitutionKeys] extends [never] + ? [] + : [substitutions: LocaleSubstitutionsFor]; + +export interface LocaleProvider { lang(): Language; languages(): Set; @@ -150,12 +168,12 @@ export interface LocaleProvider { keys(): ReadonlySet; // non-plural keys - trans>(key: K, substitutions?: LocaleSubstitutionsFor): string; + trans>(key: K, ...args: LocaleSubstitutionArgs): string; // plural keys - choice>(key: K, count: number, substitutions?: LocaleSubstitutionsFor): string; + choice>(key: K, count: number, ...args: LocaleSubstitutionArgs): string; } -export interface LocaleDynamicProvider extends LocaleProvider { +export interface LocaleDynamicProvider extends LocaleProvider { change(lang: Language): Promise; } From 8469d92c52bf55abc27cdec74bfe47206370393b Mon Sep 17 00:00:00 2001 From: Anjey Tsibylskij <130153594+atldays@users.noreply.github.com> Date: Mon, 11 May 2026 21:05:54 +0300 Subject: [PATCH 20/20] feat(workspace): add workspace mode for single and multi app structure - add Workspace enum with single and multi modes - replace shared config option with workspace - keep sharedDir as a public configurable directory - normalize sharedDir to "." for single workspace - use configured sharedDir for multi workspace - update config resolver tests for workspace behavior --- src/cli/resolvers/config.test.ts | 57 ++++++++++++++++++++++++++------ src/cli/resolvers/config.ts | 41 +++++++++++++++++------ src/main/app.ts | 2 +- src/main/config.ts | 2 +- src/types/app.ts | 5 +++ src/types/config.ts | 27 ++++++++------- 6 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/cli/resolvers/config.test.ts b/src/cli/resolvers/config.test.ts index d7f36c2f..add3a5e7 100644 --- a/src/cli/resolvers/config.test.ts +++ b/src/cli/resolvers/config.test.ts @@ -35,6 +35,7 @@ import {loadConfig} from "c12"; import resolveConfig from "./config"; +import {Workspace} from "@typing/app"; import {Language} from "@typing/locale"; const mockedLoadConfig = jest.mocked(loadConfig); @@ -44,10 +45,10 @@ describe("config resolver", () => { mockedLoadConfig.mockResolvedValue({config: {}}); }); - test("uses source directory as shared layer by default", async () => { + test("uses single workspace by default", async () => { const config = await resolveConfig({configFile: "package.json"}); - expect(config.shared).toBe(false); + expect(config.workspace).toBe(Workspace.Single); expect(config.sharedDir).toBe("."); }); @@ -81,36 +82,70 @@ describe("config resolver", () => { ); }); - test("uses default shared directory when shared is true", async () => { + test("uses default shared directory for multi workspace", async () => { const config = await resolveConfig({ configFile: "package.json", - shared: true, + workspace: "multi", }); - expect(config.shared).toBe(true); + expect(config.workspace).toBe(Workspace.Multi); expect(config.sharedDir).toBe("shared"); }); - test("uses custom shared directory when shared is a string", async () => { + test("accepts workspace enum value", async () => { const config = await resolveConfig({ configFile: "package.json", - shared: "common", + workspace: Workspace.Multi, }); - expect(config.shared).toBe("common"); + expect(config.workspace).toBe(Workspace.Multi); + expect(config.sharedDir).toBe("shared"); + }); + + test("uses custom shared directory for multi workspace", async () => { + const config = await resolveConfig({ + configFile: "package.json", + workspace: "multi", + sharedDir: "common", + }); + + expect(config.workspace).toBe(Workspace.Multi); expect(config.sharedDir).toBe("common"); }); - test("normalizes shared directory after loading user config", async () => { + test("ignores custom shared directory for single workspace", async () => { + const config = await resolveConfig({ + configFile: "package.json", + workspace: "single", + sharedDir: "common", + }); + + expect(config.workspace).toBe(Workspace.Single); + expect(config.sharedDir).toBe("."); + }); + + test("normalizes workspace after loading user config", async () => { mockedLoadConfig.mockResolvedValue({ config: { - shared: true, + workspace: "multi", }, }); const config = await resolveConfig({configFile: "package.json"}); - expect(config.shared).toBe(true); + expect(config.workspace).toBe(Workspace.Multi); expect(config.sharedDir).toBe("shared"); }); + + test("throws a clear error for invalid workspace config", async () => { + mockedLoadConfig.mockResolvedValue({ + config: { + workspace: "missing", + }, + }); + + await expect(resolveConfig({configFile: "package.json"})).rejects.toThrow( + 'Invalid workspace "missing" provided by config' + ); + }); }); diff --git a/src/cli/resolvers/config.ts b/src/cli/resolvers/config.ts index 6fd739a5..8a9d1dbd 100644 --- a/src/cli/resolvers/config.ts +++ b/src/cli/resolvers/config.ts @@ -30,8 +30,8 @@ import { import {fromRootPath, getAppPath, getAppSourcePath, getConfigFile} from "../resolvers/path"; -import {Config, OptionalConfig, ReadonlyConfig, UserConfig} from "@typing/config"; -import {Command, Mode} from "@typing/app"; +import type {Config, OptionalConfig, ReadonlyConfig, UserConfig} from "@typing/config"; +import {Command, Mode, Workspace} from "@typing/app"; import {Browser} from "@typing/browser"; import {Plugin} from "@typing/plugin"; import {ManifestVersion} from "@typing/manifest"; @@ -50,6 +50,22 @@ const resolveLanguage = (lang?: `${Language}` | Language): Language => { throw new Error(`Invalid language "${lang}" provided by config`); }; +const resolveWorkspace = (workspace?: Workspace | `${Workspace}`): Workspace => { + if (!workspace) { + return Workspace.Single; + } + + if (Object.values(Workspace).includes(workspace as Workspace)) { + return workspace as Workspace; + } + + throw new Error(`Invalid workspace "${workspace}" provided by config`); +}; + +const resolveSharedDir = (workspace: Workspace, sharedDir: string): string => { + return workspace === Workspace.Multi ? sharedDir : "."; +}; + const getUserConfig = async (config: ReadonlyConfig): Promise => { const configFilePath = getConfigFile(config); @@ -189,10 +205,11 @@ export default async (config: OptionalConfig): Promise => { lang = Language.English, incognito, specific, - shared = false, + workspace = Workspace.Single, rootDir = ".", outDir = "dist", srcDir = "src", + sharedDir = "shared", appsDir = "apps", appSrcDir = ".", localeDir = "locales", @@ -262,11 +279,11 @@ export default async (config: OptionalConfig): Promise => { specific, manifest, manifestVersion, - shared, + workspace: resolveWorkspace(workspace), rootDir, outDir, srcDir, - sharedDir: _.isString(shared) ? shared : shared ? "shared" : ".", + sharedDir, appsDir, appSrcDir, jsDir, @@ -309,19 +326,21 @@ export default async (config: OptionalConfig): Promise => { let vars = loadDotenv(resolvedConfig); - const {plugins: userPlugins = [], lang: userLang, ...userConfig} = await getUserConfig(resolvedConfig); + const { + plugins: userPlugins = [], + lang: userLang, + workspace: userWorkspace, + ...userConfig + } = await getUserConfig(resolvedConfig); resolvedConfig = { ...resolvedConfig, ...userConfig, lang: resolveLanguage(userLang ?? resolvedConfig.lang), + workspace: resolveWorkspace(userWorkspace ?? resolvedConfig.workspace), }; - resolvedConfig.sharedDir = _.isString(resolvedConfig.shared) - ? resolvedConfig.shared - : resolvedConfig.shared - ? "shared" - : "."; + resolvedConfig.sharedDir = resolveSharedDir(resolvedConfig.workspace, resolvedConfig.sharedDir); resolvedConfig = validateConfig(resolvedConfig); diff --git a/src/main/app.ts b/src/main/app.ts index 6945ef41..60f53133 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -1 +1 @@ -export {Mode, Command} from "@typing/app"; +export {Mode, Command, Workspace} from "@typing/app"; diff --git a/src/main/config.ts b/src/main/config.ts index af3fc667..24f06f88 100644 --- a/src/main/config.ts +++ b/src/main/config.ts @@ -1,4 +1,4 @@ -import {Config, ConfigDefinition, ReadonlyConfig, UserConfig} from "@typing/config"; +import type {Config, ConfigDefinition, ReadonlyConfig, UserConfig} from "@typing/config"; export type {Config, ReadonlyConfig, ConfigDefinition, UserConfig}; diff --git a/src/types/app.ts b/src/types/app.ts index 24db8171..279c4ba1 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -11,3 +11,8 @@ export enum Command { Build = "build", Watch = "watch", } + +export enum Workspace { + Single = "single", + Multi = "multi", +} diff --git a/src/types/config.ts b/src/types/config.ts index 104db621..d9ab855d 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,7 +1,7 @@ import type {Configuration as RspackConfig, Filename} from "@rspack/core"; import type {Options as HtmlOptions} from "html-rspack-tags-plugin"; -import {Command, Mode} from "@typing/app"; +import {Command, Mode, Workspace} from "@typing/app"; import {Browser, BrowserSpecific} from "@typing/browser"; import {ManifestIncognitoValue, ManifestVersion, ManifestBuilder, OptionalManifest} from "@typing/manifest"; import {Plugin} from "@typing/plugin"; @@ -198,15 +198,14 @@ export interface Config { lang: Language; /** - * Shared source layer configuration. + * Project workspace mode. * - * - `false` uses the source directory itself as the shared layer. - * - `true` uses the default `shared` directory. - * - a string uses a custom shared directory name. + * - `single` uses the source directory itself as the shared layer. + * - `multi` uses the configured shared directory. * - * @default false + * @default "single" */ - shared: boolean | string; + workspace: Workspace; /** * Path to the directory with source files for building. @@ -236,10 +235,13 @@ export interface Config { srcDir: string; /** - * Directory with common modules, content scripts, and background scripts. - * Contains code used by multiple extensions. + * Directory with shared modules (content scripts, background scripts, common code) + * used across multiple extensions. Applies only when `workspace` is `"multi"`; + * for a `"single"` workspace the value is forced to `"."`, since a single-app + * project has no separate shared layer. + * * @example "shared" - * @path Full path: `{{inputDir}}/{{srcDir}}//{{sharedDir}}` + * @path Full path: `{{inputDir}}/{{srcDir}}/{{sharedDir}}` * * @default "shared" */ @@ -724,11 +726,12 @@ export interface Config { cssIdentName: string; } -export type OptionalConfig = Omit, "lang"> & { +export type OptionalConfig = Omit, "lang" | "workspace"> & { lang?: Language | `${Language}`; + workspace?: Workspace | `${Workspace}`; }; -export type UserConfig = Omit; +export type UserConfig = Omit; export type ReadonlyConfig = Readonly; export type UserConfigCallback = (config: ReadonlyConfig) => UserConfig;