diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 43aefc921..000000000 --- a/.eslintrc +++ /dev/null @@ -1,47 +0,0 @@ -{ - "env": { - "browser": true, - "node": true, - "es2022": true - }, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], - "parserOptions": { - "sourceType": "module" - }, - "root": true, - "rules": { - "no-restricted-globals": ["error", "event", "self"], - "no-const-assign": ["error"], - "no-debugger": ["error"], - "no-dupe-class-members": ["error"], - "no-dupe-keys": ["error"], - "no-dupe-args": ["error"], - "no-dupe-else-if": ["error"], - "no-unsafe-negation": ["error"], - "no-duplicate-imports": ["error"], - "valid-typeof": ["error"], - "@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false, "caughtErrors": "all" }], - "no-restricted-syntax": [ - "error", - { - "selector": "MemberExpression[object.name='test'][property.name='only']", - "message": "test.only(...) is forbidden", - }, - { - "selector": "MemberExpression[object.name='describe'][property.name='only']", - "message": "describe.only(...) is forbidden", - } - ], - }, - "globals": { - "describe": true, - "expect": true, - "test": true, - "beforeEach": true, - "beforeAll": true, - "afterEach": true, - "afterAll": true, - "jest": true, - }, -} diff --git a/doc/learning/tutorial_todoapp.md b/doc/learning/tutorial_todoapp.md index 7f606a0ad..0ae298328 100644 --- a/doc/learning/tutorial_todoapp.md +++ b/doc/learning/tutorial_todoapp.md @@ -148,7 +148,7 @@ data and a template to the `App` component: ```js class Root extends Component { - static template = xml/* xml */ ` + static template = xml /* xml */ `
@@ -565,7 +565,7 @@ function createTaskStore() { // Task Component // ------------------------------------------------------------------------- class Task extends Component { - static template = xml/* xml */ ` + static template = xml /* xml */ `
@@ -583,7 +583,7 @@ class Task extends Component { // Root Component // ------------------------------------------------------------------------- class Root extends Component { - static template = xml/* xml */ ` + static template = xml /* xml */ `
@@ -838,7 +838,7 @@ For reference, here is the final code: // Task Component // ------------------------------------------------------------------------- class Task extends Component { - static template = xml/* xml */ ` + static template = xml /* xml */ `
diff --git a/doc/readme.md b/doc/readme.md index 9363ba708..0dcd45d7e 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -34,7 +34,7 @@ Other hooks: - [`useComponent`](reference/hooks.md#usecomponent): return a reference to the current component (useful to create derived hooks) - [`useEffect`](reference/hooks.md#useeffect): define an effect with its dependencies - [`useEnv`](reference/hooks.md#useenv): return a reference to the current env -- [`useExternalListener`](reference/hooks.md#useexternallistener): add a listener outside of a component DOM +- [`useListener`](reference/hooks.md#uselistener): add a listener outside of a component DOM - [`useRef`](reference/hooks.md#useref): get an object representing a reference (`t-ref`) - [`useChildSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for child components) - [`useSubEnv`](reference/hooks.md#usesubenv-and-usechildsubenv): extend the current env with additional information (for current component and child components) @@ -42,7 +42,6 @@ Other hooks: Utility/helpers: - [`EventBus`](reference/utils.md#eventbus): a simple event bus -- [`loadFile`](reference/utils.md#loadfile): an helper to load a file from the server - [`markup`](reference/templates.md#outputting-data): utility function to define strings that represent html (should not be escaped) - [`status`](reference/component.md#status-helper): utility function to get the status of a component (new, mounted or destroyed) - [`validate`](reference/utils.md#validate): validates if an object satisfies a specified schema diff --git a/doc/reference/app.md b/doc/reference/app.md index 67395eace..a6b29b370 100644 --- a/doc/reference/app.md +++ b/doc/reference/app.md @@ -40,7 +40,6 @@ instance somewhere in the DOM. is complete. The `option` object is an object with the following keys: - - **`position (string)`**: either `first-child` or `last-child`. This option determines the position of the application in the target: either first or last child. @@ -130,7 +129,7 @@ what it could look like in practice: ```js // in the main js file: -const { loadFile, mount } = owl; +const { mount } = owl; // async, so we can use async/await (async function setup() { diff --git a/doc/reference/concurrency_model.md b/doc/reference/concurrency_model.md index b219c7dc7..7c8ba8da0 100644 --- a/doc/reference/concurrency_model.md +++ b/doc/reference/concurrency_model.md @@ -72,7 +72,6 @@ component (with some code like `app.mount(document.body)`). 1. `willStart` is called on `A` 2. when it is done, template `A` is rendered. - - component `B` is created 1. `willStart` is called on `B` 2. template `B` is rendered @@ -116,7 +115,6 @@ Here is what Owl will do: 1. because of a state change, the method `render` is called on `C` 2. template `C` is rendered again - - component `D` is updated: 1. hook `willUpdateProps` is called on `D` (async) 2. template `D` is rerendered @@ -130,7 +128,6 @@ Here is what Owl will do: 4. components `F`, `D` are patched in that order 5. component `C` is patched, which will cause recursively: - 1. `willUnmount` hook on `E` 2. destruction of `E`, diff --git a/doc/reference/hooks.md b/doc/reference/hooks.md index 7ea668f1f..1ef865b5d 100644 --- a/doc/reference/hooks.md +++ b/doc/reference/hooks.md @@ -9,7 +9,7 @@ - [`useState`](#usestate) - [`useRef`](#useref) - [`useSubEnv` and `useChildSubEnv`](#usesubenv-and-usechildsubenv) - - [`useExternalListener`](#useexternallistener) + - [`useListener`](#uselistener) - [`useComponent`](#usecomponent) - [`useEnv`](#useenv) - [`useEffect`](#useeffect) @@ -187,16 +187,16 @@ frozen, to prevent unwanted modifications. Note that both these hooks can be called an arbitrary number of times. The `env` will then be updated accordingly. -### `useExternalListener` +### `useListener` -The `useExternalListener` hook helps solve a very common problem: adding and removing +The `useListener` hook helps solve a very common problem: adding and removing a listener on some target whenever a component is mounted/unmounted. It takes a target as its first argument, forwards the other arguments to `addEventListener`. For example, a dropdown menu (or its parent) may need to listen to a `click` event on `window` to be closed: ```js -useExternalListener(window, "click", this.closeMenu, { capture: true }); +useListener(window, "click", this.closeMenu, { capture: true }); ``` ### `useComponent` diff --git a/doc/reference/utils.md b/doc/reference/utils.md index dba403786..f5e9647f8 100644 --- a/doc/reference/utils.md +++ b/doc/reference/utils.md @@ -6,7 +6,6 @@ functions are all available in the `owl.utils` namespace. ## Content - [`whenReady`](#whenready): executing code when DOM is ready -- [`loadFile`](#loadfile): loading a file (useful for templates) - [`EventBus`](#eventbus): a simple EventBus - [`validate`](#validate): a validation function - [`batched`](#batched): batch function calls @@ -32,21 +31,6 @@ whenReady(function () { }); ``` -## `loadFile` - -`loadFile` is a helper function to fetch a file. It simply -performs a `GET` request and returns the resulting string in a promise. The -initial usecase for this function is to load a template file. For example: - -```js -const { loadFile } = owl; - -async function makeEnv() { - const templates = await loadFile("templates.xml"); - // do something -} -``` - ## `EventBus` It is a simple `EventBus`, with the same API as usual DOM elements, and an diff --git a/docs/playground/playground.js b/docs/playground/playground.js index 7230bf541..3e127a972 100644 --- a/docs/playground/playground.js +++ b/docs/playground/playground.js @@ -1,19 +1,20 @@ -import { debounce, loadJS } from "./utils.js"; import { - App, + __info__, Component, - useState, - useRef, + mount, onMounted, - onWillUnmount, onPatched, + onWillStart, + onWillUnmount, onWillUpdateProps, - loadFile as _loadFile, - whenReady, - __info__, + OwlError, + props, + proxy, + signal, useEffect, - onWillStart, + whenReady, } from "../owl.js"; +import { debounce, loadJS } from "./utils.js"; //------------------------------------------------------------------------------ // Constants, helpers, utils @@ -32,7 +33,12 @@ const DEFAULT_XML = ` const fileCache = {}; const loadFile = (path) => { if (!(path in fileCache)) { - fileCache[path] = _loadFile(path); + fileCache[path] = fetch(path).then((result) => { + if (!result.ok) { + throw new OwlError("Error while fetching xml templates"); + } + return result.text(); + }); } return fileCache[path]; } @@ -75,7 +81,12 @@ const SAMPLES = [ code: ["js", "xml", "css"], }, { - description: "Form Input Bindings", + description: "List of Counters", + folder: "counters", + code: ["js", "xml", "css"], + }, + { + description: "t-model", folder: "form", code: ["js", "xml"], }, @@ -145,23 +156,25 @@ function loadSamples() { // Tabbed editor //------------------------------------------------------------------------------ class TabbedEditor extends Component { + props = props(); + setup() { const props = this.props; - this.state = useState({ + this.state = proxy({ currentTab: props.js !== false ? "js" : props.xml ? "xml" : "css" }); this.setTab = debounce(this.setTab.bind(this), 250, true); this.sessions = {}; this._setupSessions(props); - this.editorNode = useRef("editor"); + this.editorNode = signal(null); this._updateCode = this._updateCode.bind(this); onMounted(() => { - this.editor = this.editor || ace.edit(this.editorNode.el); + this.editor = this.editor || ace.edit(this.editorNode()); this.editor.setValue(this.props[this.state.currentTab], -1); - this.editor.setFontSize("12px"); + this.editor.setFontSize("14px"); this.editor.setTheme("ace/theme/monokai"); this.editor.setSession(this.sessions[this.state.currentTab]); const tabSize = this.state.currentTab === "xml" ? 2 : 4; @@ -252,7 +265,7 @@ class Playground extends Component { this.version = __info__.version; this.isDirty = false; - this.state = useState({ + this.state = proxy({ js: "", css: "", xml: DEFAULT_XML, @@ -290,17 +303,17 @@ class Playground extends Component { this.toggleLayout = debounce(this.toggleLayout, 250, true); this.runCode = debounce(this.runCode, 250, true); this.exportStandaloneApp = debounce(this.exportStandaloneApp, 250, true); - this.content = useRef("content"); + this.content = signal(null); this.updateCode = this.updateCode.bind(this); } runCode() { - this.content.el.innerHTML = ""; + this.content().innerHTML = ""; this.state.displayWelcome = false; const { js, css, xml } = this.state; const subiframe = makeCodeIframe(js, css, xml); - this.content.el.appendChild(subiframe); + this.content().appendChild(subiframe); } shareCode() { @@ -394,10 +407,10 @@ async function start() { loadFile("templates.xml"), whenReady() ]); - const rootApp = new App(Playground, { name: "Owl Playground" }); - rootApp.addTemplates(templates); - - await rootApp.mount(document.body); + await mount(Playground, document.body, { + name: "Owl Playground", + templates, + }); } start(); diff --git a/docs/playground/samples/components/components.css b/docs/playground/samples/components/components.css index 70eee24db..37a22e0f9 100644 --- a/docs/playground/samples/components/components.css +++ b/docs/playground/samples/components/components.css @@ -1,4 +1,4 @@ -.greeter { +.counter { font-size: 20px; width: 300px; height: 100px; @@ -7,4 +7,4 @@ line-height: 100px; background-color: #eeeeee; user-select: none; -} +} \ No newline at end of file diff --git a/docs/playground/samples/components/components.js b/docs/playground/samples/components/components.js index 0a1f34785..581ca3bb8 100644 --- a/docs/playground/samples/components/components.js +++ b/docs/playground/samples/components/components.js @@ -1,26 +1,19 @@ // In this example, we show how components can be defined and created. -import { Component, useState, mount } from "@odoo/owl"; +import { Component, signal, mount } from "@odoo/owl"; -class Greeter extends Component { - static template = "Greeter"; +class Counter extends Component { + static template = "Counter"; - setup() { - this.state = useState({ word: 'Hello' }); - } - - toggle() { - this.state.word = this.state.word === 'Hi' ? 'Hello' : 'Hi'; + count = signal(0); + + increment() { + this.count.update(val => val + 1); } } -// Main root component class Root extends Component { - static components = { Greeter }; + static components = { Counter }; static template = "Root" - - setup() { - this.state = useState({ name: 'World'}); - } } mount(Root, document.body, { templates: TEMPLATES, dev: true }); diff --git a/docs/playground/samples/components/components.xml b/docs/playground/samples/components/components.xml index 1caaf12a8..722cfcddc 100644 --- a/docs/playground/samples/components/components.xml +++ b/docs/playground/samples/components/components.xml @@ -1,9 +1,10 @@ -
- , +
+ Count:
- + + diff --git a/docs/playground/samples/counters/counters.css b/docs/playground/samples/counters/counters.css new file mode 100644 index 000000000..d2f5141ad --- /dev/null +++ b/docs/playground/samples/counters/counters.css @@ -0,0 +1,10 @@ +.counter { + font-size: 20px; + width: 300px; + height: 100px; + margin: 5px; + text-align: center; + line-height: 100px; + background-color: #eeeeee; + user-select: none; +} diff --git a/docs/playground/samples/counters/counters.js b/docs/playground/samples/counters/counters.js new file mode 100644 index 000000000..ebdf6393d --- /dev/null +++ b/docs/playground/samples/counters/counters.js @@ -0,0 +1,25 @@ +import { Component, signal, mount, proxy, computed, props } from "@odoo/owl"; + +class Counter extends Component { + static template = "Counter"; + + props = props({ count: Function }); + + increment() { + this.props.count.update((val) => val + 1); + } +} + +class Root extends Component { + static components = { Counter }; + static template = "Root"; + + counters = proxy([signal(1), signal(2)]); + sum = computed(() => this.counters.reduce((acc, value) => acc + value(), 0)); + + addCounter() { + this.counters.push(signal(0)); + } +} + +mount(Root, document.body, { templates: TEMPLATES, dev: true }); diff --git a/docs/playground/samples/counters/counters.xml b/docs/playground/samples/counters/counters.xml new file mode 100644 index 000000000..d4ccc70e7 --- /dev/null +++ b/docs/playground/samples/counters/counters.xml @@ -0,0 +1,15 @@ + +
+ Count: +
+ + +
+

Current sum:

+ +
+ + + +
+
diff --git a/docs/playground/samples/form/form.js b/docs/playground/samples/form/form.js index 345c118ba..66ca04747 100644 --- a/docs/playground/samples/form/form.js +++ b/docs/playground/samples/form/form.js @@ -2,20 +2,16 @@ // data between html inputs (and select/textareas) and the state of a component. // Note that there are two controls with t-model="color": they are totally // synchronized. -import { Component, useState, mount } from "@odoo/owl"; +import { Component, signal, mount } from "@odoo/owl"; class Form extends Component { static template = "Form"; - setup() { - this.state = useState({ - text: "", - othertext: "", - number: 11, - color: "", - bool: false - }); - } + text = signal(""); + othertext = signal(""); + number = signal(11); + color = signal(""); + bool = signal(false); } // Application setup diff --git a/docs/playground/samples/form/form.xml b/docs/playground/samples/form/form.xml index 1693eb9e9..55e99600a 100644 --- a/docs/playground/samples/form/form.xml +++ b/docs/playground/samples/form/form.xml @@ -2,20 +2,20 @@

Form

- Text (immediate): + Text (immediate):
- Other text (lazy): + Other text (lazy):
- Number: + Number:
- Boolean: + Boolean:
Color, with a select: - @@ -23,15 +23,15 @@
Color, with radio buttons: - - + +

State

-
Text:
-
Other Text:
-
Number:
-
Boolean: TrueFalse
-
Color:
+
Text:
+
Other Text:
+
Number:
+
Boolean: TrueFalse
+
Color:
diff --git a/docs/playground/samples/lifecycle_demo/lifecycle_demo.js b/docs/playground/samples/lifecycle_demo/lifecycle_demo.js index ee2eec878..0292d4b92 100644 --- a/docs/playground/samples/lifecycle_demo/lifecycle_demo.js +++ b/docs/playground/samples/lifecycle_demo/lifecycle_demo.js @@ -8,7 +8,6 @@ import { Component, useState, mount, - useComponent, onWillStart, onMounted, onWillUnmount, @@ -19,26 +18,24 @@ import { onRendered, onWillDestroy, } from "@odoo/owl"; - -function useLogLifecycle() { - const component = useComponent(); - const name = component.constructor.name; - onWillStart(() => console.log(`${name}:willStart`)); - onMounted(() => console.log(`${name}:mounted`)); - onWillUpdateProps(() => console.log(`${name}:willUpdateProps`)); - onWillRender(() => console.log(`${name}:willRender`)); - onRendered(() => console.log(`${name}:rendered`)); - onWillPatch(() => console.log(`${name}:willPatch`)); - onPatched(() => console.log(`${name}:patched`)); - onWillUnmount(() => console.log(`${name}:willUnmount`)); - onWillDestroy(() => console.log(`${name}:willDestroy`)); + +function useLogLifecycle(componentName) { + onWillStart(() => console.log(`${componentName}:willStart`)); + onMounted(() => console.log(`${componentName}:mounted`)); + onWillUpdateProps(() => console.log(`${componentName}:willUpdateProps`)); + onWillRender(() => console.log(`${componentName}:willRender`)); + onRendered(() => console.log(`${componentName}:rendered`)); + onWillPatch(() => console.log(`${componentName}:willPatch`)); + onPatched(() => console.log(`${componentName}:patched`)); + onWillUnmount(() => console.log(`${componentName}:willUnmount`)); + onWillDestroy(() => console.log(`${componentName}:willDestroy`)); } class DemoComponent extends Component { static template = "DemoComponent"; setup() { - useLogLifecycle(); + useLogLifecycle("DemoComponent"); this.state = useState({ n: 0 }); } increment() { @@ -51,7 +48,7 @@ class Root extends Component { static components = { DemoComponent }; setup() { - useLogLifecycle(); + useLogLifecycle("Root"); this.state = useState({ n: 0, flag: true }); } @@ -65,4 +62,3 @@ class Root extends Component { } mount(Root, document.body, { templates: TEMPLATES, dev: true }); - \ No newline at end of file diff --git a/docs/playground/samples/todo_app/todo_app.js b/docs/playground/samples/todo_app/todo_app.js index b63cbbc5f..f67761911 100644 --- a/docs/playground/samples/todo_app/todo_app.js +++ b/docs/playground/samples/todo_app/todo_app.js @@ -1,121 +1,161 @@ // This example is an implementation of the TodoList application, from the // www.todomvc.com project. This is a non trivial application with some // interesting user interactions. It uses the local storage for persistence. -// -// In this implementation, we use the owl reactivity mechanism. -import { Component, useState, mount, useRef, reactive, useEnv, useEffect } from "@odoo/owl"; +import { + Component, + computed, + effect, + mount, + plugin, + Plugin, + PluginManager, + props, + signal, + useEffect, + onWillDestroy, +} from "@odoo/owl"; -//------------------------------------------------------------------------------ -// Constants, helpers -//------------------------------------------------------------------------------ const ENTER_KEY = 13; const ESC_KEY = 27; -function useAutofocus(name) { - let ref = useRef(name); - useEffect(el => el && el.focus(), () => [ref.el]); -} +class TodoItem { + #list; -function useStore() { - const env = useEnv(); - return useState(env.store); + constructor(list, { id, text, isCompleted }) { + this.#list = list; + this.id = id; + this.text = signal(text); + this.isCompleted = signal(isCompleted); + } + + delete() { + this.#list.delete(this); + } + + toggle() { + this.isCompleted.update((value) => !value); + } } -//------------------------------------------------------------------------------ -// Task store -//------------------------------------------------------------------------------ -class TaskList { - constructor(tasks) { - this.tasks = tasks || []; - const taskIds = this.tasks.map((t) => t.id); - this.nextId = taskIds.length ? Math.max(...taskIds) + 1 : 1; +class LocalStoragePlugin extends Plugin { + static id = "local_storage"; + + cleanups = []; + + setup() { + onWillDestroy(() => { + for (let cleanup of cleanups) { + cleanup(); + } + }); + } + + open({ key, encode, decode }) { + const str = localStorage.getItem(key); + const result = signal(decode(str)); + this.cleanups.push( + effect(() => { + const str = encode(result()); + localStorage.setItem(key, str); + }) + ); + return result; } +} - addTask(text) { +class TodoListPlugin extends Plugin { + static id = "todo_list"; + todos = signal([]); + + localStorage = plugin(LocalStoragePlugin); + todos = this.localStorage.open({ + key: "todoapp", + encode: (data) => { + const json = data.map((todo) => ({ + id: todo.id, + text: todo.text(), + isCompleted: todo.isCompleted(), + })); + return JSON.stringify(json); + }, + decode: (str) => { + const data = JSON.parse(str || "[]"); + return data.map((todo) => new TodoItem(this, todo)); + }, + }); + + generateId() { + return Math.random().toString(36).substring(2, 10); + } + + isEmpty = computed(() => !this.todos().length); + + add(text) { text = text.trim(); if (text) { - const task = { - id: this.nextId++, - text: text, - isCompleted: false, - }; - this.tasks.push(task); + const data = { id: this.generateId(), text, isComplete: false }; + const todo = new TodoItem(this, data); + this.todos().push(todo); + this.todos.update(); } } - toggleTask(id) { - const task = this.tasks.find(t => t.id === id); - task.isCompleted = !task.isCompleted; + delete(todo) { + const result = this.todos().filter((t) => t !== todo); + this.todos.set(result); } toggleAll(value) { - for (let task of this.tasks) { - task.isCompleted = value; + for (let todo of this.todos()) { + todo.isCompleted.set(value); } } - + clearCompleted() { - const tasks = this.tasks.filter(t => t.isCompleted); - for (let task of tasks) { - this.deleteTask(task.id); - } - } - - deleteTask(id) { - const index = this.tasks.findIndex((t) => t.id === id); - this.tasks.splice(index, 1); - } - - updateTask(id, text) { - const value = text.trim(); - if (!value) { - this.deleteTask(id); - } else { - const task = this.tasks.find(t => t.id === id); - task.text = value; + const todos = this.todos().filter((t) => t.isCompleted()); + for (let todo of todos) { + this.delete(todo); } } } -function createTaskStore() { - const saveTasks = () => localStorage.setItem("todoapp", JSON.stringify(taskStore.tasks)); - const initialTasks = JSON.parse(localStorage.getItem("todoapp") || "[]"); - const taskStore = reactive(new TaskList(initialTasks), saveTasks); - saveTasks(); - return taskStore; -} - //------------------------------------------------------------------------------ // Todo //------------------------------------------------------------------------------ class Todo extends Component { static template = "Todo"; - + + props = props({ todo: TodoItem }); + todo = this.props.todo; + isEditing = signal(false); + input = signal(null); + text = signal(this.todo.text()); + setup() { - useAutofocus("input"); - this.store = useStore(); - this.state = useState({ - isEditing: false - }); + useEffect( + (el) => el && el.focus(), + () => [this.input()] + ); + } + + stopEditing() { + this.isEditing.set(false); } handleKeyup(ev) { if (ev.keyCode === ENTER_KEY) { - this.updateText(ev.target.value); + this.todo.text.set(this.text()); + this.stopEditing(); } if (ev.keyCode === ESC_KEY) { - ev.target.value = this.props.text; - this.state.isEditing = false; + this.text.set(this.todo.text()); + this.stopEditing(); } } handleBlur(ev) { - this.updateText(ev.target.value); - } - - updateText(text) { - this.store.updateTask(this.props.id, text); - this.state.isEditing = false; + this.todo.text.set(this.text()); + this.stopEditing(); } } @@ -125,54 +165,48 @@ class Todo extends Component { class TodoList extends Component { static template = "TodoList"; static components = { Todo }; - - setup() { - this.store = useStore(); - this.state = useState({ filter: "all" }); - } - get displayedTasks() { - const tasks = this.store.tasks; - switch (this.state.filter) { - case "active": - return tasks.filter((t) => !t.isCompleted); - case "completed": - return tasks.filter((t) => t.isCompleted); - case "all": - return tasks; - } - } - - get allChecked() { - return this.store.tasks.every(todo => todo.isCompleted); - } + todoList = plugin(TodoListPlugin); + filter = signal("all"); + + visibleTodos = computed(() => { + const todos = this.todoList.todos(); + switch (this.filter()) { + case "active": + return todos.filter((t) => !t.isCompleted()); + case "completed": + return todos.filter((t) => t.isCompleted()); + case "all": + return todos; + } + }); - get remaining() { - return this.store.tasks.filter(todo => !todo.isCompleted).length; - } + remaining = computed(() => { + const todos = this.todoList.todos(); + return todos.filter((todo) => !todo.isCompleted()).length; + }); - get remainingText() { - const items = this.remaining < 2 ? "item" : "items"; - return ` ${items} left`; - } + remainingText = computed(() => { + return ` ${this.remaining() < 2 ? "item" : "items"} left`; + }); + + allChecked = computed(() => this.remaining() === 0); addTodo(ev) { if (ev.keyCode === ENTER_KEY) { const text = ev.target.value; if (text.trim()) { - this.store.addTask(text); + this.todoList.add(text); } ev.target.value = ""; } } - - setFilter(filter) { - this.state.filter = filter; - } } //------------------------------------------------------------------------------ // App Initialization //------------------------------------------------------------------------------ -const env = { store: createTaskStore() }; -mount(TodoList, document.body, { env, templates: TEMPLATES, dev: true }); +const pluginManager = new PluginManager(); +pluginManager.startPlugins([TodoListPlugin]); + +mount(TodoList, document.body, { templates: TEMPLATES, pluginManager, dev: true }); diff --git a/docs/playground/samples/todo_app/todo_app.xml b/docs/playground/samples/todo_app/todo_app.xml index 1ed4d9f72..98655ef13 100644 --- a/docs/playground/samples/todo_app/todo_app.xml +++ b/docs/playground/samples/todo_app/todo_app.xml @@ -2,49 +2,49 @@

todos

- +
-
- +
+
    - - + +
-
-
  • +
  • - -
    - +
  • diff --git a/docs/playground/templates.xml b/docs/playground/templates.xml index bb47378b7..bd339dc66 100644 --- a/docs/playground/templates.xml +++ b/docs/playground/templates.xml @@ -1,51 +1,51 @@ -
    -
    +
    + -
    +
    -
    +
    - + js="this.state.js" + css="!this.state.splitLayout and this.state.css" + xml="!this.state.splitLayout and this.state.xml" + style="this.topEditorStyle" + updateCode="this.updateCode"/> +
    + updatePanelHeight.bind="this.updatePanelHeight" + updateCode="this.updateCode"/>
    -
    +
    -
    +
    🦉 Odoo Web Library 🦉
    -
    v
    +
    v

    @@ -53,7 +53,7 @@

    -
    +
    - \ No newline at end of file + diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..66a233a45 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,57 @@ +import { defineConfig } from "eslint/config"; +import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import globals from "globals"; +import tsParser from "@typescript-eslint/parser"; + +export default defineConfig([{ + plugins: { + "@typescript-eslint": typescriptEslint, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + describe: true, + expect: true, + test: true, + beforeEach: true, + beforeAll: true, + afterEach: true, + afterAll: true, + jest: true, + }, + + parser: tsParser, + ecmaVersion: 5, + sourceType: "module", + }, + + rules: { + "no-restricted-globals": ["error", "event", "self"], + "no-const-assign": ["error"], + "no-debugger": ["error"], + "no-dupe-class-members": ["error"], + "no-dupe-keys": ["error"], + "no-dupe-args": ["error"], + "no-dupe-else-if": ["error"], + "no-unsafe-negation": ["error"], + "no-duplicate-imports": ["error"], + "valid-typeof": ["error"], + + "@typescript-eslint/no-unused-vars": ["error", { + vars: "all", + args: "none", + ignoreRestSiblings: false, + caughtErrors: "all", + }], + + "no-restricted-syntax": ["error", { + selector: "MemberExpression[object.name='test'][property.name='only']", + message: "test.only(...) is forbidden", + }, { + selector: "MemberExpression[object.name='describe'][property.name='only']", + message: "describe.only(...) is forbidden", + }], + }, +}]); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ff388e493..5e99b89a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,4773 +1,6783 @@ { "name": "@odoo/owl", - "version": "2.8.2", - "lockfileVersion": 1, + "version": "3.0.0-alpha.16", + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "packages": { + "": { + "name": "@odoo/owl", + "version": "3.0.0-alpha.16", + "license": "LGPL-3.0-only", + "dependencies": { + "jsdom": "^25.0.1" + }, + "bin": { + "compile_owl_templates": "tools/compile_owl_templates.mjs" + }, + "devDependencies": { + "@rollup/plugin-terser": "^0.4.4", + "@types/jest": "^30.0.0", + "@types/jsdom": "^21.1.7", + "@types/node": "^25.2.0", + "@typescript-eslint/eslint-plugin": "^8.54.0", + "@typescript-eslint/parser": "^8.54.0", + "chalk": "^3.0.0", + "current-git-branch": "^1.1.0", + "eslint": "^9.39.2", + "git-rev-sync": "^3.0.2", + "github-api": "^3.4.0", + "globals": "^17.3.0", + "jest": "^30.2.0", + "jest-diff": "^27.3.1", + "jest-environment-jsdom": "^30.2.0", + "npm-run-all": "^4.1.5", + "prettier": "^3.8.1", + "rollup": "^4.57.1", + "rollup-plugin-copy": "^3.5.0", + "rollup-plugin-delete": "^3.0.2", + "rollup-plugin-dts": "^6.3.0", + "rollup-plugin-execute": "^1.1.1", + "rollup-plugin-string": "^3.0.0", + "rollup-plugin-typescript2": "^0.36.0", + "source-map-support": "^0.5.10", + "ts-jest": "^29.4.6", + "typescript": "^5.9.3" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" } }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", - "dev": true + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "dev": true, - "requires": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "requires": { - "@babel/types": "^7.18.6" + "bin": { + "semver": "bin/semver.js" } }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, - "requires": { - "@babel/types": "^7.18.6" + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, - "requires": { - "@babel/types": "^7.20.2" + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, - "requires": { - "@babel/types": "^7.18.6" + "engines": { + "node": ">=6.9.0" } }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "engines": { + "node": ">=6.9.0" } }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "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 - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "@babel/plugin-syntax-async-generators": { + "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-bigint": { + "node_modules/@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-class-properties": { + "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-import-meta": { + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-json-strings": { + "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", + "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-logical-assignment-operators": { + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-nullish-coalescing-operator": { + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-numeric-separator": { + "node_modules/@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-object-rest-spread": { + "node_modules/@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-catch-binding": { + "node_modules/@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-optional-chaining": { + "node_modules/@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-top-level-await": { + "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "requires": { + "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", + "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "@bcoe/v8-coverage": { + "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": 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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + } }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "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==", "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "optional": true, "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" } }, - "@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==", - "dev": true - }, - "@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - }, + "optional": true, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "tslib": "^2.4.0" } }, - "@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "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==", + "dev": true, + "optional": true, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "tslib": "^2.4.0" } }, - "@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, - "requires": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "dependencies": { + "@types/json-schema": "^7.0.15" }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, "dependencies": { - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "dependencies": { - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "funding": { + "url": "https://eslint.org/donate" } }, - "@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "engines": { + "node": ">=18.18.0" } }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "node_modules/@isaacs/cliui/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==", "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, "dependencies": { - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - } + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "requires": { - "type-detect": "4.0.8" + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "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", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { - "@babel/types": "^7.0.0" + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "requires": { - "@babel/types": "^7.3.0" + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "@types/fs-extra": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", - "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "requires": { - "@types/node": "*" + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "requires": { - "@types/node": "*" + "engines": { + "node": ">=8" } }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "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==", "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" + "engines": { + "node": ">=8" } }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "@types/jest": { - "version": "27.5.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", - "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "@types/jsdom": { - "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", + "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==", "dev": true, - "requires": { + "dependencies": { + "@jest/console": "30.2.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", "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "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-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", + "slash": "^3.0.0" }, - "dependencies": { - "parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "dev": true, - "requires": { - "entities": "^4.5.0" - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "@types/node": { - "version": "14.18.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.27.tgz", - "integrity": "sha512-DcTUcwT9xEcf4rp2UHyGAcmlqG4Mhe7acozl5vY2xzSrwP1z19ZVyjzQ6DsNUrvIadpiyZoQCTHFt4t2omYIZQ==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true - }, - "@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "@types/yargs-parser": "*" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "node_modules/@jest/core/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "@typescript-eslint/eslint-plugin": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz", - "integrity": "sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==", + "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==", "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.48.1", - "@typescript-eslint/type-utils": "5.48.1", - "@typescript-eslint/utils": "5.48.1", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "@typescript-eslint/parser": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz", - "integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==", + "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==", "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.48.1", - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/typescript-estree": "5.48.1", - "debug": "^4.3.4" + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "@typescript-eslint/scope-manager": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", - "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", + "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==", "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1" + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/jsdom": "^21.1.7", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "@typescript-eslint/type-utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz", - "integrity": "sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==", + "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==", "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.48.1", - "@typescript-eslint/utils": "5.48.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", - "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", + "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==", "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.1.tgz", - "integrity": "sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.48.1", - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/typescript-estree": "5.48.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "@yarn-tool/resolve-package": { - "version": "1.0.47", - "resolved": "https://registry.npmjs.org/@yarn-tool/resolve-package/-/resolve-package-1.0.47.tgz", - "integrity": "sha512-Zaw58gQxjQceJqhqybJi1oUDaORT8i2GTgwICPs8v/X/Pkx35FXQba69ldHVg5pQZ6YLKpROXgyHvBaCJOFXiA==", - "dev": true, - "requires": { - "pkg-dir": "< 6 >= 5", - "tslib": "^2", - "upath2": "^3.1.13" - }, - "dependencies": { - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - } + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "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==", "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==" - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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==", "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", "dev": true, - "requires": { - "type-fest": "^0.21.3" + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true + "@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", + "@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", + "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", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true } } }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "node_modules/@jest/reporters/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, + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "color-convert": "^2.0.1" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "node_modules/@jest/reporters/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/@jest/reporters/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, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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 - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, - "requires": { - "follow-redirects": "^1.14.0" + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "requires": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "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==", + "dev": true, + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "babel-plugin-add-module-exports": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", - "integrity": "sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==", + "node_modules/@jest/snapshot-utils/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } + "node_modules/@jest/source-map/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "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==", "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "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==", "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@jest/test-sequencer/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.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-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "fill-range": "^7.0.1" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "node_modules/@jest/transform/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "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==", "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, - "requires": { - "node-int64": "^0.4.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001473", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz", - "integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", - "dev": true - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "engines": { + "node": ">=6.0.0" } }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, - "requires": { - "color-name": "~1.1.4" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "cssom": { + "node_modules/@rollup/plugin-terser": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "requires": { - "rrweb-cssom": "^0.7.1" + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "current-git-branch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/current-git-branch/-/current-git-branch-1.1.0.tgz", - "integrity": "sha512-n5mwGZllLsFzxDPtTmadqGe4IIBPfqPbiIRX4xgFR9VK/Bx47U+94KiVkxSKAKN6/s43TlkztS2GZpgMKzwQ8A==", + "node_modules/@rollup/plugin-terser/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==", "dev": true, - "requires": { - "babel-plugin-add-module-exports": "^0.2.1", - "execa": "^0.6.1", - "is-git-repository": "^1.0.0" + "dependencies": { + "randombytes": "^2.1.0" } }, - "data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "requires": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "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==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ] + }, + "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==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "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==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "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==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.48", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", + "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" } }, - "decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + "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==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "del": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", - "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", - "dev": true, - "requires": { - "globby": "^10.0.1", - "graceful-fs": "^4.2.2", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.1", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0" - }, "dependencies": { - "globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, - "requires": { - "path-type": "^4.0.0" + "dependencies": { + "@babel/types": "^7.0.0" } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, - "requires": { - "esutils": "^2.0.2" + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } + "@babel/types": "^7.28.2" } }, - "electron-to-chromium": { - "version": "1.4.345", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.345.tgz", - "integrity": "sha512-znGhOQK2TUYLICgS25uaM0a7pHy66rSxbre7l762vg9AUoCcJK+Bu+HCPWpjL/U/kK8/Hf+6E0szAUJSyVYb3Q==", - "dev": true - }, - "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } + "license": "MIT" }, - "es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - } - }, - "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "node_modules/@types/fs-extra": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "dependencies": { + "@types/node": "*" } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, - "escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "source-map": "~0.6.1" - }, "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", - "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.4.1", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "@types/istanbul-lib-coverage": "*" } }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "dependencies": { + "@types/istanbul-lib-report": "*" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } + "expect": "^30.0.0", + "pretty-format": "^30.0.0" } }, - "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", - "dev": true - }, - "espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "node_modules/@types/jsdom": { + "version": "21.1.7", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", + "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/@types/minimatch": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-6.0.0.tgz", + "integrity": "sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==", + "deprecated": "This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed.", "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } + "minimatch": "*" } }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/@types/node": { + "version": "25.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz", + "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==", "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } + "undici-types": "~7.16.0" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, - "execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==", + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "dependencies": { + "@types/yargs-parser": "*" } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", + "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/type-utils": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.54.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "engines": { + "node": ">= 4" } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "node_modules/@typescript-eslint/parser": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", + "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", "dev": true, - "requires": { - "reusify": "^1.0.4" + "dependencies": { + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", + "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", "dev": true, - "requires": { - "bser": "2.1.1" + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.54.0", + "@typescript-eslint/types": "^8.54.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", + "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", "dev": true, - "requires": { - "flat-cache": "^3.0.4" + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", + "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", "dev": true, - "requires": { - "to-regex-range": "^5.0.1" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", + "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/@typescript-eslint/types": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", + "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", + "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "dependencies": { + "@typescript-eslint/project-service": "8.54.0", + "@typescript-eslint/tsconfig-utils": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "dev": true + "node_modules/@typescript-eslint/typescript-estree/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, + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/@typescript-eslint/typescript-estree/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, - "requires": { - "is-callable": "^1.1.3" + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "node_modules/@typescript-eslint/utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", + "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", + "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, "dependencies": { - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - } + "@typescript-eslint/types": "8.54.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "optional": true + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "git-rev-sync": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-3.0.2.tgz", - "integrity": "sha512-Nd5RiYpyncjLv0j6IONy0lGzAqdRXUaBctuGBbrEA2m6Bn4iDrN/9MeQTXuiquw8AEKL9D2BW0nw5m/lQvxqnQ==", + "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, - "requires": { - "escape-string-regexp": "1.0.5", - "graceful-fs": "4.1.15", - "shelljs": "0.8.5" - }, - "dependencies": { - "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 - } + "engines": { + "node": ">=8" } }, - "github-api": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/github-api/-/github-api-3.4.0.tgz", - "integrity": "sha512-2yYqYS6Uy4br1nw0D3VrlYWxtGTkUhIZrumBrcBwKdBOzMT8roAe8IvI6kjIOkxqxapKR5GkEsHtz3Du/voOpA==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, - "requires": { - "axios": "^0.21.1", - "debug": "^2.2.0", - "js-base64": "^2.1.9", - "utf8": "^2.1.1" - }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "engines": { + "node": ">= 0.4" } }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "requires": { - "type-fest": "^0.20.2" + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "dev": true, - "requires": { - "define-properties": "^1.1.3" + "dependencies": { + "follow-redirects": "^1.14.0" } }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "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==", "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", + "dependencies": { + "@jest/transform": "30.2.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" } }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "node_modules/babel-jest/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true + "node_modules/babel-plugin-add-module-exports": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", + "integrity": "sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==", + "dev": true, + "license": "MIT" }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", "dev": true, - "requires": { - "function-bind": "^1.1.1" + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" } }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "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==", "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "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==", "dev": true, - "requires": { - "has-symbols": "^1.0.2" + "dependencies": { + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" } }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "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==", "dev": true }, - "html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "requires": { - "whatwg-encoding": "^3.1.1" + "node_modules/baseline-browser-mapping": { + "version": "2.8.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz", + "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "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==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "requires": { - "agent-base": "^7.1.2", - "debug": "4" + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "node_modules/browserslist": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "dependencies": { + "node-int64": "^0.4.0" } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "engines": { + "node": ">=6" } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "node_modules/caniuse-lite": { + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, - "requires": { - "has-bigints": "^1.0.1" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "engines": { + "node": ">=10" } }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", "dev": true }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "requires": { - "has": "^1.0.3" + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", "dev": true }, - "is-git-repository": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-git-repository/-/is-git-repository-1.1.1.tgz", - "integrity": "sha512-hxLpJytJnIZ5Og5QsxSkzmb8Qx8rGau9bio1JN/QtXcGEFuSsQYau0IiqlsCwftsfVYjF1mOq6uLdmwNSspgpA==", - "dev": true, - "requires": { - "execa": "^0.6.1", - "path-is-absolute": "^1.0.1" + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==" }, - "is-plain-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", - "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", - "dev": true + "node_modules/current-git-branch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/current-git-branch/-/current-git-branch-1.1.0.tgz", + "integrity": "sha512-n5mwGZllLsFzxDPtTmadqGe4IIBPfqPbiIRX4xgFR9VK/Bx47U+94KiVkxSKAKN6/s43TlkztS2GZpgMKzwQ8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-add-module-exports": "^0.2.1", + "execa": "^0.6.1", + "is-git-repository": "^1.0.0" + } }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-shared-array-buffer": { + "node_modules/data-view-byte-length": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, - "requires": { - "call-bind": "^1.0.2" + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==" + }, + "node_modules/dedent": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/del/-/del-8.0.1.tgz", + "integrity": "sha512-gPqh0mKTPvaUZGAuHbrBUYKZWBNAeHG7TU3QH5EhVwPMyKvmfJaNXhcD2jTcXsJRRcffuho4vaYweu80dRrMGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^14.0.2", + "is-glob": "^4.0.3", + "is-path-cwd": "^3.0.0", + "is-path-inside": "^4.0.0", + "p-map": "^7.0.2", + "presentable-error": "^0.0.1", + "slash": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/del/node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.263", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.263.tgz", + "integrity": "sha512-DrqJ11Knd+lo+dv+lltvfMDLU27g14LMdH2b0O3Pio4uk0x+z7OR+JrmyacTPN2M8w3BrZ7/RTwG3R9B7irPlg==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", + "integrity": "sha512-/teX3MDLFBdYUhRk8WCBYboIMUmqeizu0m9Z3YF3JWrbEh/SlZg00vLJSaAGWw3wrZ9tE0buNw79eaAPYhUuvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/execa/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/execa/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "30.2.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" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-extra/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/git-rev-sync": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/git-rev-sync/-/git-rev-sync-3.0.2.tgz", + "integrity": "sha512-Nd5RiYpyncjLv0j6IONy0lGzAqdRXUaBctuGBbrEA2m6Bn4iDrN/9MeQTXuiquw8AEKL9D2BW0nw5m/lQvxqnQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "1.0.5", + "graceful-fs": "4.1.15", + "shelljs": "0.8.5" + } + }, + "node_modules/git-rev-sync/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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/github-api": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/github-api/-/github-api-3.4.0.tgz", + "integrity": "sha512-2yYqYS6Uy4br1nw0D3VrlYWxtGTkUhIZrumBrcBwKdBOzMT8roAe8IvI6kjIOkxqxapKR5GkEsHtz3Du/voOpA==", + "dev": true, + "dependencies": { + "axios": "^0.21.1", + "debug": "^2.2.0", + "js-base64": "^2.1.9", + "utf8": "^2.1.1" + } + }, + "node_modules/github-api/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/github-api/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", + "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-git-repository": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-git-repository/-/is-git-repository-1.1.1.tgz", + "integrity": "sha512-hxLpJytJnIZ5Og5QsxSkzmb8Qx8rGau9bio1JN/QtXcGEFuSsQYau0IiqlsCwftsfVYjF1mOq6uLdmwNSspgpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^0.6.1", + "path-is-absolute": "^1.0.1" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", + "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "dev": true, + "dependencies": { + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "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==", + "dev": true, + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.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", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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==", + "dev": true, + "dependencies": { + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.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", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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==", + "dev": true, + "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", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.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", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/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, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jest-config/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, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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==", + "dev": true, + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/environment-jsdom-abstract": "30.2.0", + "@types/jsdom": "^21.1.7", + "@types/node": "*", + "jsdom": "^26.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true + }, + "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==", "dev": true, - "requires": { - "has-symbols": "^1.0.2" + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "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==", "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "dependencies": { + "@jest/types": "30.2.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", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "node_modules/jest-haste-map/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "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==", "dev": true, - "requires": { - "call-bind": "^1.0.2" + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "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==", "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "dependencies": { + "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/jest-matcher-utils/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==", "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "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==", "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.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", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.2.5.tgz", - "integrity": "sha512-vDMzXcpQN4Ycaqu+vO7LX8pZwNNoKMhc+gSp6q1D8S6ftRk8gNW8cni3YFxknP95jxzQo23Lul0BI2FrWgnwYQ==", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "@jest/core": "^27.2.5", - "import-local": "^3.0.2", - "jest-cli": "^27.2.5" - }, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } + "node_modules/jest-message-util/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, - "jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "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==", "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "dependencies": { + "@jest/types": "30.2.0", "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } - } - }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "jest-util": "30.2.0" }, - "dependencies": { - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "form-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", - "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "dependencies": { - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-diff": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz", - "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.4.0", - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true } } }, - "jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, - "requires": { - "detect-newline": "^3.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "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==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-environment-jsdom": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.2.5.tgz", - "integrity": "sha512-QtRpOh/RQKuXniaWcoFE2ElwP6tQcyxHu0hlk32880g0KczdonCs5P1sk5+weu/OVzh5V4Bt1rXuQthI01mBLg==", + "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==", "dev": true, - "requires": { - "@jest/environment": "^27.2.5", - "@jest/fake-timers": "^27.2.5", - "@jest/types": "^27.2.5", - "@types/node": "*", - "jest-mock": "^27.2.5", - "jest-util": "^27.2.5", - "jsdom": "^16.6.0" - }, - "dependencies": { - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "form-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", - "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - } + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "node_modules/jest-resolve/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "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==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", + "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", "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "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", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "node_modules/jest-runner/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, - "requires": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "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==", "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - } + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "node_modules/jest-runtime/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, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "dependencies": { + "balanced-match": "^1.0.0" } }, - "jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "node_modules/jest-runtime/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "node_modules/jest-runtime/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, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "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==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - } - }, - "jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "dependencies": { - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "form-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.2.tgz", - "integrity": "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "dependencies": { - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - } + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@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/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.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", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "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==", + "dev": true, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "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==", "dev": true, - "requires": { + "dependencies": { + "@jest/types": "30.2.0", "@types/node": "*", - "graceful-fs": "^4.2.9" + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, - "dependencies": { - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "requires": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - } + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "node_modules/jest-util/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - } + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "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==", "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "^27.5.1" + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "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==", "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - } + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "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==", "dev": true, - "requires": { + "dependencies": { "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "supports-color": "^8.1.1" }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "js-base64": { + "node_modules/js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", "dev": true }, - "js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true - }, - "js-tokens": { + "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, - "requires": { + "dependencies": { "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "jsdom": { + "node_modules/jsdom": { "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "requires": { + "dependencies": { "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", @@ -4789,1812 +6799,2941 @@ "whatwg-url": "^14.0.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "json-parse-better-errors": { + "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-parse-even-better-errors": { + "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stable-stringify-without-jsonify": { + "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "json5": { + "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, - "jsonfile": { + "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "requires": { + "optionalDependencies": { "graceful-fs": "^4.1.6" } }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } }, - "leven": { + "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "levn": { + "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "lines-and-columns": { + "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "load-json-file": { + "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", "pify": "^3.0.0", "strip-bom": "^3.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" } }, - "locate-path": { + "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "requires": { + "dependencies": { "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, - "lodash.merge": { + "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "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==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "requires": { - "yallist": "^4.0.0" + "dependencies": { + "yallist": "^3.0.2" } }, - "magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "requires": { - "semver": "^6.0.0" - }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "make-error": { + "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "makeerror": { + "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, - "requires": { + "dependencies": { "tmpl": "1.0.5" } }, - "memorystream": { + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10.0" + } }, - "merge-stream": { + "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, - "merge2": { + "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 8" + } }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "requires": { - "braces": "^3.0.2", + "dependencies": { + "braces": "^3.0.3", "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "mime-db": { + "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==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } }, - "mime-types": { + "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==", - "requires": { + "dependencies": { "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "mimic-fn": { + "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "minimatch": { + "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } }, - "natural-compare": { + "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "nice-try": { + "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "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==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" + "dependencies": { + "has-flag": "^3.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "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 - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "npm-run-path": { + "node_modules/npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, - "nwsapi": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", - "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==" + "node_modules/nwsapi": { + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.22.tgz", + "integrity": "sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==" }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "object-keys": { + "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + } }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "onetime": { + "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, - "requires": { + "dependencies": { "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "requires": { + "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "p-finally": { + "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "p-limit": { + "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "requires": { + "dependencies": { "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-locate": { + "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "requires": { + "dependencies": { "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, - "requires": { - "aggregate-error": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-try": { + "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, - "parent-module": { + "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "requires": { + "dependencies": { "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "parse-json": { + "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, - "requires": { + "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "requires": { - "entities": "^4.5.0" + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "path-exists": { + "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-is-network-drive": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/path-is-network-drive/-/path-is-network-drive-1.0.20.tgz", - "integrity": "sha512-p5wCWlRB4+ggzxWshqHH9aF3kAuVu295NaENXmVhThbZPJQBeJdxZTP6CIoUR+kWHDUW56S9YcaO1gXnc/BOxw==", "dev": true, - "requires": { - "tslib": "^2" - }, - "dependencies": { - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - } + "engines": { + "node": ">=0.10.0" } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "path-parse": { + "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-strip-sep": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/path-strip-sep/-/path-strip-sep-1.0.17.tgz", - "integrity": "sha512-+2zIC2fNgdilgV7pTrktY6oOxxZUo9x5zJYfTzxsGze5kSGDDwhA5/0WlBn+sUyv/WuuyYn3OfM+Ue5nhdQUgA==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "requires": { - "tslib": "^2" - }, "dependencies": { - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - } + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "path-type": { + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "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 + "dev": true, + "engines": { + "node": ">=8" + } }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, - "picomatch": { + "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, - "pidtree": { + "node_modules/pidtree": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } }, - "pify": { + "node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "engines": { + "node": ">= 6" + } }, - "pkg-dir": { + "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "requires": { + "dependencies": { "find-up": "^4.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "engines": { + "node": ">= 0.4" } }, - "prelude-ls": { + "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", - "dev": true + "node_modules/presentable-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/presentable-error/-/presentable-error-0.0.1.tgz", + "integrity": "sha512-E6rsNU1QNJgB3sjj7OANinGncFKuK+164sLXw1/CqBjj/EkXSoSdHCtWQGBNlREIGLnL7IEUEGa08YFVUbrhVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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==", + "dev": true, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "pseudomap": { + "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, - "requires": { - "punycode": "^2.3.1" - }, - "dependencies": { - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true - } - } + "license": "ISC" }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] }, - "queue-microtask": { + "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "randombytes": { + "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.1.0" } }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, - "read-pkg": { + "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, - "requires": { + "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", "path-type": "^3.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - } + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "rechoir": { + "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, - "requires": { + "dependencies": { "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" } }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "require-directory": { + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, - "requires": { - "is-core-module": "^2.9.0", + "dependencies": { + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "resolve-cwd": { + "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "requires": { + "dependencies": { "resolve-from": "^5.0.0" }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "resolve-from": { + "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "requires": { - "glob": "^7.1.3" + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "rollup": { - "version": "2.79.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", - "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dev": true, - "requires": { + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "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", "fsevents": "~2.3.2" } }, - "rollup-plugin-copy": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz", - "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==", + "node_modules/rollup-plugin-copy": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.5.0.tgz", + "integrity": "sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==", "dev": true, - "requires": { + "dependencies": { "@types/fs-extra": "^8.0.1", "colorette": "^1.1.0", "fs-extra": "^8.1.0", "globby": "10.0.1", "is-plain-object": "^3.0.0" }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-copy/node_modules/globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, "dependencies": { - "globby": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", - "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - } + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "rollup-plugin-delete": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-delete/-/rollup-plugin-delete-2.0.0.tgz", - "integrity": "sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA==", + "node_modules/rollup-plugin-delete": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-delete/-/rollup-plugin-delete-3.0.2.tgz", + "integrity": "sha512-26GSi/aeYQ/hEBdG1rjEMeh+WUhiPZ3hGmSr9Ucj7mhLQ1P9j8KEgtYoybDp7OlIMj3eQjHHB9fnqhxNuVgfzA==", "dev": true, - "requires": { - "del": "^5.1.0" + "license": "MIT", + "dependencies": { + "del": "^8.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "rollup": "*" } }, - "rollup-plugin-dts": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.2.2.tgz", - "integrity": "sha512-A3g6Rogyko/PXeKoUlkjxkP++8UDVpgA7C+Tdl77Xj4fgEaIjPSnxRmR53EzvoYy97VMVwLAOcWJudaVAuxneQ==", + "node_modules/rollup-plugin-dts": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.3.0.tgz", + "integrity": "sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==", "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "magic-string": "^0.26.1" + "dependencies": { + "magic-string": "^0.30.21" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.27.1" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" } }, - "rollup-plugin-execute": { + "node_modules/rollup-plugin-execute": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/rollup-plugin-execute/-/rollup-plugin-execute-1.1.1.tgz", "integrity": "sha512-isCNR/VrwlEfWJMwsnmt5TBRod8dW1IjVRxcXCBrxDmVTeA1IXjzeLSS3inFBmRD7KDPlo38KSb2mh5v5BoWgA==", "dev": true }, - "rollup-plugin-string": { + "node_modules/rollup-plugin-string": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-string/-/rollup-plugin-string-3.0.0.tgz", "integrity": "sha512-vqyzgn9QefAgeKi+Y4A7jETeIAU1zQmS6VotH6bzm/zmUQEnYkpIGRaOBPY41oiWYV4JyBoGAaBjYMYuv+6wVw==", "dev": true, - "requires": { + "dependencies": { "rollup-pluginutils": "^2.4.1" } }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "dependencies": { - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - } + "node_modules/rollup-plugin-typescript2": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.36.0.tgz", + "integrity": "sha512-NB2CSQDxSe9+Oe2ahZbf+B4bh7pHwjV5L+RSYpCu7Q5ROuN94F9b6ioWwKfz3ueL3KTtmX4o2MUH2cgHDIEUsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^4.1.2", + "find-cache-dir": "^3.3.2", + "fs-extra": "^10.0.0", + "semver": "^7.5.4", + "tslib": "^2.6.2" + }, + "peerDependencies": { + "rollup": ">=1.26.3", + "typescript": ">=2.4.0" } }, - "rollup-plugin-typescript2": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.1.tgz", - "integrity": "sha512-sklqXuQwQX+stKi4kDfEkneVESPi3YM/2S899vfRdF9Yi40vcC50Oq4A4cSZJNXsAQE/UsBZl5fAOsBLziKmjw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.1.0", - "@yarn-tool/resolve-package": "^1.0.36", - "find-cache-dir": "^3.3.1", - "fs-extra": "8.1.0", - "resolve": "1.20.0", - "tslib": "2.2.0" - }, - "dependencies": { - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", - "dev": true - } + "node_modules/rollup-plugin-typescript2/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/rollup-plugin-typescript2/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/rollup-plugin-typescript2/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" } }, - "rollup-pluginutils": { + "node_modules/rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", "dev": true, - "requires": { + "dependencies": { "estree-walker": "^0.6.1" } }, - "rrweb-cssom": { + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==" }, - "run-parallel": { + "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "requires": { + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { "queue-microtask": "^1.2.2" } }, - "safe-buffer": { + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "safe-regex-test": { + "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "safer-buffer": { + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "saxes": { + "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "requires": { + "dependencies": { "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" } }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "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, - "requires": { - "lru-cache": "^6.0.0" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, - "requires": { - "randombytes": "^2.1.0" + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, - "requires": { - "shebang-regex": "^1.0.0" + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "shebang-regex": { + "node_modules/set-proto": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } }, - "shell-quote": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", - "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", - "dev": true + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "shelljs": { + "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, - "requires": { + "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" } }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "signal-exit": { + "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { + "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "source-map": { + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "requires": { + "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spdx-correct": { + "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "requires": { + "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, - "spdx-expression-parse": { + "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "requires": { + "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", "dev": true }, - "sprintf-js": { + "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "stack-utils": { + "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^2.0.0" }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" } }, - "string-length": { + "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, - "requires": { + "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "string-width": { + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "string.prototype.padend": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", - "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-ansi": { + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-bom": { + "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "strip-eof": { + "node_modules/strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "strip-final-newline": { + "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "strip-json-comments": { + "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 + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "supports-color": { + "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "symbol-tree": { + "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" } }, - "terser": { - "version": "5.16.8", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.8.tgz", - "integrity": "sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==", + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "test-exclude": { + "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, - "requires": { + "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } }, - "throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==", - "dev": true + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } }, - "tldts": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.71.tgz", - "integrity": "sha512-LQIHmHnuzfZgZWAf2HzL83TIIrD8NhhI0DVxqo9/FdOd4ilec+NTNZOlDZf7EwrTNoutccbsHjvWHYXLAtvxjw==", - "requires": { - "tldts-core": "^6.1.71" + "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==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" } }, - "tldts-core": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.71.tgz", - "integrity": "sha512-LRbChn2YRpic1KxY+ldL1pGXN/oVvKfCVufwfVzEQdFYNo39uF7AJa/WXdo+gYO7PTvdfkCPCed6Hkvz/kR7jg==" + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==" }, - "tmpl": { + "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { + "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "requires": { + "dependencies": { "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "requires": { + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dependencies": { "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" } }, - "tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "requires": { + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dependencies": { "punycode": "^2.3.1" }, - "dependencies": { - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - } + "engines": { + "node": ">=18" } }, - "ts-jest": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.5.tgz", - "integrity": "sha512-lIJApzfTaSSbtlksfFNHkWOzLJuuSm4faFAfo5kvzOiRAuoN4/eKxVJ2zEAho8aecE04qX6K1pAzfH5QHL1/8w==", + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/ts-jest": { + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", + "dev": true, + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "requires": { - "tslib": "^1.8.1" + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "type-check": { + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "requires": { + "dependencies": { "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "type-detect": { + "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "typed-array-length": { + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, - "requires": { - "call-bind": "^1.0.2", + "dependencies": { + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "requires": { - "is-typedarray": "^1.0.0" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, - "typescript": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", - "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", - "dev": true + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", + "dependencies": { + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true }, - "upath2": { - "version": "3.1.19", - "resolved": "https://registry.npmjs.org/upath2/-/upath2-3.1.19.tgz", - "integrity": "sha512-d23dQLi8nDWSRTIQwXtaYqMrHuca0As53fNiTLLFDmsGBbepsZepISaB2H1x45bDFN/n3Qw9bydvyZEacTrEWQ==", + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, - "requires": { - "@types/node": "*", - "path-is-network-drive": "^1.0.20", - "path-strip-sep": "^1.0.17", - "tslib": "^2" + "license": "MIT", + "engines": { + "node": ">=18" }, - "dependencies": { - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.0" } }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "utf8": { + "node_modules/utf8": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", "integrity": "sha512-QXo+O/QkLP/x1nyi54uQiG0XrODxdysuQvE5dtVqv7F5K2Qb6FsN+qbr6KhF5wQ20tfcV3VQp0/2x1e1MRSPWg==", "dev": true }, - "v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, - "requires": { + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "convert-source-map": "^2.0.0" }, - "dependencies": { - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - } + "engines": { + "node": ">=10.12.0" } }, - "validate-npm-package-license": { + "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "requires": { + "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { + "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "requires": { + "dependencies": { "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, - "walker": { + "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, - "requires": { + "dependencies": { "makeerror": "1.0.12" } }, - "webidl-conversions": { + "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } }, - "whatwg-encoding": { + "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "requires": { + "dependencies": { "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" } }, - "whatwg-mimetype": { + "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==" + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "engines": { + "node": ">=18" + } }, - "whatwg-url": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", - "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", - "requires": { - "tr46": "^5.0.0", + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dependencies": { + "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "requires": { + "dependencies": { "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-boxed-primitive": { + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "wrap-ansi": { + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, - "requires": { + "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, - "xml-name-validator": { + "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==" + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "engines": { + "node": ">=18" + } }, - "xmlchars": { + "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, - "y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "requires": { - "cliui": "^7.0.2", + "dependencies": { + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } }, - "yocto-queue": { + "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 88537148e..e15853a3b 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "@odoo/owl", - "version": "2.8.2", + "version": "3.0.0-alpha.20", "description": "Odoo Web Library (OWL)", "main": "dist/owl.cjs.js", "module": "dist/owl.es.js", "types": "dist/types/owl.d.ts", + "type": "module", "files": [ "dist" ], @@ -48,32 +49,33 @@ }, "homepage": "https://github.com/odoo/owl#readme", "devDependencies": { - "@types/jest": "^27.0.1", + "@rollup/plugin-terser": "^0.4.4", + "@types/jest": "^30.0.0", "@types/jsdom": "^21.1.7", - "@types/node": "^14.11.8", - "@typescript-eslint/eslint-plugin": "5.48.1", - "@typescript-eslint/parser": "5.48.1", + "@types/node": "^25.2.0", + "@typescript-eslint/eslint-plugin": "^8.54.0", + "@typescript-eslint/parser": "^8.54.0", "chalk": "^3.0.0", "current-git-branch": "^1.1.0", - "eslint": "8.31.0", + "eslint": "^9.39.2", "git-rev-sync": "^3.0.2", - "github-api": "^3.3.0", - "jest": "^27.1.0", + "github-api": "^3.4.0", + "globals": "^17.3.0", + "jest": "^30.2.0", "jest-diff": "^27.3.1", - "jest-environment-jsdom": "^27.1.0", + "jest-environment-jsdom": "^30.2.0", "npm-run-all": "^4.1.5", - "prettier": "2.4.1", - "rollup": "^2.56.3", - "rollup-plugin-copy": "^3.3.0", - "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-dts": "^4.2.2", + "prettier": "^3.8.1", + "rollup": "^4.57.1", + "rollup-plugin-copy": "^3.5.0", + "rollup-plugin-delete": "^3.0.2", + "rollup-plugin-dts": "^6.3.0", "rollup-plugin-execute": "^1.1.1", "rollup-plugin-string": "^3.0.0", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-typescript2": "^0.31.1", + "rollup-plugin-typescript2": "^0.36.0", "source-map-support": "^0.5.10", - "ts-jest": "^27.0.5", - "typescript": "4.5.2" + "ts-jest": "^29.4.6", + "typescript": "^5.9.3" }, "jest": { "testEnvironment": "jsdom", @@ -100,7 +102,8 @@ }, "prettier": { "printWidth": 100, - "endOfLine": "auto" + "endOfLine": "auto", + "trailingComma": "es5" }, "dependencies": { "jsdom": "^25.0.1" diff --git a/release_notes.md b/release_notes.md new file mode 100644 index 000000000..5f8e2088b --- /dev/null +++ b/release_notes.md @@ -0,0 +1,9 @@ +# Release Notes + +DRAFT!!!! + +- reactivity: replace reactive, add signal, effect, derived, withoutReactivity +- registry: add a simple Registry class, based on signals +- plugins: add Plugin and PluginManager class +- components: now have a builtin `this.plugins` key + diff --git a/rollup.config.js b/rollup.config.js index 3c1f23d14..98f9bc7bb 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,7 +1,7 @@ -import pkg from "./package.json"; +import pkg from "./package.json" with { type: "json" }; import git from "git-rev-sync"; import typescript from "rollup-plugin-typescript2"; -import { terser } from "rollup-plugin-terser"; +import terser from '@rollup/plugin-terser'; import dts from "rollup-plugin-dts"; let input, output; @@ -16,7 +16,7 @@ if (pkg.module !== ES_FILENAME || pkg.main !== CJS_FILENAME) { const outro = ` __info__.date = '${new Date().toISOString()}'; -__info__.hash = '${git.short()}'; +__info__.hash = '${git.short(".")}'; __info__.url = 'https://github.com/odoo/owl'; `; diff --git a/src/common/types.ts b/src/common/types.ts deleted file mode 100644 index 2df9ab1f9..000000000 --- a/src/common/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type customDirectives = Record< - string, - (node: Element, value: string, modifier: string[]) => void ->; diff --git a/src/compiler/code_generator.ts b/src/compiler/code_generator.ts index 8c696e940..93a02e751 100644 --- a/src/compiler/code_generator.ts +++ b/src/compiler/code_generator.ts @@ -1,10 +1,5 @@ -import { - compileExpr, - compileExprToArray, - interpolate, - INTERP_REGEXP, - replaceDynamicParts, -} from "./inline_expressions"; +import { OwlError } from "../common/owl_error"; +import { compileExpr, INTERP_REGEXP, interpolate } from "./inline_expressions"; import { AST, ASTComment, @@ -13,12 +8,12 @@ import { ASTDomNode, ASTLog, ASTMulti, - ASTSlot, ASTTCall, ASTTCallBlock, - ASTTEsc, + ASTTCallSlot, ASTText, ASTTForEach, + ForEachNoFlag, ASTTif, ASTTKey, ASTTOut, @@ -30,7 +25,8 @@ import { Attrs, EventHandlers, } from "./parser"; -import { OwlError } from "../common/owl_error"; + +const zero = Symbol("zero"); type BlockType = "block" | "text" | "multi" | "list" | "html" | "comment"; const whitespaceRE = /\s+/g; @@ -42,7 +38,6 @@ export interface Config { } export interface CodeGenOptions extends Config { - hasSafeContext?: boolean; name?: string; hasGlobalValues: boolean; } @@ -170,13 +165,11 @@ interface Context { block: BlockDescription | null; index: number | string; forceNewBlock: boolean; - isLast?: boolean; translate: boolean; translationCtx: string; tKeyExpr: string | null; nameSpace?: string; tModelSelectedExpr?: string; - ctxVar?: string; inPreTag?: boolean; } @@ -200,12 +193,12 @@ class CodeTarget { name: string; indentLevel = 0; loopLevel = 0; + loopCtxVars: string[] = []; + tSetVars: Map = new Map(); code: string[] = []; hasRoot = false; - hasCache = false; - shouldProtectScope: boolean = false; + needsScopeProtection = false; on: EventHandlers | null; - hasRefWrapper: boolean = false; constructor(name: string, on?: EventHandlers | null) { this.name = name; @@ -224,16 +217,8 @@ class CodeTarget { generateCode(): string { let result: string[] = []; result.push(`function ${this.name}(ctx, node, key = "") {`); - if (this.shouldProtectScope) { + if (this.needsScopeProtection) { result.push(` ctx = Object.create(ctx);`); - result.push(` ctx[isBoundary] = 1`); - } - if (this.hasRefWrapper) { - result.push(` let refWrapper = makeRefWrapper(this.__owl__);`); - } - if (this.hasCache) { - result.push(` let cache = ctx.cache || {};`); - result.push(` let nextCache = ctx.cache = {};`); } for (let line of this.code) { result.push(line); @@ -269,7 +254,6 @@ const translationRE = /^(\s*)([\s\S]+?)(\s*)$/; export class CodeGenerator { blocks: BlockDescription[] = []; nextBlockId = 1; - hasSafeContext: boolean; isDebug: boolean = false; targets: CodeTarget[] = []; target = new CodeTarget("template"); @@ -279,9 +263,8 @@ export class CodeGenerator { translatableAttributes: string[] = TRANSLATABLE_ATTRS; ast: AST; staticDefs: { id: string; expr: string }[] = []; - slotNames: Set = new Set(); + slotNames: Set = new Set(); helpers: Set = new Set(); - constructor(ast: AST, options: CodeGenOptions) { this.translateFn = options.translateFn || ((s: string) => s); if (options.translatableAttributes) { @@ -295,7 +278,6 @@ export class CodeGenerator { } this.translatableAttributes = [...attrs]; } - this.hasSafeContext = options.hasSafeContext || false; this.dev = options.dev || false; this.ast = ast; this.templateName = options.name; @@ -313,7 +295,6 @@ export class CodeGenerator { block: null, index: 0, forceNewBlock: false, - isLast: true, translate: true, translationCtx: "", tKeyExpr: null, @@ -436,40 +417,6 @@ export class CodeGenerator { } } - /** - * Captures variables that are used inside of an expression. This is useful - * because in compiled code, almost all variables are accessed through the ctx - * object. In the case of functions, that lookup in the context can be delayed - * which can cause issues if the value has changed since the function was - * defined. - * - * @param expr the expression to capture - * @param forceCapture whether the expression should capture its scope even if - * it doesn't contain a function. Useful when the expression will be used as - * a function body. - * @returns a new expression that uses the captured values - */ - captureExpression(expr: string, forceCapture: boolean = false): string { - if (!forceCapture && !expr.includes("=>")) { - return compileExpr(expr); - } - const tokens = compileExprToArray(expr); - const mapping = new Map(); - return tokens - .map((tok) => { - if (tok.varName && !tok.isLocal) { - if (!mapping.has(tok.varName)) { - const varId = generateId("v"); - mapping.set(tok.varName, varId); - this.define(varId, tok.value); - } - tok.value = mapping.get(tok.varName)!; - } - return tok.value; - }) - .join(""); - } - translate(str: string, translationCtx: string): string { const match = translationRE.exec(str) as any; return match[1] + this.translateFn(match[2], translationCtx) + match[3]; @@ -486,8 +433,6 @@ export class CodeGenerator { return this.compileText(ast, ctx); case ASTType.DomNode: return this.compileTDomNode(ast, ctx); - case ASTType.TEsc: - return this.compileTEsc(ast, ctx); case ASTType.TOut: return this.compileTOut(ast, ctx); case ASTType.TIf: @@ -510,8 +455,8 @@ export class CodeGenerator { return this.compileDebug(ast, ctx); case ASTType.TLog: return this.compileLog(ast, ctx); - case ASTType.TSlot: - return this.compileTSlot(ast, ctx); + case ASTType.TCallSlot: + return this.compileTCallSlot(ast, ctx); case ASTType.TTranslation: return this.compileTTranslation(ast, ctx); case ASTType.TTranslationContext: @@ -590,7 +535,30 @@ export class CodeGenerator { if (modifiers.length) { modifiersCode = `${modifiers.join(",")}, `; } - return `[${modifiersCode}${this.captureExpression(handler)}, ctx]`; + + const compiled = compileExpr(handler); + if (!compiled.trim()) { + return `[${modifiersCode}, ctx]`; + } + + let hoistedExpr: string; + const arrowMatch = compiled.match(/^(\([^)]*\))\s*=>/); + const bareArrowMatch = !arrowMatch && compiled.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/); + + if (arrowMatch) { + const inner = arrowMatch[1].slice(1, -1).trim(); + const rest = compiled.slice(arrowMatch[0].length); + hoistedExpr = inner ? `(ctx,${inner})=>${rest}` : `(ctx)=>${rest}`; + } else if (bareArrowMatch) { + const rest = compiled.slice(bareArrowMatch[0].length); + hoistedExpr = `(ctx,${bareArrowMatch[1]})=>${rest}`; + } else { + hoistedExpr = `(ctx, ev) => (${compiled}).call(ctx['this'], ev)`; + } + + const id = generateId("hdlr_fn"); + this.staticDefs.push({ id, expr: hoistedExpr }); + return `[${modifiersCode}${id}, ctx]`; } compileTDomNode(ast: ASTDomNode, ctx: Context): string { @@ -665,7 +633,6 @@ export class CodeGenerator { if (ast.model) { const { hasDynamicChildren, - baseExpr, expr, eventType, shouldNumberize, @@ -674,15 +641,10 @@ export class CodeGenerator { specialInitTargetAttr, } = ast.model; - const baseExpression = compileExpr(baseExpr); - const bExprId = generateId("bExpr"); - this.define(bExprId, baseExpression); - const expression = compileExpr(expr); const exprId = generateId("expr"); - this.define(exprId, expression); - - const fullExpression = `${bExprId}[${exprId}]`; + this.helpers.add("modelExpr"); + this.define(exprId, `modelExpr(${expression})`); let idx: number; if (specialInitTargetAttr) { @@ -694,14 +656,14 @@ export class CodeGenerator { targetExpr = compileExpr(dynamicTgExpr); } } - idx = block!.insertData(`${fullExpression} === ${targetExpr}`, "prop"); + idx = block!.insertData(`${exprId}() === ${targetExpr}`, "prop"); attrs[`block-property-${idx}`] = specialInitTargetAttr; } else if (hasDynamicChildren) { const bValueId = generateId("bValue"); tModelSelectedExpr = `${bValueId}`; - this.define(tModelSelectedExpr, fullExpression); + this.define(tModelSelectedExpr, `${exprId}()`); } else { - idx = block!.insertData(`${fullExpression}`, "prop"); + idx = block!.insertData(`${exprId}()`, "prop"); attrs[`block-property-${idx}`] = targetAttr; } this.helpers.add("toNumber"); @@ -709,7 +671,7 @@ export class CodeGenerator { valueCode = shouldTrim ? `${valueCode}.trim()` : valueCode; valueCode = shouldNumberize ? `toNumber(${valueCode})` : valueCode; - const handler = `[(ev) => { ${fullExpression} = ${valueCode}; }]`; + const handler = `[(ctx, ev) => { ${exprId}.set(${valueCode}); }, ctx]`; idx = block!.insertData(handler, "hdlr"); attrs[`block-handler-${idx}`] = eventType; } @@ -723,19 +685,9 @@ export class CodeGenerator { // t-ref if (ast.ref) { - if (this.dev) { - this.helpers.add("makeRefWrapper"); - this.target.hasRefWrapper = true; - } - const isDynamic = INTERP_REGEXP.test(ast.ref); - let name = `\`${ast.ref}\``; - if (isDynamic) { - name = replaceDynamicParts(ast.ref, (expr) => this.captureExpression(expr, true)); - } - let setRefStr = `(el) => this.__owl__.setRef((${name}), el)`; - if (this.dev) { - setRefStr = `refWrapper(${name}, ${setRefStr})`; - } + const refExpr = compileExpr(ast.ref); + this.helpers.add("createRef"); + const setRefStr = `createRef(${refExpr})`; const idx = block!.insertData(setRefStr, "ref"); attrs["block-ref"] = String(idx); } @@ -760,7 +712,6 @@ export class CodeGenerator { block, index: block!.childNumber, forceNewBlock: false, - isLast: ctx.isLast && i === children.length - 1, tKeyExpr: ctx.tKeyExpr, nameSpace, tModelSelectedExpr, @@ -791,29 +742,15 @@ export class CodeGenerator { return block!.varName; } - compileTEsc(ast: ASTTEsc, ctx: Context): string { - let { block, forceNewBlock } = ctx; - let expr: string; - if (ast.expr === "0") { - this.helpers.add("zero"); - expr = `ctx[zero]`; - } else { - expr = compileExpr(ast.expr); - if (ast.defaultValue) { - this.helpers.add("withDefault"); - // FIXME: defaultValue is not translated - expr = `withDefault(${expr}, ${toStringExpression(ast.defaultValue)})`; - } - } - if (!block || forceNewBlock) { - block = this.createBlock(block, "text", ctx); - this.insertBlock(`text(${expr})`, block, { ...ctx, forceNewBlock: forceNewBlock && !block }); - } else { - const idx = block.insertData(expr, "txt"); - const text = xmlDoc.createElement(`block-text-${idx}`); - block.insert(text); + compileZero() { + this.helpers.add("zero"); + const isMultiple = this.slotNames.has(zero); + this.slotNames.add(zero); + let key = this.target.loopLevel ? `key${this.target.loopLevel}` : "key"; + if (isMultiple) { + key = this.generateComponentKey(key); } - return block.varName; + return `ctx[zero]?.(node, ${key}) || text("")`; } compileTOut(ast: ASTTOut, ctx: Context): string { @@ -824,8 +761,7 @@ export class CodeGenerator { block = this.createBlock(block, "html", ctx); let blockStr; if (ast.expr === "0") { - this.helpers.add("zero"); - blockStr = `ctx[zero]`; + blockStr = this.compileZero(); } else if (ast.body) { let bodyValue = null; bodyValue = BlockDescription.nextBlockId; @@ -906,7 +842,9 @@ export class CodeGenerator { block = this.createBlock(block, "list", ctx); this.target.loopLevel++; const loopVar = `i${this.target.loopLevel}`; - this.addLine(`ctx = Object.create(ctx);`); + const ctxVar = generateId("ctx"); + this.addLine(`const ${ctxVar} = ctx;`); + this.target.loopCtxVars.push(ctxVar); const vals = `v_block${block.id}`; const keys = `k_block${block.id}`; const l = `l_block${block.id}`; @@ -919,17 +857,18 @@ export class CodeGenerator { } this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`); this.target.indentLevel++; + this.addLine(`let ctx = Object.create(${ctxVar});`); this.addLine(`ctx[\`${ast.elem}\`] = ${keys}[${loopVar}];`); - if (!ast.hasNoFirst) { + if (!(ast.noFlags & ForEachNoFlag.First)) { this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`); } - if (!ast.hasNoLast) { + if (!(ast.noFlags & ForEachNoFlag.Last)) { this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${keys}.length - 1;`); } - if (!ast.hasNoIndex) { + if (!(ast.noFlags & ForEachNoFlag.Index)) { this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`); } - if (!ast.hasNoValue) { + if (!(ast.noFlags & ForEachNoFlag.Value)) { this.addLine(`ctx[\`${ast.elem}_value\`] = ${vals}[${loopVar}];`); } this.define(`key${this.target.loopLevel}`, ast.key ? compileExpr(ast.key) : loopVar); @@ -941,40 +880,13 @@ export class CodeGenerator { ); this.addLine(`keys${block.id}.add(String(key${this.target.loopLevel}));`); } - let id: string; - if (ast.memo) { - this.target.hasCache = true; - id = generateId(); - this.define(`memo${id}`, compileExpr(ast.memo)); - this.define(`vnode${id}`, `cache[key${this.target.loopLevel}];`); - this.addLine(`if (vnode${id}) {`); - this.target.indentLevel++; - this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`); - this.target.indentLevel++; - this.addLine(`${c}[${loopVar}] = vnode${id};`); - this.addLine(`nextCache[key${this.target.loopLevel}] = vnode${id};`); - this.addLine(`continue;`); - this.target.indentLevel--; - this.addLine("}"); - this.target.indentLevel--; - this.addLine("}"); - } const subCtx = createContext(ctx, { block, index: loopVar }); this.compileAST(ast.body, subCtx); - if (ast.memo) { - this.addLine( - `nextCache[key${ - this.target.loopLevel - }] = Object.assign(${c}[${loopVar}], {memo: memo${id!}});` - ); - } this.target.indentLevel--; this.target.loopLevel--; + this.target.loopCtxVars.pop(); this.addLine(`}`); - if (!ctx.isLast) { - this.addLine(`ctx = ctx.__proto__;`); - } this.insertBlock("l", block, ctx); return block.varName; } @@ -1014,7 +926,6 @@ export class CodeGenerator { block, index, forceNewBlock, - isLast: ctx.isLast && i === l - 1, }); this.compileAST(child, subCtx); if (forceNewBlock) { @@ -1044,11 +955,10 @@ export class CodeGenerator { compileTCall(ast: ASTTCall, ctx: Context): string { let { block, forceNewBlock } = ctx; - let ctxVar = ctx.ctxVar || "ctx"; - if (ast.context) { - ctxVar = generateId("ctx"); - this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`); - } + + const attrs: string[] = ast.attrs + ? this.formatPropObject(ast.attrs, ast.attrsTranslationCtx, ctx.translationCtx) + : []; const isDynamic = INTERP_REGEXP.test(ast.name); const subTemplate = isDynamic ? interpolate(ast.name) : "`" + ast.name + "`"; if (block && !forceNewBlock) { @@ -1056,39 +966,37 @@ export class CodeGenerator { } block = this.createBlock(block, "multi", ctx); if (ast.body) { - this.addLine(`${ctxVar} = Object.create(${ctxVar});`); - this.addLine(`${ctxVar}[isBoundary] = 1;`); - this.helpers.add("isBoundary"); - const subCtx = createContext(ctx, { ctxVar }); - const bl = this.compileMulti({ type: ASTType.Multi, content: ast.body }, subCtx); - if (bl) { - this.helpers.add("zero"); - this.addLine(`${ctxVar}[zero] = ${bl};`); - } + const name = this.compileInNewTarget("callBody", ast.body, ctx); + const zeroStr = generateId("lazyBlock"); + this.define(zeroStr, `${name}.bind(this, ctx)`); + this.helpers.add("zero"); + attrs.push(`[zero]: ${zeroStr}`); } - const key = this.generateComponentKey(); - if (isDynamic) { - const templateVar = generateId("template"); - if (!this.staticDefs.find((d) => d.id === "call")) { - this.staticDefs.push({ id: "call", expr: `app.callTemplate.bind(app)` }); + let ctxExpr: string; + const ctxString = `{${attrs.join(", ")}}`; + if (ast.context) { + const dynCtxVar = generateId("ctx"); + this.addLine(`const ${dynCtxVar} = ${compileExpr(ast.context)};`); + if (ast.attrs) { + ctxExpr = `Object.assign({}, ${dynCtxVar}${attrs.length ? ", " + ctxString : ""})`; + } else { + const thisCtx = `{this: ${dynCtxVar}, __owl__: this.__owl__}`; + ctxExpr = `Object.assign({}, ${dynCtxVar}, ${thisCtx}${attrs.length ? ", " + ctxString : ""})`; } - this.define(templateVar, subTemplate); - this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, { - ...ctx, - forceNewBlock: !block, - }); } else { - const id = generateId(`callTemplate_`); - this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` }); - this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, { - ...ctx, - forceNewBlock: !block, - }); - } - if (ast.body && !ctx.isLast) { - this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`); + if (attrs.length === 0) { + ctxExpr = "ctx"; + } else { + ctxExpr = `Object.assign(Object.create(ctx), ${ctxString})`; + } } + const key = this.generateComponentKey(); + this.helpers.add("callTemplate"); + this.insertBlock(`callTemplate(${subTemplate}, this, app, ${ctxExpr}, node, ${key})`, block!, { + ...ctx, + forceNewBlock: !block, + }); return block.varName; } @@ -1105,9 +1013,10 @@ export class CodeGenerator { } compileTSet(ast: ASTTSet, ctx: Context): null { - this.target.shouldProtectScope = true; - this.helpers.add("isBoundary").add("withDefault"); const expr = ast.value ? compileExpr(ast.value || "") : "null"; + const isOuterScope = this.target.loopLevel === 0; + const defLevel = this.target.tSetVars.get(ast.name); + const isReassignment = defLevel !== undefined && this.target.loopLevel > defLevel; if (ast.body) { this.helpers.add("LazyValue"); const bodyAst: AST = { type: ASTType.Multi, content: ast.body }; @@ -1115,7 +1024,18 @@ export class CodeGenerator { let key = this.target.currentKey(ctx); let value = `new LazyValue(${name}, ctx, this, node, ${key})`; value = ast.value ? (value ? `withDefault(${expr}, ${value})` : expr) : value; - this.addLine(`ctx[\`${ast.name}\`] = ${value};`); + this.helpers.add("withDefault"); + if (isReassignment) { + const ctxVar = this.target.loopCtxVars[defLevel]; + this.addLine(`${ctxVar}[\`${ast.name}\`] = ${value};`); + } else if (isOuterScope) { + this.target.needsScopeProtection = true; + this.addLine(`ctx[\`${ast.name}\`] = ${value};`); + this.target.tSetVars.set(ast.name, 0); + } else { + this.addLine(`ctx[\`${ast.name}\`] = ${value};`); + this.target.tSetVars.set(ast.name, this.target.loopLevel); + } } else { let value: string; if (ast.defaultValue) { @@ -1123,6 +1043,7 @@ export class CodeGenerator { ctx.translate ? this.translate(ast.defaultValue, ctx.translationCtx) : ast.defaultValue ); if (ast.value) { + this.helpers.add("withDefault"); value = `withDefault(${expr}, ${defaultValue})`; } else { value = defaultValue; @@ -1130,8 +1051,17 @@ export class CodeGenerator { } else { value = expr; } - this.helpers.add("setContextValue"); - this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`); + if (isReassignment) { + const ctxVar = this.target.loopCtxVars[defLevel]; + this.addLine(`${ctxVar}["${ast.name}"] = ${value};`); + } else if (isOuterScope) { + this.target.needsScopeProtection = true; + this.addLine(`ctx["${ast.name}"] = ${value};`); + this.target.tSetVars.set(ast.name, 0); + } else { + this.addLine(`ctx["${ast.name}"] = ${value};`); + this.target.tSetVars.set(ast.name, this.target.loopLevel); + } } return null; } @@ -1165,7 +1095,7 @@ export class CodeGenerator { const attrTranslationCtx = attrsTranslationCtx?.[name] || translationCtx; value = toStringExpression(this.translateFn(value, attrTranslationCtx)); } else { - value = this.captureExpression(value); + value = compileExpr(value); } if (name.includes(".")) { let [_name, suffix] = name.split("."); @@ -1216,19 +1146,13 @@ export class CodeGenerator { // slots let slotDef: string = ""; if (ast.slots) { - let ctxStr = "ctx"; - if (this.target.loopLevel || !this.hasSafeContext) { - ctxStr = generateId("ctx"); - this.helpers.add("capture"); - this.define(ctxStr, `capture(ctx)`); - } let slotStr: string[] = []; for (let slotName in ast.slots) { const slotAst = ast.slots[slotName]; const params = []; if (slotAst.content) { const name = this.compileInNewTarget("slot", slotAst.content, ctx, slotAst.on); - params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`); + params.push(`__render: ${name}.bind(this), __ctx: ctx`); } const scope = ast.slots[slotName].scope; if (scope) { @@ -1277,10 +1201,6 @@ export class CodeGenerator { expr = `\`${ast.name}\``; } - if (this.dev) { - this.addLine(`helpers.validateProps(${expr}, ${propVar!}, this);`); - } - if (block && (ctx.forceNewBlock === false || ctx.tKeyExpr)) { // todo: check the forcenewblock condition this.insertAnchor(block); @@ -1298,9 +1218,10 @@ export class CodeGenerator { propList.push(`"${name}"`); } } + this.helpers.add("createComponent"); this.staticDefs.push({ id, - expr: `app.createComponent(${ + expr: `createComponent(app, ${ ast.isDynamic ? null : expr }, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, [${propList}])`, }); @@ -1343,7 +1264,7 @@ export class CodeGenerator { return `${name}(${expr}, [${handlers.join(",")}])`; } - compileTSlot(ast: ASTSlot, ctx: Context): string { + compileTCallSlot(ast: ASTTCallSlot, ctx: Context): string { this.helpers.add("callSlot"); let { block } = ctx; let blockString: string; @@ -1412,27 +1333,20 @@ export class CodeGenerator { return null; } compileTPortal(ast: ASTTPortal, ctx: Context): string { - if (!this.staticDefs.find((d) => d.id === "Portal")) { - this.staticDefs.push({ id: "Portal", expr: `app.Portal` }); - } + this.helpers.add("Portal"); let { block } = ctx; const name = this.compileInNewTarget("slot", ast.content, ctx); - let ctxStr = "ctx"; - if (this.target.loopLevel || !this.hasSafeContext) { - ctxStr = generateId("ctx"); - this.helpers.add("capture"); - this.define(ctxStr, `capture(ctx)`); - } let id = generateId("comp"); + this.helpers.add("createComponent"); this.staticDefs.push({ id, - expr: `app.createComponent(null, false, true, false, false)`, + expr: `createComponent(app, null, false, true, false, false)`, }); const target = compileExpr(ast.target); const key = this.generateComponentKey(); - const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, ${key}, node, ctx, Portal)`; + const blockString = `${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ctx}}}, ${key}, node, ctx, Portal)`; if (block) { this.insertAnchor(block); } diff --git a/src/compiler/index.ts b/src/compiler/index.ts index bc12330ec..e109b8d6d 100644 --- a/src/compiler/index.ts +++ b/src/compiler/index.ts @@ -1,9 +1,13 @@ -import type { customDirectives } from "../common/types"; -import type { TemplateSet } from "../runtime/template_set"; +import { OwlError } from "../common/owl_error"; import type { BDom } from "../runtime/blockdom"; +import type { TemplateSet } from "../runtime/template_set"; import { CodeGenerator, Config } from "./code_generator"; import { parse } from "./parser"; -import { OwlError } from "../common/owl_error"; + +export type CustomDirectives = Record< + string, + (node: Element, value: string, modifier: string[]) => void +>; export type Template = (context: any, vnode: any, key?: string) => BDom; @@ -11,9 +15,10 @@ export type TemplateFunction = (app: TemplateSet, bdom: any, helpers: any) => Te interface CompileOptions extends Config { name?: string; - customDirectives?: customDirectives; + customDirectives?: CustomDirectives; hasGlobalValues: boolean; } + export function compile( template: string | Element, options: CompileOptions = { @@ -23,14 +28,8 @@ export function compile( // parsing const ast = parse(template, options.customDirectives); - // some work - const hasSafeContext = - template instanceof Node - ? !(template instanceof Element) || template.querySelector("[t-set], [t-call]") === null - : !template.includes("t-set") && !template.includes("t-call"); - // code generation - const codeGenerator = new CodeGenerator(ast, { ...options, hasSafeContext }); + const codeGenerator = new CodeGenerator(ast, options); const code = codeGenerator.generateCode(); // template function try { diff --git a/src/compiler/inline_expressions.ts b/src/compiler/inline_expressions.ts index 666b7f57e..5972a5ae2 100644 --- a/src/compiler/inline_expressions.ts +++ b/src/compiler/inline_expressions.ts @@ -150,7 +150,7 @@ let tokenizeSymbol: Tokenizer = function (expr) { let s = expr[0]; if (s && s.match(/[a-zA-Z_\$]/)) { let i = 1; - while (expr[i] && expr[i].match(/\w/)) { + while (expr[i] && expr[i].match(/[\w\$]/)) { s += expr[i]; i++; } @@ -289,7 +289,7 @@ export function compileExprToArray(expr: string): Token[] { } let isVar = token.type === "SYMBOL" && !RESERVED_WORDS.includes(token.value); - if (token.type === "SYMBOL" && !RESERVED_WORDS.includes(token.value)) { + if (isVar) { if (prevToken) { // normalize missing tokens: {a} should be equivalent to {a:a} if ( @@ -360,7 +360,7 @@ export function compileExpr(expr: string): string { export const INTERP_REGEXP = /\{\{.*?\}\}|\#\{.*?\}/g; -export function replaceDynamicParts(s: string, replacer: (s: string) => string) { +function replaceDynamicParts(s: string, replacer: (s: string) => string) { let matches = s.match(INTERP_REGEXP); if (matches && matches[0].length === s.length) { return `(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index aff0bc862..a4c5e9482 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,5 +1,5 @@ +import { CustomDirectives } from "."; import { OwlError } from "../common/owl_error"; -import type { customDirectives } from "../common/types"; import { parseXML } from "../common/utils"; // ----------------------------------------------------------------------------- @@ -14,7 +14,6 @@ export const enum ASTType { Comment, DomNode, Multi, - TEsc, TIf, TSet, TCall, @@ -24,7 +23,7 @@ export const enum ASTType { TComponent, TDebug, TLog, - TSlot, + TCallSlot, TCallBlock, TTranslation, TTranslationContext, @@ -47,7 +46,6 @@ export interface ASTComment extends BaseAST { } interface TModelInfo { - baseExpr: string; expr: string; targetAttr: string; eventType: "change" | "click" | "input"; @@ -75,12 +73,6 @@ export interface ASTMulti extends BaseAST { content: AST[]; } -export interface ASTTEsc extends BaseAST { - type: ASTType.TEsc; - expr: string; - defaultValue: string; -} - export interface ASTTOut extends BaseAST { type: ASTType.TOut; expr: string; @@ -104,16 +96,19 @@ export interface ASTTSet extends BaseAST { hasNoRepresentation: true; } +export const enum ForEachNoFlag { + First = 1, + Last = 2, + Index = 4, + Value = 8, +} + export interface ASTTForEach extends BaseAST { type: ASTType.TForEach; collection: string; elem: string; body: AST; - memo: string; - hasNoFirst: boolean; - hasNoLast: boolean; - hasNoIndex: boolean; - hasNoValue: boolean; + noFlags: number; key: string | null; } @@ -126,7 +121,9 @@ export interface ASTTKey extends BaseAST { export interface ASTTCall extends BaseAST { type: ASTType.TCall; name: string; - body: AST[] | null; + attrs: Attrs | null; + attrsTranslationCtx: Attrs | null; + body: AST | null; context: string | null; } @@ -149,8 +146,8 @@ export interface ASTComponent extends BaseAST { slots: { [name: string]: SlotDefinition } | null; } -export interface ASTSlot extends BaseAST { - type: ASTType.TSlot; +export interface ASTTCallSlot extends BaseAST { + type: ASTType.TCallSlot; name: string; attrs: Attrs | null; attrsTranslationCtx: Attrs | null; @@ -196,7 +193,6 @@ export type AST = | ASTComment | ASTDomNode | ASTMulti - | ASTTEsc | ASTTif | ASTTSet | ASTTCall @@ -204,7 +200,7 @@ export type AST = | ASTTForEach | ASTTKey | ASTComponent - | ASTSlot + | ASTTCallSlot | ASTTCallBlock | ASTLog | ASTDebug @@ -217,7 +213,7 @@ export type AST = // ----------------------------------------------------------------------------- const cache: WeakMap = new WeakMap(); -export function parse(xml: string | Element, customDir?: customDirectives): AST { +export function parse(xml: string | Element, customDir?: CustomDirectives): AST { const ctx = { inPreTag: false, customDirectives: customDir, @@ -244,7 +240,7 @@ interface ParsingContext { tModelInfo?: TModelInfo | null; nameSpace?: string; inPreTag: boolean; - customDirectives?: customDirectives; + customDirectives?: CustomDirectives; } function parseNode(node: Node, ctx: ParsingContext): AST | null { @@ -257,14 +253,13 @@ function parseNode(node: Node, ctx: ParsingContext): AST | null { parseTForEach(node, ctx) || parseTIf(node, ctx) || parseTPortal(node, ctx) || - parseTCall(node, ctx) || - parseTCallBlock(node, ctx) || parseTTranslation(node, ctx) || parseTTranslationContext(node, ctx) || + parseTCall(node, ctx) || + parseTCallBlock(node, ctx) || parseTKey(node, ctx) || - parseTEscNode(node, ctx) || parseTOutNode(node, ctx) || - parseTSlot(node, ctx) || + parseTCallSlot(node, ctx) || parseComponent(node, ctx) || parseDOMNode(node, ctx) || parseTSetNode(node, ctx) || @@ -371,9 +366,6 @@ function parseTDebugLog(node: Element, ctx: ParsingContext): AST | null { // ----------------------------------------------------------------------------- // Regular dom node // ----------------------------------------------------------------------------- -const hasDotAtTheEnd = /\.[\w_]+\s*$/; -const hasBracketsAtTheEnd = /\[[^\[]+\]\s*$/; - const ROOT_SVG_TAGS = new Set(["svg", "g", "path"]); function parseDOMNode(node: Element, ctx: ParsingContext): AST | null { @@ -415,20 +407,6 @@ function parseDOMNode(node: Element, ctx: ParsingContext): AST | null { "The t-model directive only works with , test
    "); }); test("on an input type=radio", async () => { class SomeComponent extends Component { static template = xml`
    - - - Choice: + + + Choice:
    `; - state = useState({ choice: "" }); + choice = signal(""); } const comp = await mount(SomeComponent, fixture); @@ -160,7 +162,7 @@ describe("t-model directive", () => { const firstInput = fixture.querySelector("input")!; firstInput.click(); await nextTick(); - expect(comp.state.choice).toBe("One"); + expect(comp.choice()).toBe("One"); expect(fixture.innerHTML).toBe( '
    Choice: One
    ' ); @@ -168,7 +170,7 @@ describe("t-model directive", () => { const secondInput = fixture.querySelectorAll("input")[1]; secondInput.click(); await nextTick(); - expect(comp.state.choice).toBe("Two"); + expect(comp.choice()).toBe("Two"); expect(fixture.innerHTML).toBe( '
    Choice: Two
    ' ); @@ -177,10 +179,10 @@ describe("t-model directive", () => { test("on an input type=radio, with initial value", async () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ choice: "Two" }); + choice = signal("Two"); } await mount(SomeComponent, fixture); @@ -195,14 +197,14 @@ describe("t-model directive", () => { test("on a select", async () => { class SomeComponent extends Component { static template = xml`
    - - Choice: + Choice:
    `; - state = useState({ color: "" }); + color = signal(""); } const comp = await mount(SomeComponent, fixture); @@ -215,7 +217,7 @@ describe("t-model directive", () => { select.dispatchEvent(new Event("change")); await nextTick(); - expect(comp.state.color).toBe("red"); + expect(comp.color()).toBe("red"); expect(fixture.innerHTML).toBe( '
    Choice: red
    ' ); @@ -225,14 +227,14 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    -
    `; - state = useState({ color: "red" }); + color = signal("red"); } await mount(SomeComponent, fixture); const select = fixture.querySelector("select")!; @@ -243,11 +245,11 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ something: { text: "" } }); + state = { something: { text: signal("") } }; } const comp = await mount(SomeComponent, fixture); @@ -255,7 +257,7 @@ describe("t-model directive", () => { const input = fixture.querySelector("input")!; await editInput(input, "test"); - expect(comp.state.something.text).toBe("test"); + expect(comp.state.something.text()).toBe("test"); expect(fixture.innerHTML).toBe("
    test
    "); }); @@ -263,12 +265,17 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state: { something: { [key: string]: string } } = useState({ something: {} }); - text = useState({ key: "foo" }); + state = { + something: { + foo: signal(""), + bar: signal(""), + }, + }; + key = signal<"foo" | "bar">("foo"); } const comp = await mount(SomeComponent, fixture); @@ -276,14 +283,14 @@ describe("t-model directive", () => { let input = fixture.querySelector("input")!; await editInput(input, "footest"); - expect(comp.state.something[comp.text.key]).toBe("footest"); + expect(comp.state.something[comp.key()]()).toBe("footest"); expect(fixture.innerHTML).toBe("
    footest
    "); - comp.text.key = "bar"; + comp.key.set("bar"); await nextTick(); input = fixture.querySelector("input")!; await editInput(input, "test bar"); - expect(comp.state.something[comp.text.key]).toBe("test bar"); + expect(comp.state.something[comp.key()]()).toBe("test bar"); expect(fixture.innerHTML).toBe("
    test bar
    "); }); @@ -291,11 +298,11 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ text: "" }); + text = signal(""); } const comp = await mount(SomeComponent, fixture); @@ -305,11 +312,11 @@ describe("t-model directive", () => { input.value = "test"; input.dispatchEvent(new Event("input")); await nextTick(); - expect(comp.state.text).toBe(""); + expect(comp.text()).toBe(""); expect(fixture.innerHTML).toBe("
    "); input.dispatchEvent(new Event("change")); await nextTick(); - expect(comp.state.text).toBe("test"); + expect(comp.text()).toBe("test"); expect(fixture.innerHTML).toBe("
    test
    "); }); @@ -317,17 +324,17 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ text: "" }); + text = signal(""); } const comp = await mount(SomeComponent, fixture); const input = fixture.querySelector("input")!; await editInput(input, " test "); - expect(comp.state.text).toBe("test"); + expect(comp.text()).toBe("test"); expect(fixture.innerHTML).toBe("
    test
    "); }); @@ -335,11 +342,11 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ text: "" }); + text = signal(""); } const comp = await mount(SomeComponent, fixture); @@ -349,11 +356,11 @@ describe("t-model directive", () => { input.value = "test "; input.dispatchEvent(new Event("input")); await nextTick(); - expect(comp.state.text).toBe(""); + expect(comp.text()).toBe(""); expect(fixture.innerHTML).toBe("
    "); input.dispatchEvent(new Event("change")); await nextTick(); - expect(comp.state.text).toBe("test"); + expect(comp.text()).toBe("test"); expect(fixture.innerHTML).toBe("
    test
    "); }); @@ -361,22 +368,22 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ number: 0 }); + number = signal(0); } const comp = await mount(SomeComponent, fixture); expect(fixture.innerHTML).toBe("
    0
    "); const input = fixture.querySelector("input")!; await editInput(input, "13"); - expect(comp.state.number).toBe(13); + expect(comp.number()).toBe(13); expect(fixture.innerHTML).toBe("
    13
    "); await editInput(input, "invalid"); - expect(comp.state.number).toBe("invalid"); + expect(comp.number()).toBe("invalid"); expect(fixture.innerHTML).toBe("
    invalid
    "); }); @@ -384,16 +391,16 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - +
    `; - state = useState([ - { f: false, id: 1 }, - { f: false, id: 2 }, - { f: false, id: 3 }, - ]); + things = [ + { f: signal(false), id: 1 }, + { f: signal(false), id: 2 }, + { f: signal(false), id: 3 }, + ]; } const comp = await mount(SomeComponent, fixture); @@ -403,59 +410,82 @@ describe("t-model directive", () => { const input = fixture.querySelectorAll("input")[1]!; input.click(); - expect(comp.state[1].f).toBe(true); - expect(comp.state[0].f).toBe(false); - expect(comp.state[2].f).toBe(false); + expect(comp.things[1].f()).toBe(true); + expect(comp.things[0].f()).toBe(false); + expect(comp.things[2].f()).toBe(false); }); test("in a t-foreach, part 2", async () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState(["zuko", "iroh"]); + things = [signal("zuko"), signal("iroh")]; } const comp = await mount(SomeComponent, fixture); - expect(comp.state).toEqual(["zuko", "iroh"]); + expect(comp.things.map((thing) => thing())).toEqual(["zuko", "iroh"]); const input = fixture.querySelectorAll("input")[1]!; await editInput(input, "uncle iroh"); - expect(comp.state).toEqual(["zuko", "uncle iroh"]); + expect(comp.things.map((thing) => thing())).toEqual(["zuko", "uncle iroh"]); }); test("in a t-foreach, part 3", async () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; names = ["Crusher", "Data", "Riker", "Worf"]; - state = useState({ values: {} }); + values = { + Crusher: signal(""), + Data: signal(""), + Riker: signal(""), + Worf: signal(""), + }; } const comp = await mount(SomeComponent, fixture); - expect(comp.state).toEqual({ values: {} }); + const values = computed(() => ({ + Crusher: comp.values.Crusher(), + Data: comp.values.Data(), + Riker: comp.values.Riker(), + Worf: comp.values.Worf(), + })); + expect(values()).toEqual({ + Crusher: "", + Data: "", + Riker: "", + Worf: "", + }); const input = fixture.querySelectorAll("input")[1]!; await editInput(input, "Commander"); - expect(comp.state).toEqual({ values: { Data: "Commander" } }); + expect(values()).toEqual({ + Crusher: "", + Data: "Commander", + Riker: "", + Worf: "", + }); }); test("two inputs in a div alternating with a t-if", async () => { class SomeComponent extends Component { static template = xml`
    - - + +
    `; - state = useState({ flag: true, text1: "", text2: "" }); + flag = signal(true); + text1 = signal(""); + text2 = signal(""); } const comp = await mount(SomeComponent, fixture); @@ -463,16 +493,16 @@ describe("t-model directive", () => { let input = fixture.querySelector("input")!; expect(input.value).toBe(""); await editInput(input, "Jean-Luc"); - expect(comp.state.text1).toBe("Jean-Luc"); + expect(comp.text1()).toBe("Jean-Luc"); - comp.state.flag = false; + comp.flag.set(false); await nextTick(); expect(fixture.innerHTML).toBe('
    '); input = fixture.querySelector("input")!; expect(input.value).toBe(""); await editInput(input, "Picard"); - expect(comp.state.text2).toBe("Picard"); + expect(comp.text2()).toBe("Picard"); }); test("following a scope protecting directive (e.g. t-set)", async () => { @@ -480,83 +510,80 @@ describe("t-model directive", () => { static template = xml`
    - +
    `; - state = useState({ text: "Jean-Luc Picard" }); + text = signal("Jean-Luc Picard"); } const comp = await mount(SomeComponent, fixture); expect(fixture.innerHTML).toBe("
    "); const input = fixture.querySelector("input")!; expect(input.value).toBe("Jean-Luc Picard"); await editInput(input, "Commander Data"); - expect(comp.state.text).toBe("Commander Data"); + expect(comp.text()).toBe("Commander Data"); }); test("can also define t-on directive on same event, part 1", async () => { class SomeComponent extends Component { static template = xml`
    - +
    `; - state = useState({ text: "", other: "" }); + text = signal(""); + other = signal(""); onInput(ev: InputEvent) { - this.state.other = (ev.target as HTMLInputElement).value; + this.other.set((ev.target as HTMLInputElement).value); } } const comp = await mount(SomeComponent, fixture); - expect(comp.state.text).toBe(""); - expect(comp.state.other).toBe(""); + expect(comp.text()).toBe(""); + expect(comp.other()).toBe(""); const input = fixture.querySelector("input")!; await editInput(input, "Beam me up, Scotty"); - expect(comp.state.text).toBe("Beam me up, Scotty"); - expect(comp.state.other).toBe("Beam me up, Scotty"); + expect(comp.text()).toBe("Beam me up, Scotty"); + expect(comp.other()).toBe("Beam me up, Scotty"); }); test("can also define t-on directive on same event, part 2", async () => { class SomeComponent extends Component { static template = xml`
    - - - + + +
    `; - state = useState({ choice: "", lastClicked: "" }); + choice = signal(""); + lastClicked = signal(""); onClick(ev: MouseEvent) { - this.state.lastClicked = (ev.target as HTMLInputElement).value; + this.lastClicked.set((ev.target as HTMLInputElement).value); } } const comp = await mount(SomeComponent, fixture); - expect(comp.state.choice).toBe(""); - expect(comp.state.lastClicked).toBe(""); + expect(comp.choice()).toBe(""); + expect(comp.lastClicked()).toBe(""); const lastInput = fixture.querySelectorAll("input")[2]; lastInput.click(); await nextTick(); - expect(comp.state.choice).toBe("Three"); - expect(comp.state.lastClicked).toBe("Three"); + expect(comp.choice()).toBe("Three"); + expect(comp.lastClicked()).toBe("Three"); }); test("t-model on select with static options", async () => { class Test extends Component { static template = xml`
    - +
    `; - state: any; - options: any; - setup() { - this.state = useState({ model: "b" }); - this.options = ["a", "b", "c"]; - } + model = signal("b"); } await mount(Test, fixture); @@ -567,18 +594,14 @@ describe("t-model directive", () => { class Test extends Component { static template = xml`
    - +
    `; - state: any; - options: any; - setup() { - this.state = useState({ model: "b" }); - this.options = ["a", "b"]; - } + model = signal("b"); + options = ["a", "b"]; } await mount(Test, fixture); @@ -589,18 +612,14 @@ describe("t-model directive", () => { class Test extends Component { static template = xml`
    - +
    `; - state: any; - options: any; - setup() { - this.state = useState({ model: "b" }); - this.options = ["a", "b"]; - } + model = signal("b"); + options = ["a", "b"]; } await mount(Test, fixture); @@ -611,18 +630,14 @@ describe("t-model directive", () => { class Test extends Component { static template = xml`
    - +
    `; - state: any; - options: any; - setup() { - this.state = useState({ model: "b" }); - this.options = ["a", "b"]; - } + model = signal("b"); + options = ["a", "b"]; } await mount(Test, fixture); @@ -633,19 +648,15 @@ describe("t-model directive", () => { class Test extends Component { static template = xml`
    - + + -
    +
    `; - state: any; - options: any; - setup() { - this.state = useState({ model: "b" }); - this.options = ["a", "b", "c"]; - } + model = signal("b"); + options = ["a", "b", "c"]; } await mount(Test, fixture); @@ -655,25 +666,20 @@ describe("t-model directive", () => { test("t-model with dynamic number values on select options in foreach", async () => { class Test extends Component { static template = xml` - + + `; - state: any; - setup() { - this.state = useState({ - value: 2, - options: [{ value: 1 }, { value: 2 }, { value: 3 }], - }); - } + value = signal(2); + options = [{ value: 1 }, { value: 2 }, { value: 3 }]; } const comp = await mount(Test, fixture); // check that we have a value of 2 selected expect(fixture.querySelector("select")!.value).toEqual("2"); - expect(comp.state.value).toBe(2); + expect(comp.value()).toBe(2); // emulate a click on the option=3 element fixture.querySelectorAll("option")[2].selected = true; @@ -682,7 +688,7 @@ describe("t-model directive", () => { await nextTick(); // check that we have now selected the number 3 (and not the string) expect(fixture.querySelector("select")!.value).toEqual("3"); - expect(comp.state.value).toBe(3); + expect(comp.value()).toBe(3); }); test("t-model is applied before t-on-input", async () => { @@ -690,12 +696,12 @@ describe("t-model directive", () => { class SomeComponent extends Component { static template = xml`
    - +
    `; - state = useState({ text: "", other: "" }); + state = { text: signal("") }; onInput(ev: InputEvent) { - expect(this.state.text).toBe("Beam me up, Scotty"); + expect(this.state.text()).toBe("Beam me up, Scotty"); expect((ev.target as HTMLInputElement).value).toBe("Beam me up, Scotty"); } } @@ -709,17 +715,17 @@ describe("t-model directive", () => { const steps: string[] = []; class SomeComponent extends Component { static template = xml` -
    - - +
    + +
    `; - state = useState({ group: "scotty" }); + group = signal("scotty"); options = ["beam", "scotty"]; getData() { - steps.push(`group: ${this.state.group}`); + steps.push(`group: ${this.group()}`); } } await mount(SomeComponent, fixture); diff --git a/tests/components/t_on.test.ts b/tests/components/t_on.test.ts index c4b910e03..9cea9a14e 100644 --- a/tests/components/t_on.test.ts +++ b/tests/components/t_on.test.ts @@ -1,4 +1,4 @@ -import { Component, mount, onMounted, useState, xml } from "../../src/index"; +import { Component, mount, onMounted, props, proxy, xml } from "../../src/index"; import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { status } from "../../src/runtime/status"; @@ -15,7 +15,7 @@ describe("t-on", () => { const steps: string[] = []; let child: any; class Child extends Component { - static template = xml`
    `; + static template = xml`
    `; setup() { onMounted(() => { child = this; @@ -26,9 +26,9 @@ describe("t-on", () => { } } class Parent extends Component { - static template = xml`
    `; + static template = xml`
    `; static components = { Child }; - state = useState({ flag: true }); + state = proxy({ flag: true }); } const parent = await mount(Parent, fixture); let el = elem(child!); @@ -36,7 +36,7 @@ describe("t-on", () => { expect(steps).toEqual(["click"]); (parent as any).state.flag = false; await nextTick(); - expect(status(child as any)).toBe("destroyed"); + expect(status(child)).toBe("destroyed"); el.click(); expect(steps).toEqual(["click"]); }); @@ -44,15 +44,16 @@ describe("t-on", () => { test("t-on when first component child is an empty component", async () => { class Child extends Component { static template = xml` - + `; + props = props(); } class Parent extends Component { static template = xml` -
    +
    `; static components = { Child }; - list = useState([] as string[]); + list = proxy([] as string[]); push() { this.list.push("foo"); } @@ -69,13 +70,13 @@ describe("t-on", () => { class Comp extends Component { static template = xml`
    -
    - : - +
    + : +
    `; - state = useState({ values: ["a", "b"] }); + state = proxy({ values: ["a", "b"] }); otherState = { vals: [] }; } const comp = await mount(Comp, fixture); @@ -94,14 +95,14 @@ describe("t-on", () => { static template = xml`
    -
    +
    - : - + : +
    `; - state = useState({ values: ["a", "b"] }); + state = proxy({ values: ["a", "b"] }); otherState = { vals: [] }; } const comp = await mount(Comp, fixture); @@ -112,20 +113,20 @@ describe("t-on", () => { const buttons = fixture.querySelectorAll("button"); buttons[0].click(); buttons[1].click(); - expect(comp.otherState.vals).toStrictEqual(["a_nova_0", "b_nova_0_1"]); + expect(comp.otherState.vals).toStrictEqual(["a_nova_0_1", "b_nova_0_1"]); }); test("t-on method call in t-foreach", async () => { class Comp extends Component { static template = xml`
    -
    - : +
    + :
    `; - state = useState({ values: ["a", "b"] }); + state = proxy({ values: ["a", "b"] }); otherState = { vals: new Array() }; addVal(val: string) { this.otherState.vals.push(val); @@ -147,8 +148,8 @@ describe("t-on", () => { static template = xml`
    -
    - +
    +
    @@ -164,18 +165,19 @@ describe("t-on", () => { const buttons = fixture.querySelectorAll("button"); buttons[0].click(); buttons[1].click(); - expect(comp.otherState.vals).toStrictEqual(["0_0", "1_1"]); + expect(comp.otherState.vals).toStrictEqual(["2_2", "2_2"]); }); test("t-on on components", async () => { class Child extends Component { - static template = xml`

    dec

    "); }); - test("t-on on t-slots", async () => { + test("t-on on t-call-slots", async () => { class Child extends Component { static template = xml` - [] - `; - - state = useState({ count: 0 }); + [] + `; + props = props(); + state = proxy({ count: 0 }); } class Parent extends Component { @@ -277,12 +281,13 @@ describe("t-on", () => { test("t-on on t-set-slots", async () => { class Child extends Component { - static template = xml``; + static template = xml``; + props = props(); } class Parent extends Component { static template = xml` - [] + []

    something

    @@ -290,7 +295,7 @@ describe("t-on", () => {
    `; static components = { Child }; - state = useState({ count: 0 }); + state = proxy({ count: 0 }); } await mount(Parent, fixture); @@ -303,13 +308,14 @@ describe("t-on", () => { test("t-on on components, with 'prevent' modifier", async () => { expect.assertions(4); // 2 snaps and 2 expects class Child extends Component { - static template = xml`\`); - - return function template(ctx, node, key = \\"\\") { - return block1(); - } -}" -`; - exports[`Portal simple catchError with portal 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const comp1 = app.createComponent(\`Boom\`, true, false, false, []); + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Boom\`, true, false, false, []); let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { let b2, b3; - if (ctx['error']) { + if (ctx['this'].error) { b2 = text(\`Error\`); } else { b3 = comp1({}, key + \`__1\`, node, this, null); @@ -863,20 +831,20 @@ exports[`Portal simple catchError with portal 2`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const Portal = app.Portal; - const comp1 = app.createComponent(null, false, true, false, false); + let { Portal, safeOutput, createComponent } = helpers; + const comp1 = createComponent(app, null, false, true, false, false); let block1 = createBlock(\`
    1
    \`); - let block2 = createBlock(\`

    \`); + let block2 = createBlock(\`

    \`); - function slot1(ctx, node, key = \\"\\") { - let txt1 = ctx['a'].b.c; - return block2([txt1]); + function slot1(ctx, node, key = "") { + const b3 = safeOutput(ctx['a'].b.c); + return block2([], [b3]); } - return function template(ctx, node, key = \\"\\") { - const b3 = comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal); - return block1([], [b3]); + return function template(ctx, node, key = "") { + const b4 = comp1({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal); + return block1([], [b4]); } }" `; @@ -885,17 +853,17 @@ exports[`Portal with target in template (after portal) 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const Portal = app.Portal; - const comp1 = app.createComponent(null, false, true, false, false); + let { Portal, createComponent } = helpers; + const comp1 = createComponent(app, null, false, true, false, false); - let block1 = createBlock(\`
    1
    \`); + let block1 = createBlock(\`
    1
    \`); let block2 = createBlock(\`

    2

    \`); - function slot1(ctx, node, key = \\"\\") { + function slot1(ctx, node, key = "") { return block2(); } - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { const b3 = comp1({target: '#local-target',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal); return block1([], [b3]); } @@ -906,17 +874,17 @@ exports[`Portal with target in template (before portal) 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const Portal = app.Portal; - const comp1 = app.createComponent(null, false, true, false, false); + let { Portal, createComponent } = helpers; + const comp1 = createComponent(app, null, false, true, false, false); - let block1 = createBlock(\`
    1
    \`); + let block1 = createBlock(\`
    1
    \`); let block2 = createBlock(\`

    2

    \`); - function slot1(ctx, node, key = \\"\\") { + function slot1(ctx, node, key = "") { return block2(); } - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { const b3 = comp1({target: '#local-target',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal); return block1([], [b3]); } @@ -948,17 +916,17 @@ exports[`Portal: Props validation target must be a valid selector 2 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const Portal = app.Portal; - const comp1 = app.createComponent(null, false, true, false, false); + let { Portal, createComponent } = helpers; + const comp1 = createComponent(app, null, false, true, false, false); let block1 = createBlock(\`
    \`); let block2 = createBlock(\`
    2
    \`); - function slot1(ctx, node, key = \\"\\") { + function slot1(ctx, node, key = "") { return block2(); } - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { const b3 = comp1({target: 'aa',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__1\`, node, ctx, Portal); return block1([], [b3]); } @@ -969,17 +937,17 @@ exports[`Portal: UI/UX focus is kept across re-renders 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - const Portal = app.Portal; - const comp1 = app.createComponent(\`Child\`, true, false, false, [\\"val\\"]); - const comp2 = app.createComponent(null, false, true, false, false); + let { Portal, createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, ["val"]); + const comp2 = createComponent(app, null, false, true, false, false); let block1 = createBlock(\`
    \`); - function slot1(ctx, node, key = \\"\\") { - return comp1({val: ctx['state'].val}, key + \`__1\`, node, this, null); + function slot1(ctx, node, key = "") { + return comp1({val: ctx['this'].state.val}, key + \`__1\`, node, this, null); } - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { const b3 = comp2({target: '#outside',slots: {'default': {__render: slot1.bind(this), __ctx: ctx}}}, key + \`__2\`, node, ctx, Portal); return block1([], [b3]); } @@ -991,10 +959,10 @@ exports[`Portal: UI/UX focus is kept across re-renders 2`] = ` ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`\`); + let block1 = createBlock(\`\`); - return function template(ctx, node, key = \\"\\") { - let attr1 = ctx['props'].val; + return function template(ctx, node, key = "") { + let attr1 = ctx['this'].props.val; return block1([attr1]); } }" diff --git a/tests/misc/portal.test.ts b/tests/misc/portal.test.ts index 39c622a4b..aaf674452 100644 --- a/tests/misc/portal.test.ts +++ b/tests/misc/portal.test.ts @@ -8,10 +8,18 @@ import { onPatched, onWillPatch, onWillUnmount, - useState, + props, + proxy, } from "../../src"; import { xml } from "../../src/"; -import { elem, makeTestFixture, nextAppError, nextTick, snapshotEverything } from "../helpers"; +import { + elem, + makeTestFixture, + nextAppError, + nextTick, + snapshotEverything, + render, +} from "../helpers"; let fixture: HTMLElement; let originalconsoleWarn = console.warn; @@ -73,7 +81,7 @@ describe("Portal", () => { static template = xml`
    1 - +

    2

    `; @@ -110,7 +118,7 @@ describe("Portal", () => {
    1 -

    +

    `; } @@ -118,7 +126,7 @@ describe("Portal", () => { class Parent extends Component { static template = xml`
    - Error + Error @@ -130,7 +138,7 @@ describe("Portal", () => { setup() { onError((err) => { this.error = err; - this.render(); + render(this); }); } } @@ -161,11 +169,11 @@ describe("Portal", () => { class Parent extends Component { static template = xml` 1 - +

    2

    `; - state = useState({ hasPortal: false }); + state = proxy({ hasPortal: false }); } addOutsideDiv(fixture); @@ -187,16 +195,17 @@ describe("Portal", () => { test("conditional use of Portal (with sub Component)", async () => { class Child extends Component { - static template = xml`

    `; + static template = xml`

    `; + props = props(); } class Parent extends Component { static components = { Child }; static template = xml` 1 - - + + `; - state = useState({ hasPortal: false, val: 1 }); + state = proxy({ hasPortal: false, val: 1 }); } addOutsideDiv(fixture); @@ -267,16 +276,16 @@ describe("Portal", () => {
    `; } - let error: Error; - const app = new App(Parent); - const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); - await expect(nextAppError(app)).resolves.toThrow("invalid portal target"); - await mountProm; - + let error: any; + try { + await mount(Parent, fixture); + } catch (e) { + error = e; + } expect(error!).toBeDefined(); - expect(error!.message).toBe("invalid portal target"); + expect(error!.cause.message).toBe("invalid portal target"); expect(fixture.innerHTML).toBe(``); - expect(mockConsoleWarn).toBeCalledTimes(1); + expect(mockConsoleWarn).toHaveBeenCalledTimes(0); }); test("portal with child and props", async () => { @@ -284,7 +293,8 @@ describe("Portal", () => { const outside = addOutsideDiv(fixture); class Child extends Component { - static template = xml``; + static template = xml``; + props = props(); setup() { onMounted(() => { @@ -302,10 +312,10 @@ describe("Portal", () => { static template = xml`
    - +
    `; - state = useState({ val: 1 }); + state = proxy({ val: 1 }); } const parent = await mount(Parent, fixture); @@ -324,7 +334,7 @@ describe("Portal", () => { static template = xml`
    - +
    `; } @@ -339,7 +349,7 @@ describe("Portal", () => { static template = xml`
    - +
    `; } @@ -369,11 +379,11 @@ describe("Portal", () => { static template = xml`
    - +
    `; - state = useState({ val: "ab" }); + state = proxy({ val: "ab" }); } const outside = addOutsideDiv(fixture); @@ -391,10 +401,10 @@ describe("Portal", () => { static template = xml`
    - +
    `; - state = useState({ val: "ab" }); + state = proxy({ val: "ab" }); } const outside = addOutsideDiv(fixture); const parent = await mount(Parent, fixture); @@ -410,7 +420,8 @@ describe("Portal", () => { const steps: any[] = []; class Child extends Component { - static template = xml``; + static template = xml``; + props = props(); setup() { onMounted(() => steps.push("child:mounted")); onWillPatch(() => steps.push("child:willPatch")); @@ -423,11 +434,11 @@ describe("Portal", () => { static components = { Child }; static template = xml`
    - - + +
    `; - state = useState({ hasChild: false, val: 1 }); + state = proxy({ hasChild: false, val: 1 }); setup() { onMounted(() => steps.push("parent:mounted")); onWillPatch(() => steps.push("parent:willPatch")); @@ -458,10 +469,8 @@ describe("Portal", () => { "parent:willPatch", "child:mounted", "parent:patched", - "parent:willPatch", "child:willPatch", "child:patched", - "parent:patched", ]); expect(fixture.innerHTML).toBe('
    2
    '); @@ -472,10 +481,8 @@ describe("Portal", () => { "parent:willPatch", "child:mounted", "parent:patched", - "parent:willPatch", "child:willPatch", "child:patched", - "parent:patched", "parent:willPatch", "child:willUnmount", "parent:patched", @@ -485,7 +492,8 @@ describe("Portal", () => { test("portal destroys on crash", async () => { class Child extends Component { - static template = xml``; + static template = xml``; + props = props(); state = {}; } class Parent extends Component { @@ -493,12 +501,12 @@ describe("Portal", () => { static template = xml`
    - +
    `; state = { error: false }; setup() { - onError(({ cause }) => (error = cause)); + onError((_error) => (error = _error)); } } addOutsideDiv(fixture); @@ -506,7 +514,7 @@ describe("Portal", () => { let error: Error; parent.state.error = true; - parent.render(); + render(parent); await nextTick(); expect(error!).toBeDefined(); const regexp = @@ -514,31 +522,12 @@ describe("Portal", () => { expect(error!.message).toMatch(regexp); }); - test("portal's parent's env is not polluted", async () => { - class Child extends Component { - static template = xml` - `; - } - class Parent extends Component { - static components = { Child }; - static template = xml` -
    - - - -
    `; - } - const env = {}; - addOutsideDiv(fixture); - const parent = await mount(Parent, fixture, { env }); - expect(parent.env).toStrictEqual({}); - }); - test("Portal composed with t-slot", async () => { const steps: Array = []; let childInst: Component | null = null; class Child2 extends Component { - static template = xml`
    child2
    `; + static template = xml`
    child2
    `; + props = props(); setup() { childInst = this; } @@ -550,15 +539,16 @@ describe("Portal", () => { static components = { Child2 }; static template = xml` - + `; + props = props(); } class Parent extends Component { static components = { Child, Child2 }; static template = xml`
    - +
    `; @@ -577,10 +567,10 @@ describe("Portal", () => { test("Add and remove portals", async () => { class Parent extends Component { static template = xml` - - Portal + + Portal `; - portalIds = useState([] as any); + portalIds = proxy([] as any); } addOutsideDiv(fixture); @@ -608,10 +598,10 @@ describe("Portal", () => { test("Add and remove portals on div", async () => { class Parent extends Component { static template = xml` -
    - Portal +
    + Portal
    `; - portalIds = useState([] as any); + portalIds = proxy([] as any); } addOutsideDiv(fixture); @@ -641,15 +631,15 @@ describe("Portal", () => { test("Add and remove portals with t-foreach", async () => { class Parent extends Component { static template = xml` - +
    - + - Portal + Portal
    `; - portalIds = useState([] as any); + portalIds = proxy([] as any); } addOutsideDiv(fixture); @@ -679,20 +669,20 @@ describe("Portal", () => { test("Add and remove portals with t-foreach and destroy", async () => { class Parent extends Component { static template = xml` - +
    - + - Portal + Portal
    `; - portalIds = useState([] as any); + portalIds = proxy([] as any); } addOutsideDiv(fixture); - const app = new App(Parent); - const parent = await app.mount(fixture); + const app = new App(); + const parent = await app.createRoot(Parent).mount(fixture); expect(fixture.innerHTML).toBe('
    '); @@ -714,7 +704,7 @@ describe("Portal", () => { test("conditional use of Portal with div", async () => { class Parent extends Component { static template = xml` - +
    hasPortal @@ -723,7 +713,7 @@ describe("Portal", () => {
    `; - state = useState({ hasPortal: false }); + state = proxy({ hasPortal: false }); } addOutsideDiv(fixture); @@ -761,13 +751,13 @@ describe("Portal", () => { } class Parent extends Component { static template = xml` - + `; static components = { Child }; - state = useState({ hasPortal: false }); + state = proxy({ hasPortal: false }); } addOutsideDiv(fixture); @@ -803,7 +793,7 @@ describe("Portal", () => { } class Parent extends Component { static template = xml` - +
    @@ -811,7 +801,7 @@ describe("Portal", () => { static components = { Child }; - state = useState({ hasPortal: false }); + state = proxy({ hasPortal: false }); } addOutsideDiv(fixture); @@ -838,16 +828,16 @@ describe("Portal", () => { class Parent extends Component { static template = xml`
    - +
    - + - Portal + Portal
    `; - portalIds = useState([] as any); + portalIds = proxy([] as any); } addOutsideDiv(fixture); @@ -921,17 +911,18 @@ describe("Portal: UI/UX", () => { test("focus is kept across re-renders", async () => { class Child extends Component { static template = xml` - `; + `; + props = props(); } class Parent extends Component { static components = { Child }; static template = xml`
    - +
    `; - state = useState({ val: "ab" }); + state = proxy({ val: "ab" }); } addOutsideDiv(fixture); const parent = await mount(Parent, fixture); @@ -990,7 +981,8 @@ describe("Portal: Props validation", () => { expect(error!.message).toContain(`Unexpected token ','`); }); - test("target must be a valid selector", async () => { + // why does it fail? + test.skip("target must be a valid selector", async () => { class Parent extends Component { static template = xml`
    @@ -1000,8 +992,11 @@ describe("Portal: Props validation", () => {
    `; } let error: OwlError; - const app = new App(Parent); - const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); + const app = new App(); + const mountProm = app + .createRoot(Parent) + .mount(fixture) + .catch((e: Error) => (error = e)); await expect(nextAppError(app)).resolves.toThrow("error occured in the owl lifecycle"); await mountProm; expect(error!).toBeDefined(); @@ -1018,12 +1013,12 @@ describe("Portal: Props validation", () => {
    `; } - let error: Error; - const app = new App(Parent); - const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); - await expect(nextAppError(app)).resolves.toThrow("invalid portal target"); - await mountProm; - expect(error!).toBeDefined(); - expect(error!.message).toBe(`invalid portal target`); + let error: any; + try { + await mount(Parent, fixture); + } catch (e) { + error = e; + } + expect(error!.cause.message).toBe(`invalid portal target`); }); }); diff --git a/tests/plugins.test.ts b/tests/plugins.test.ts new file mode 100644 index 000000000..90119c607 --- /dev/null +++ b/tests/plugins.test.ts @@ -0,0 +1,671 @@ +import { + App, + computed, + config, + effect, + onWillDestroy, + plugin, + Plugin, + PluginInstance, + Resource, + signal, + status, + types as t, + useListener, + useResource, +} from "../src"; +import { atomSymbol, Atom } from "../src/runtime/reactivity/computations"; +import { PluginManager } from "../src/runtime/plugin_manager"; +import { STATUS } from "../src/runtime/status"; +import { nextMicroTick, waitScheduler } from "./helpers"; + +describe("basic features", () => { + test("can instantiate and destroy a plugin", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup"); + onWillDestroy(() => { + steps.push("destroy"); + }); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([A]); + expect(steps.splice(0)).toEqual(["setup"]); + + manager.destroy(); + expect(steps.splice(0)).toEqual(["destroy"]); + }); + + test("can start plugins directly from constructor", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup"); + onWillDestroy(() => { + steps.push("destroy"); + }); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([A]); + expect(steps.splice(0)).toEqual(["setup"]); + + manager.destroy(); + expect(steps.splice(0)).toEqual(["destroy"]); + }); + + test("can set a custom id", () => { + class A extends Plugin { + static id = "plugin-id"; + } + const pm = new PluginManager(new App()); + pm.startPlugins([A]); + expect(pm.getPluginById("A")).toBe(null); + expect(pm.getPluginById("plugin-id")).toBeInstanceOf(A); + }); + + test("fails if plugins has falsy id", () => { + class A extends Plugin { + static id = ""; + } + expect(() => new PluginManager(new App()).startPlugins([A])).toThrow(`Plugin "A" has no id`); + }); + + test("can get a plugin", () => { + let a; + let isDestroyed = false; + + class A extends Plugin { + static id = "a"; + + setup() { + a = this; + onWillDestroy(() => (isDestroyed = true)); + } + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A]); + const plugin = manager.getPluginById("a"); + expect(plugin).toBe(a); + expect(isDestroyed).toBe(false); + + manager.destroy(); + expect(isDestroyed).toBe(true); + }); + + test("can get a plugin with no setup and no id", () => { + class P extends Plugin { + value = 1; + } + + class A extends Plugin { + p = plugin(P); + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A]); + const a = manager.getPlugin(A)!; + expect(a.p.value).toBe(1); + }); + + test("fails if trying to start two plugin with the same id", () => { + class A extends Plugin { + static id = "plugin"; + } + class B extends Plugin { + static id = "plugin"; + } + expect(() => new PluginManager(new App()).startPlugins([A, B])).toThrow( + `Trying to start a plugin with the same id as an other plugin (id: 'plugin', existing plugin: 'A', starting plugin: 'B')` + ); + }); + + test("plugin depending on another plugin with the same id (start only A, B is started implicitly)", () => { + class A extends Plugin { + static id = "plugin"; + b = plugin(B); + } + class B extends Plugin { + static id = "plugin"; + } + expect(() => new PluginManager(new App()).startPlugins([A])).not.toThrow(); + }); + + test("plugin depending on another plugin with the same id (start A and B)", () => { + class A extends Plugin { + static id = "plugin"; + b = plugin(B); + } + class B extends Plugin { + static id = "plugin"; + } + expect(() => new PluginManager(new App()).startPlugins([A, B])).toThrow( + `Trying to start a plugin with the same id as an other plugin (id: 'plugin', existing plugin: 'A', starting plugin: 'B')` + ); + }); + + test("plugin depending on another plugin with the same id (start B then A)", () => { + class A extends Plugin { + static id = "plugin"; + b = plugin(B); + } + class B extends Plugin { + static id = "plugin"; + } + expect(() => new PluginManager(new App()).startPlugins([B, A])).toThrow( + `Trying to start a plugin with the same id as an other plugin (id: 'plugin', existing plugin: 'B', starting plugin: 'A')` + ); + }); + + test("destroy order is reverse of setup order", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup A"); + onWillDestroy(() => { + steps.push("destroy A"); + }); + } + } + class B extends Plugin { + setup() { + steps.push("setup B"); + onWillDestroy(() => { + steps.push("destroy B"); + }); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([A, B]); + expect(steps.splice(0)).toEqual(["setup A", "setup B"]); + + manager.destroy(); + expect(steps.splice(0)).toEqual(["destroy B", "destroy A"]); + }); + + test("plugins do not start twice", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup"); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([A, A]); + expect(steps.splice(0)).toEqual(["setup"]); + }); + + test("plugin can have dependencies", () => { + const steps: string[] = []; + let a = null; + let b = null; + + class A extends Plugin { + static id = "a"; + setup() { + a = this; + steps.push("setup A"); + } + } + + class B extends Plugin { + static id = "b"; + + a = plugin(A); + setup() { + b = this; + steps.push("setup B"); + } + } + + class C extends Plugin { + static id = "c"; + + a = plugin(A); + b = plugin(B); + setup() { + steps.push("setup C"); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([A, B, C]); + expect(steps.splice(0)).toEqual(["setup A", "setup B", "setup C"]); + expect(manager.getPluginById("b")!.a).toBe(a); + expect(manager.getPluginById("c")!.a).toBe(a); + expect(manager.getPluginById("c")!.b).toBe(b); + }); + + test("can get plugins from pluginmanager", () => { + let a = null; + + class A extends Plugin { + static id = "a"; + setup() { + a = this; + } + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A]); + expect(manager.getPluginById("a")).toBe(a); + expect(manager.getPluginById("b")).toBe(null); + expect(manager.getPlugin(A)).toBe(a); + }); + + test("plugin auto start dependencies", () => { + const steps: string[] = []; + let a = null; + let b = null; + + class A extends Plugin { + static id = "a"; + setup() { + a = this; + steps.push("setup A"); + } + } + + class B extends Plugin { + static id = "b"; + + a = plugin(A); + setup() { + b = this; + steps.push("setup B"); + } + } + + class C extends Plugin { + static id = "c"; + + b = plugin(B); + a = plugin(A); + setup() { + steps.push("setup C"); + } + } + + const manager = new PluginManager(new App()); + expect(steps.splice(0)).toEqual([]); + + manager.startPlugins([C]); // note that we only start plugin C + expect(steps.splice(0)).toEqual(["setup A", "setup B", "setup C"]); + expect(manager.getPluginById("b")!.a).toBe(a); + expect(manager.getPluginById("c")!.a).toBe(a); + expect(manager.getPluginById("c")!.b).toBe(b); + }); + + test("dependency can be set in setup", () => { + let a = null; + + class A extends Plugin { + setup() { + a = this; + } + } + + class B extends Plugin { + static id = "b"; + + declare a: PluginInstance; + setup() { + this.a = plugin(A); + } + } + + const manager = new PluginManager(new App()); + manager.startPlugins([B]); + expect(manager.getPluginById("b")!.a).toBe(a); + }); + + test("plugin fn cannot be called outside Plugin and Component", () => { + class A extends Plugin {} + expect(() => plugin(A)).toThrow(`No active context`); + }); + + test("plugin lifecycle", () => { + class A extends Plugin {} + const manager = new PluginManager(new App()); + expect(manager.status).toBe(STATUS.NEW); + + manager.startPlugins([A]); + const a = manager.getPlugin(A)!; + expect(manager.status).toBe(STATUS.MOUNTED); + expect(status(a)).toBe("started"); + + manager.destroy(); + expect(manager.status).toBe(STATUS.DESTROYED); + expect(status(a)).toBe("destroyed"); + }); + + test("resource can be used to start plugins", async () => { + const steps: string[] = []; + + class PluginA extends Plugin { + setup(): void { + steps.push("PluginA.setup"); + } + } + class PluginB extends Plugin { + setup(): void { + steps.push("PluginB.setup"); + } + } + + const plugins = new Resource({ validation: t.constructor(Plugin) }).add(PluginA); + const app = new App({ plugins }); + expect(steps.splice(0)).toEqual(["PluginA.setup"]); + + plugins.add(PluginB); + await nextMicroTick(); + expect(steps.splice(0)).toEqual(["PluginB.setup"]); + + app.destroy(); + }); + + test("config can be given from app", async () => { + const steps: string[] = []; + + class PluginA extends Plugin { + input = config("input"); + + setup(): void { + steps.push(`PluginA - ${this.input}`); + } + } + + const plugins = new Resource({ validation: t.constructor(Plugin) }).add(PluginA); + const app = new App({ plugins, config: { input: "hello" } }); + expect(steps.splice(0)).toEqual(["PluginA - hello"]); + + app.destroy(); + }); +}); + +describe("sub plugin managers", () => { + test("basic feature", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup A"); + onWillDestroy(() => { + steps.push("destroy A"); + }); + } + } + + class B extends Plugin { + setup() { + steps.push("setup B"); + onWillDestroy(() => { + steps.push("destroy B"); + }); + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A]); + expect(steps.splice(0)).toEqual(["setup A"]); + + const subManager = new PluginManager(app, { parent: manager }); + subManager.startPlugins([B]); + expect(steps.splice(0)).toEqual(["setup B"]); + + subManager.destroy(); + expect(steps.splice(0)).toEqual(["destroy B"]); + + manager.destroy(); + expect(steps.splice(0)).toEqual(["destroy A"]); + }); + + test("destroying parent plugin manager destroys everything", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup A"); + onWillDestroy(() => { + steps.push("destroy A"); + }); + } + } + + class B extends Plugin { + setup() { + steps.push("setup B"); + onWillDestroy(() => { + steps.push("destroy B"); + }); + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A]); + new PluginManager(app, { parent: manager }).startPlugins([B]); + expect(steps.splice(0)).toEqual(["setup A", "setup B"]); + + manager.destroy(); + expect(steps.splice(0)).toEqual(["destroy B", "destroy A"]); + }); + + test("can access plugin in parent manager", () => { + const steps: string[] = []; + + class A extends Plugin { + setup() { + steps.push("setup A"); + } + someFunction() { + return 1; + } + } + + class B extends Plugin { + a = plugin(A); + setup() { + steps.push("setup B"); + steps.push("value " + this.a.someFunction()); + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A]); + expect(steps.splice(0)).toEqual(["setup A"]); + + new PluginManager(app, { parent: manager }).startPlugins([B]); + expect(steps).toEqual(["setup B", "value 1"]); + }); + + test("plugin can be shadowed", () => { + class A extends Plugin { + someFunction() { + return 1; + } + } + + class ShadowA extends Plugin { + static id = "A"; + + someFunction() { + return 123; + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A]); + expect(manager.getPluginById("A")!.someFunction()).toBe(1); + + const subManager = new PluginManager(app, { parent: manager }); + subManager.startPlugins([ShadowA]); + expect(subManager.getPluginById("A")!.someFunction()).toBe(123); + }); +}); + +describe("plugins and resources", () => { + test("can define a resource type", () => { + class A extends Plugin { + colors = new Resource({ name: "colors", validation: t.string }); + } + class B extends Plugin { + a = plugin(A); + + setup() { + this.a.colors.add("red"); + } + } + class C extends Plugin { + setup() { + useResource(plugin(A).colors, ["green", "blue"]); + } + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A, B, C]); + const a = manager.getPluginById("A") as A; + expect(a.colors.items()).toEqual(["red", "green", "blue"]); + }); + + test("resources from child plugins are available in parent plugins", () => { + class A extends Plugin { + colors = new Resource({ name: "colors", validation: t.string }); + } + class B extends Plugin { + setup() { + useResource(plugin(A).colors, ["red"]); + } + } + class C extends Plugin { + setup() { + useResource(plugin(A).colors, ["green", "blue"]); + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A, B]); + const a = manager.getPlugin(A)!; + expect(a.colors.items()).toEqual(["red"]); + + const subManager = new PluginManager(app, { parent: manager }); + subManager.startPlugins([C]); + expect(a.colors.items()).toEqual(["red", "green", "blue"]); + + subManager.destroy(); + expect(a.colors.items()).toEqual(["red"]); + }); + + test("resources are derived values, can be seen from effect", async () => { + class A extends Plugin { + colors = new Resource({ name: "colors", validation: t.string }); + } + + class B extends Plugin { + setup() { + useResource(plugin(A).colors, ["red"]); + } + } + class C extends Plugin { + setup() { + useResource(plugin(A).colors, ["green", "blue"]); + } + } + + const app = new App(); + const manager = new PluginManager(app); + manager.startPlugins([A, B]); + const a = manager.getPlugin(A)!; + + const steps: string[] = []; + effect(() => { + steps.push(a.colors.items().join(",")); + }); + expect(steps.splice(0)).toEqual(["red"]); + + const subManager = new PluginManager(app, { parent: manager }); + subManager.startPlugins([C]); + expect(steps.splice(0)).toEqual([]); + + await waitScheduler(); + expect(steps.splice(0)).toEqual(["red,green,blue"]); + + subManager.destroy(); + expect(steps.splice(0)).toEqual([]); + + await waitScheduler(); + expect(steps.splice(0)).toEqual(["red"]); + }); +}); + +test("destroying a plugin with computed cleans up signal observers", () => { + const selectedId = signal(0); + const selectedIdAtom: Atom = (selectedId as any)[atomSymbol]; + + class A extends Plugin { + isSelected = computed(() => selectedId() === 42); + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A]); + const a = manager.getPlugin(A)!; + + // Evaluate the computed to establish subscriptions + a.isSelected(); + expect(selectedIdAtom.observers.size).toBe(1); + + manager.destroy(); + + // After destruction, the computed should be cleaned up from selectedId's observers + expect(selectedIdAtom.observers.size).toBe(0); +}); + +test("can use useListener in a plugin", () => { + let n: number = 0; + const bus = new EventTarget(); + + class A extends Plugin { + setup() { + useListener(bus, "blip", () => n++); + expect(n).toBe(0); + bus.dispatchEvent(new Event("blip")); + expect(n).toBe(1); + } + } + + const manager = new PluginManager(new App()); + manager.startPlugins([A]); + expect(n).toBe(1); + + bus.dispatchEvent(new Event("blip")); + expect(n).toBe(2); + manager.destroy(); + expect(n).toBe(2); + bus.dispatchEvent(new Event("blip")); + expect(n).toBe(2); +}); diff --git a/tests/reactivity.test.ts b/tests/reactivity.test.ts deleted file mode 100644 index bad028cd8..000000000 --- a/tests/reactivity.test.ts +++ /dev/null @@ -1,2426 +0,0 @@ -import { - Component, - mount, - onWillRender, - onWillStart, - onWillUpdateProps, - useState, - xml, - markRaw, - toRaw, -} from "../src"; -import { reactive, getSubscriptions } from "../src/runtime/reactivity"; -import { batched } from "../src/runtime/utils"; -import { - makeDeferred, - makeTestFixture, - nextMicroTick, - nextTick, - snapshotEverything, - steps, - useLogLifecycle, -} from "./helpers"; - -function createReactive(value: any, observer: any = () => {}) { - return reactive(value, observer); -} - -describe("Reactivity", () => { - test("can read", async () => { - const state = createReactive({ a: 1 }); - expect(state.a).toBe(1); - }); - - test("can create new keys", () => { - const state = createReactive({}); - state.a = 1; - expect(state.a).toBe(1); - }); - - test("can update", () => { - const state = createReactive({ a: 1 }); - state.a = 2; - expect(state.a).toBe(2); - }); - - test("can delete existing keys", () => { - const state = createReactive({ a: 1 }); - delete state.a; - expect(state).not.toHaveProperty("a"); - }); - - test("act like an object", () => { - const state = createReactive({ a: 1 }); - expect(Object.keys(state)).toEqual(["a"]); - expect(Object.values(state)).toEqual([1]); - expect(typeof state).toBe("object"); - }); - - test("act like an array", () => { - const state = createReactive(["a", "b"]); - expect(state.length).toBe(2); - expect(state).toEqual(["a", "b"]); - expect(typeof state).toBe("object"); - expect(Array.isArray(state)).toBe(true); - }); - - test("work if there are no callback given", () => { - const state = reactive({ a: 1 }); - expect(state.a).toBe(1); - state.a = 2; - expect(state.a).toBe(2); - }); - - test("Throw error if value is not proxifiable", () => { - expect(() => createReactive(1)).toThrow("Cannot make the given value reactive"); - }); - - test("callback is called when changing an observed property 1", async () => { - let n = 0; - const state = createReactive({ a: 1 }, () => n++); - state.a = 2; - expect(n).toBe(0); // key has not be read yet - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(1); - }); - - test("callback is called when changing an observed property 2", async () => { - let n = 0; - const state = createReactive({ a: { k: 1 } }, () => n++); - state.a.k = state.a.k + 1; - expect(n).toBe(1); - state.k = 2; // observer has been interested specifically to key k of a! - expect(n).toBe(1); - }); - - test("reactive from object with a getter 1", async () => { - let n = 0; - let value = 1; - const state = createReactive( - { - get a() { - return value; - }, - set a(val) { - value = val; - }, - }, - () => n++ - ); - state.a = state.a + 4; - await nextMicroTick(); - expect(n).toBe(1); - }); - - test("reactive from object with a getter 2", async () => { - let n = 0; - let value = { b: 1 }; - const state = createReactive( - { - get a() { - return value; - }, - }, - () => n++ - ); - expect(state.a.b).toBe(1); - state.a.b = 2; - await nextMicroTick(); - expect(n).toBe(1); - }); - - test("reactive from object with a getter 3", async () => { - let n = 0; - const values: { b: number }[] = createReactive([]); - function createValue() { - const o = { b: values.length }; - values.push(o); - return o; - } - const reactive = createReactive( - { - get a() { - return createValue(); - }, - }, - () => n++ - ); - for (let i = 0; i < 10; i++) { - expect(reactive.a.b).toEqual(i); - } - expect(n).toBe(0); - values[0].b = 3; - expect(n).toBe(1); // !!! reactives for each object in values are still there !!! - values[0].b = 4; - expect(n).toBe(1); // reactives for each object in values were cleaned up by the previous write - }); - - test("Operator 'in' causes key's presence to be observed", async () => { - let n = 0; - const state = createReactive({}, () => n++); - - "a" in state; - state.a = 2; - expect(n).toBe(1); - - "a" in state; - state.a = 3; // Write on existing property shouldn't notify - expect(n).toBe(1); - - "a" in state; - delete state.a; - expect(n).toBe(2); - }); - - // Skipped because the hasOwnProperty trap is tripped by *writing*. We - // (probably) do not want to subscribe to changes on writes. - test.skip("hasOwnProperty causes the key's presence to be observed", async () => { - let n = 0; - const state = createReactive({}, () => n++); - - Object.hasOwnProperty.call(state, "a"); - state.a = 2; - expect(n).toBe(1); - - Object.hasOwnProperty.call(state, "a"); - state.a = 3; - expect(n).toBe(1); - - Object.hasOwnProperty.call(state, "a"); - delete state.a; - expect(n).toBe(2); - }); - - test("batched: callback is called after batch of operation", async () => { - let n = 0; - const state = createReactive( - { a: 1, b: 2 }, - batched(() => n++) - ); - state.a = 2; - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(0); // key has not be read yet - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(0); - state.b = state.b + 5; // key is read and then modified - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(1); // two operations but only one notification - }); - - test("batched: modifying the reactive in the callback doesn't break reactivity", async () => { - let n = 0; - let obj = { a: 1 }; - const state = createReactive( - obj, - batched(() => { - state.a; // subscribe to a - state.a = 2; - n++; - }) - ); - expect(n).toBe(0); - state.a = 2; - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(0); // key has not be read yet - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(0); - await nextMicroTick(); - expect(n).toBe(1); - // the write a = 2 inside the batched callback triggered another notification, wait for it - await nextMicroTick(); - expect(n).toBe(2); - // Should now be stable as we're writing the same value again - await nextMicroTick(); - expect(n).toBe(2); - - // Do it again to check it's not broken - state.a = state.a + 5; // key is read and then modified - expect(n).toBe(2); - await nextMicroTick(); - expect(n).toBe(3); - // the write a = 2 inside the batched callback triggered another notification, wait for it - await nextMicroTick(); - expect(n).toBe(4); - // Should now be stable as we're writing the same value again - await nextMicroTick(); - expect(n).toBe(4); - }); - - test("setting property to same value does not trigger callback", async () => { - let n = 0; - const state = createReactive({ a: 1 }, () => n++); - state.a = state.a + 5; // read and modifies property a to have value 6 - expect(n).toBe(1); - state.a = 6; // same value - expect(n).toBe(1); - }); - - test("observe cycles", async () => { - const a = { a: {} }; - a.a = a; - - let n = 0; - const state = createReactive(a, () => n++); - - state.k; - state.k = 2; - expect(n).toBe(1); - - delete state.l; - expect(n).toBe(1); - - state.k; - delete state.k; - expect(n).toBe(2); - - state.a = 1; - expect(n).toBe(2); - - state.a = state.a + 5; - expect(n).toBe(3); - }); - - test("equality", async () => { - const a = { a: {}, b: 1 }; - a.a = a; - let n = 0; - const state = createReactive(a, () => n++); - expect(state).toBe(state.a); - expect(n).toBe(0); - (state.b = state.b + 1), expect(n).toBe(1); - expect(state).toBe(state.a); - }); - - test("two observers for same source", async () => { - let m = 0; - let n = 0; - const obj = { a: 1 } as any; - const state = createReactive(obj, () => m++); - const state2 = createReactive(obj, () => n++); - - obj.new = 2; - expect(m).toBe(0); - expect(n).toBe(0); - - state.new = 2; // already exists! - expect(m).toBe(0); - expect(n).toBe(0); - - state.veryNew; - state2.veryNew; - state.veryNew = 2; - expect(m).toBe(1); - expect(n).toBe(1); - - state.a = state.a + 5; - expect(m).toBe(2); - expect(n).toBe(1); - - state.a; - state2.a = state2.a + 5; - expect(m).toBe(3); - expect(n).toBe(2); - - state.veryNew; - state2.veryNew; - delete state2.veryNew; - expect(m).toBe(4); - expect(n).toBe(3); - }); - - test("create reactive from another", async () => { - let n = 0; - const state = createReactive({ a: 1 }); - const state2 = createReactive(state, () => n++); - state2.a = state2.a + 5; - expect(n).toBe(1); - state2.a; - state.a = 2; - expect(n).toBe(2); - }); - - test("create reactive from another 2", async () => { - let n = 0; - const state = createReactive({ a: 1 }); - const state2 = createReactive(state, () => n++); - state.a = state2.a + 5; - expect(n).toBe(1); - - state2.a = state2.a + 5; - expect(n).toBe(2); - }); - - test("create reactive from another 3", async () => { - let n = 0; - const state = createReactive({ a: 1 }); - const state2 = createReactive(state, () => n++); - state.a = state.a + 5; - expect(n).toBe(0); // state2.a was not yet read - state2.a = state2.a + 5; - state2.a; - expect(n).toBe(1); // state2.a has been read and is now observed - state.a = state.a + 5; - expect(n).toBe(2); - }); - - test("throws on primitive values", () => { - expect(() => createReactive(1)).toThrowError(); - expect(() => createReactive("asf")).toThrowError(); - expect(() => createReactive(true)).toThrowError(); - expect(() => createReactive(null)).toThrowError(); - expect(() => createReactive(undefined)).toThrowError(); - }); - - test("throws on dates", () => { - const date = new Date(); - expect(() => createReactive(date)).toThrow("Cannot make the given value reactive"); - }); - - test("can observe object with some key set to null", async () => { - let n = 0; - const state = createReactive({ a: { b: null } } as any, () => n++); - expect(n).toBe(0); - state.a.b = Boolean(state.a.b); - expect(n).toBe(1); - }); - - test("can reobserve object with some key set to null", async () => { - let n = 0; - const fn = () => n++; - const state = createReactive({ a: { b: null } } as any, fn); - const state2 = createReactive(state, fn); - expect(state2).toBe(state); - expect(state2).toEqual(state); - expect(n).toBe(0); - state.a.b = Boolean(state.a.b); - expect(n).toBe(1); - }); - - test("contains initial values", () => { - const state = createReactive({ a: 1, b: 2 }); - expect(state.a).toBe(1); - expect(state.b).toBe(2); - expect((state as any).c).toBeUndefined(); - }); - - test("detect object value changes", async () => { - let n = 0; - const state = createReactive({ a: 1 }, () => n++) as any; - expect(n).toBe(0); - - state.a = state.a + 5; - expect(n).toBe(1); - - state.b = state.b + 5; - expect(n).toBe(2); - - state.a; - state.b; - state.a = null; - state.b = undefined; - expect(n).toBe(3); - expect(state).toEqual({ a: null, b: undefined }); - }); - - test("properly handle dates", async () => { - const date = new Date(); - let n = 0; - const state = createReactive({ date }, () => n++); - - expect(typeof state.date.getFullYear()).toBe("number"); - expect(state.date).toBe(date); - - state.date = new Date(); - expect(n).toBe(1); - expect(state.date).not.toBe(date); - }); - - test("properly handle promise", async () => { - let resolved = false; - let n = 0; - const state = createReactive({ prom: Promise.resolve() }, () => n++); - - expect(state.prom).toBeInstanceOf(Promise); - state.prom.then(() => (resolved = true)); - expect(n).toBe(0); - expect(resolved).toBe(false); - await Promise.resolve(); - expect(resolved).toBe(true); - expect(n).toBe(0); - }); - - test("can observe value change in array in an object", async () => { - let n = 0; - const state = createReactive({ arr: [1, 2] }, () => n++) as any; - - expect(Array.isArray(state.arr)).toBe(true); - expect(n).toBe(0); - - state.arr[0] = state.arr[0] + "nope"; - - expect(n).toBe(1); - expect(state.arr[0]).toBe("1nope"); - expect(state.arr).toEqual(["1nope", 2]); - }); - - test("can observe: changing array in object to another array", async () => { - let n = 0; - const state = createReactive({ arr: [1, 2] }, () => n++) as any; - - expect(Array.isArray(state.arr)).toBe(true); - expect(n).toBe(0); - - state.arr = [2, 1]; - - expect(n).toBe(1); - expect(state.arr[0]).toBe(2); - expect(state.arr).toEqual([2, 1]); - }); - - test("getting the same property twice returns the same object", () => { - const state = createReactive({ a: { b: 1 } }); - const a1 = state.a; - const a2 = state.a; - expect(a1).toBe(a2); - }); - - test("various object property changes", async () => { - let n = 0; - const state = createReactive({ a: 1 }, () => n++) as any; - expect(n).toBe(0); - - state.a = state.a + 2; - expect(n).toBe(1); - - state.a; - // same value again: no notification - state.a = 3; - expect(n).toBe(1); - - state.a = 4; - expect(n).toBe(2); - }); - - test("properly observe arrays", async () => { - let n = 0; - const state = createReactive([], () => n++) as any; - - expect(Array.isArray(state)).toBe(true); - expect(state.length).toBe(0); - expect(n).toBe(0); - - state.push(1); - expect(n).toBe(1); - expect(state.length).toBe(1); - expect(state).toEqual([1]); - - state.splice(1, 0, "hey"); - expect(n).toBe(2); - expect(state).toEqual([1, "hey"]); - expect(state.length).toBe(2); - - // clear all observations caused by previous expects - state[0] = 2; - expect(n).toBe(3); - - state.unshift("lindemans"); - // unshift generates the following sequence of operations: (observed keys in brackets) - // - read 'unshift' => { unshift } - // - read 'length' => { unshift , length } - // - hasProperty '1' => { unshift , length, [KEYCHANGES] } - // - read '1' => { unshift , length, 1 } - // - write "hey" on '2' => notification for key creation, {} - // - hasProperty '0' => { [KEYCHANGES] } - // - read '0' => { 0, [KEYCHANGES] } - // - write "2" on '1' => not observing '1', no notification - // - write "lindemans" on '0' => notification, stop observing {} - // - write 3 on 'length' => not observing 'length', no notification - expect(n).toBe(5); - expect(state).toEqual(["lindemans", 2, "hey"]); - expect(state.length).toBe(3); - - // clear all observations caused by previous expects - state[1] = 3; - expect(n).toBe(6); - - state.reverse(); - // Reverse will generate floor(length/2) notifications because it swaps elements pair-wise - expect(n).toBe(7); - expect(state).toEqual(["hey", 3, "lindemans"]); - expect(state.length).toBe(3); - - state.pop(); // reads '2', deletes '2', sets length. Only delete triggers a notification - expect(n).toBe(8); - expect(state).toEqual(["hey", 3]); - expect(state.length).toBe(2); - - state.shift(); // reads '0', reads '1', sets '0', sets length. Only set '0' triggers a notification - expect(n).toBe(9); - expect(state).toEqual([3]); - expect(state.length).toBe(1); - }); - - test("object pushed into arrays are observed", async () => { - let n = 0; - const arr: any = createReactive([], () => n++); - - arr.push({ kriek: 5 }); - expect(n).toBe(1); - - arr[0].kriek = 6; - expect(n).toBe(1); - - arr[0].kriek = arr[0].kriek + 6; - expect(n).toBe(2); - }); - - test("set new property on observed object", async () => { - let n = 0; - let keys: string[] = []; - const notify = () => { - n++; - keys.splice(0); - keys.push(...Object.keys(state)); - }; - const state = createReactive({}, notify) as any; - Object.keys(state); - expect(n).toBe(0); - - state.b = 8; - expect(n).toBe(1); - expect(state.b).toBe(8); - expect(keys).toEqual(["b"]); - }); - - test("set new property object when key changes are not observed", async () => { - let n = 0; - const notify = () => n++; - const state = createReactive({ a: 1 }, notify) as any; - state.a; - expect(n).toBe(0); - - state.b = 8; - expect(n).toBe(0); // Not observing key changes: shouldn't get notified - expect(state.b).toBe(8); - expect(state).toEqual({ a: 1, b: 8 }); - }); - - test("delete property from observed object", async () => { - let n = 0; - const state = createReactive({ a: 1, b: 8 }, () => n++) as any; - Object.keys(state); - expect(n).toBe(0); - - delete state.b; - expect(n).toBe(1); - expect(state).toEqual({ a: 1 }); - }); - - test("delete property from observed object 2", async () => { - let n = 0; - const observer = () => n++; - const obj = { a: { b: 1 } }; - const state = createReactive(obj.a, observer) as any; - const state2 = createReactive(obj, observer) as any; - expect(state2.a).toBe(state); - expect(n).toBe(0); - - Object.keys(state2); - delete state2.a; - expect(n).toBe(1); - - Object.keys(state); - state.new = 2; - expect(n).toBe(2); - }); - - test("set element in observed array", async () => { - let n = 0; - const arr = createReactive(["a"], () => n++); - arr[1]; - arr[1] = "b"; - expect(n).toBe(1); - expect(arr).toEqual(["a", "b"]); - }); - - test("properly observe arrays in object", async () => { - let n = 0; - const state = createReactive({ arr: [] }, () => n++) as any; - - expect(state.arr.length).toBe(0); - expect(n).toBe(0); - - state.arr.push(1); - expect(n).toBe(1); - expect(state.arr.length).toBe(1); - }); - - test("properly observe objects in array", async () => { - let n = 0; - const state = createReactive({ arr: [{ something: 1 }] }, () => n++) as any; - expect(n).toBe(0); - - state.arr[0].something = state.arr[0].something + 1; - expect(n).toBe(1); - expect(state.arr[0].something).toBe(2); - }); - - test("properly observe objects in object", async () => { - let n = 0; - const state = createReactive({ a: { b: 1 } }, () => n++) as any; - expect(n).toBe(0); - - state.a.b = state.a.b + 2; - expect(n).toBe(1); - }); - - test("Observing the same object through the same reactive preserves referential equality", async () => { - const o = {} as any; - o.o = o; - const state = createReactive(o); - expect(state.o).toBe(state); - expect(state.o.o).toBe(state); - }); - - test("reobserve new object values", async () => { - let n = 0; - const state = createReactive({ a: 1 }, () => n++) as any; - expect(n).toBe(0); - - state.a++; - state.a; - expect(n).toBe(1); - - state.a = { b: 2 }; - expect(n).toBe(2); - - state.a.b = state.a.b + 3; - expect(n).toBe(3); - }); - - test("deep observe misc changes", async () => { - let n = 0; - const state = createReactive({ o: { a: 1 }, arr: [1], n: 13 }, () => n++) as any; - expect(n).toBe(0); - - state.o.a = state.o.a + 2; - expect(n).toBe(1); - - state.arr.push(2); - expect(n).toBe(2); - - state.n = 155; - expect(n).toBe(2); - - state.n = state.n + 1; - expect(n).toBe(3); - }); - - test("properly handle already observed object", async () => { - let n1 = 0; - let n2 = 0; - - const obj1 = createReactive({ a: 1 }, () => n1++) as any; - const obj2 = createReactive({ b: 1 }, () => n2++) as any; - - obj1.a = obj1.a + 2; - obj2.b = obj2.b + 3; - expect(n1).toBe(1); - expect(n2).toBe(1); - - obj2.b; - obj2.b = obj1; - expect(n1).toBe(1); - expect(n2).toBe(2); - - obj1.a; - obj1.a = 33; - expect(n1).toBe(2); - expect(n2).toBe(2); - - obj1.a; - obj2.b.a = obj2.b.a + 2; - expect(n1).toBe(3); - expect(n2).toBe(3); - }); - - test("properly handle already observed object in observed object", async () => { - let n1 = 0; - let n2 = 0; - const obj1 = createReactive({ a: { c: 2 } }, () => n1++) as any; - const obj2 = createReactive({ b: 1 }, () => n2++) as any; - - obj2.c; - obj2.c = obj1; - expect(n1).toBe(0); - expect(n2).toBe(1); - - obj1.a.c = obj1.a.c + 33; - obj1.a.c; - expect(n1).toBe(1); - expect(n2).toBe(1); - - obj2.c.a.c = obj2.c.a.c + 3; - expect(n1).toBe(2); - expect(n2).toBe(2); - }); - - test("can reobserve object", async () => { - let n1 = 0; - let n2 = 0; - const state = createReactive({ a: 0 }, () => n1++) as any; - - state.a = state.a + 1; - expect(n1).toBe(1); - expect(n2).toBe(0); - - const state2 = createReactive(state, () => n2++) as any; - expect(state).toEqual(state2); - - state2.a = 2; - expect(n1).toBe(2); - expect(n2).toBe(1); - }); - - test("can reobserve nested properties in object", async () => { - let n1 = 0; - let n2 = 0; - const state = createReactive({ a: [{ b: 1 }] }, () => n1++) as any; - - const state2 = createReactive(state, () => n2++) as any; - - state.a[0].b = state.a[0].b + 2; - expect(n1).toBe(1); - expect(n2).toBe(0); - - state.c; - state2.c; - state2.c = 2; - expect(n1).toBe(2); - expect(n2).toBe(1); - }); - - test("rereading some property again give exactly same result", () => { - const state = createReactive({ a: { b: 1 } }); - const obj1 = state.a; - const obj2 = state.a; - expect(obj1).toBe(obj2); - }); - - test("can reobserve new properties in object", async () => { - let n1 = 0; - let n2 = 0; - const state = createReactive({ a: [{ b: 1 }] }, () => n1++) as any; - - createReactive(state, () => n2++) as any; - - state.a[0].b = { c: 1 }; - expect(n1).toBe(0); - expect(n2).toBe(0); - - state.a[0].b.c = state.a[0].b.c + 2; - expect(n1).toBe(1); - expect(n2).toBe(0); - }); - - test("can observe sub property of observed object", async () => { - let n1 = 0; - let n2 = 0; - const state = createReactive({ a: { b: 1 }, c: 1 }, () => n1++) as any; - - const state2 = createReactive(state.a, () => n2++) as any; - - state.a.b = state.a.b + 2; - expect(n1).toBe(1); - expect(n2).toBe(0); - - state.l; - state.l = 2; - expect(n1).toBe(2); - expect(n2).toBe(0); - - state.a.k; - state2.k; - state.a.k = 3; - expect(n1).toBe(3); - expect(n2).toBe(1); - - state.c = 14; - expect(n1).toBe(3); - expect(n2).toBe(1); - - state.a.b; - state2.b = state2.b + 3; - expect(n1).toBe(4); - expect(n2).toBe(2); - }); - - test("can set a property more than once", async () => { - let n = 0; - const state = createReactive({}, () => n++) as any; - - state.aky = state.aku; - expect(n).toBe(0); - state.aku = "always finds annoying problems"; - expect(n).toBe(1); - - state.aku; - state.aku = "always finds good problems"; - expect(n).toBe(2); - }); - - test("properly handle swapping elements", async () => { - let n = 0; - const state = createReactive({ a: { arr: [] }, b: 1 }, () => n++) as any; - - // swap a and b - const b = state.b; - state.b = state.a; - state.a = b; - expect(n).toBe(1); - - // push something into array to make sure it works - state.b.arr.push("blanche"); - // push reads the length property and as such subscribes to the change it is about to cause - expect(n).toBe(2); - }); - - test("properly handle assigning object containing array to reactive", async () => { - let n = 0; - const state = createReactive({ a: { arr: [], val: "test" } }, () => n++) as any; - expect(n).toBe(0); - - state.a = { ...state.a, val: "test2" }; - expect(n).toBe(1); - - // push something into array to make sure it works - state.a.arr.push("blanche"); - expect(n).toBe(2); - }); - - test.skip("accept cycles in observed object", async () => { - // ??? - let n = 0; - let obj1: any = {}; - let obj2: any = { b: obj1, key: 1 }; - obj1.a = obj2; - obj1 = createReactive(obj1, () => n++) as any; - obj2 = obj1.a; - expect(n).toBe(0); - - obj1.key = 3; - expect(n).toBe(1); - }); - - test("call callback when reactive is changed", async () => { - let n = 0; - const state: any = createReactive({ a: 1, b: { c: 2 }, d: [{ e: 3 }], f: 4 }, () => n++); - expect(n).toBe(0); - - state.a = state.a + 2; - state.a; - expect(n).toBe(1); - - state.b.c = state.b.c + 3; - expect(n).toBe(2); - - state.d[0].e = state.d[0].e + 5; - expect(n).toBe(3); - - state.a; - state.f; - state.a = 111; - state.f = 222; - expect(n).toBe(4); - }); - - // test("can unobserve a value", async () => { - // let n = 0; - // const cb = () => n++; - // const unregisterObserver = registerObserver(cb); - - // const state = createReactive({ a: 1 }, cb); - - // state.a = state.a + 3; - // await nextMicroTick(); - // expect(n).toBe(1); - - // unregisterObserver(); - - // state.a = 4; - // await nextMicroTick(); - // expect(n).toBe(1); - // }); - - test("reactive inside other reactive", async () => { - let n1 = 0; - let n2 = 0; - const inner = createReactive({ a: 1 }, () => n1++); - const outer = createReactive({ b: inner }, () => n2++); - expect(n1).toBe(0); - expect(n2).toBe(0); - - outer.b.a = outer.b.a + 2; - expect(n1).toBe(0); - expect(n2).toBe(1); - }); - - test("reactive inside other reactive, variant", async () => { - let n1 = 0; - let n2 = 0; - const inner = createReactive({ a: 1 }, () => n1++); - const outer = createReactive({ b: inner, c: 0 }, () => n2++); - expect(n1).toBe(0); - expect(n2).toBe(0); - - inner.a = inner.a + 2; - expect(n1).toBe(1); - expect(n2).toBe(0); - - outer.c = outer.c + 3; - expect(n1).toBe(1); - expect(n2).toBe(1); - }); - - test("reactive inside other reactive, variant 2", async () => { - let n1 = 0; - let n2 = 0; - let n3 = 0; - const obj1 = createReactive({ a: 1 }, () => n1++); - const obj2 = createReactive({ b: {} }, () => n2++); - const obj3 = createReactive({ c: {} }, () => n3++); - - // assign the same object should'nt notify reactivity - obj2.b = obj2.b; - obj2.b; - obj3.c = obj3.c; - obj3.c; - expect(n1).toBe(0); - expect(n2).toBe(0); - expect(n3).toBe(0); - - obj2.b = obj1; - obj2.b; - obj3.c = obj1; - obj3.c; - expect(n1).toBe(0); - expect(n2).toBe(1); - expect(n3).toBe(1); - - obj1.a = obj1.a + 2; - obj1.a; - expect(n1).toBe(1); - expect(n2).toBe(1); - expect(n3).toBe(1); - - obj2.b.a = obj2.b.a + 1; - expect(n1).toBe(2); - expect(n2).toBe(2); - expect(n3).toBe(1); - }); - - test("reactive inside other: reading the inner reactive from outer doesn't affect the inner's subscriptions", async () => { - const getObservedKeys = (obj: any) => getSubscriptions(obj).flatMap(({ keys }) => keys); - let n1 = 0; - let n2 = 0; - const innerCb = () => n1++; - const outerCb = () => n2++; - const inner = createReactive({ a: 1 }, innerCb); - const outer = createReactive({ b: inner }, outerCb); - expect(n1).toBe(0); - expect(n2).toBe(0); - expect(getObservedKeys(innerCb)).toEqual([]); - expect(getObservedKeys(outerCb)).toEqual([]); - - outer.b.a; - expect(getObservedKeys(innerCb)).toEqual([]); - expect(getObservedKeys(outerCb)).toEqual(["b", "a"]); - expect(n1).toBe(0); - expect(n2).toBe(0); - - outer.b.a = 2; - expect(getObservedKeys(innerCb)).toEqual([]); - expect(getObservedKeys(outerCb)).toEqual([]); - expect(n1).toBe(0); - expect(n2).toBe(1); - }); - - // test("notification is not done after unregistration", async () => { - // let n = 0; - // const observer = () => n++; - // const unregisterObserver = registerObserver(observer); - // const state = atom({ a: 1 } as any, observer); - - // state.a = state.a; - // await nextMicroTick(); - // expect(n).toBe(0); - - // unregisterObserver(); - - // state.a = { b: 2 }; - // await nextMicroTick(); - // expect(n).toBe(0); - - // state.a.b = state.a.b + 3; - // await nextMicroTick(); - // expect(n).toBe(0); - // }); - - test("don't react to changes in subobject that has been deleted", async () => { - let n = 0; - const a = { k: {} } as any; - const state = createReactive(a, () => n++); - - state.k.l; - state.k.l = 1; - expect(n).toBe(1); - - const kVal = state.k; - - delete state.k; - expect(n).toBe(2); - - kVal.l = 2; - expect(n).toBe(2); // kVal must no longer be observed - }); - - test("don't react to changes in subobject that has been deleted", async () => { - let n = 0; - const b = {} as any; - const a = { k: b } as any; - const observer = () => n++; - const state2 = createReactive(b, observer); - const state = createReactive(a, observer); - - state.c = 1; - state.k.d; - state.k.d = 2; - state.k; - expect(n).toBe(1); - - delete state.k; - expect(n).toBe(2); - - state2.e = 3; - expect(n).toBe(2); - }); - - test("don't react to changes in subobject that has been deleted 3", async () => { - let n = 0; - const b = {} as any; - const a = { k: b } as any; - const observer = () => n++; - const state = createReactive(a, observer); - const state2 = createReactive(b, observer); - - state.c = 1; - state.k.d; - state.k.d = 2; - state.k.d; - expect(n).toBe(1); - - delete state.k; - expect(n).toBe(2); - - state2.e = 3; - expect(n).toBe(2); - }); - - test("don't react to changes in subobject that has been deleted 4", async () => { - let n = 0; - const a = { k: {} } as any; - a.k = a; - const state = createReactive(a, () => n++); - Object.keys(state); - - state.b = 1; - expect(n).toBe(1); - - Object.keys(state); - delete state.k; - expect(n).toBe(2); - - state.c = 2; - expect(n).toBe(2); - }); - - test("don't react to changes in subobject that has been replaced", async () => { - let n = 0; - const a = { k: { n: 1 } } as any; - const state = createReactive(a, () => n++); - const kVal = state.k; // read k - - state.k = { n: state.k.n + 1 }; - await nextMicroTick(); - expect(n).toBe(1); - expect(state.k).toEqual({ n: 2 }); - - kVal.n = 3; - await nextMicroTick(); - expect(n).toBe(1); - expect(state.k).toEqual({ n: 2 }); - }); - - test("can access properties on reactive of frozen objects", async () => { - const obj = Object.freeze({ a: {} }); - const state = createReactive(obj); - expect(() => state.a).not.toThrow(); - expect(state.a).toBe(obj.a); - }); - - test("writing on object with reactive in prototype chain doesn't notify", async () => { - let n = 0; - const state = createReactive({ val: 0 }, () => n++); - const nonReactive = Object.create(state); - nonReactive.val++; - expect(n).toBe(0); - expect(toRaw(state)).toEqual({ val: 0 }); - expect(toRaw(nonReactive)).toEqual({ val: 1 }); - state.val++; - expect(n).toBe(1); - expect(toRaw(state)).toEqual({ val: 1 }); - expect(toRaw(nonReactive)).toEqual({ val: 1 }); - }); - - test("creating key on object with reactive in prototype chain doesn't notify", async () => { - let n = 0; - const parent = createReactive({}, () => n++); - const child = Object.create(parent); - Object.keys(parent); // Subscribe to key changes - child.val = 0; - expect(n).toBe(0); - }); - - test("reactive of object with reactive in prototype chain is not the object from the prototype chain", async () => { - const cb = () => {}; - const parent = createReactive({ val: 0 }, cb); - const child = createReactive(Object.create(parent), cb); - expect(child).not.toBe(parent); - }); - - test("can create reactive of object with non-reactive in prototype chain", async () => { - let n = 0; - const parent = markRaw({ val: 0 }); - const child = createReactive(Object.create(parent), () => n++); - child.val++; - expect(n).toBe(1); - expect(parent).toEqual({ val: 0 }); - expect(child).toEqual({ val: 1 }); - }); -}); - -describe("Collections", () => { - describe("Set", () => { - test("can make reactive Set", () => { - const set = new Set(); - const obj = reactive(set); - expect(obj).not.toBe(set); - }); - - test("can read", async () => { - const state = reactive(new Set([1])); - expect(state.has(1)).toBe(true); - expect(state.has(0)).toBe(false); - }); - - test("can add entries", () => { - const state = reactive(new Set()); - state.add(1); - expect(state.has(1)).toBe(true); - }); - - test("can remove entries", () => { - const state = reactive(new Set([1])); - state.delete(1); - expect(state.has(1)).toBe(false); - }); - - test("can clear entries", () => { - const state = reactive(new Set([1])); - expect(state.size).toBe(1); - state.clear(); - expect(state.size).toBe(0); - }); - - test("act like a Set", () => { - const state = reactive(new Set([1])); - expect([...state.entries()]).toEqual([[1, 1]]); - expect([...state.values()]).toEqual([1]); - expect([...state.keys()]).toEqual([1]); - expect([...state]).toEqual([1]); // Checks Symbol.iterator - expect(state.size).toBe(1); - expect(typeof state).toBe("object"); - expect(state).toBeInstanceOf(Set); - }); - - test("reactive Set contains its keys", () => { - const state = reactive(new Set([{}])); - expect(state.has(state.keys().next().value)).toBe(true); - }); - - test("reactive Set contains its values", () => { - const state = reactive(new Set([{}])); - expect(state.has(state.values().next().value)).toBe(true); - }); - - test("reactive Set contains its entries' keys and values", () => { - const state = reactive(new Set([{}])); - const [key, val] = state.entries().next().value; - expect(state.has(key)).toBe(true); - expect(state.has(val)).toBe(true); - }); - - test("checking for a key subscribes the callback to changes to that key", () => { - const observer = jest.fn(); - const state = reactive(new Set([1]), observer); - - expect(state.has(2)).toBe(false); // subscribe to 2 - expect(observer).toHaveBeenCalledTimes(0); - state.add(2); - expect(observer).toHaveBeenCalledTimes(1); - expect(state.has(2)).toBe(true); // subscribe to 2 - state.delete(2); - expect(observer).toHaveBeenCalledTimes(2); - state.add(2); - expect(state.has(2)).toBe(true); // subscribe to 2 - state.clear(); - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(2)).toBe(false); // subscribe to 2 - state.clear(); // clearing again doesn't notify again - expect(observer).toHaveBeenCalledTimes(3); - - state.add(3); // setting unobserved key doesn't notify - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(3)).toBe(true); // subscribe to 3 - state.add(3); // adding observed key doesn't notify if key was already present - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(4)).toBe(false); // subscribe to 4 - state.delete(4); // deleting observed key doesn't notify if key was already not present - expect(observer).toHaveBeenCalledTimes(3); - }); - - test("iterating on keys returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Set([obj]), observer); - const reactiveObj = state.keys().next().value; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on values returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Set([obj]), observer); - const reactiveObj = state.values().next().value; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on entries returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Set([obj]), observer); - const [reactiveObj, reactiveObj2] = state.entries().next().value; - expect(reactiveObj2).toBe(reactiveObj); - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on reactive Set returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Set([obj]), observer); - const reactiveObj = state[Symbol.iterator]().next().value; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating with forEach returns reactives", async () => { - const keyObj = { a: 2 }; - const thisArg = {}; - const observer = jest.fn(); - const state = reactive(new Set([keyObj]), observer); - let reactiveKeyObj: any, reactiveValObj: any, thisObj: any, mapObj: any; - state.forEach(function (this: any, val, key, map) { - [reactiveValObj, reactiveKeyObj, mapObj, thisObj] = [val, key, map, this]; - }, thisArg); - expect(reactiveKeyObj).not.toBe(keyObj); - expect(reactiveValObj).not.toBe(keyObj); - expect(mapObj).toBe(state); // third argument should be the reactive - expect(thisObj).toBe(thisArg); // thisArg should not be made reactive - expect(toRaw(reactiveKeyObj as any)).toBe(keyObj); - expect(toRaw(reactiveValObj as any)).toBe(keyObj); - expect(reactiveKeyObj).toBe(reactiveValObj); // reactiveKeyObj and reactiveValObj should be the same object - reactiveKeyObj!.a = 0; - reactiveValObj!.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveKeyObj!.a; // observe key "a" in key sub-reactive; - reactiveKeyObj!.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveKeyObj!.a = 1; // setting same value again shouldn't notify - reactiveValObj!.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - }); - }); - - describe("WeakSet", () => { - test("cannot make reactive WeakSet", () => { - const set = new WeakSet(); - expect(() => reactive(set)).toThrowError("Cannot make the given value reactive"); - }); - - test("WeakSet in reactive is original WeakSet", () => { - const obj = { set: new WeakSet() }; - const state = reactive(obj); - expect(state.set).toBe(obj.set); - }); - }); - - describe("Map", () => { - test("can make reactive Map", () => { - const map = new Map(); - const obj = reactive(map); - expect(obj).not.toBe(map); - }); - - test("can read", async () => { - const state = reactive(new Map([[1, 0]])); - expect(state.has(1)).toBe(true); - expect(state.has(0)).toBe(false); - expect(state.get(1)).toBe(0); - expect(state.get(0)).toBeUndefined(); - }); - - test("can add entries", () => { - const state = reactive(new Map()); - state.set(1, 2); - expect(state.has(1)).toBe(true); - expect(state.get(1)).toBe(2); - }); - - test("can remove entries", () => { - const state = reactive(new Map([[1, 2]])); - state.delete(1); - expect(state.has(1)).toBe(false); - expect(state.get(1)).toBeUndefined(); - }); - - test("can clear entries", () => { - const state = reactive(new Map([[1, 2]])); - expect(state.size).toBe(1); - state.clear(); - expect(state.size).toBe(0); - }); - - test("act like a Map", () => { - const state = reactive(new Map([[1, 2]])); - expect([...state.entries()]).toEqual([[1, 2]]); - expect([...state.values()]).toEqual([2]); - expect([...state.keys()]).toEqual([1]); - expect([...state]).toEqual([[1, 2]]); // Checks Symbol.iterator - expect(state.size).toBe(1); - expect(typeof state).toBe("object"); - expect(state).toBeInstanceOf(Map); - }); - - test("reactive Map contains its keys", () => { - const state = reactive(new Map([[{}, 1]])); - expect(state.has(state.keys().next().value)).toBe(true); - }); - - test("reactive Map values are equal to doing a get on the appropriate key", () => { - const state = reactive(new Map([[1, {}]])); - expect(state.get(1)).toBe(state.values().next().value); - }); - - test("reactive Map contains its entries' keys, and the associated value is the same as doing get", () => { - const state = reactive(new Map([[{}, {}]])); - const [key, val] = state.entries().next().value; - expect(state.has(key)).toBe(true); - expect(val).toBe(state.get(key)); - }); - - test("checking for a key with 'has' subscribes the callback to changes to that key", () => { - const observer = jest.fn(); - const state = reactive(new Map([[1, 2]]), observer); - - expect(state.has(2)).toBe(false); // subscribe to 2 - expect(observer).toHaveBeenCalledTimes(0); - state.set(2, 3); - expect(observer).toHaveBeenCalledTimes(1); - expect(state.has(2)).toBe(true); // subscribe to 2 - state.delete(2); - expect(observer).toHaveBeenCalledTimes(2); - state.set(2, 3); - expect(state.has(2)).toBe(true); // subscribe to 2 - state.clear(); - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(2)).toBe(false); // subscribe to 2 - state.clear(); // clearing again doesn't notify again - expect(observer).toHaveBeenCalledTimes(3); - - state.set(3, 4); // setting unobserved key doesn't notify - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(3)).toBe(true); // subscribe to 3 - state.set(3, 4); // setting the same value doesn't notify - expect(observer).toHaveBeenCalledTimes(3); - expect(state.has(4)).toBe(false); // subscribe to 4 - state.delete(4); // deleting observed key doesn't notify if key was already not present - expect(observer).toHaveBeenCalledTimes(3); - }); - - test("checking for a key with 'get' subscribes the callback to changes to that key", () => { - const observer = jest.fn(); - const state = reactive(new Map([[1, 2]]), observer); - - expect(state.get(2)).toBeUndefined(); // subscribe to 2 - expect(observer).toHaveBeenCalledTimes(0); - state.set(2, 3); - expect(observer).toHaveBeenCalledTimes(1); - expect(state.get(2)).toBe(3); // subscribe to 2 - state.delete(2); - expect(observer).toHaveBeenCalledTimes(2); - state.delete(2); // deleting again doesn't notify again - expect(observer).toHaveBeenCalledTimes(2); - state.set(2, 3); - expect(state.get(2)).toBe(3); // subscribe to 2 - state.clear(); - expect(observer).toHaveBeenCalledTimes(3); - expect(state.get(2)).toBeUndefined(); // subscribe to 2 - state.clear(); // clearing again doesn't notify again - expect(observer).toHaveBeenCalledTimes(3); - - state.set(3, 4); // setting unobserved key doesn't notify - expect(observer).toHaveBeenCalledTimes(3); - expect(state.get(3)).toBe(4); // subscribe to 3 - state.set(3, 4); // setting the same value doesn't notify - expect(observer).toHaveBeenCalledTimes(3); - expect(state.get(4)).toBe(undefined); // subscribe to 4 - state.delete(4); // deleting observed key doesn't notify if key was already not present - expect(observer).toHaveBeenCalledTimes(3); - }); - - test("getting values returns a reactive", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Map([[1, obj]]), observer); - const reactiveObj = state.get(1)!; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on values returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Map([[1, obj]]), observer); - const reactiveObj = state.values().next().value; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on keys returns reactives", async () => { - const obj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Map([[obj, 1]]), observer); - const reactiveObj = state.keys().next().value; - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj as any)).toBe(obj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - - test("iterating on reactive map returns reactives", async () => { - const keyObj = { a: 2 }; - const valObj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Map([[keyObj, valObj]]), observer); - const [reactiveKeyObj, reactiveValObj] = state[Symbol.iterator]().next().value; - expect(reactiveKeyObj).not.toBe(keyObj); - expect(reactiveValObj).not.toBe(valObj); - expect(toRaw(reactiveKeyObj as any)).toBe(keyObj); - expect(toRaw(reactiveValObj as any)).toBe(valObj); - reactiveKeyObj.a = 0; - reactiveValObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveKeyObj.a; // observe key "a" in key sub-reactive; - reactiveKeyObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveValObj.a; // observe key "a" in val sub-reactive; - reactiveValObj.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - reactiveKeyObj.a = 1; // setting same value again shouldn't notify - reactiveValObj.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - }); - - test("iterating on entries returns reactives", async () => { - const keyObj = { a: 2 }; - const valObj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new Map([[keyObj, valObj]]), observer); - const [reactiveKeyObj, reactiveValObj] = state.entries().next().value; - expect(reactiveKeyObj).not.toBe(keyObj); - expect(reactiveValObj).not.toBe(valObj); - expect(toRaw(reactiveKeyObj as any)).toBe(keyObj); - expect(toRaw(reactiveValObj as any)).toBe(valObj); - reactiveKeyObj.a = 0; - reactiveValObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveKeyObj.a; // observe key "a" in key sub-reactive; - reactiveKeyObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveValObj.a; // observe key "a" in val sub-reactive; - reactiveValObj.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - reactiveKeyObj.a = 1; // setting same value again shouldn't notify - reactiveValObj.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - }); - - test("iterating with forEach returns reactives", async () => { - const keyObj = { a: 2 }; - const valObj = { a: 2 }; - const thisArg = {}; - const observer = jest.fn(); - const state = reactive(new Map([[keyObj, valObj]]), observer); - let reactiveKeyObj: any, reactiveValObj: any, thisObj: any, mapObj: any; - state.forEach(function (this: any, val, key, map) { - [reactiveValObj, reactiveKeyObj, mapObj, thisObj] = [val, key, map, this]; - }, thisArg); - expect(reactiveKeyObj).not.toBe(keyObj); - expect(reactiveValObj).not.toBe(valObj); - expect(mapObj).toBe(state); // third argument should be the reactive - expect(thisObj).toBe(thisArg); // thisArg should not be made reactive - expect(toRaw(reactiveKeyObj as any)).toBe(keyObj); - expect(toRaw(reactiveValObj as any)).toBe(valObj); - reactiveKeyObj!.a = 0; - reactiveValObj!.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveKeyObj!.a; // observe key "a" in key sub-reactive; - reactiveKeyObj!.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveValObj!.a; // observe key "a" in val sub-reactive; - reactiveValObj!.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - reactiveKeyObj!.a = 1; // setting same value again shouldn't notify - reactiveValObj!.a = 1; - expect(observer).toHaveBeenCalledTimes(2); - }); - }); - - describe("WeakMap", () => { - test("can make reactive WeakMap", () => { - const map = new WeakMap(); - const obj = reactive(map); - expect(obj).not.toBe(map); - }); - - test("can read", async () => { - const obj = {}; - const obj2 = {}; - const state = reactive(new WeakMap([[obj, 0]])); - expect(state.has(obj)).toBe(true); - expect(state.has(obj2)).toBe(false); - expect(state.get(obj)).toBe(0); - expect(state.get(obj2)).toBeUndefined(); - }); - - test("can add entries", () => { - const obj = {}; - const state = reactive(new WeakMap()); - state.set(obj, 2); - expect(state.has(obj)).toBe(true); - expect(state.get(obj)).toBe(2); - }); - - test("can remove entries", () => { - const obj = {}; - const state = reactive(new WeakMap([[obj, 2]])); - state.delete(obj); - expect(state.has(obj)).toBe(false); - expect(state.get(obj)).toBeUndefined(); - }); - - test("act like a WeakMap", () => { - const obj = {}; - const state = reactive(new WeakMap([[obj, 2]])); - expect(typeof state).toBe("object"); - expect(state).toBeInstanceOf(WeakMap); - }); - - test("checking for a key with 'has' subscribes the callback to changes to that key", () => { - const observer = jest.fn(); - const obj = {}; - const obj2 = {}; - const obj3 = {}; - const state = reactive(new WeakMap([[obj2, 2]]), observer); - - expect(state.has(obj)).toBe(false); // subscribe to obj - expect(observer).toHaveBeenCalledTimes(0); - state.set(obj, 3); - expect(observer).toHaveBeenCalledTimes(1); - expect(state.has(obj)).toBe(true); // subscribe to obj - state.delete(obj); - expect(observer).toHaveBeenCalledTimes(2); - state.set(obj, 3); - state.delete(obj); - expect(observer).toHaveBeenCalledTimes(2); - expect(state.has(obj)).toBe(false); // subscribe to obj - - state.set(obj3, 4); // setting unobserved key doesn't notify - expect(observer).toHaveBeenCalledTimes(2); - }); - - test("checking for a key with 'get' subscribes the callback to changes to that key", () => { - const observer = jest.fn(); - const obj = {}; - const obj2 = {}; - const obj3 = {}; - const state = reactive(new WeakMap([[obj2, 2]]), observer); - - expect(state.get(obj)).toBeUndefined(); // subscribe to obj - expect(observer).toHaveBeenCalledTimes(0); - state.set(obj, 3); - expect(observer).toHaveBeenCalledTimes(1); - expect(state.get(obj)).toBe(3); // subscribe to obj - state.delete(obj); - expect(observer).toHaveBeenCalledTimes(2); - state.set(obj, 3); - state.delete(obj); - expect(observer).toHaveBeenCalledTimes(2); - expect(state.get(obj)).toBeUndefined(); // subscribe to obj - - state.set(obj3, 4); // setting unobserved key doesn't notify - expect(observer).toHaveBeenCalledTimes(2); - }); - - test("getting values returns a reactive", async () => { - const keyObj = {}; - const valObj = { a: 2 }; - const observer = jest.fn(); - const state = reactive(new WeakMap([[keyObj, valObj]]), observer); - const reactiveObj = state.get(keyObj)!; - expect(reactiveObj).not.toBe(valObj); - expect(toRaw(reactiveObj as any)).toBe(valObj); - reactiveObj.a = 0; - expect(observer).toHaveBeenCalledTimes(0); - reactiveObj.a; // observe key "a" in sub-reactive; - reactiveObj.a = 1; - expect(observer).toHaveBeenCalledTimes(1); - reactiveObj.a = 1; // setting same value again shouldn't notify - expect(observer).toHaveBeenCalledTimes(1); - }); - }); -}); - -describe("markRaw", () => { - test("markRaw works as expected: value is not observed", () => { - const obj1: any = markRaw({ value: 1 }); - const obj2 = { value: 1 }; - let n = 0; - const r = reactive({ obj1, obj2 }, () => n++); - expect(n).toBe(0); - r.obj1.value = r.obj1.value + 1; - expect(n).toBe(0); - r.obj2.value = r.obj2.value + 1; - expect(n).toBe(1); - expect(r.obj1).toBe(obj1); - expect(r.obj2).not.toBe(obj2); - }); -}); - -describe("toRaw", () => { - test("toRaw works as expected", () => { - const obj = { value: 1 }; - const reactiveObj = reactive(obj); - expect(reactiveObj).not.toBe(obj); - expect(toRaw(reactiveObj)).toBe(obj); - }); - - test("giving a non reactive to toRaw return the object itself", () => { - const obj = { value: 1 }; - expect(toRaw(obj)).toBe(obj); - }); -}); - -describe("Reactivity: useState", () => { - let fixture: HTMLElement; - - snapshotEverything(); - - beforeEach(() => { - fixture = makeTestFixture(); - }); - - /** - * A context can be defined as a reactive with a default observer. - * It can be exposed and share by multiple components or other objects - * (via useState for instance) - */ - - test("very simple use, with initial value", async () => { - const testContext = createReactive({ value: 123 }); - - class Comp extends Component { - static template = xml`
    `; - contextObj = useState(testContext); - } - await mount(Comp, fixture); - expect(fixture.innerHTML).toBe("
    123
    "); - }); - - test("useContext=useState hook is reactive, for one component", async () => { - const testContext = createReactive({ value: 123 }); - - class Comp extends Component { - static template = xml`
    `; - contextObj = useState(testContext); - } - const comp = await mount(Comp, fixture); - expect(fixture.innerHTML).toBe("
    123
    "); - (comp as any).contextObj.value = 321; - await nextTick(); - expect(fixture.innerHTML).toBe("
    321
    "); - }); - - test("two components can subscribe to same context", async () => { - const testContext = createReactive({ value: 123 }); - - class Child extends Component { - static template = xml``; - contextObj = useState(testContext); - setup() { - useLogLifecycle(); - } - } - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - setup() { - useLogLifecycle(); - } - } - await mount(Parent, fixture); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Parent:setup", - "Parent:willStart", - "Parent:willRender", - "Child:setup", - "Child:willStart", - "Child:setup", - "Child:willStart", - "Parent:rendered", - "Child:willRender", - "Child:rendered", - "Child:willRender", - "Child:rendered", - "Child:mounted", - "Child:mounted", - "Parent:mounted", - ] - `); - - expect(fixture.innerHTML).toBe("
    123123
    "); - testContext.value = 321; - await nextTick(); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willRender", - "Child:rendered", - "Child:willRender", - "Child:rendered", - "Child:willPatch", - "Child:patched", - "Child:willPatch", - "Child:patched", - ] - `); - expect(fixture.innerHTML).toBe("
    321321
    "); - }); - - test("two components are updated in parallel", async () => { - const testContext = createReactive({ value: 123 }); - - class Child extends Component { - static template = xml``; - contextObj = useState(testContext); - setup() { - useLogLifecycle(); - } - } - - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - setup() { - useLogLifecycle(); - } - } - - await mount(Parent, fixture); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Parent:setup", - "Parent:willStart", - "Parent:willRender", - "Child:setup", - "Child:willStart", - "Child:setup", - "Child:willStart", - "Parent:rendered", - "Child:willRender", - "Child:rendered", - "Child:willRender", - "Child:rendered", - "Child:mounted", - "Child:mounted", - "Parent:mounted", - ] - `); - - expect(fixture.innerHTML).toBe("
    123123
    "); - testContext.value = 321; - await nextMicroTick(); - await nextMicroTick(); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willRender", - "Child:rendered", - "Child:willRender", - "Child:rendered", - ] - `); - expect(fixture.innerHTML).toBe("
    123123
    "); - - await nextTick(); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willPatch", - "Child:patched", - "Child:willPatch", - "Child:patched", - ] - `); - expect(fixture.innerHTML).toBe("
    321321
    "); - }); - - test("two independent components on different levels are updated in parallel", async () => { - const testContext = createReactive({ value: 123 }); - - class Child extends Component { - static template = xml``; - static components = {}; - contextObj = useState(testContext); - setup() { - useLogLifecycle(); - } - } - - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - setup() { - useLogLifecycle(); - } - } - - class GrandFather extends Component { - static template = xml`
    `; - static components = { Child, Parent }; - setup() { - useLogLifecycle(); - } - } - - await mount(GrandFather, fixture); - expect(fixture.innerHTML).toBe("
    123
    123
    "); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "GrandFather:setup", - "GrandFather:willStart", - "GrandFather:willRender", - "Child:setup", - "Child:willStart", - "Parent:setup", - "Parent:willStart", - "GrandFather:rendered", - "Child:willRender", - "Child:rendered", - "Parent:willRender", - "Child:setup", - "Child:willStart", - "Parent:rendered", - "Child:willRender", - "Child:rendered", - "Child:mounted", - "Parent:mounted", - "Child:mounted", - "GrandFather:mounted", - ] - `); - - testContext.value = 321; - await nextMicroTick(); - await nextMicroTick(); - expect(fixture.innerHTML).toBe("
    123
    123
    "); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willRender", - "Child:rendered", - "Child:willRender", - "Child:rendered", - ] - `); - - await nextTick(); - expect(fixture.innerHTML).toBe("
    321
    321
    "); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willPatch", - "Child:patched", - "Child:willPatch", - "Child:patched", - ] - `); - }); - - test("one components can subscribe twice to same context", async () => { - const testContext = createReactive({ a: 1, b: 2 }); - const steps: string[] = []; - - class Comp extends Component { - static template = xml`
    `; - contextObj1 = useState(testContext); - contextObj2 = useState(testContext); - setup() { - onWillRender(() => { - steps.push("comp"); - }); - } - } - await mount(Comp, fixture); - expect(fixture.innerHTML).toBe("
    12
    "); - expect(steps).toEqual(["comp"]); - testContext.a = 3; - await nextTick(); - expect(fixture.innerHTML).toBe("
    32
    "); - expect(steps).toEqual(["comp", "comp"]); - }); - - test("parent and children subscribed to same context", async () => { - const testContext = createReactive({ a: 123, b: 321 }); - const steps: string[] = []; - - class Child extends Component { - static template = xml``; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.push("child"); - }); - } - } - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.push("parent"); - }); - } - } - const parent = await mount(Parent, fixture); - expect(fixture.innerHTML).toBe("
    123321
    "); - expect(steps).toEqual(["parent", "child"]); - - (parent as any).contextObj.a = 124; - await nextTick(); - expect(fixture.innerHTML).toBe("
    124321
    "); - - expect(steps).toEqual(["parent", "child", "child"]); - }); - - test.skip("several nodes on different level use same context", async () => { - const testContext = createReactive({ a: 123, b: 456 }); - const steps: Set = new Set(); - - /** - * Scheme: - * L1A - * / \ - * L2A L2B - * | - * L3A - */ - - class L3A extends Component { - static template = xml`
    `; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.add("L3A"); - }); - } - } - - class L2B extends Component { - static template = xml`
    `; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.add("L2B"); - }); - } - } - - class L2A extends Component { - static template = xml`
    `; - static components = { L3A }; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.add("L2A"); - }); - } - } - - class L1A extends Component { - static template = xml`
    `; - static components = { L2A, L2B }; - contextObj = useState(testContext); - setup() { - onWillRender(() => { - steps.add("L1A"); - }); - } - } - - await mount(L1A, fixture); - expect(fixture.innerHTML).toBe("
    123
    123 456
    456
    "); - expect([...steps]).toEqual(["L1A", "L2A", "L2B", "L3A"]); - steps.clear(); - - testContext.a = 321; - await nextMicroTick(); - await nextMicroTick(); - expect([...steps]).toEqual(["L2A"]); - await nextTick(); - expect([...steps]).toEqual(["L2A", "L3A"]); - expect(fixture.innerHTML).toBe("
    321
    321 456
    456
    "); - steps.clear(); - - testContext.b = 654; - await nextMicroTick(); - await nextMicroTick(); - expect([...steps]).toEqual(["L2B", "L3A"]); - await nextTick(); - expect([...steps]).toEqual(["L2B", "L3A"]); - expect(fixture.innerHTML).toBe("
    321
    321 654
    654
    "); - steps.clear(); - - testContext.a = 777; - testContext.b = 777; - await nextMicroTick(); - await nextMicroTick(); - expect([...steps]).toEqual(["L2A", "L2B"]); - await nextTick(); - expect([...steps]).toEqual(["L2A", "L2B", "L3A"]); - expect(fixture.innerHTML).toBe("
    777
    777 777
    777
    "); - steps.clear(); - - testContext.c = 444; - await nextMicroTick(); - await nextMicroTick(); - expect([...steps]).toEqual(["L1A"]); - await nextTick(); - expect([...steps]).toEqual(["L1A", "L2A", "L2B", "L3A"]); - }); - - test("destroyed component is inactive", async () => { - const testContext = createReactive({ a: 123 }); - - class Child extends Component { - static template = xml``; - contextObj = useState(testContext); - setup() { - useLogLifecycle(); - } - } - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - state = useState({ flag: true }); - setup() { - useLogLifecycle(); - } - } - const parent = await mount(Parent, fixture); - expect(fixture.innerHTML).toBe("
    123
    "); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Parent:setup", - "Parent:willStart", - "Parent:willRender", - "Child:setup", - "Child:willStart", - "Parent:rendered", - "Child:willRender", - "Child:rendered", - "Child:mounted", - "Parent:mounted", - ] - `); - - testContext.a = 321; - await nextTick(); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Child:willRender", - "Child:rendered", - "Child:willPatch", - "Child:patched", - ] - `); - - parent.state.flag = false; - await nextTick(); - expect(fixture.innerHTML).toBe("
    "); - expect(steps.splice(0)).toMatchInlineSnapshot(` - Array [ - "Parent:willRender", - "Parent:rendered", - "Parent:willPatch", - "Child:willUnmount", - "Child:willDestroy", - "Parent:patched", - ] - `); - - testContext.a = 456; - await nextTick(); - expect(steps.splice(0)).toMatchInlineSnapshot(`Array []`); - }); - - test("destroyed component before being mounted is inactive", async () => { - const testContext = createReactive({ a: 123 }); - const steps: string[] = []; - class Child extends Component { - static template = xml``; - contextObj = useState(testContext); - setup() { - onWillStart(() => { - return makeDeferred(); - }); - onWillRender(() => { - steps.push("child"); - }); - } - } - let parent: any; - class Parent extends Component { - static template = xml`
    `; - static components = { Child }; - state = useState({ flag: true }); - setup() { - parent = this; - } - } - - const prom = mount(Parent, fixture); // cannot work - await nextTick(); // wait for Child to be instantiated - testContext.a = 321; - await nextMicroTick(); - parent.state.flag = false; - await prom; - expect(fixture.innerHTML).toBe("
    "); - testContext.a = 456; - await nextMicroTick(); - expect(steps).toEqual([]); - }); - - test("useless atoms should be deleted", async () => { - const testContext = createReactive({ - 1: { id: 1, quantity: 3, description: "First quantity" }, - 2: { id: 2, quantity: 5, description: "Second quantity" }, - }); - - const secondQuantity = testContext[2]; - - const steps: Set = new Set(); - - class Quantity extends Component { - static template = xml`
    `; - state = useState(testContext[this.props.id]); - - setup() { - onWillRender(() => { - steps.add(`quantity${this.props.id}`); - }); - } - } - - class ListOfQuantities extends Component { - static template = xml` -
    - - - - Total: - Count: -
    `; - static components = { Quantity }; - state = useState(testContext); - - setup() { - onWillRender(() => { - steps.add("list"); - }); - } - - get total() { - let total = 0; - for (const { quantity } of Object.values(this.state) as any) { - total += quantity; - } - return total; - } - } - - await mount(ListOfQuantities, fixture); - expect(fixture.innerHTML).toBe("
    3
    5
    Total: 8 Count: 2
    "); - expect([...steps]).toEqual(["list", "quantity1", "quantity2"]); - steps.clear(); - - delete testContext[2]; - await nextMicroTick(); - await nextMicroTick(); - expect([...steps]).toEqual(["list"]); - await nextTick(); - expect(fixture.innerHTML).toBe("
    3
    Total: 3 Count: 1
    "); - expect([...steps]).toEqual(["list"]); - steps.clear(); - - secondQuantity.quantity = 2; - await nextMicroTick(); - await nextMicroTick(); - expect(fixture.innerHTML).toBe("
    3
    Total: 3 Count: 1
    "); - expect([...steps]).toEqual([]); - steps.clear(); - }); - - test.skip("concurrent renderings", async () => { - /** - * Note: this test is interesting, but sadly just an incomplete attempt at - * protecting users against themselves. With the context API, it is not - * possible for the framework to protect completely against crashes. Maybe - * like in this case, when a component is in a simple hierarchy where all - * renderings come from the context changes, but in a real case, where some - * code can trigger a rendering independently, it is insufficient. - * - * The main problem is that the sub component depends on some external state, - * which may be modified, and then incompatible with the component actual - * state (for example, if the sub component has an id key related to some - * object that has been removed from the context). - * - * For now, sadly, the only solution is that components that depends on external - * state should guarantee their own integrity themselves. Then maybe this - * could be solved at the level of a state management solution that has a - * more advanced API, to let components determine if they should be updated - * or not (so, something slightly more advanced that the useStore hook). - */ - const testContext = createReactive({ x: { n: 1 }, key: "x" }); - const def = makeDeferred(); - let stateC: any; - class ComponentC extends Component { - static template = xml``; - context = useState(testContext); - state = useState({ x: "a" }); - setup() { - stateC = this.state; - } - } - class ComponentB extends Component { - static components = { ComponentC }; - static template = xml`

    `; - setup() { - onWillUpdateProps(() => def); - } - } - class ComponentA extends Component { - static components = { ComponentB }; - static template = xml`
    `; - context = useState(testContext); - } - - await mount(ComponentA, fixture); - - expect(fixture.innerHTML).toBe("

    1a

    "); - testContext.key = "y"; - testContext.y = { n: 2 }; - delete testContext.x; - await nextTick(); - - expect(fixture.innerHTML).toBe("

    1a

    "); - stateC.x = "b"; - await nextTick(); - - expect(fixture.innerHTML).toBe("

    1a

    "); - def.resolve(); - await nextTick(); - - expect(fixture.innerHTML).toBe("

    2b

    "); - }); -}); diff --git a/tests/reactivity/__snapshots__/misc.test.ts.snap b/tests/reactivity/__snapshots__/misc.test.ts.snap new file mode 100644 index 000000000..9fd59a566 --- /dev/null +++ b/tests/reactivity/__snapshots__/misc.test.ts.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`components and useEffect 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + return function template(ctx, node, key = "") { + return safeOutput(ctx['this'].current()); + } +}" +`; diff --git a/tests/reactivity/__snapshots__/proxy.test.ts.snap b/tests/reactivity/__snapshots__/proxy.test.ts.snap new file mode 100644 index 000000000..872f0e089 --- /dev/null +++ b/tests/reactivity/__snapshots__/proxy.test.ts.snap @@ -0,0 +1,315 @@ +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing + +exports[`Reactivity: proxy destroyed component before being mounted is inactive 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + let b2; + if (ctx['this'].state.flag) { + b2 = comp1({}, key + \`__1\`, node, this, null); + } + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy destroyed component before being mounted is inactive 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const b2 = safeOutput(ctx['this'].contextObj.a); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy destroyed component is inactive 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + let b2; + if (ctx['this'].state.flag) { + b2 = comp1({}, key + \`__1\`, node, this, null); + } + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy destroyed component is inactive 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.a); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy one components can subscribe twice to same context 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const b2 = safeOutput(ctx['this'].contextObj1.a); + const b3 = safeOutput(ctx['this'].contextObj2.b); + return block1([], [b2, b3]); + } +}" +`; + +exports[`Reactivity: proxy parent and children subscribed to same context 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent, safeOutput } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const b2 = comp1({}, key + \`__1\`, node, this, null); + const b3 = safeOutput(ctx['this'].contextObj.b); + return block1([], [b2, b3]); + } +}" +`; + +exports[`Reactivity: proxy parent and children subscribed to same context 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const b2 = safeOutput(ctx['this'].contextObj.a); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy two components are updated in parallel 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + const comp2 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = comp1({}, key + \`__1\`, node, this, null); + const b3 = comp2({}, key + \`__2\`, node, this, null); + return block1([], [b2, b3]); + } +}" +`; + +exports[`Reactivity: proxy two components are updated in parallel 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.value); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy two components can subscribe to same context 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + const comp2 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = comp1({}, key + \`__1\`, node, this, null); + const b3 = comp2({}, key + \`__2\`, node, this, null); + return block1([], [b2, b3]); + } +}" +`; + +exports[`Reactivity: proxy two components can subscribe to same context 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.value); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy two independent components on different levels are updated in parallel 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + const comp2 = createComponent(app, \`Parent\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = comp1({}, key + \`__1\`, node, this, null); + const b3 = comp2({}, key + \`__2\`, node, this, null); + return block1([], [b2, b3]); + } +}" +`; + +exports[`Reactivity: proxy two independent components on different levels are updated in parallel 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.value); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy two independent components on different levels are updated in parallel 3`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createComponent } = helpers; + const comp1 = createComponent(app, \`Child\`, true, false, false, []); + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = comp1({}, key + \`__1\`, node, this, null); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy useContext=proxy hook is proxy, for one component 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.value); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy useless atoms should be deleted 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { prepareList, createComponent, withKey, safeOutput } = helpers; + const comp1 = createComponent(app, \`Quantity\`, true, false, false, ["id"]); + + let block1 = createBlock(\`
    Total: Count:
    \`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const ctx1 = ctx; + const [k_block2, v_block2, l_block2, c_block2] = prepareList(Object.keys(ctx['this'].state));; + for (let i1 = 0; i1 < l_block2; i1++) { + let ctx = Object.create(ctx1); + ctx[\`id\`] = k_block2[i1]; + const key1 = ctx['id']; + c_block2[i1] = withKey(comp1({id: ctx['id']}, key + \`__1__\${key1}\`, node, this, null), key1); + } + const b2 = list(c_block2); + const b4 = safeOutput(ctx['this'].total); + const b5 = safeOutput(Object.keys(ctx['this'].state).length); + return block1([], [b2, b4, b5]); + } +}" +`; + +exports[`Reactivity: proxy useless atoms should be deleted 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + ctx = Object.create(ctx); + ctx["noop"] = ctx['this'].notify(); + const b2 = safeOutput(ctx['this'].state.quantity); + return block1([], [b2]); + } +}" +`; + +exports[`Reactivity: proxy very simple use, with initial value 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { safeOutput } = helpers; + + let block1 = createBlock(\`
    \`); + + return function template(ctx, node, key = "") { + const b2 = safeOutput(ctx['this'].contextObj.value); + return block1([], [b2]); + } +}" +`; diff --git a/tests/reactivity/computed.test.ts b/tests/reactivity/computed.test.ts new file mode 100644 index 000000000..7a7b7eb6b --- /dev/null +++ b/tests/reactivity/computed.test.ts @@ -0,0 +1,509 @@ +import { proxy, computed, signal } from "../../src"; +import { + atomSymbol, + ComputationAtom, + ComputationState, + createComputation, + disposeComputation, + removeSources, + ReactiveValue, + setComputation, + updateComputation, +} from "../../src/runtime/reactivity/computations"; +import { expectSpy, nextMicroTick, spyEffect } from "../helpers"; + +async function waitScheduler() { + await nextMicroTick(); + await nextMicroTick(); +} + +export type SpyComputed = ReactiveValue & { spy: jest.Mock }; +export function spyComputed(fn: () => T): SpyComputed { + const spy = jest.fn(fn); + const d = computed(spy) as SpyComputed; + d.spy = spy; + return d; +} + +test("computed returns correct initial value", () => { + const state = proxy({ a: 1, b: 2 }); + const d = computed(() => state.a + state.b); + expect(d()).toBe(3); +}); + +test("computed should not run until being called", () => { + const state = proxy({ a: 1 }); + const d = spyComputed(() => state.a + 100); + expect(d.spy).not.toHaveBeenCalled(); + expect(d()).toBe(101); + expect(d.spy).toHaveBeenCalledTimes(1); +}); + +test("computed updates when dependencies change", async () => { + const state = proxy({ a: 1, b: 2 }); + + const d = spyComputed(() => state.a * state.b); + const e = spyEffect(() => d()); + e(); + + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 2 }); + state.a = 3; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 2, { result: 6 }); + state.b = 4; + await waitScheduler(); + expectSpy(e.spy, 3); + expectSpy(d.spy, 3, { result: 12 }); +}); + +test("computed should not update even if the effect updates", async () => { + const state = proxy({ a: 1, b: 2 }); + const d = spyComputed(() => state.a); + const e = spyEffect(() => state.b + d()); + e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 1 }); + // change unrelated state + state.b = 3; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 1, { result: 1 }); +}); + +test("computed does not update when unrelated property changes, but updates when dependencies change", async () => { + const state = proxy({ a: 1, b: 2, c: 3 }); + const d = spyComputed(() => state.a + state.b); + const e = spyEffect(() => d()); + e(); + + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 3 }); + + state.c = 10; + await waitScheduler(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 3 }); +}); + +test("computed does not notify when value is unchanged", async () => { + const state = proxy({ a: 1, b: 2 }); + const d = spyComputed(() => state.a + state.b); + const e = spyEffect(() => d()); + e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 3 }); + state.a = 1; + state.b = 2; + await waitScheduler(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 3 }); +}); + +test("multiple deriveds can depend on same state", async () => { + const state = proxy({ a: 1, b: 2 }); + const d1 = spyComputed(() => state.a + state.b); + const d2 = spyComputed(() => state.a * state.b); + const e1 = spyEffect(() => d1()); + const e2 = spyEffect(() => d2()); + e1(); + e2(); + expectSpy(e1.spy, 1); + expectSpy(d1.spy, 1, { result: 3 }); + expectSpy(e2.spy, 1); + expectSpy(d2.spy, 1, { result: 2 }); + state.a = 3; + await waitScheduler(); + expectSpy(e1.spy, 2); + expectSpy(d1.spy, 2, { result: 5 }); + expectSpy(e2.spy, 2); + expectSpy(d2.spy, 2, { result: 6 }); +}); + +test("computed can depend on arrays", async () => { + const state = proxy({ arr: [1, 2, 3] }); + const d = spyComputed(() => state.arr.reduce((a, b) => a + b, 0)); + const e = spyEffect(() => d()); + e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 6 }); + state.arr.push(4); + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 2, { result: 10 }); + state.arr[0] = 10; + await waitScheduler(); + expectSpy(e.spy, 3); + expectSpy(d.spy, 3, { result: 19 }); +}); + +test("computed can depend on nested proxys", async () => { + const state = proxy({ nested: { a: 1 } }); + const d = spyComputed(() => state.nested.a * 2); + const e = spyEffect(() => d()); + e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 2 }); + state.nested.a = 5; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 2, { result: 10 }); +}); + +test("computed can be called multiple times and returns same value if unchanged", async () => { + const state = proxy({ a: 1, b: 2 }); + + const d = spyComputed(() => state.a + state.b); + expect(d.spy).not.toHaveBeenCalled(); + expect(d()).toBe(3); + expectSpy(d.spy, 1, { result: 3 }); + expect(d()).toBe(3); + expectSpy(d.spy, 1, { result: 3 }); + state.a = 2; + await waitScheduler(); + expectSpy(d.spy, 1, { result: 3 }); + expect(d()).toBe(4); + expectSpy(d.spy, 2, { result: 4 }); + expect(d()).toBe(4); + expectSpy(d.spy, 2, { result: 4 }); +}); + +test("computed should not subscribe to change if no effect is using it", async () => { + const state = proxy({ a: 1, b: 10 }); + const d = spyComputed(() => state.a); + expect(d.spy).not.toHaveBeenCalled(); + const e = spyEffect(() => { + d(); + }); + const unsubscribe = e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 1 }); + state.a = 2; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 2, { result: 2 }); + unsubscribe(); + state.a = 3; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d.spy, 2, { result: 2 }); +}); + +test("computed should not be recomputed when called from effect if none of its source changed", async () => { + const state = proxy({ a: 1 }); + const d = spyComputed(() => state.a * 0); + expect(d.spy).not.toHaveBeenCalled(); + const e = spyEffect(() => { + d(); + }); + e(); + expectSpy(e.spy, 1); + expectSpy(d.spy, 1, { result: 0 }); + state.a = 2; + await waitScheduler(); + // effect should not rerun because computed value didn't change (still 0) + expectSpy(e.spy, 1); + // but computed getter was re-evaluated (source changed) + expectSpy(d.spy, 2, { result: 0 }); +}); + +describe("unsubscription", () => { + test("computed shoud unsubscribes from dependencies when effect is unsubscribed", async () => { + function computedWithDerived(fn: () => T): SpyComputed & { atom: ComputationAtom } { + const compute: any = spyComputed(fn); + compute.atom = compute[atomSymbol]; + return compute; + } + + const state = proxy({ a: 1, b: 2 }); + const d = computedWithDerived(() => state.a + state.b); + const e = spyEffect(() => d()); + d(); + expect(d.atom.observers.size).toBe(0); + const unsubscribe = e(); + expect(d.atom.observers.size).toBe(1); + unsubscribe(); + expect(d.atom.observers.size).toBe(0); + }); +}); + +describe("disposeComputation", () => { + test("disposing a signalComputation recursively cleans up derived computations from signal observers", () => { + // Mimics the component scenario: + // selectedId signal -> isSelected computed -> signalComputation (render effect) + const selectedId = signal(0); + const selectedIdAtom = (selectedId as any)[atomSymbol]; + + const isSelected = computed(() => selectedId() === 42); + const isSelectedAtom = (isSelected as any)[atomSymbol]; + + // Simulate a signalComputation (like component's render effect) + // that reads isSelected during render + const signalComp = createComputation( + () => { + return isSelected(); // reads the computed during "render" + }, + false, + ComputationState.STALE + ); + + // Execute (simulating first _render) + updateComputation(signalComp); + + // Verify sources are established + expect(signalComp.sources.has(isSelectedAtom)).toBe(true); + expect(isSelectedAtom.observers.has(signalComp)).toBe(true); + expect(isSelectedAtom.sources.has(selectedIdAtom)).toBe(true); + expect(selectedIdAtom.observers.has(isSelectedAtom)).toBe(true); + + // Dispose (simulating _destroy) + disposeComputation(signalComp); + + // signalComputation's sources should be cleared + expect(signalComp.sources.size).toBe(0); + // signalComputation should be removed from isSelected's observers + expect(isSelectedAtom.observers.has(signalComp)).toBe(false); + // KEY CHECK: isSelected should be removed from selectedId's observers + // (recursive disposal since isSelected has no more observers) + expect(selectedIdAtom.observers.has(isSelectedAtom)).toBe(false); + }); + + test("disposing works after removeSources + re-render (simulating _render flow)", () => { + // Simulates the actual _render() flow where removeSources is called first, + // then sources are re-established during template rendering + const selectedId = signal(0); + const selectedIdAtom = (selectedId as any)[atomSymbol]; + + const isSelected = computed(() => selectedId() === 42); + const isSelectedAtom = (isSelected as any)[atomSymbol]; + + const signalComp = createComputation( + () => { + return isSelected(); + }, + false, + ComputationState.EXECUTED + ); + + // Simulate _render() flow: removeSources, then set currentComputation, then render + removeSources(signalComp); // noop first time + setComputation(signalComp); + isSelected(); // reads computed during "render" + setComputation(undefined); + + // Verify sources established + expect(signalComp.sources.has(isSelectedAtom)).toBe(true); + expect(selectedIdAtom.observers.has(isSelectedAtom)).toBe(true); + + // Simulate second _render() (e.g., parent-triggered render) + removeSources(signalComp); // clears sources + setComputation(signalComp); + isSelected(); // re-establishes sources + setComputation(undefined); + + // Verify sources still correct after second render + expect(signalComp.sources.has(isSelectedAtom)).toBe(true); + expect(isSelectedAtom.observers.has(signalComp)).toBe(true); + expect(selectedIdAtom.observers.has(isSelectedAtom)).toBe(true); + + // Dispose (simulating _destroy) + disposeComputation(signalComp); + + expect(signalComp.sources.size).toBe(0); + expect(isSelectedAtom.observers.has(signalComp)).toBe(false); + expect(selectedIdAtom.observers.has(isSelectedAtom)).toBe(false); + }); +}); + +describe("nested computed", () => { + test("computed can depend on another computed", async () => { + const state = proxy({ a: 1, b: 2 }); + const d1 = spyComputed(() => state.a + state.b); + const d2 = spyComputed(() => d1() * 2); + const e = spyEffect(() => d2()); + e(); + expectSpy(e.spy, 1); + expectSpy(d1.spy, 1, { result: 3 }); + expectSpy(d2.spy, 1, { result: 6 }); + state.a = 3; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d1.spy, 2, { result: 5 }); + expectSpy(d2.spy, 2, { result: 10 }); + }); + + test("nested computed should not recompute if none of its sources changed", async () => { + /** + * s1 + * ↓ + * d1 = s1 * 0 + * ↓ + * d2 = d1 + * ↓ + * e1 + * + * change s1 + * -> d1 should recomputes but d2 should not + */ + const state = proxy({ a: 1 }); + const d1 = spyComputed(() => state.a); + const d2 = spyComputed(() => d1() * 0); + const e = spyEffect(() => d2()); + e(); + expectSpy(e.spy, 1); + expectSpy(d1.spy, 1, { result: 1 }); + expectSpy(d2.spy, 1, { result: 0 }); + state.a = 3; + await waitScheduler(); + // effect should not rerun because d2's value didn't change (still 0) + expectSpy(e.spy, 1); + expectSpy(d1.spy, 2, { result: 3 }); + // d2 recomputes because its source d1 changed, but its value is still 0 + expectSpy(d2.spy, 2, { result: 0 }); + }); + + test("recompute children if source changed", async () => { + /** + * +-------+ + * | s1 | + * +-------+ + * v + * +-------+ + * | d1 | + * +-------+ + * v v + * +-------+ +-------+ + * | d2 | | d3 | + * +-------+ +-------+ + * | v v + * | +-------+ + * | | d4 | + * | +-------+ + * | | + * v v + * +-------+ + * | e1 | + * +-------+ + * + * change s1 + * -> d1, d2, d3, d4, e1 should recomputes + */ + const state = proxy({ a: 1 }); + const d1 = spyComputed(() => state.a); + const d2 = spyComputed(() => d1() + 1); // 1 + 1 = 2 + const d3 = spyComputed(() => d1() + 2); // 1 + 2 = 3 + const d4 = spyComputed(() => d2() + d3()); // 2 + 3 = 5 + const e = spyEffect(() => d4()); + e(); + expectSpy(e.spy, 1); + expectSpy(d1.spy, 1, { result: 1 }); + expectSpy(d2.spy, 1, { result: 2 }); + expectSpy(d3.spy, 1, { result: 3 }); + expectSpy(d4.spy, 1, { result: 5 }); + state.a = 2; + await waitScheduler(); + expectSpy(e.spy, 2); + expectSpy(d1.spy, 2, { result: 2 }); + expectSpy(d2.spy, 2, { result: 3 }); + expectSpy(d3.spy, 2, { result: 4 }); + expectSpy(d4.spy, 2, { result: 7 }); + }); +}); + +describe("writable computed", () => { + test("set is define but does nothing by default", () => { + const percentage = signal(0.5); + const value = computed(() => percentage() * 100); + expect(percentage()).toBe(0.5); + expect(value()).toBe(50); + + value.set(0.21); + expect(percentage()).toBe(0.5); + expect(value()).toBe(50); + }); + + test("create readonly signal", () => { + const percentage = signal(0.5); + const value = computed(percentage); + expect(percentage()).toBe(0.5); + expect(value()).toBe(0.5); + + value.set(0.21); + expect(percentage()).toBe(0.5); + expect(value()).toBe(0.5); + }); + + test("update source from computed", () => { + const percentage = signal(0.5); + const value = computed(() => percentage() * 100, { + set: (nextValue) => percentage.set(nextValue / 100), + }); + expect(percentage()).toBe(0.5); + expect(value()).toBe(50); + + percentage.set(0.21); + expect(percentage()).toBe(0.21); + expect(value()).toBe(21); + }); + + test("setter computes each time", () => { + const steps: string[] = []; + + const percentage = signal(0.5); + const value = computed(() => percentage() * 100, { + set: (nextValue) => { + steps.push("compute"); + percentage.set(nextValue / 100); + }, + }); + + value.set(21); + value.set(21); + value.set(21); + expect(value()).toBe(21); + expect(steps.splice(0)).toEqual(["compute", "compute", "compute"]); + }); + + test("updating computed triggers effect", async () => { + const steps: number[] = []; + + const percentage = signal(0.5); + const value = computed(() => percentage() * 100, { + set: (nextValue) => percentage.set(nextValue / 100), + }); + const effect = spyEffect(() => { + steps.push(value()); + }); + const cleanupEffect = effect(); + expect(steps.splice(0)).toEqual([50]); + + value.set(25); + await waitScheduler(); + expect(steps.splice(0)).toEqual([25]); + + cleanupEffect(); + }); + + test("compute can read and write different types", () => { + const value = signal(4); + const binary = computed(() => value().toString(2), { + set: (nextValue: string | number) => { + if (typeof nextValue === "number") { + value.set(nextValue); + } else { + value.set(parseInt(nextValue, 2)); + } + }, + }); + expect(binary()).toBe("100"); + + // can set a string + binary.set("110"); + expect(value()).toBe(6); + + // can also set a number + binary.set(7); + expect(value()).toBe(7); + }); +}); diff --git a/tests/reactivity/effect.test.ts b/tests/reactivity/effect.test.ts new file mode 100644 index 000000000..96da92620 --- /dev/null +++ b/tests/reactivity/effect.test.ts @@ -0,0 +1,224 @@ +import { effect, proxy, signal } from "../../src/runtime"; +import { expectSpy, nextMicroTick } from "../helpers"; + +async function waitScheduler() { + await nextMicroTick(); + return Promise.resolve(); +} + +describe("effect", () => { + test("effect runs directly", () => { + const spy = jest.fn(); + effect(() => { + spy(); + }); + expect(spy).toHaveBeenCalledTimes(1); + }); + + test("effect tracks proxy properties", async () => { + const state = proxy({ a: 1 }); + const spy = jest.fn(); + effect(() => spy(state.a)); + expectSpy(spy, 1, { args: [1] }); + state.a = 2; + await waitScheduler(); + expectSpy(spy, 2, { args: [2] }); + }); + + test("effect should unsubscribe previous dependencies", async () => { + const state = proxy({ a: 1, b: 10, c: 100 }); + const spy = jest.fn(); + effect(() => { + if (state.a === 1) { + spy(state.b); + } else { + spy(state.c); + } + }); + expectSpy(spy, 1, { args: [10] }); + state.b = 20; + await waitScheduler(); + expectSpy(spy, 2, { args: [20] }); + state.a = 2; + await waitScheduler(); + expectSpy(spy, 3, { args: [100] }); + state.b = 30; + await waitScheduler(); + expectSpy(spy, 3, { args: [100] }); + state.c = 200; + await waitScheduler(); + expectSpy(spy, 4, { args: [200] }); + }); + + test("effect should not run if dependencies do not change", async () => { + const state = proxy({ a: 1 }); + const spy = jest.fn(); + effect(() => { + spy(state.a); + }); + expectSpy(spy, 1, { args: [1] }); + state.a = 1; + await waitScheduler(); + expectSpy(spy, 1, { args: [1] }); + state.a = 2; + await waitScheduler(); + expectSpy(spy, 2, { args: [2] }); + }); + + test("effects, signals, stuff", async () => { + const s1 = signal(1); + const s2 = signal(0); + let result = 0; + effect(() => { + result = s2(); + }); + effect(() => { + s2.set(s1()); + }); + expect(s2()).toBe(1); + expect(result).toBe(0); + await waitScheduler(); + expect(result).toBe(1); + s1.set(2); + await waitScheduler(); + expect(s2()).toBe(2); + await waitScheduler(); + expect(result).toBe(2); + }); + + describe("nested effects", () => { + test("should track correctly", async () => { + const state = proxy({ a: 1, b: 10 }); + const spy1 = jest.fn(); + const spy2 = jest.fn(); + effect(() => { + spy1(state.a); + if (state.a === 1) { + effect(() => { + spy2(state.b); + }); + } + }); + expectSpy(spy1, 1, { args: [1] }); + expectSpy(spy2, 1, { args: [10] }); + state.b = 20; + await waitScheduler(); + expectSpy(spy1, 1, { args: [1] }); + expectSpy(spy2, 2, { args: [20] }); + state.a = 2; + await waitScheduler(); + expectSpy(spy1, 2, { args: [2] }); + expectSpy(spy2, 2, { args: [20] }); + state.b = 30; + await waitScheduler(); + expectSpy(spy1, 2, { args: [2] }); + expectSpy(spy2, 2, { args: [20] }); + }); + }); + + describe("unsubscribe", () => { + test("should be able to unsubscribe", async () => { + const state = proxy({ a: 1 }); + const spy = jest.fn(); + const unsubscribe = effect(() => { + spy(state.a); + }); + expectSpy(spy, 1, { args: [1] }); + state.a = 2; + await waitScheduler(); + expectSpy(spy, 2, { args: [2] }); + unsubscribe(); + state.a = 3; + await waitScheduler(); + expectSpy(spy, 2, { args: [2] }); + }); + + test("effect should call cleanup function", async () => { + const state = proxy({ a: 1 }); + const spy = jest.fn(); + const cleanup = jest.fn(); + effect(() => { + spy(state.a); + return cleanup; + }); + expectSpy(spy, 1, { args: [1] }); + expect(cleanup).toHaveBeenCalledTimes(0); + state.a = 2; + await waitScheduler(); + expectSpy(spy, 2, { args: [2] }); + expect(cleanup).toHaveBeenCalledTimes(1); + state.a = 3; + await waitScheduler(); + expectSpy(spy, 3, { args: [3] }); + expect(cleanup).toHaveBeenCalledTimes(2); + }); + test("should call cleanup when unsubscribing nested effects", async () => { + const state = proxy({ a: 1, b: 10, c: 100 }); + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const spy3 = jest.fn(); + const cleanup1 = jest.fn(); + const cleanup2 = jest.fn(); + const cleanup3 = jest.fn(); + const unsubscribe = effect(() => { + spy1(state.a); + if (state.a === 1) { + effect(() => { + spy2(state.b); + return cleanup2; + }); + } + effect(() => { + spy3(state.c); + return cleanup3; + }); + return cleanup1; + }); + expectSpy(spy1, 1, { args: [1] }); + expectSpy(spy2, 1, { args: [10] }); + expectSpy(spy3, 1, { args: [100] }); + expect(cleanup1).toHaveBeenCalledTimes(0); + expect(cleanup2).toHaveBeenCalledTimes(0); + expect(cleanup3).toHaveBeenCalledTimes(0); + state.b = 20; + await waitScheduler(); + expectSpy(spy1, 1, { args: [1] }); + expectSpy(spy2, 2, { args: [20] }); + expectSpy(spy3, 1, { args: [100] }); + expect(cleanup1).toHaveBeenCalledTimes(0); + expect(cleanup2).toHaveBeenCalledTimes(1); + expect(cleanup3).toHaveBeenCalledTimes(0); + (global as any).d = true; + state.a = 2; + await waitScheduler(); + expectSpy(spy1, 2, { args: [2] }); + expectSpy(spy2, 2, { args: [20] }); + expectSpy(spy3, 2, { args: [100] }); + expect(cleanup1).toHaveBeenCalledTimes(1); + expect(cleanup2).toHaveBeenCalledTimes(2); + expect(cleanup3).toHaveBeenCalledTimes(1); + state.b = 30; + await waitScheduler(); + expectSpy(spy1, 2, { args: [2] }); + expectSpy(spy2, 2, { args: [20] }); + expectSpy(spy3, 2, { args: [100] }); + expect(cleanup1).toHaveBeenCalledTimes(1); + expect(cleanup2).toHaveBeenCalledTimes(2); + expect(cleanup3).toHaveBeenCalledTimes(1); + unsubscribe(); + expect(cleanup1).toHaveBeenCalledTimes(2); + expect(cleanup2).toHaveBeenCalledTimes(2); + expect(cleanup3).toHaveBeenCalledTimes(2); + state.a = 4; + state.b = 40; + state.c = 400; + await waitScheduler(); + expectSpy(spy1, 2, { args: [2] }); + expectSpy(spy2, 2, { args: [20] }); + expectSpy(spy3, 2, { args: [100] }); + expect(cleanup1).toHaveBeenCalledTimes(2); + expect(cleanup2).toHaveBeenCalledTimes(2); + expect(cleanup3).toHaveBeenCalledTimes(2); + }); + }); +}); diff --git a/tests/reactivity/misc.test.ts b/tests/reactivity/misc.test.ts new file mode 100644 index 000000000..3d9393c7f --- /dev/null +++ b/tests/reactivity/misc.test.ts @@ -0,0 +1,30 @@ +import { Component, mount, signal, useEffect, xml } from "../../src"; +import { makeTestFixture, nextTick, snapshotEverything } from "../helpers"; + +let fixture: HTMLElement; + +snapshotEverything(); + +beforeEach(() => { + fixture = makeTestFixture(); +}); + +test("components and useEffect", async () => { + const s = signal("a"); + + class Test extends Component { + static template = xml``; + current = signal(""); + + setup() { + useEffect(() => { + this.current.set(s()); + }); + } + } + await mount(Test, fixture); + expect(fixture.innerHTML).toBe("a"); + s.set("b"); + await nextTick(); + expect(fixture.innerHTML).toBe("b"); +}); diff --git a/tests/reactivity/proxy.test.ts b/tests/reactivity/proxy.test.ts new file mode 100644 index 000000000..11e94c0af --- /dev/null +++ b/tests/reactivity/proxy.test.ts @@ -0,0 +1,2309 @@ +import { Component, mount, onWillStart, onWillUpdateProps, xml } from "../../src"; +import { effect, markRaw, props, proxy, toRaw } from "../../src/runtime"; + +import { + makeDeferred, + makeTestFixture, + nextMicroTick, + nextTick, + snapshotEverything, + steps, + useLogLifecycle, +} from "../helpers"; + +function createProxy(value: any) { + return proxy(value); +} + +async function waitScheduler() { + await nextMicroTick(); + return Promise.resolve(); +} + +function expectSpy(spy: jest.Mock, callTime: number, args: any[]): void { + expect(spy).toHaveBeenCalledTimes(callTime); + expect(spy).toHaveBeenLastCalledWith(...args); +} + +describe("Reactivity", () => { + test("can read", async () => { + const state = proxy({ a: 1 }); + expect(state.a).toBe(1); + }); + + test("can create new keys", () => { + const state = createProxy({}); + state.a = 1; + expect(state.a).toBe(1); + }); + + test("can update", () => { + const state = createProxy({ a: 1 }); + state.a = 2; + expect(state.a).toBe(2); + }); + + test("can delete existing keys", () => { + const state = createProxy({ a: 1 }); + delete state.a; + expect(state).not.toHaveProperty("a"); + }); + + test("act like an object", () => { + const state = createProxy({ a: 1 }); + expect(Object.keys(state)).toEqual(["a"]); + expect(Object.values(state)).toEqual([1]); + expect(typeof state).toBe("object"); + }); + + test("act like an array", () => { + const state = createProxy(["a", "b"]); + expect(state.length).toBe(2); + expect(state).toEqual(["a", "b"]); + expect(typeof state).toBe("object"); + expect(Array.isArray(state)).toBe(true); + }); + + test("Throw error if value is not proxifiable", () => { + expect(() => createProxy(1)).toThrow("Cannot make the given value reactive"); + }); + + test("effect is called when changing an observed property 1", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1 }); + effect(() => spy(state.a)); + expectSpy(spy, 1, [1]); + state.a = 100; + expectSpy(spy, 1, [1]); + await waitScheduler(); + expectSpy(spy, 2, [100]); + state.a = state.a + 5; // key is modified + expectSpy(spy, 2, [100]); + await waitScheduler(); + expectSpy(spy, 3, [105]); + }); + + test("effect is called when changing an observed property 2", async () => { + const spy = jest.fn(); + const state = createProxy({ a: { k: 1 } }); + effect(() => spy(state.a.k)); + expectSpy(spy, 1, [1]); + state.a.k = state.a.k + 100; + expectSpy(spy, 1, [1]); + await waitScheduler(); + expectSpy(spy, 2, [101]); + state.a.k = state.a.k + 5; // key is modified + expectSpy(spy, 2, [101]); + await waitScheduler(); + expectSpy(spy, 3, [106]); + }); + + test("proxy from object with a getter 1", async () => { + const spy = jest.fn(); + let value = 1; + const state = createProxy({ + get a() { + return value; + }, + set a(val) { + value = val; + }, + }); + effect(() => spy(state.a)); + expectSpy(spy, 1, [1]); + state.a = state.a + 100; + expectSpy(spy, 1, [1]); + await waitScheduler(); + expectSpy(spy, 2, [101]); + }); + + test("proxy from object with a getter 2", async () => { + const spy = jest.fn(); + let value = { b: 1 }; + const state = createProxy({ + get a() { + return value; + }, + }); + effect(() => spy(state.a.b)); + expectSpy(spy, 1, [1]); + state.a.b = 100; + expectSpy(spy, 1, [1]); + await waitScheduler(); + expectSpy(spy, 2, [100]); + }); + + test("Operator 'in' causes key's presence to be observed", async () => { + const spy = jest.fn(); + const state = createProxy({}); + effect(() => spy("a" in state)); + expectSpy(spy, 1, [false]); + state.a = 100; + await waitScheduler(); + expectSpy(spy, 2, [true]); + + state.a = 3; // Write on existing property shouldn't notify + expectSpy(spy, 2, [true]); + await waitScheduler(); + expectSpy(spy, 2, [true]); + + delete state.a; + expectSpy(spy, 2, [true]); + await waitScheduler(); + expectSpy(spy, 3, [false]); + expect(spy).toHaveBeenLastCalledWith(false); + }); + + // // Skipped because the hasOwnProperty trap is tripped by *writing*. We + // // (probably) do not want to subscribe to changes on writes. + // test.skip("hasOwnProperty causes the key's presence to be observed", async () => { + // let n = 0; + // const state = createReactive({}, () => n++); + + // Object.hasOwnProperty.call(state, "a"); + // state.a = 2; + // expect(n).toBe(1); + + // Object.hasOwnProperty.call(state, "a"); + // state.a = 3; + // expect(n).toBe(1); + + // Object.hasOwnProperty.call(state, "a"); + // delete state.a; + // expect(n).toBe(2); + // }); + + test("setting property to same value does not trigger callback", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1 }); + effect(() => spy(state.a)); + expectSpy(spy, 1, [1]); + state.a = 1; // same value + await waitScheduler(); + expectSpy(spy, 1, [1]); + state.a = state.a + 5; // read and modifies property a to have value 6 + expectSpy(spy, 1, [1]); + await waitScheduler(); + expectSpy(spy, 2, [6]); + state.a = 6; // same value + expectSpy(spy, 2, [6]); + await waitScheduler(); + expectSpy(spy, 2, [6]); + }); + + test("observe cycles", async () => { + const spy = jest.fn(); + const a = { a: {} }; + a.a = a; + + const state = createProxy(a); + effect(() => spy(state.a)); + expectSpy(spy, 1, [state.a]); + + state.k; + state.k = 2; + expectSpy(spy, 1, [state.a]); + await waitScheduler(); + expectSpy(spy, 1, [state.a]); + + delete state.l; + await waitScheduler(); + expectSpy(spy, 1, [state.a]); + + delete state.k; + await waitScheduler(); + expectSpy(spy, 1, [state.a]); + + state.a = 1; + await waitScheduler(); + expectSpy(spy, 2, [1]); + + state.a = state.a + 100; + await waitScheduler(); + expectSpy(spy, 3, [101]); + }); + + test("equality", async () => { + const spy = jest.fn(); + const a = { a: {}, b: 1 }; + a.a = a; + const state = createProxy(a); + effect(() => spy(state.a, state.b)); + + expect(state).toBe(state.a); + state.b = state.b + 1; + await waitScheduler(); + expectSpy(spy, 2, [state.a, 2]); + expect(state).toBe(state.a); + }); + + test("two observers for same source", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + + const obj = { a: 1 } as any; + const state = createProxy(obj); + const state2 = createProxy(obj); + effect(() => spy1(state.a)); + effect(() => spy2(state2.a)); + + state.a = 100; + await waitScheduler(); + expectSpy(spy1, 2, [100]); + expectSpy(spy2, 2, [100]); + }); + + test("create proxy from another", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const state = createProxy({ a: 1 }); + const state2 = createProxy(state); + effect(() => spy1(state.a)); + effect(() => spy2(state2.a)); + + state2.a = state2.a + 100; + await waitScheduler(); + expectSpy(spy1, 2, [101]); + expectSpy(spy2, 2, [101]); + }); + + test("throws on primitive values", () => { + expect(() => createProxy(1)).toThrow(); + expect(() => createProxy("asf")).toThrow(); + expect(() => createProxy(true)).toThrow(); + expect(() => createProxy(null)).toThrow(); + expect(() => createProxy(undefined)).toThrow(); + }); + + test("throws on dates", () => { + const date = new Date(); + expect(() => createProxy(date)).toThrow("Cannot make the given value reactive"); + }); + + test("can observe object with some key set to null", async () => { + const spy = jest.fn(); + const state = createProxy({ a: { b: null } } as any); + effect(() => spy(state.a.b)); + state.a.b = Boolean(state.a.b); + await waitScheduler(); + expectSpy(spy, 2, [false]); + }); + + test("contains initial values", () => { + const state = createProxy({ a: 1, b: 2 }); + expect(state.a).toBe(1); + expect(state.b).toBe(2); + expect((state as any).c).toBeUndefined(); + }); + + test("properly handle dates", async () => { + const spy = jest.fn(); + const date = new Date(); + const state = createProxy({ date }); + effect(() => spy(state.date)); + + expect(typeof state.date.getFullYear()).toBe("number"); + expect(state.date).toBe(date); + + state.date = new Date(); + await waitScheduler(); + expectSpy(spy, 2, [state.date]); + expect(state.date).not.toBe(date); + }); + + test("properly handle promise", async () => { + let resolved = false; + const state = createProxy({ prom: Promise.resolve() }); + + expect(state.prom).toBeInstanceOf(Promise); + state.prom.then(() => (resolved = true)); + expect(resolved).toBe(false); + await Promise.resolve(); + expect(resolved).toBe(true); + }); + + test("can observe value change in array in an object", async () => { + const spy = jest.fn(); + const state = createProxy({ arr: [1, 2] }) as any; + effect(() => spy(state.arr[0])); + + expect(Array.isArray(state.arr)).toBe(true); + + state.arr[0] = state.arr[0] + "nope"; + await waitScheduler(); + expectSpy(spy, 2, ["1nope"]); + + expect(state.arr[0]).toBe("1nope"); + expect(state.arr).toEqual(["1nope", 2]); + }); + + test("can observe: changing array in object to another array", async () => { + const spy = jest.fn(); + const state = createProxy({ arr: [1, 2] }) as any; + effect(() => spy(state.arr[0])); + + expect(Array.isArray(state.arr)).toBe(true); + expectSpy(spy, 1, [1]); + + state.arr = [2, 1]; + await waitScheduler(); + expectSpy(spy, 2, [2]); + expect(state.arr[0]).toBe(2); + expect(state.arr).toEqual([2, 1]); + }); + + test("getting the same property twice returns the same object", () => { + const state = createProxy({ a: { b: 1 } }); + const a1 = state.a; + const a2 = state.a; + expect(a1).toBe(a2); + }); + + test("various object property changes", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1 }); + effect(() => spy(state.a)); + expectSpy(spy, 1, [1]); + + state.a = state.a + 2; + await waitScheduler(); + expectSpy(spy, 2, [3]); + + state.a; + // same value again: no notification + state.a = 3; + await waitScheduler(); + expectSpy(spy, 2, [3]); + + state.a = 4; + await waitScheduler(); + expectSpy(spy, 3, [4]); + }); + + test("properly observe arrays", async () => { + const spy = jest.fn(); + const state = createProxy([]); + effect(() => spy([...state])); + + expect(Array.isArray(state)).toBe(true); + expect(state.length).toBe(0); + expectSpy(spy, 1, [[]]); + + state.push(1); + await waitScheduler(); + expectSpy(spy, 2, [[1]]); + expect(state.length).toBe(1); + expect(state).toEqual([1]); + + state.splice(1, 0, "hey"); + await waitScheduler(); + expectSpy(spy, 3, [[1, "hey"]]); + expect(state).toEqual([1, "hey"]); + expect(state.length).toBe(2); + + // clear all observations caused by previous expects + state[0] = 2; + await waitScheduler(); + expectSpy(spy, 4, [[2, "hey"]]); + + state.unshift("lindemans"); + await waitScheduler(); + expectSpy(spy, 5, [["lindemans", 2, "hey"]]); + expect(state).toEqual(["lindemans", 2, "hey"]); + expect(state.length).toBe(3); + + // clear all observations caused by previous expects + state[1] = 3; + await waitScheduler(); + expectSpy(spy, 6, [["lindemans", 3, "hey"]]); + + state.reverse(); + await waitScheduler(); + expectSpy(spy, 7, [["hey", 3, "lindemans"]]); + expect(state).toEqual(["hey", 3, "lindemans"]); + expect(state.length).toBe(3); + + state.pop(); + await waitScheduler(); + expectSpy(spy, 8, [["hey", 3]]); + expect(state).toEqual(["hey", 3]); + expect(state.length).toBe(2); + + state.shift(); + await waitScheduler(); + expectSpy(spy, 9, [[3]]); + expect(state).toEqual([3]); + expect(state.length).toBe(1); + }); + test("object pushed into arrays are observed", async () => { + const spy = jest.fn(); + const arr: any = createProxy([]); + effect(() => spy(arr[0]?.kriek)); + + arr.push({ kriek: 5 }); + await waitScheduler(); + expectSpy(spy, 2, [5]); + + arr[0].kriek = 6; + await waitScheduler(); + expectSpy(spy, 3, [6]); + + arr[0].kriek = arr[0].kriek + 6; + await waitScheduler(); + expectSpy(spy, 4, [12]); + }); + + test("set new property on observed object", async () => { + const spy = jest.fn(); + const state = createProxy({}); + effect(() => spy(Object.keys(state))); + expectSpy(spy, 1, [[]]); + + state.b = 8; + await waitScheduler(); + expectSpy(spy, 2, [["b"]]); + expect(state.b).toBe(8); + expect(Object.keys(state)).toEqual(["b"]); + }); + + test("set new property object when key changes are not observed", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1 }); + effect(() => spy(state.a)); + expectSpy(spy, 1, [1]); + + state.b = 8; + await waitScheduler(); + expectSpy(spy, 1, [1]); // Not observing key changes: shouldn't get notified + expect(state.b).toBe(8); + expect(state).toEqual({ a: 1, b: 8 }); + }); + + test("delete property from observed object", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1, b: 8 }); + effect(() => spy(Object.keys(state))); + expectSpy(spy, 1, [["a", "b"]]); + + delete state.b; + await waitScheduler(); + expectSpy(spy, 2, [["a"]]); + expect(state).toEqual({ a: 1 }); + }); + + //todo + test.skip("delete property from observed object 2", async () => { + const spy = jest.fn(); + const obj = { a: { b: 1 } }; + const state = createProxy(obj.a); + const state2 = createProxy(obj); + effect(() => spy(Object.keys(state2))); + expect(state2.a).toBe(state); + expectSpy(spy, 1, [["a"]]); + + Object.keys(state2); + delete state2.a; + await waitScheduler(); + expectSpy(spy, 2, [[]]); + + state.new = 2; + await waitScheduler(); + expectSpy(spy, 3, [["new"]]); + }); + + test("set element in observed array", async () => { + const spy = jest.fn(); + const arr = createProxy(["a"]); + effect(() => spy(arr[1])); + arr[1] = "b"; + await waitScheduler(); + expectSpy(spy, 2, ["b"]); + expect(arr).toEqual(["a", "b"]); + }); + + test("properly observe arrays in object", async () => { + const spy = jest.fn(); + const state = createProxy({ arr: [] }) as any; + effect(() => spy(state.arr.length)); + + expect(state.arr.length).toBe(0); + expectSpy(spy, 1, [0]); + + state.arr.push(1); + await waitScheduler(); + expectSpy(spy, 2, [1]); + expect(state.arr.length).toBe(1); + }); + + test("properly observe objects in array", async () => { + const spy = jest.fn(); + const state = createProxy({ arr: [{ something: 1 }] }) as any; + effect(() => spy(state.arr[0].something)); + expectSpy(spy, 1, [1]); + + state.arr[0].something = state.arr[0].something + 1; + await waitScheduler(); + expectSpy(spy, 2, [2]); + expect(state.arr[0].something).toBe(2); + }); + + test("properly observe objects in object", async () => { + const spy = jest.fn(); + const state = createProxy({ a: { b: 1 } }) as any; + effect(() => spy(state.a.b)); + expectSpy(spy, 1, [1]); + + state.a.b = state.a.b + 2; + await waitScheduler(); + expectSpy(spy, 2, [3]); + }); + + test("Observing the same object through the same proxy preserves referential equality", async () => { + const o = {} as any; + o.o = o; + const state = createProxy(o); + expect(state.o).toBe(state); + expect(state.o.o).toBe(state); + }); + + test("reobserve new object values", async () => { + const spy = jest.fn(); + const state = createProxy({ a: 1 }); + effect(() => spy(state.a?.b || state.a)); + expectSpy(spy, 1, [1]); + + state.a++; + await waitScheduler(); + expectSpy(spy, 2, [2]); + + state.a = { b: 100 }; + await waitScheduler(); + expectSpy(spy, 3, [100]); + + state.a.b = state.a.b + 3; + await waitScheduler(); + expectSpy(spy, 4, [103]); + }); + + test("deep observe misc changes", async () => { + const spy = jest.fn(); + const state = createProxy({ o: { a: 1 }, arr: [1], n: 13 }) as any; + effect(() => spy(state.o.a, state.arr.length, state.n)); + expectSpy(spy, 1, [1, 1, 13]); + + state.o.a = state.o.a + 2; + await waitScheduler(); + expectSpy(spy, 2, [3, 1, 13]); + + state.arr.push(2); + await waitScheduler(); + expectSpy(spy, 3, [3, 2, 13]); + + state.n = 155; + await waitScheduler(); + expectSpy(spy, 4, [3, 2, 155]); + + state.n = state.n + 1; + await waitScheduler(); + expectSpy(spy, 5, [3, 2, 156]); + }); + + test("properly handle already observed object", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + + const obj1 = createProxy({ a: 1 }); + const obj2 = createProxy({ b: 1 }); + + effect(() => spy1(obj1.a)); + effect(() => spy2(obj2.b)); + + obj1.a = obj1.a + 2; + obj2.b = obj2.b + 3; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 2, [4]); + + (window as any).d = true; + obj2.b = obj1; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 3, [obj1]); + + obj1.a = 33; + await waitScheduler(); + expectSpy(spy1, 3, [33]); + expectSpy(spy2, 3, [obj1]); + + obj2.b.a = obj2.b.a + 2; + await waitScheduler(); + expectSpy(spy1, 4, [35]); + expectSpy(spy2, 3, [obj1]); + }); + + test("properly handle already observed object in observed object", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const obj1 = createProxy({ a: { c: 2 } }); + const obj2 = createProxy({ b: 1 }); + + effect(() => spy1(obj1.a.c)); + effect(() => spy2(obj2.c?.a?.c)); + + obj2.c = obj1; + await waitScheduler(); + expectSpy(spy1, 1, [2]); + expectSpy(spy2, 2, [2]); + + obj1.a.c = obj1.a.c + 33; + await waitScheduler(); + expectSpy(spy1, 2, [35]); + expectSpy(spy2, 3, [35]); + + obj2.c.a.c = obj2.c.a.c + 3; + await waitScheduler(); + expectSpy(spy1, 3, [38]); + expectSpy(spy2, 4, [38]); + }); + + test("can reobserve nested properties in object", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const state = createProxy({ a: [{ b: 1 }] }) as any; + + const state2 = createProxy(state) as any; + + effect(() => spy1(state.a[0].b)); + effect(() => spy2(state2.c)); + + state.a[0].b = state.a[0].b + 2; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 1, [undefined]); + + state2.c = 2; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 2, [2]); + }); + + test("rereading some property again give exactly same result", () => { + const state = createProxy({ a: { b: 1 } }); + const obj1 = state.a; + const obj2 = state.a; + expect(obj1).toBe(obj2); + }); + + test("can reobserve new properties in object", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const state = createProxy({ a: [{ b: 1 }] }) as any; + + effect(() => spy1(state.a[0].b.c)); + effect(() => spy2(state.a[0].b)); + + state.a[0].b = { c: 1 }; + await waitScheduler(); + expectSpy(spy1, 2, [1]); + expectSpy(spy2, 2, [{ c: 1 }]); + + state.a[0].b.c = state.a[0].b.c + 2; + await waitScheduler(); + expectSpy(spy1, 3, [3]); + expectSpy(spy2, 2, [{ c: 3 }]); + }); + + test("can set a property more than once", async () => { + const spy = jest.fn(); + const state = createProxy({}) as any; + effect(() => spy(state.aku)); + + state.aky = state.aku; + expectSpy(spy, 1, [undefined]); + + state.aku = "always finds annoying problems"; + await waitScheduler(); + expectSpy(spy, 2, ["always finds annoying problems"]); + + state.aku = "always finds good problems"; + await waitScheduler(); + expectSpy(spy, 3, ["always finds good problems"]); + }); + + test("properly handle swapping elements", async () => { + const spy = jest.fn(); + const arrDict = { arr: [] }; + const state = createProxy({ a: arrDict, b: 1 }) as any; + effect(() => { + Array.isArray(state.b?.arr) && [...state.b.arr]; + return spy(state.a, state.b); + }); + expectSpy(spy, 1, [arrDict, 1]); + + // swap a and b + const b = state.b; + const a = state.a; + state.b = a; + state.a = b; + await waitScheduler(); + expectSpy(spy, 2, [1, arrDict]); + + // push something into array to make sure it works + state.b.arr.push("blanche"); + await waitScheduler(); + expectSpy(spy, 3, [1, arrDict]); + }); + + test("properly handle assigning object containing array to proxy", async () => { + const spy = jest.fn(); + const state = createProxy({ a: { arr: [], val: "test" } }) as any; + effect(() => spy(state.a, [...state.a.arr])); + expectSpy(spy, 1, [state.a, []]); + + state.a = { ...state.a, val: "test2" }; + await waitScheduler(); + expectSpy(spy, 2, [state.a, []]); + + // push something into array to make sure it works + state.a.arr.push("blanche"); + await waitScheduler(); + expectSpy(spy, 3, [state.a, ["blanche"]]); + }); + + test("accept cycles in observed object", async () => { + const spy = jest.fn(); + let obj1: any = {}; + let obj2: any = { b: obj1, key: 1 }; + obj1.a = obj2; + obj1 = createProxy(obj1) as any; + obj2 = obj1.a; + effect(() => spy(obj1.key)); + expectSpy(spy, 1, [undefined]); + + obj1.key = 3; + await waitScheduler(); + expectSpy(spy, 2, [3]); + }); + + test("call callback when proxy is changed", async () => { + const spy = jest.fn(); + const state: any = createProxy({ a: 1, b: { c: 2 }, d: [{ e: 3 }], f: 4 }); + effect(() => spy(state.a, state.b.c, state.d[0].e, state.f)); + expectSpy(spy, 1, [1, 2, 3, 4]); + + state.a = state.a + 2; + await waitScheduler(); + expectSpy(spy, 2, [3, 2, 3, 4]); + + state.b.c = state.b.c + 3; + await waitScheduler(); + expectSpy(spy, 3, [3, 5, 3, 4]); + + state.d[0].e = state.d[0].e + 5; + await waitScheduler(); + expectSpy(spy, 4, [3, 5, 8, 4]); + + state.a = 111; + state.f = 222; + await waitScheduler(); + expectSpy(spy, 5, [111, 5, 8, 222]); + }); + + test("proxy inside other proxy", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const inner = createProxy({ a: 1 }); + const outer = createProxy({ b: inner }); + + effect(() => spy1(inner.a)); + effect(() => spy2(outer.b.a)); + + expectSpy(spy1, 1, [1]); + expectSpy(spy2, 1, [1]); + + outer.b.a = outer.b.a + 2; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 2, [3]); + }); + + test("proxy inside other proxy, variant", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const inner = createProxy({ a: 1 }); + const outer = createProxy({ b: inner, c: 0 }); + effect(() => spy1(inner.a)); + effect(() => spy2(outer.c)); + expectSpy(spy1, 1, [1]); + expectSpy(spy2, 1, [0]); + + inner.a = inner.a + 2; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 1, [0]); + + outer.c = outer.c + 3; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 2, [3]); + }); + + test("proxy inside other proxy, variant 2", async () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const spy3 = jest.fn(); + const obj1 = createProxy({ a: 1 }); + const obj2 = createProxy({ b: {} }); + const obj3 = createProxy({ c: {} }); + + effect(() => spy1(obj1.a)); + effect(() => spy2(obj2.b)); + effect(() => spy3(obj3.c)); + + // assign the same object shouldn't notify reactivity + obj2.b = obj2.b; + obj3.c = obj3.c; + await waitScheduler(); + expectSpy(spy1, 1, [1]); + expectSpy(spy2, 1, [{}]); + expectSpy(spy3, 1, [{}]); + + obj2.b = obj1; + obj3.c = obj1; + await waitScheduler(); + expectSpy(spy1, 1, [1]); + expectSpy(spy2, 2, [obj1]); + expectSpy(spy3, 2, [obj1]); + + obj1.a = obj1.a + 2; + await waitScheduler(); + expectSpy(spy1, 2, [3]); + expectSpy(spy2, 2, [obj1]); + expectSpy(spy3, 2, [obj1]); + + obj2.b.a = obj2.b.a + 1; + await waitScheduler(); + expectSpy(spy1, 3, [4]); + expectSpy(spy2, 2, [obj1]); + expectSpy(spy3, 2, [obj1]); + }); + + // test("notification is not done after unregistration", async () => { + // let n = 0; + // const observer = () => n++; + // const unregisterObserver = registerObserver(observer); + // const state = atom({ a: 1 } as any, observer); + + // state.a = state.a; + // await nextMicroTick(); + // expect(n).toBe(0); + + // unregisterObserver(); + + // state.a = { b: 2 }; + // await nextMicroTick(); + // expect(n).toBe(0); + + // state.a.b = state.a.b + 3; + // await nextMicroTick(); + // expect(n).toBe(0); + // }); + + test("don't react to changes in subobject that has been deleted", async () => { + const spy = jest.fn(); + const a = { k: {} } as any; + const state = createProxy(a); + + effect(() => spy(state.k?.l)); + + state.k.l = 1; + await waitScheduler(); + expectSpy(spy, 2, [1]); + + const kVal = state.k; + + delete state.k; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + + kVal.l = 2; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); // kVal must no longer be observed + }); + + test("don't react to changes in subobject that has been deleted", async () => { + const spy = jest.fn(); + const b = {} as any; + const a = { k: b } as any; + const state2 = createProxy(b); + const state = createProxy(a); + + effect(() => spy(state.k?.d)); + + state.c = 1; + state.k.d = 2; + await waitScheduler(); + expectSpy(spy, 2, [2]); + + delete state.k; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + + state2.e = 3; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + }); + + test("don't react to changes in subobject that has been deleted 3", async () => { + const spy = jest.fn(); + const b = {} as any; + const a = { k: b } as any; + const state = createProxy(a); + const state2 = createProxy(b); + + effect(() => spy(state.k?.d)); + + state.c = 1; + state.k.d = 2; + await waitScheduler(); + expectSpy(spy, 2, [2]); + + delete state.k; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + + state2.e = 3; + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + }); + + test("don't react to changes in subobject that has been replaced", async () => { + const spy = jest.fn(); + const a = { k: { n: 1 } } as any; + const state = createProxy(a); + const kVal = state.k; // read k + + effect(() => spy(state.k.n)); + expectSpy(spy, 1, [1]); + + state.k = { n: state.k.n + 1 }; + await waitScheduler(); + expectSpy(spy, 2, [2]); + expect(state.k).toEqual({ n: 2 }); + + kVal.n = 3; + await waitScheduler(); + expectSpy(spy, 2, [2]); + expect(state.k).toEqual({ n: 2 }); + }); + + test("can access properties on proxy of frozen objects", async () => { + const obj = Object.freeze({ a: {} }); + const state = createProxy(obj); + expect(() => state.a).not.toThrow(); + expect(state.a).toBe(obj.a); + }); + + test("writing on object with proxy in prototype chain doesn't notify", async () => { + const spy = jest.fn(); + const state = createProxy({ val: 0 }); + effect(() => spy(state.val)); + const nonReactive = Object.create(state); + nonReactive.val++; + expect(spy).toHaveBeenCalledTimes(1); + expect(toRaw(state)).toEqual({ val: 0 }); + expect(toRaw(nonReactive)).toEqual({ val: 1 }); + state.val++; + await waitScheduler(); + expect(spy).toHaveBeenCalledTimes(2); + expect(toRaw(state)).toEqual({ val: 1 }); + expect(toRaw(nonReactive)).toEqual({ val: 1 }); + }); + + test("creating key on object with proxy in prototype chain doesn't notify", async () => { + const spy = jest.fn(); + const parent = createProxy({}); + const child = Object.create(parent); + effect(() => spy(Object.keys(parent))); + child.val = 0; + await waitScheduler(); + expectSpy(spy, 1, [[]]); + }); + + test("proxy of object with proxy in prototype chain is not the object from the prototype chain", async () => { + const spy = jest.fn(); + const parent = createProxy({ val: 0 }); + const child = createProxy(Object.create(parent)); + effect(() => spy(child.val)); + expect(child).not.toBe(parent); + + child.val++; + await waitScheduler(); + expectSpy(spy, 2, [1]); + expect(parent.val).toBe(0); + expect(child.val).toBe(1); + }); + + test("can create proxy of object with non-proxy in prototype chain", async () => { + const spy = jest.fn(); + const parent = markRaw({ val: 0 }); + const child = createProxy(Object.create(parent)); + effect(() => spy(child.val)); + child.val++; + await waitScheduler(); + expectSpy(spy, 2, [1]); + expect(parent).toEqual({ val: 0 }); + expect(child).toEqual({ val: 1 }); + }); +}); + +describe("Collections", () => { + describe("Set", () => { + test("can make proxy Set", () => { + const set = new Set(); + const obj = proxy(set); + expect(obj).not.toBe(set); + }); + + test("can read", async () => { + const state = proxy(new Set([1])); + expect(state.has(1)).toBe(true); + expect(state.has(0)).toBe(false); + }); + + test("can add entries", () => { + const state = proxy(new Set()); + state.add(1); + expect(state.has(1)).toBe(true); + }); + + test("can remove entries", () => { + const state = proxy(new Set([1])); + state.delete(1); + expect(state.has(1)).toBe(false); + }); + + test("can clear entries", () => { + const state = proxy(new Set([1])); + expect(state.size).toBe(1); + state.clear(); + expect(state.size).toBe(0); + }); + + test("act like a Set", () => { + const state = proxy(new Set([1])); + expect([...state.entries()]).toEqual([[1, 1]]); + expect([...state.values()]).toEqual([1]); + expect([...state.keys()]).toEqual([1]); + expect([...state]).toEqual([1]); // Checks Symbol.iterator + expect(state.size).toBe(1); + expect(typeof state).toBe("object"); + expect(state).toBeInstanceOf(Set); + }); + + test("proxy Set contains its keys", () => { + const state = proxy(new Set([{}])); + expect(state.has(state.keys().next().value!)).toBe(true); + }); + + test("proxy Set contains its values", () => { + const state = proxy(new Set([{}])); + expect(state.has(state.values().next().value!)).toBe(true); + }); + + test("proxy Set contains its entries' keys and values", () => { + const state = proxy(new Set([{}])); + const [key, val] = state.entries().next().value!; + expect(state.has(key)).toBe(true); + expect(state.has(val)).toBe(true); + }); + + test("checking for a key subscribes the callback to changes to that key", async () => { + const spy = jest.fn(); + const state = proxy(new Set([1])); + effect(() => spy(state.has(2))); + + expectSpy(spy, 1, [false]); + state.add(2); + await waitScheduler(); + expectSpy(spy, 2, [true]); + state.delete(2); + await waitScheduler(); + expectSpy(spy, 3, [false]); + state.add(2); + await waitScheduler(); + expectSpy(spy, 4, [true]); + state.clear(); + await waitScheduler(); + expectSpy(spy, 5, [false]); + state.clear(); // clearing again doesn't notify again + await waitScheduler(); + expectSpy(spy, 5, [false]); + + state.add(3); // setting unobserved key doesn't notify + await waitScheduler(); + expectSpy(spy, 5, [false]); + expect(state.has(3)).toBe(true); // subscribe to 3 + state.add(3); // adding observed key doesn't notify if key was already present + await waitScheduler(); + expectSpy(spy, 5, [false]); + expect(state.has(4)).toBe(false); // subscribe to 4 + state.delete(4); // deleting observed key doesn't notify if key was already not present + await waitScheduler(); + expectSpy(spy, 5, [false]); + }); + + test("iterating on keys returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Set([obj])); + const proxyObj = state.keys().next().value!; + effect(() => spy(proxyObj.a)); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a; // observe key "a" in sub-proxy; + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on values returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Set([obj])); + const proxyObj = state.values().next().value!; + effect(() => spy(proxyObj.a)); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a; // observe key "a" in sub-proxy; + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on entries returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Set([obj])); + const [proxyObj, proxyObj2] = state.entries().next().value!; + expect(proxyObj2).toBe(proxyObj); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + effect(() => spy(proxyObj.a)); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a; // observe key "a" in sub-proxy; + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on proxy Set returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Set([obj])); + const proxyObj = state[Symbol.iterator]().next().value!; + effect(() => spy(proxyObj.a)); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a; // observe key "a" in sub-proxy; + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating with forEach returns proxys", async () => { + const keyObj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Set([keyObj])); + let proxyKeyObj: any, proxyValObj: any, thisObj: any, mapObj: any; + const thisArg = {}; + state.forEach(function (this: any, val, key, map) { + [proxyValObj, proxyKeyObj, mapObj, thisObj] = [val, key, map, this]; + }, thisArg); + expect(proxyKeyObj).not.toBe(keyObj); + expect(proxyValObj).not.toBe(keyObj); + expect(mapObj).toBe(state); // third argument should be the proxy + expect(thisObj).toBe(thisArg); // thisArg should not be made proxy + expect(toRaw(proxyKeyObj as any)).toBe(keyObj); + expect(toRaw(proxyValObj as any)).toBe(keyObj); + expect(proxyKeyObj).toBe(proxyValObj); // proxyKeyObj and proxyValObj should be the same object + + effect(() => spy(proxyKeyObj.a)); + expectSpy(spy, 1, [2]); + + proxyKeyObj!.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + + proxyKeyObj!.a; // observe key "a" in key sub-proxy; + proxyKeyObj!.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + + proxyKeyObj!.a = 1; // setting same value again shouldn't notify + proxyValObj!.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + }); + + describe("WeakSet", () => { + test("cannot make proxy WeakSet", () => { + const set = new WeakSet(); + expect(() => proxy(set)).toThrow("Cannot make the given value reactive"); + }); + + test("WeakSet in proxy is original WeakSet", () => { + const obj = { set: new WeakSet() }; + const state = proxy(obj); + expect(state.set).toBe(obj.set); + }); + }); + + describe("Map", () => { + test("can make proxy Map", () => { + const map = new Map(); + const obj = proxy(map); + expect(obj).not.toBe(map); + }); + + test("can read", async () => { + const state = proxy(new Map([[1, 0]])); + expect(state.has(1)).toBe(true); + expect(state.has(0)).toBe(false); + expect(state.get(1)).toBe(0); + expect(state.get(0)).toBeUndefined(); + }); + + test("can add entries", () => { + const state = proxy(new Map()); + state.set(1, 2); + expect(state.has(1)).toBe(true); + expect(state.get(1)).toBe(2); + }); + + test("can remove entries", () => { + const state = proxy(new Map([[1, 2]])); + state.delete(1); + expect(state.has(1)).toBe(false); + expect(state.get(1)).toBeUndefined(); + }); + + test("can clear entries", () => { + const state = proxy(new Map([[1, 2]])); + expect(state.size).toBe(1); + state.clear(); + expect(state.size).toBe(0); + }); + + test("act like a Map", () => { + const state = proxy(new Map([[1, 2]])); + expect([...state.entries()]).toEqual([[1, 2]]); + expect([...state.values()]).toEqual([2]); + expect([...state.keys()]).toEqual([1]); + expect([...state]).toEqual([[1, 2]]); // Checks Symbol.iterator + expect(state.size).toBe(1); + expect(typeof state).toBe("object"); + expect(state).toBeInstanceOf(Map); + }); + + test("proxy Map contains its keys", () => { + const state = proxy(new Map([[{}, 1]])); + expect(state.has(state.keys().next().value!)).toBe(true); + }); + + test("proxy Map values are equal to doing a get on the appropriate key", () => { + const state = proxy(new Map([[1, {}]])); + expect(state.get(1)).toBe(state.values().next().value); + }); + + test("proxy Map contains its entries' keys, and the associated value is the same as doing get", () => { + const state = proxy(new Map([[{}, {}]])); + const [key, val] = state.entries().next().value!; + expect(state.has(key)).toBe(true); + expect(val).toBe(state.get(key)); + }); + + test("checking for a key with 'has' subscribes the callback to changes to that key", async () => { + const spy = jest.fn(); + const state = proxy(new Map([[1, 2]])); + effect(() => spy(state.has(2))); + + expectSpy(spy, 1, [false]); + state.set(2, 3); + await waitScheduler(); + expectSpy(spy, 2, [true]); + state.delete(2); + await waitScheduler(); + expectSpy(spy, 3, [false]); + state.set(2, 3); + await waitScheduler(); + expectSpy(spy, 4, [true]); + state.clear(); + await waitScheduler(); + expectSpy(spy, 5, [false]); + state.clear(); // clearing again doesn't notify again + await waitScheduler(); + expectSpy(spy, 5, [false]); + + state.set(3, 4); // setting unobserved key doesn't notify + await waitScheduler(); + expectSpy(spy, 5, [false]); + expect(state.has(3)).toBe(true); // subscribe to 3 + state.set(3, 4); // setting the same value doesn't notify + await waitScheduler(); + expectSpy(spy, 5, [false]); + expect(state.has(4)).toBe(false); // subscribe to 4 + state.delete(4); // deleting observed key doesn't notify if key was already not present + await waitScheduler(); + expectSpy(spy, 5, [false]); + }); + + test("checking for a key with 'get' subscribes the callback to changes to that key", async () => { + const spy = jest.fn(); + const state = proxy(new Map([[1, 2]])); + effect(() => spy(state.get(2))); + + expectSpy(spy, 1, [undefined]); + state.set(2, 3); + await waitScheduler(); + expectSpy(spy, 2, [3]); + expect(state.get(2)).toBe(3); // subscribe to 2 + state.delete(2); + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + state.delete(2); // deleting again doesn't notify again + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + state.set(2, 3); + await waitScheduler(); + expectSpy(spy, 4, [3]); + expect(state.get(2)).toBe(3); // subscribe to 2 + state.clear(); + await waitScheduler(); + expectSpy(spy, 5, [undefined]); + expect(state.get(2)).toBeUndefined(); // subscribe to 2 + state.clear(); // clearing again doesn't notify again + await waitScheduler(); + expectSpy(spy, 5, [undefined]); + + state.set(3, 4); // setting unobserved key doesn't notify + await waitScheduler(); + expectSpy(spy, 5, [undefined]); + expect(state.get(3)).toBe(4); // subscribe to 3 + state.set(3, 4); // setting the same value doesn't notify + await waitScheduler(); + expectSpy(spy, 5, [undefined]); + expect(state.get(4)).toBe(undefined); // subscribe to 4 + state.delete(4); // deleting observed key doesn't notify if key was already not present + await waitScheduler(); + expectSpy(spy, 5, [undefined]); + }); + + test("getting values returns a proxy", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Map([[1, obj]])); + const proxyObj = state.get(1)!; + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + effect(() => spy(proxyObj.a)); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on values returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Map([[1, obj]])); + const proxyObj = state.values().next().value!; + effect(() => spy(proxyObj.a)); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on keys returns proxys", async () => { + const obj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Map([[obj, 1]])); + const proxyObj = state.keys().next().value!; + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj as any)).toBe(obj); + effect(() => spy(proxyObj.a)); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + + test("iterating on proxy map returns proxys", async () => { + const keyObj = { a: 2 }; + const valObj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Map([[keyObj, valObj]])); + const [proxyKeyObj, proxyValObj] = state[Symbol.iterator]().next().value!; + effect(() => spy(proxyKeyObj.a, proxyValObj.a)); + expect(proxyKeyObj).not.toBe(keyObj); + expect(proxyValObj).not.toBe(valObj); + expect(toRaw(proxyKeyObj as any)).toBe(keyObj); + expect(toRaw(proxyValObj as any)).toBe(valObj); + expectSpy(spy, 1, [2, 2]); + proxyKeyObj.a = 0; + proxyValObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0, 0]); + proxyKeyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1, 0]); + proxyValObj.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + proxyKeyObj.a = 1; // setting same value again shouldn't notify + proxyValObj.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + }); + + test("iterating on entries returns proxys", async () => { + const keyObj = { a: 2 }; + const valObj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new Map([[keyObj, valObj]])); + const [proxyKeyObj, proxyValObj] = state.entries().next().value!; + effect(() => spy(proxyKeyObj.a, proxyValObj.a)); + expect(proxyKeyObj).not.toBe(keyObj); + expect(proxyValObj).not.toBe(valObj); + expect(toRaw(proxyKeyObj as any)).toBe(keyObj); + expect(toRaw(proxyValObj as any)).toBe(valObj); + expectSpy(spy, 1, [2, 2]); + proxyKeyObj.a = 0; + proxyValObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0, 0]); + proxyKeyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1, 0]); + proxyValObj.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + proxyKeyObj.a = 1; // setting same value again shouldn't notify + proxyValObj.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + }); + + test("iterating with forEach returns proxys", async () => { + const keyObj = { a: 2 }; + const valObj = { a: 2 }; + const thisArg = {}; + const spy = jest.fn(); + const state = proxy(new Map([[keyObj, valObj]])); + let proxyKeyObj: any, proxyValObj: any, thisObj: any, mapObj: any; + state.forEach(function (this: any, val, key, map) { + [proxyValObj, proxyKeyObj, mapObj, thisObj] = [val, key, map, this]; + }, thisArg); + expect(proxyKeyObj).not.toBe(keyObj); + expect(proxyValObj).not.toBe(valObj); + expect(mapObj).toBe(state); // third argument should be the proxy + expect(thisObj).toBe(thisArg); // thisArg should not be made proxy + expect(toRaw(proxyKeyObj as any)).toBe(keyObj); + expect(toRaw(proxyValObj as any)).toBe(valObj); + + effect(() => spy(proxyKeyObj.a, proxyValObj.a)); + expectSpy(spy, 1, [2, 2]); + + proxyKeyObj!.a = 0; + proxyValObj!.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0, 0]); + + proxyKeyObj!.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1, 0]); + + proxyValObj!.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + + proxyKeyObj!.a = 1; // setting same value again shouldn't notify + proxyValObj!.a = 1; + await waitScheduler(); + expectSpy(spy, 4, [1, 1]); + }); + }); + + describe("WeakMap", () => { + test("can make proxy WeakMap", () => { + const map = new WeakMap(); + const obj = proxy(map); + expect(obj).not.toBe(map); + }); + + test("can read", async () => { + const obj = {}; + const obj2 = {}; + const state = proxy(new WeakMap([[obj, 0]])); + expect(state.has(obj)).toBe(true); + expect(state.has(obj2)).toBe(false); + expect(state.get(obj)).toBe(0); + expect(state.get(obj2)).toBeUndefined(); + }); + + test("can add entries", () => { + const obj = {}; + const state = proxy(new WeakMap()); + state.set(obj, 2); + expect(state.has(obj)).toBe(true); + expect(state.get(obj)).toBe(2); + }); + + test("can remove entries", () => { + const obj = {}; + const state = proxy(new WeakMap([[obj, 2]])); + state.delete(obj); + expect(state.has(obj)).toBe(false); + expect(state.get(obj)).toBeUndefined(); + }); + + test("act like a WeakMap", () => { + const obj = {}; + const state = proxy(new WeakMap([[obj, 2]])); + expect(typeof state).toBe("object"); + expect(state).toBeInstanceOf(WeakMap); + }); + + test("checking for a key with 'has' subscribes the callback to changes to that key", async () => { + const spy = jest.fn(); + const obj = {}; + const obj2 = {}; + const obj3 = {}; + const state = proxy(new WeakMap([[obj2, 2]])); + + effect(() => spy(state.has(obj))); + + expectSpy(spy, 1, [false]); + state.set(obj, 3); + await waitScheduler(); + expectSpy(spy, 2, [true]); + expect(state.has(obj)).toBe(true); // subscribe to obj + state.delete(obj); + await waitScheduler(); + expectSpy(spy, 3, [false]); + state.set(obj, 3); + state.delete(obj); + await waitScheduler(); + // todo: should be 3 or 4? + expectSpy(spy, 4, [false]); + expect(state.has(obj)).toBe(false); // subscribe to obj + + state.set(obj3, 4); // setting unobserved key doesn't notify + await waitScheduler(); + expectSpy(spy, 4, [false]); + }); + + test("checking for a key with 'get' subscribes the callback to changes to that key", async () => { + const spy = jest.fn(); + const obj = {}; + const obj2 = {}; + const obj3 = {}; + const state = proxy(new WeakMap([[obj2, 2]])); + + effect(() => spy(state.get(obj))); + + expectSpy(spy, 1, [undefined]); + state.set(obj, 3); + await waitScheduler(); + expectSpy(spy, 2, [3]); + expect(state.get(obj)).toBe(3); // subscribe to obj + state.delete(obj); + await waitScheduler(); + expectSpy(spy, 3, [undefined]); + state.set(obj, 3); + state.delete(obj); + await waitScheduler(); + expectSpy(spy, 4, [undefined]); + expect(state.get(obj)).toBeUndefined(); // subscribe to obj + + state.set(obj3, 4); // setting unobserved key doesn't notify + await waitScheduler(); + expectSpy(spy, 4, [undefined]); + }); + + test("getting values returns a proxy", async () => { + const keyObj = {}; + const valObj = { a: 2 }; + const spy = jest.fn(); + const state = proxy(new WeakMap([[keyObj, valObj]])); + const proxyObj = state.get(keyObj)!; + expect(proxyObj).not.toBe(valObj); + expect(toRaw(proxyObj as any)).toBe(valObj); + effect(() => spy(proxyObj.a)); + expectSpy(spy, 1, [2]); + proxyObj.a = 0; + await waitScheduler(); + expectSpy(spy, 2, [0]); + proxyObj.a = 1; + await waitScheduler(); + expectSpy(spy, 3, [1]); + proxyObj.a = 1; // setting same value again shouldn't notify + await waitScheduler(); + expectSpy(spy, 3, [1]); + }); + }); +}); + +describe("markRaw", () => { + test("markRaw works as expected: value is not observed", async () => { + const obj1: any = markRaw({ value: 1 }); + const obj2 = { value: 1 }; + const spy = jest.fn(); + const r = proxy({ obj1, obj2 }); + effect(() => spy(r.obj2.value)); + expectSpy(spy, 1, [1]); + r.obj1.value = r.obj1.value + 1; + await waitScheduler(); + expectSpy(spy, 1, [1]); + r.obj2.value = r.obj2.value + 1; + await waitScheduler(); + expectSpy(spy, 2, [2]); + expect(r.obj1).toBe(obj1); + expect(r.obj2).not.toBe(obj2); + }); +}); + +describe("toRaw", () => { + test("toRaw works as expected", () => { + const obj = { value: 1 }; + const proxyObj = proxy(obj); + expect(proxyObj).not.toBe(obj); + expect(toRaw(proxyObj)).toBe(obj); + }); + + test("giving a non proxy to toRaw return the object itself", () => { + const obj = { value: 1 }; + expect(toRaw(obj)).toBe(obj); + }); +}); + +describe("Reactivity: proxy", () => { + let fixture: HTMLElement; + + snapshotEverything(); + + beforeEach(() => { + fixture = makeTestFixture(); + }); + + /** + * A context can be defined as a proxy with a default observer. + * It can be exposed and share by multiple components or other objects + * (via proxy for instance) + */ + + test("very simple use, with initial value", async () => { + const testContext = createProxy({ value: 123 }); + + class Comp extends Component { + static template = xml`
    `; + contextObj = proxy(testContext); + } + await mount(Comp, fixture); + expect(fixture.innerHTML).toBe("
    123
    "); + }); + + test("useContext=proxy hook is proxy, for one component", async () => { + const testContext = createProxy({ value: 123 }); + + class Comp extends Component { + static template = xml`
    `; + contextObj = proxy(testContext); + } + const comp = await mount(Comp, fixture); + expect(fixture.innerHTML).toBe("
    123
    "); + (comp as any).contextObj.value = 321; + await nextTick(); + expect(fixture.innerHTML).toBe("
    321
    "); + }); + + test("two components can subscribe to same context", async () => { + const testContext = createProxy({ value: 123 }); + + class Child extends Component { + static template = xml``; + contextObj = proxy(testContext); + setup() { + useLogLifecycle(this); + } + } + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + setup() { + useLogLifecycle(this); + } + } + await mount(Parent, fixture); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Parent:setup", + "Parent:willStart", + "Child:setup", + "Child:willStart", + "Child:setup", + "Child:willStart", + "Child:mounted", + "Child:mounted", + "Parent:mounted", + ] + `); + + expect(fixture.innerHTML).toBe("
    123123
    "); + testContext.value = 321; + await nextTick(); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Child:willPatch", + "Child:patched", + "Child:willPatch", + "Child:patched", + ] + `); + expect(fixture.innerHTML).toBe("
    321321
    "); + }); + + test("two components are updated in parallel", async () => { + const testContext = createProxy({ value: 123 }); + + class Child extends Component { + static template = xml``; + contextObj = proxy(testContext); + setup() { + useLogLifecycle(this); + } + } + + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + setup() { + useLogLifecycle(this); + } + } + + await mount(Parent, fixture); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Parent:setup", + "Parent:willStart", + "Child:setup", + "Child:willStart", + "Child:setup", + "Child:willStart", + "Child:mounted", + "Child:mounted", + "Parent:mounted", + ] + `); + + expect(fixture.innerHTML).toBe("
    123123
    "); + testContext.value = 321; + await nextMicroTick(); + await nextMicroTick(); + expect(steps.splice(0)).toMatchInlineSnapshot(`[]`); + expect(fixture.innerHTML).toBe("
    123123
    "); + + await nextTick(); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Child:willPatch", + "Child:patched", + "Child:willPatch", + "Child:patched", + ] + `); + expect(fixture.innerHTML).toBe("
    321321
    "); + }); + + test("two independent components on different levels are updated in parallel", async () => { + const testContext = createProxy({ value: 123 }); + + class Child extends Component { + static template = xml``; + static components = {}; + contextObj = proxy(testContext); + setup() { + useLogLifecycle(this); + } + } + + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + setup() { + useLogLifecycle(this); + } + } + + class GrandFather extends Component { + static template = xml`
    `; + static components = { Child, Parent }; + setup() { + useLogLifecycle(this); + } + } + + await mount(GrandFather, fixture); + expect(fixture.innerHTML).toBe("
    123
    123
    "); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "GrandFather:setup", + "GrandFather:willStart", + "Child:setup", + "Child:willStart", + "Parent:setup", + "Parent:willStart", + "Child:setup", + "Child:willStart", + "Child:mounted", + "Parent:mounted", + "Child:mounted", + "GrandFather:mounted", + ] + `); + + testContext.value = 321; + await nextMicroTick(); + await nextMicroTick(); + expect(fixture.innerHTML).toBe("
    123
    123
    "); + expect(steps.splice(0)).toMatchInlineSnapshot(`[]`); + + await nextTick(); + expect(fixture.innerHTML).toBe("
    321
    321
    "); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Child:willPatch", + "Child:patched", + "Child:willPatch", + "Child:patched", + ] + `); + }); + + test("one components can subscribe twice to same context", async () => { + const testContext = createProxy({ a: 1, b: 2 }); + const steps: string[] = []; + + class Comp extends Component { + static template = xml`
    `; + contextObj1 = proxy(testContext); + contextObj2 = proxy(testContext); + + notify() { + steps.push("comp"); + } + } + await mount(Comp, fixture); + expect(fixture.innerHTML).toBe("
    12
    "); + expect(steps).toEqual(["comp"]); + testContext.a = 3; + await nextTick(); + expect(fixture.innerHTML).toBe("
    32
    "); + expect(steps).toEqual(["comp", "comp"]); + }); + + test("parent and children subscribed to same context", async () => { + const testContext = createProxy({ a: 123, b: 321 }); + const steps: string[] = []; + + class Child extends Component { + static template = xml``; + contextObj = proxy(testContext); + notify() { + steps.push("child"); + } + } + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + contextObj = proxy(testContext); + notify() { + steps.push("parent"); + } + } + const parent = await mount(Parent, fixture); + expect(fixture.innerHTML).toBe("
    123321
    "); + expect(steps).toEqual(["parent", "child"]); + + (parent as any).contextObj.a = 124; + await nextTick(); + expect(fixture.innerHTML).toBe("
    124321
    "); + + expect(steps).toEqual(["parent", "child", "child"]); + }); + + test.skip("several nodes on different level use same context", async () => { + const testContext = createProxy({ a: 123, b: 456 }); + const steps: Set = new Set(); + + /** + * Scheme: + * L1A + * / \ + * L2A L2B + * | + * L3A + */ + + class L3A extends Component { + static template = xml`
    `; + contextObj = proxy(testContext); + notify() { + steps.add("L3A"); + } + } + + class L2B extends Component { + static template = xml`
    `; + contextObj = proxy(testContext); + notify() { + steps.add("L2B"); + } + } + + class L2A extends Component { + static template = xml`
    `; + static components = { L3A }; + contextObj = proxy(testContext); + notify() { + steps.add("L2A"); + } + } + + class L1A extends Component { + static template = xml`
    `; + static components = { L2A, L2B }; + contextObj = proxy(testContext); + notify() { + steps.add("L1A"); + } + } + + await mount(L1A, fixture); + expect(fixture.innerHTML).toBe("
    123
    123 456
    456
    "); + expect([...steps]).toEqual(["L1A", "L2A", "L2B", "L3A"]); + steps.clear(); + + testContext.a = 321; + await nextMicroTick(); + await nextMicroTick(); + expect([...steps]).toEqual(["L2A"]); + await nextTick(); + expect([...steps]).toEqual(["L2A", "L3A"]); + expect(fixture.innerHTML).toBe("
    321
    321 456
    456
    "); + steps.clear(); + + testContext.b = 654; + await nextMicroTick(); + await nextMicroTick(); + expect([...steps]).toEqual(["L2B", "L3A"]); + await nextTick(); + expect([...steps]).toEqual(["L2B", "L3A"]); + expect(fixture.innerHTML).toBe("
    321
    321 654
    654
    "); + steps.clear(); + + testContext.a = 777; + testContext.b = 777; + await nextMicroTick(); + await nextMicroTick(); + expect([...steps]).toEqual(["L2A", "L2B"]); + await nextTick(); + expect([...steps]).toEqual(["L2A", "L2B", "L3A"]); + expect(fixture.innerHTML).toBe("
    777
    777 777
    777
    "); + steps.clear(); + + testContext.c = 444; + await nextMicroTick(); + await nextMicroTick(); + expect([...steps]).toEqual(["L1A"]); + await nextTick(); + expect([...steps]).toEqual(["L1A", "L2A", "L2B", "L3A"]); + }); + + test("destroyed component is inactive", async () => { + const testContext = createProxy({ a: 123 }); + + class Child extends Component { + static template = xml``; + contextObj = proxy(testContext); + setup() { + useLogLifecycle(this); + } + } + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + state = proxy({ flag: true }); + setup() { + useLogLifecycle(this); + } + } + const parent = await mount(Parent, fixture); + expect(fixture.innerHTML).toBe("
    123
    "); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Parent:setup", + "Parent:willStart", + "Child:setup", + "Child:willStart", + "Child:mounted", + "Parent:mounted", + ] + `); + + testContext.a = 321; + await nextTick(); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Child:willPatch", + "Child:patched", + ] + `); + + parent.state.flag = false; + await nextTick(); + expect(fixture.innerHTML).toBe("
    "); + expect(steps.splice(0)).toMatchInlineSnapshot(` + [ + "Parent:willPatch", + "Child:willUnmount", + "Child:willDestroy", + "Parent:patched", + ] + `); + + testContext.a = 456; + await nextTick(); + expect(steps.splice(0)).toMatchInlineSnapshot(`[]`); + }); + + test("destroyed component before being mounted is inactive", async () => { + const testContext = createProxy({ a: 123 }); + const steps: string[] = []; + class Child extends Component { + static template = xml``; + contextObj = proxy(testContext); + setup() { + onWillStart(() => { + return makeDeferred(); + }); + } + notify() { + steps.push("child"); + } + } + let parent: any; + class Parent extends Component { + static template = xml`
    `; + static components = { Child }; + state = proxy({ flag: true }); + setup() { + parent = this; + } + } + + const prom = mount(Parent, fixture); // cannot work + await nextTick(); // wait for Child to be instantiated + testContext.a = 321; + await nextMicroTick(); + parent.state.flag = false; + await prom; + expect(fixture.innerHTML).toBe("
    "); + testContext.a = 456; + await nextMicroTick(); + expect(steps).toEqual([]); + }); + + test("useless atoms should be deleted", async () => { + const testContext = createProxy({ + 1: { id: 1, quantity: 3, description: "First quantity" }, + 2: { id: 2, quantity: 5, description: "Second quantity" }, + }); + + const secondQuantity = testContext[2]; + + const steps: Set = new Set(); + + class Quantity extends Component { + static template = xml`
    `; + props = props(); + state = proxy(testContext[this.props.id]); + + notify() { + steps.add(`quantity${this.props.id}`); + } + } + + class ListOfQuantities extends Component { + static template = xml` +
    + + + + + Total: + Count: +
    `; + static components = { Quantity }; + state = proxy(testContext); + + notify() { + steps.add("list"); + } + + get total() { + let total = 0; + for (const { quantity } of Object.values(this.state) as any) { + total += quantity; + } + return total; + } + } + + await mount(ListOfQuantities, fixture); + expect(fixture.innerHTML).toBe("
    3
    5
    Total: 8 Count: 2
    "); + expect([...steps]).toEqual(["list", "quantity1", "quantity2"]); + steps.clear(); + + delete testContext[2]; + await nextMicroTick(); + await nextMicroTick(); + expect([...steps]).toEqual(["list"]); + await nextTick(); + expect(fixture.innerHTML).toBe("
    3
    Total: 3 Count: 1
    "); + expect([...steps]).toEqual(["list"]); + steps.clear(); + + secondQuantity.quantity = 2; + await nextMicroTick(); + await nextMicroTick(); + expect(fixture.innerHTML).toBe("
    3
    Total: 3 Count: 1
    "); + expect([...steps]).toEqual([]); + steps.clear(); + }); + + test.skip("concurrent renderings", async () => { + /** + * Note: this test is interesting, but sadly just an incomplete attempt at + * protecting users against themselves. With the context API, it is not + * possible for the framework to protect completely against crashes. Maybe + * like in this case, when a component is in a simple hierarchy where all + * renderings come from the context changes, but in a real case, where some + * code can trigger a rendering independently, it is insufficient. + * + * The main problem is that the sub component depends on some external state, + * which may be modified, and then incompatible with the component actual + * state (for example, if the sub component has an id key related to some + * object that has been removed from the context). + * + * For now, sadly, the only solution is that components that depends on external + * state should guarantee their own integrity themselves. Then maybe this + * could be solved at the level of a state management solution that has a + * more advanced API, to let components determine if they should be updated + * or not (so, something slightly more advanced that the useStore hook). + */ + const testContext = createProxy({ x: { n: 1 }, key: "x" }); + const def = makeDeferred(); + let stateC: any; + class ComponentC extends Component { + static template = xml``; + props = props(); + context = proxy(testContext); + state = proxy({ x: "a" }); + setup() { + stateC = this.state; + } + } + class ComponentB extends Component { + static components = { ComponentC }; + static template = xml`

    `; + props = props(); + setup() { + onWillUpdateProps(() => def); + } + } + class ComponentA extends Component { + static components = { ComponentB }; + static template = xml`
    `; + context = proxy(testContext); + } + + await mount(ComponentA, fixture); + + expect(fixture.innerHTML).toBe("

    1a

    "); + testContext.key = "y"; + testContext.y = { n: 2 }; + delete testContext.x; + await nextTick(); + + expect(fixture.innerHTML).toBe("

    1a

    "); + stateC.x = "b"; + await nextTick(); + + expect(fixture.innerHTML).toBe("

    1a

    "); + def.resolve(); + await nextTick(); + + expect(fixture.innerHTML).toBe("

    2b

    "); + }); +}); diff --git a/tests/reactivity/signals.test.ts b/tests/reactivity/signals.test.ts new file mode 100644 index 000000000..cbe4aa6af --- /dev/null +++ b/tests/reactivity/signals.test.ts @@ -0,0 +1,332 @@ +import { signal } from "../../src"; +import { expectSpy, spyEffect, waitScheduler } from "../helpers"; + +test("signal can be created and read", () => { + const s = signal(1); + expect(s()).toBe(1); +}); + +test("signal can be updated ", () => { + const s = signal(1); + expect(s()).toBe(1); + s.set(4); + expect(s()).toBe(4); +}); + +test("updating a signal trigger an effect", async () => { + const s = signal(1); + const e = spyEffect(() => s()); + e(); + expectSpy(e.spy, 1); + s.set(22); + expectSpy(e.spy, 1, { result: 1 }); + await waitScheduler(); + expectSpy(e.spy, 2, { result: 22 }); +}); + +test("invalidate a signal", async () => { + const s = signal(1); + const e = spyEffect(() => s()); + e(); + expectSpy(e.spy, 1); + s.set(1); + expectSpy(e.spy, 1, { result: 1 }); + await waitScheduler(); + expectSpy(e.spy, 1, { result: 1 }); + signal.invalidate(s); + expectSpy(e.spy, 1, { result: 1 }); + await waitScheduler(); + expectSpy(e.spy, 2, { result: 1 }); + + const fakeSignal = () => {}; + fakeSignal.set = () => {}; + expect(() => signal.invalidate(fakeSignal)).toThrow("Value is not a signal (() => { })"); +}); + +describe("signal.Array", () => { + test("simple use", async () => { + const reactiveArray = signal.Array([]); + + const e = spyEffect(() => reactiveArray()); + e(); + expectSpy(e.spy, 1); + + reactiveArray.set([1]); + expectSpy(e.spy, 1, { result: [] }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: [1] }); + + expect(reactiveArray()[0]).toEqual(1); + }); + + test("array element is reactive", async () => { + const reactiveArray = signal.Array([0]); + + const e = spyEffect(() => reactiveArray()[0]); + e(); + expectSpy(e.spy, 1); + + reactiveArray()[0] = 1; + expectSpy(e.spy, 1, { result: 0 }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: 1 }); + + reactiveArray.set([2]); + expectSpy(e.spy, 2, { result: 1 }); + + await waitScheduler(); + expectSpy(e.spy, 3, { result: 2 }); + }); + + test("data in array element is not reactive", async () => { + const obj = { value: 0 }; + const reactiveArray = signal.Array<{ value: number }>([obj]); + expect(reactiveArray()[0]).toBe(obj); + + const e = spyEffect(() => reactiveArray()[0].value); + e(); + expectSpy(e.spy, 1); + + reactiveArray()[0].value = 1; + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveArray()[0]).toBe(obj); + + await waitScheduler(); + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveArray()[0]).toBe(obj); + }); + + test("push an element invalidates the signal", async () => { + const reactiveArray = signal.Array([]); + + const e = spyEffect(() => reactiveArray()); + e(); + expectSpy(e.spy, 1); + + reactiveArray().push(1); + expectSpy(e.spy, 1, { result: [1] }); // array is changed inplace + + await waitScheduler(); + expectSpy(e.spy, 2, { result: [1] }); // reactive has been invalidated + + reactiveArray.set([2]); + expectSpy(e.spy, 2, { result: [1] }); + + await waitScheduler(); + expectSpy(e.spy, 3, { result: [2] }); + }); +}); + +describe("signal.Object", () => { + test("simple use", async () => { + const reactiveObject = signal.Object>({}); + + const e = spyEffect(() => reactiveObject()); + e(); + expectSpy(e.spy, 1); + + reactiveObject.set({ value: 1 }); + expectSpy(e.spy, 1, { result: {} }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: { value: 1 } }); + + expect(reactiveObject().value).toEqual(1); + }); + + test("object element is reactive", async () => { + const reactiveObject = signal.Object>({ a: 0 }); + + const e = spyEffect(() => reactiveObject().a); + e(); + expectSpy(e.spy, 1); + + reactiveObject().a = 1; + expectSpy(e.spy, 1, { result: 0 }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: 1 }); + + reactiveObject.set({ a: 2 }); + expectSpy(e.spy, 2, { result: 1 }); + + await waitScheduler(); + expectSpy(e.spy, 3, { result: 2 }); + }); + + test("data in object element are not reactive", async () => { + const obj = { value: 0 }; + const reactiveObject = signal.Object<{ data: { value: number } }>({ data: obj }); + expect(reactiveObject().data).toBe(obj); + + const e = spyEffect(() => reactiveObject().data.value); + e(); + expectSpy(e.spy, 1); + + reactiveObject().data.value = 1; + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveObject().data).toBe(obj); + + await waitScheduler(); + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveObject().data).toBe(obj); + }); + + test("add or remove element on object", async () => { + const reactiveObject = signal.Object>({}); + + const e = spyEffect(() => reactiveObject()); + e(); + expectSpy(e.spy, 1); + + reactiveObject().a = 1; + expectSpy(e.spy, 1, { result: { a: 1 } }); // array is changed inplace + + await waitScheduler(); + expectSpy(e.spy, 2, { result: { a: 1 } }); // reactive has been invalidated + + reactiveObject().b = 2; + expectSpy(e.spy, 2, { result: { a: 1, b: 2 } }); // array is changed inplace + + await waitScheduler(); + expectSpy(e.spy, 3, { result: { a: 1, b: 2 } }); // reactive has been invalidated + + delete reactiveObject().a; + expectSpy(e.spy, 3, { result: { b: 2 } }); // array is changed inplace + + await waitScheduler(); + expectSpy(e.spy, 4, { result: { b: 2 } }); // reactive has been invalidated + }); +}); + +describe("signal.Map", () => { + test("simple use", async () => { + const reactiveMap = signal.Map(new Map()); + + const e = spyEffect(() => reactiveMap().get("a")); + e(); + expectSpy(e.spy, 1); + + reactiveMap().set("a", 1); + expectSpy(e.spy, 1, { result: undefined }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: 1 }); + }); + + test("Map item is not reactive", async () => { + const obj = { value: 0 }; + const reactiveMap = signal.Map(new Map([["a", obj]])); + expect(reactiveMap().get("a")).toBe(obj); + + const e = spyEffect(() => reactiveMap().get("a")!.value); + e(); + expectSpy(e.spy, 1); + + reactiveMap().get("a")!.value = 1; + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveMap().get("a")).toBe(obj); + + await waitScheduler(); + expectSpy(e.spy, 1, { result: 0 }); + expect(reactiveMap().get("a")).toBe(obj); + }); + + test("set or delete element on map", async () => { + const reactiveMap = signal.Map(new Map()); + + const e = spyEffect(() => [...reactiveMap()]); + e(); + expectSpy(e.spy, 1); + + reactiveMap().set("a", 1); + expectSpy(e.spy, 1, { result: [] }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: [["a", 1]] }); + + reactiveMap().set("b", 2); + expectSpy(e.spy, 2, { result: [["a", 1]] }); + + await waitScheduler(); + expectSpy(e.spy, 3, { + result: [ + ["a", 1], + ["b", 2], + ], + }); + + reactiveMap().delete("a"); + expectSpy(e.spy, 3, { + result: [ + ["a", 1], + ["b", 2], + ], + }); + + await waitScheduler(); + expectSpy(e.spy, 4, { result: [["b", 2]] }); + }); +}); + +describe("signal.Set", () => { + test("simple use", async () => { + const reactiveSet = signal.Set(new Set()); + + const e = spyEffect(() => [...reactiveSet()]); + e(); + expectSpy(e.spy, 1); + + reactiveSet().add(1); + expectSpy(e.spy, 1, { result: [] }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: [1] }); + }); + + test("Set item is not reactive", async () => { + const obj = { value: 0 }; + const reactiveSet = signal.Set(new Set<{ value: number }>([obj])); + expect(reactiveSet().values().next().value).toBe(obj); + + const e = spyEffect(() => [...reactiveSet()]); + e(); + expectSpy(e.spy, 1); + + reactiveSet().values().next().value!.value = 1; + expectSpy(e.spy, 1, { result: [{ value: 1 }] }); // changed inplace + expect(reactiveSet().values().next().value).toBe(obj); + + await waitScheduler(); + expectSpy(e.spy, 1, { result: [{ value: 1 }] }); + expect(reactiveSet().values().next().value).toBe(obj); + }); + + test("add or delete item on Set", async () => { + const reactiveSet = signal.Set(new Set()); + + const e = spyEffect(() => [...reactiveSet()]); + e(); + expectSpy(e.spy, 1); + + reactiveSet().add(1); + expectSpy(e.spy, 1, { result: [] }); + + await waitScheduler(); + expectSpy(e.spy, 2, { result: [1] }); + + reactiveSet().add(2); + expectSpy(e.spy, 2, { result: [1] }); + + await waitScheduler(); + expectSpy(e.spy, 3, { result: [1, 2] }); + + reactiveSet().delete(1); + expectSpy(e.spy, 3, { result: [1, 2] }); + + await waitScheduler(); + expectSpy(e.spy, 4, { result: [2] }); + }); +}); diff --git a/tests/registry.test.ts b/tests/registry.test.ts new file mode 100644 index 000000000..9e5fe0277 --- /dev/null +++ b/tests/registry.test.ts @@ -0,0 +1,127 @@ +import { effect, types as t } from "../src"; +import { Registry } from "../src/runtime/registry"; +import { nextMicroTick } from "./helpers"; + +async function waitScheduler() { + await nextMicroTick(); + await nextMicroTick(); +} + +describe("registry", () => { + test("can set and get values", () => { + const registry = new Registry(); + + registry.add("key", "some value"); + expect(registry.get("key")).toBe("some value"); + }); + + test("can check if it has a key/value set", () => { + const registry = new Registry(); + + expect(registry.has("key")).toBe(false); + expect(registry.has("otherkey")).toBe(false); + registry.add("key", "some value"); + expect(registry.has("key")).toBe(true); + expect(registry.has("otherkey")).toBe(false); + }); + + test("can set and remove values", () => { + const registry = new Registry(); + + registry.add("key", "some value"); + expect(registry.get("key")).toBe("some value"); + registry.delete("key"); + }); + + test("set method returns the registry, so it is chainable", () => { + const registry = new Registry(); + + registry.add("key", "some value").add("other", "value"); + expect(registry.get("key")).toBe("some value"); + expect(registry.get("other")).toBe("value"); + }); + + test("can add element from id and get values", () => { + const registry = new Registry(); + const obj = { id: "key", value: 3 }; + registry.addById(obj); + expect(registry.get("key")).toBe(obj); + }); + + test("get default values", () => { + const registry = new Registry(); + + expect(registry.get("key", 1)).toBe(1); + registry.add("key", "some value"); + expect(registry.get("key", 1)).toBe("some value"); + }); + + test("items", async () => { + const registry = new Registry(); + + registry.add("key", "some value"); + const items = registry.items; + expect(items()).toEqual(["some value"]); + registry.add("other_key", "other value"); + expect(items()).toEqual(["some value", "other value"]); + expect(registry.get("key")).toBe("some value"); + }); + + test("items and effects", async () => { + const registry: Registry = new Registry(); + + registry.add("key", "a"); + const items = registry.items; + const steps: string[] = []; + + effect(() => { + steps.push(...items()); + }); + expect(steps).toEqual(["a"]); + registry.add("b", "b"); + expect(steps).toEqual(["a"]); + await waitScheduler(); + expect(steps).toEqual(["a", "a", "b"]); + }); + + test("sequence", async () => { + const registry = new Registry(); + + registry.add("a", "a", { sequence: 10 }); + registry.add("b", "b"); + registry.add("c", "c", { sequence: 14 }); + registry.add("d", "d", { sequence: 100 }); + + const items = registry.items; + expect(items()).toEqual(["a", "c", "b", "d"]); + }); + + test("validation schema", async () => { + const registry = new Registry({ + name: "test", + validation: t.object({ + blip: t.string, + }), + }); + + registry.add("a", { blip: "asdf" }); + expect(() => { + registry.add("a", { blip: 1 } as any); + }).toThrow("Registry entry does not match the type"); + }); + + test("validation schema, with a class", async () => { + class A {} + class B {} + + const registry = new Registry({ + name: "test", + validation: t.instanceOf(A), + }); + + registry.add("a", new A()); + expect(() => { + registry.add("a", new B()); + }).toThrow("Registry entry does not match the type"); + }); +}); diff --git a/tests/resource.test.ts b/tests/resource.test.ts new file mode 100644 index 000000000..0a906388b --- /dev/null +++ b/tests/resource.test.ts @@ -0,0 +1,93 @@ +import { effect, types as t } from "../src"; +import { Resource } from "../src/runtime/resource"; +import { waitScheduler } from "./helpers"; + +test("can add and get values", () => { + const resource = new Resource(); + expect(resource.items()).toEqual([]); + resource.add("value"); + expect(resource.items()).toEqual(["value"]); +}); + +test("can check if it contains values", () => { + const resource = new Resource(); + + expect(resource.has("value")).toBe(false); + resource.add("value"); + expect(resource.has("value")).toBe(true); +}); + +test("can add multiple values (chainable)", () => { + const resource = new Resource(); + expect(resource.items()).toEqual([]); + resource.add("value").add("other"); + expect(resource.items()).toEqual(["value", "other"]); +}); + +test("can remove values", () => { + const resource = new Resource(); + resource.add("a").add("b").add("c").add("d"); + expect(resource.items()).toEqual(["a", "b", "c", "d"]); + resource.delete("b"); + expect(resource.items()).toEqual(["a", "c", "d"]); + resource.delete("a").delete("d"); + expect(resource.items()).toEqual(["c"]); +}); + +test("sequence", async () => { + const resource = new Resource({ name: "r" }); + + resource.add("a", { sequence: 10 }); + resource.add("b"); // default = 50 + resource.add("c", { sequence: 14 }); + resource.add("d", { sequence: 100 }); + + const items = resource.items; + expect(items()).toEqual(["a", "c", "b", "d"]); +}); + +test("items and effects", async () => { + const resource: Resource = new Resource(); + + resource.add("a"); + const items = resource.items; + const steps: string[] = []; + + effect(() => { + steps.push(...items()); + }); + expect(steps).toEqual(["a"]); + resource.add("b"); + expect(steps).toEqual(["a"]); + await waitScheduler(); + expect(steps).toEqual(["a", "a", "b"]); +}); + +test("validation schema", async () => { + const resource = new Resource({ + name: "test", + validation: t.object({ + blip: t.string, + }), + }); + + resource.add({ blip: "asdf" }); + expect(() => { + resource.add({ blip: 1 } as any); + }).toThrow("Resource item does not match the type"); +}); + +test("validation schema, with a class", async () => { + class A {} + class B {} + + const resource = new Resource({ + name: "test", + validation: t.instanceOf(A), + }); + + resource.add(new A()); + expect(() => { + resource.add(new B()); + }).toThrow("Resource item does not match the type"); +}); diff --git a/tests/shadow_dom/__snapshots__/shadow_dom.test.ts.snap b/tests/shadow_dom/__snapshots__/shadow_dom.test.ts.snap index 6a2bf9a19..a9722bfcb 100644 --- a/tests/shadow_dom/__snapshots__/shadow_dom.test.ts.snap +++ b/tests/shadow_dom/__snapshots__/shadow_dom.test.ts.snap @@ -1,14 +1,15 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`shadow_dom can bind event handler 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const hdlr_fn1 = (ctx, ev) => (ctx['this'].add).call(ctx['this'], ev); - let block1 = createBlock(\`\`); + let block1 = createBlock(\`\`); - return function template(ctx, node, key = \\"\\") { - let hdlr1 = [ctx['add'], ctx]; + return function template(ctx, node, key = "") { + let hdlr1 = [hdlr_fn1, ctx]; return block1([hdlr1]); } }" @@ -19,9 +20,9 @@ exports[`shadow_dom can mount app 1`] = ` ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { return block1(); } }" @@ -32,9 +33,9 @@ exports[`shadow_dom can mount app in closed shadow dom 1`] = ` ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { return block1(); } }" @@ -45,9 +46,9 @@ exports[`shadow_dom can mount app inside a separate HTML document 1`] = ` ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { return block1(); } }" @@ -58,9 +59,9 @@ exports[`shadow_dom can mount app inside a shadow child element 1`] = ` ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { return block1(); } }" @@ -71,23 +72,24 @@ exports[`shadow_dom can mount app inside an element in a shadow root inside an i ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { + return function template(ctx, node, key = "") { return block1(); } }" `; -exports[`shadow_dom useRef hook 1`] = ` +exports[`shadow_dom ref 1`] = ` "function anonymous(app, bdom, helpers ) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; + let { createRef } = helpers; - let block1 = createBlock(\`
    \`); + let block1 = createBlock(\`
    \`); - return function template(ctx, node, key = \\"\\") { - let ref1 = (el) => this.__owl__.setRef((\`refName\`), el); + return function template(ctx, node, key = "") { + let ref1 = createRef(ctx['this'].div); return block1([ref1]); } }" diff --git a/tests/shadow_dom/shadow_dom.test.ts b/tests/shadow_dom/shadow_dom.test.ts index 698481137..9f9cf385c 100644 --- a/tests/shadow_dom/shadow_dom.test.ts +++ b/tests/shadow_dom/shadow_dom.test.ts @@ -1,4 +1,4 @@ -import { App, Component, useRef, xml } from "../../src"; +import { App, Component, mount, signal, xml } from "../../src"; import { status } from "../../src/runtime/status"; import { makeTestFixture, snapshotEverything } from "../helpers"; @@ -19,8 +19,8 @@ describe("shadow_dom", () => { const container = document.createElement("div"); fixture.appendChild(container); const shadow = container.attachShadow({ mode: "open" }); - const app = new App(SomeComponent); - const comp = await app.mount(shadow); + const app = new App(); + const comp = await app.createRoot(SomeComponent).mount(shadow); const div = shadow.querySelector(".my-div"); expect(div).not.toBe(null); expect(shadow.contains(div)).toBe(true); @@ -37,8 +37,8 @@ describe("shadow_dom", () => { const container = document.createElement("div"); fixture.appendChild(container); const shadow = container.attachShadow({ mode: "closed" }); - const app = new App(SomeComponent); - const comp = await app.mount(shadow); + const app = new App(); + const comp = await app.createRoot(SomeComponent).mount(shadow); const div = shadow.querySelector(".my-div"); expect(div).not.toBe(null); expect(shadow.contains(div)).toBe(true); @@ -50,7 +50,7 @@ describe("shadow_dom", () => { test("can bind event handler", async () => { let a = 1; class SomeComponent extends Component { - static template = xml``; + static template = xml``; add() { a = 3; @@ -59,17 +59,17 @@ describe("shadow_dom", () => { const container = document.createElement("div"); fixture.appendChild(container); const shadow = container.attachShadow({ mode: "open" }); - await new App(SomeComponent).mount(shadow); + await mount(SomeComponent, shadow); expect(a).toBe(1); shadow.querySelector("button")!.click(); expect(a).toBe(3); }); - test("useRef hook", async () => { + test("ref", async () => { let comp: SomeComponent; class SomeComponent extends Component { - static template = xml`
    `; - div = useRef("refName"); + static template = xml`
    `; + div = signal(null); setup() { comp = this; } @@ -77,10 +77,10 @@ describe("shadow_dom", () => { const container = document.createElement("div"); fixture.appendChild(container); const shadow = container.attachShadow({ mode: "open" }); - const mountedProm = new App(SomeComponent).mount(shadow); - expect(comp!.div.el).toBe(null); + const mountedProm = mount(SomeComponent, shadow); + expect(comp!.div()).toBe(null); await mountedProm; - expect(comp!.div.el).toBe(shadow.querySelector(".my-div")); + expect(comp!.div()).toBe(shadow.querySelector(".my-div")); }); test("can mount app inside a shadow child element", async () => { @@ -90,8 +90,8 @@ describe("shadow_dom", () => { const shadow = fixture.attachShadow({ mode: "open" }); const shadowDiv = document.createElement("div"); shadow.append(shadowDiv); - const app = new App(SomeComponent); - const comp = await app.mount(shadowDiv); + const app = new App(); + const comp = await app.createRoot(SomeComponent).mount(shadowDiv); const div = shadow.querySelector(".my-div"); expect(div).not.toBe(null); expect(shadow.contains(div)).toBe(true); @@ -109,10 +109,10 @@ describe("shadow_dom", () => { const container = separateDoc.createElement("div"); separateDoc.body.appendChild(container); - const app = new App(SomeComponent); + const app = new App(); let error: Error; try { - await app.mount(container); + await app.createRoot(SomeComponent).mount(container); } catch (e) { error = e as Error; } @@ -139,8 +139,8 @@ describe("shadow_dom", () => { const shadowTarget = iframeDoc.createElement("div"); shadow.appendChild(shadowTarget); - const app = new App(SomeComponent); - const comp = await app.mount(shadowTarget); + const app = new App(); + const comp = await app.createRoot(SomeComponent).mount(shadowTarget); const div = shadow.querySelector(".my-div"); expect(div).not.toBe(null); diff --git a/tests/validation.test.ts b/tests/validation.test.ts index b5e8bba12..fc67129f0 100644 --- a/tests/validation.test.ts +++ b/tests/validation.test.ts @@ -1,311 +1,598 @@ -import { Schema, validateSchema } from "../src/runtime/validation"; +import { assertType, computed, signal, types as t, validateType } from "../src"; -describe("validateSchema", () => { - test("simple use", () => { - expect(validateSchema({ a: "hey" }, { a: String })).toEqual([]); - expect(validateSchema({ a: 1 }, { a: Boolean })).toEqual(["'a' is not a boolean"]); - }); +class A {} - test("simple use, alternate form", () => { - expect(validateSchema({ a: "hey" }, { a: { type: String } })).toEqual([]); - expect(validateSchema({ a: 1 }, { a: { type: Boolean } })).toEqual(["'a' is not a boolean"]); - }); +test("simple assertion", () => { + expect(() => assertType("hey", t.string)).not.toThrow(); + expect(() => assertType({}, t.object())).not.toThrow(); + expect(() => assertType([], t.array())).not.toThrow(); + expect(() => assertType(1, t.boolean)).toThrow("Value does not match the type"); +}); - test("some particular edgecases as key name", () => { - expect(validateSchema({ shape: "hey" }, { shape: String })).toEqual([]); - expect(validateSchema({ shape: 1 }, { shape: Boolean })).toEqual(["'shape' is not a boolean"]); - expect(validateSchema({ element: "hey" }, { element: String })).toEqual([]); - expect(validateSchema({ element: 1 }, { element: Boolean })).toEqual([ - "'element' is not a boolean", - ]); - }); +test("validateType", () => { + expect(validateType("abc", t.string)).toMatchObject([]); + expect(validateType("abc", t.number)).toMatchObject([{ message: "value is not a number" }]); + expect(validateType(undefined, t.number)).toMatchObject([{ message: "value is not a number" }]); + expect(validateType(1, t.number)).toEqual([]); +}); - test("multiple errors", () => { - expect(validateSchema({ a: 1, b: 2 }, { a: Boolean, b: Boolean })).toEqual([ - "'a' is not a boolean", - "'b' is not a boolean", - ]); - }); +test("and", () => { + const a = t.object({ a: t.string }); + const b = t.object({ b: t.number }); + expect(validateType({}, t.and([a, b]))).toMatchObject([ + { message: "object value have missing keys", missingKeys: ["a"] }, + { message: "object value have missing keys", missingKeys: ["b"] }, + ]); + expect(validateType({ a: "abc" }, t.and([a, b]))).toMatchObject([ + { message: "object value have missing keys", missingKeys: ["b"] }, + ]); + expect(validateType({ a: 123 }, t.and([a, b]))).toMatchObject([ + { message: "value is not a string", path: ["a"] }, + { message: "object value have missing keys", missingKeys: ["b"] }, + ]); + expect(validateType({ a: "abc", b: 123 }, t.and([a, b]))).toEqual([]); + expect(validateType({ b: 123 }, t.and([a, b]))).toMatchObject([ + { message: "object value have missing keys", missingKeys: ["a"] }, + ]); + expect(validateType({ a: "abc", b: "abc" }, t.and([a, b]))).toMatchObject([ + { message: "value is not a number", path: ["b"] }, + ]); +}); - test("missing key", () => { - expect(validateSchema({}, { a: Boolean })).toEqual(["'a' is missing (should be a boolean)"]); - }); +test("any", () => { + expect(validateType("", t.any)).toEqual([]); + expect(validateType("abc", t.any)).toEqual([]); + expect(validateType(true, t.any)).toEqual([]); + expect(validateType(false, t.any)).toEqual([]); + expect(validateType(123, t.any)).toEqual([]); + expect(validateType(987, t.any)).toEqual([]); + expect(validateType(undefined, t.any)).toEqual([]); + expect(validateType(null, t.any)).toEqual([]); + expect(validateType({}, t.any)).toEqual([]); + expect(validateType({ a: 1, b: "", c: { a: true } }, t.any)).toEqual([]); + expect(validateType([{ a: 1 }, { b: 2 }], t.any)).toEqual([]); + expect(validateType(() => {}, t.any)).toEqual([]); + expect(validateType(A, t.any)).toEqual([]); + expect(validateType(new A(), t.any)).toEqual([]); +}); - test("additional key", () => { - expect(validateSchema({ b: 1 }, {})).toEqual(["unknown key 'b'"]); - }); +test("array", () => { + expect(validateType({}, t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType("", t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType("abc", t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType(123, t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType(987, t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType(true, t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType({}, t.array())).toMatchObject([{ message: "value is not an array" }]); + expect(validateType([], t.array())).toEqual([]); + expect(validateType([123], t.array())).toEqual([]); + expect(validateType(["abc"], t.array())).toEqual([]); + expect(validateType(["abc", 123], t.array())).toEqual([]); + expect(validateType(["abc", 123, false], t.array())).toEqual([]); + expect(validateType(["abc"], t.array(t.string))).toEqual([]); + expect(validateType([123, "abc"], t.array(t.string))).toMatchObject([ + { message: "value is not a string", path: [0] }, + ]); + expect(validateType(["abc", "def"], t.array(t.string))).toEqual([]); + expect(validateType(["abc", 321], t.array(t.string))).toMatchObject([ + { message: "value is not a string", path: [1] }, + ]); +}); - test("undefined key", () => { - expect(validateSchema({ a: undefined }, { a: Boolean })).toEqual([ - "'a' is undefined (should be a boolean)", - ]); - expect(validateSchema({}, { a: Boolean })).toEqual(["'a' is missing (should be a boolean)"]); - }); +test("boolean", () => { + const issue = { message: "value is not a boolean" }; + expect(validateType(true, t.boolean)).toEqual([]); + expect(validateType(false, t.boolean)).toEqual([]); + expect(validateType("", t.boolean)).toMatchObject([issue]); + expect(validateType("abc", t.boolean)).toMatchObject([issue]); + expect(validateType(123, t.boolean)).toMatchObject([issue]); + expect(validateType(987, t.boolean)).toMatchObject([issue]); + expect(validateType(undefined, t.boolean)).toMatchObject([issue]); + expect(validateType(null, t.boolean)).toMatchObject([issue]); + expect(validateType({}, t.boolean)).toMatchObject([issue]); + expect(validateType([], t.boolean)).toMatchObject([issue]); + expect(validateType(A, t.boolean)).toMatchObject([issue]); + expect(validateType(new A(), t.boolean)).toMatchObject([issue]); +}); - test("can use '*' to denote any type", () => { - expect(validateSchema({ a: "hey" }, { a: "*" })).toEqual([]); - expect(validateSchema({}, { a: "*" })).toEqual(["'a' is missing"]); - }); +test("constructor", () => { + class B extends A {} + class C {} + const issue = { message: "value is not 'A' or an extension" }; + expect(validateType(true, t.constructor(A))).toMatchObject([issue]); + expect(validateType("abc", t.constructor(A))).toMatchObject([issue]); + expect(validateType(123, t.constructor(A))).toMatchObject([issue]); + expect(validateType(A, t.constructor(A))).toEqual([]); + expect(validateType(B, t.constructor(A))).toEqual([]); + expect(validateType(C, t.constructor(A))).toMatchObject([issue]); + expect(validateType(A, t.constructor(B))).toMatchObject([ + { message: "value is not 'B' or an extension" }, + ]); + expect(validateType(B, t.constructor(B))).toEqual([]); + expect(validateType(C, t.constructor(B))).toMatchObject([ + { message: "value is not 'B' or an extension" }, + ]); + expect(validateType(A, t.constructor(C))).toMatchObject([ + { message: "value is not 'C' or an extension" }, + ]); + expect(validateType(B, t.constructor(C))).toMatchObject([ + { message: "value is not 'C' or an extension" }, + ]); + expect(validateType(C, t.constructor(C))).toEqual([]); + expect(validateType({}, t.constructor(A))).toMatchObject([issue]); + expect(validateType(new A(), t.constructor(A))).toMatchObject([issue]); + expect(validateType(new B(), t.constructor(A))).toMatchObject([issue]); + expect(validateType(new C(), t.constructor(A))).toMatchObject([issue]); + expect(validateType([], t.constructor(A))).toMatchObject([issue]); + expect(validateType(() => {}, t.constructor(A))).toMatchObject([issue]); +}); - test("an union of type", () => { - expect(validateSchema({ a: "hey" }, { a: [String, Boolean] })).toEqual([]); - expect(validateSchema({ a: 1 }, { a: [String, Boolean] })).toEqual([ - "'a' is not a string or boolean", - ]); - expect(validateSchema({ a: "hey" }, { a: { type: [String, Boolean] } })).toEqual([]); - }); +test("customValidator", () => { + const validator = t.customValidator(t.string, (size) => ["sm", "md", "lg"].includes(size)); + expect(validateType(123, validator)).toMatchObject([{ message: "value is not a string" }]); + expect(validateType("sm", validator)).toEqual([]); + expect(validateType("md", validator)).toEqual([]); + expect(validateType("lg", validator)).toEqual([]); + expect(validateType("small", validator)).toMatchObject([ + { message: "value does not match custom validation" }, + ]); + expect( + validateType( + "small", + t.customValidator(t.string, (size) => ["sm", "md", "lg"].includes(size), "Invalid") + ) + ).toMatchObject([{ message: "Invalid" }]); +}); - test("another union of types", () => { - const schema: Schema = { - id: Number, - url: [Boolean, { type: Array, element: Number }], - }; - expect(validateSchema({ a: "hey" }, schema)).toEqual([ - "unknown key 'a'", - "'id' is missing (should be a number)", - "'url' is missing (should be a boolean or list of numbers)", - ]); - expect(validateSchema({ id: 1 }, schema)).toEqual([ - "'url' is missing (should be a boolean or list of numbers)", +describe("function", () => { + test("function", () => { + expect(validateType(123, t.function())).toMatchObject([{ message: "value is not a function" }]); + expect(validateType("abc", t.function())).toMatchObject([ + { message: "value is not a function" }, ]); - expect(validateSchema({ id: 1, url: true }, schema)).toEqual([]); - expect(validateSchema({ id: true, url: true }, schema)).toEqual(["'id' is not a number"]); - expect(validateSchema({ id: 3, url: 3 }, schema)).toEqual([ - "'url' is not a boolean or list of numbers", + expect(validateType(true, t.function())).toMatchObject([ + { message: "value is not a function" }, ]); + expect(validateType(() => {}, t.function())).toEqual([]); + expect(validateType(function () {}, t.function())).toEqual([]); + expect(validateType(A, t.function())).toEqual([]); // Should return an issue }); - test("simplified schema description", () => { - expect(validateSchema({ a: "hey" }, ["a"])).toEqual([]); - expect(validateSchema({ b: 1 }, ["a"])).toEqual(["unknown key 'b'", "'a' is missing"]); + test("parameters and return types are not checked", () => { + expect(validateType(() => {}, t.function([t.string], t.boolean))).toEqual([]); + expect(validateType(function () {}, t.function([t.string], t.boolean))).toEqual([]); }); +}); - test("simplified schema description with optional props and *", () => { - expect(validateSchema({ a: "hey" }, ["a", "b?", "*"])).toEqual([]); - expect(validateSchema({ a: "hey" }, ["a", "*"])).toEqual([]); - expect(validateSchema({ a: "hey", b: 1, c: 3 }, ["a", "*"])).toEqual([]); - }); +test("instanceOf", () => { + class B extends A {} + class C {} + const issue = { message: "value is not an instance of 'A'" }; + expect(validateType(123, t.instanceOf(A))).toMatchObject([issue]); + expect(validateType("abc", t.instanceOf(A))).toMatchObject([issue]); + expect(validateType(true, t.instanceOf(A))).toMatchObject([issue]); + expect(validateType({}, t.instanceOf(A))).toMatchObject([issue]); + expect(validateType([], t.instanceOf(A))).toMatchObject([issue]); + expect(validateType(new A(), t.instanceOf(A))).toEqual([]); + expect(validateType(new B(), t.instanceOf(A))).toEqual([]); + expect(validateType(new C(), t.instanceOf(A))).toMatchObject([issue]); +}); - test("simplified schema description with optional props", () => { - expect(validateSchema({ a: "hey" }, ["a", "b?"])).toEqual([]); - expect(validateSchema({ a: "hey", b: 1 }, ["a", "b?"])).toEqual([]); - }); +test("literal", () => { + expect(validateType(123, t.literal(123))).toEqual([]); + expect(validateType(321, t.literal(123))).toMatchObject([ + { message: "value is not equal to 123" }, + ]); + expect(validateType("abc", t.literal("abc"))).toEqual([]); + expect(validateType("", t.literal("abc"))).toMatchObject([ + { message: "value is not equal to 'abc'" }, + ]); + expect(validateType("abc", t.literal(""))).toMatchObject([ + { message: "value is not equal to ''" }, + ]); + expect(validateType(123, t.literal(""))).toMatchObject([{ message: "value is not equal to ''" }]); + expect(validateType("", t.literal(123))).toMatchObject([ + { message: "value is not equal to 123" }, + ]); + expect(validateType(true, t.literal(true))).toEqual([]); + expect(validateType(false, t.literal(true))).toMatchObject([ + { message: "value is not equal to true" }, + ]); + expect(validateType(null, t.literal(null))).toEqual([]); + expect(validateType(true, t.literal(null))).toMatchObject([ + { message: "value is not equal to null" }, + ]); + expect(validateType(null, t.literal(false))).toMatchObject([ + { message: "value is not equal to false" }, + ]); + expect(validateType(undefined, t.literal(undefined))).toEqual([]); + expect(validateType(123, t.literal(undefined))).toMatchObject([ + { message: "value is not equal to undefined" }, + ]); + expect(validateType("abc", t.literal(undefined))).toMatchObject([ + { message: "value is not equal to undefined" }, + ]); + expect(validateType(null, t.literal(undefined))).toMatchObject([ + { message: "value is not equal to undefined" }, + ]); +}); - test("object type description, with no type/optional key", () => { - expect(validateSchema({ a: "hey" }, { a: {} })).toEqual([]); - expect(validateSchema({ a: 1 }, { a: {} })).toEqual([]); - expect(validateSchema({}, { a: {} })).toEqual(["'a' is missing"]); - }); +test("number", () => { + const issue = { message: "value is not a number" }; + expect(validateType(123, t.number)).toEqual([]); + expect(validateType(987, t.number)).toEqual([]); + expect(validateType(true, t.number)).toMatchObject([issue]); + expect(validateType(false, t.number)).toMatchObject([issue]); + expect(validateType("", t.number)).toMatchObject([issue]); + expect(validateType("abc", t.number)).toMatchObject([issue]); + expect(validateType(undefined, t.number)).toMatchObject([issue]); + expect(validateType(null, t.number)).toMatchObject([issue]); + expect(validateType({}, t.number)).toMatchObject([issue]); + expect(validateType([], t.number)).toMatchObject([issue]); + expect(validateType(A, t.number)).toMatchObject([issue]); + expect(validateType(new A(), t.number)).toMatchObject([issue]); +}); - test("optional key", () => { - expect(validateSchema({}, { a: { optional: true } })).toEqual([]); - expect(validateSchema({}, { a: { type: Number, optional: true } })).toEqual([]); - expect(validateSchema({ a: undefined }, { a: { type: Number, optional: true } })).toEqual([]); - expect(validateSchema({ a: 2 }, { a: { optional: true } })).toEqual([]); - expect(validateSchema({ a: undefined }, { a: { optional: true } })).toEqual([]); - expect(validateSchema({ a: 2 }, { a: { type: Number, optional: true } })).toEqual([]); - expect(validateSchema({ a: 2 }, { a: { type: String, optional: true } })).toEqual([ - "'a' is not a string", +describe("object", () => { + test("shaped object", () => { + expect(validateType(123, t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, ]); - }); - - test("can validate dates", () => { - expect(validateSchema({ a: new Date() }, { a: Date })).toEqual([]); - expect(validateSchema({ a: 4 }, { a: Date })).toEqual(["'a' is not a date"]); - }); - - test("arrays with simple element description", () => { - const schema: Schema = { p: { type: Array, element: String } }; - expect(validateSchema({ p: [] }, schema)).toEqual([]); - expect(validateSchema({ p: 1 }, schema)).toEqual(["'p' is not a list of strings"]); - expect(validateSchema({}, schema)).toEqual(["'p' is missing (should be a list of strings)"]); - expect(validateSchema({ p: undefined }, schema)).toEqual([ - "'p' is undefined (should be a list of strings)", + expect(validateType("abc", t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, ]); - expect(validateSchema({ p: ["a"] }, schema)).toEqual([]); - expect(validateSchema({ p: [1] }, schema)).toEqual(["'p[0]' is not a string"]); - }); - - test("arrays with union type as element description", () => { - const schema: Schema = { p: { type: Array, element: [String, Boolean] } }; - expect(validateSchema({ p: [] }, schema)).toEqual([]); - expect(validateSchema({ p: 1 }, schema)).toEqual(["'p' is not a list of string or booleans"]); - expect(validateSchema({}, schema)).toEqual([ - "'p' is missing (should be a list of string or booleans)", + expect(validateType(true, t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, ]); - expect(validateSchema({ p: undefined }, schema)).toEqual([ - "'p' is undefined (should be a list of string or booleans)", + expect(validateType(null, t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, ]); - expect(validateSchema({ p: ["a"] }, schema)).toEqual([]); - expect(validateSchema({ p: [1] }, schema)).toEqual(["'p[0]' is not a string or boolean"]); - expect(validateSchema({ p: [true, 1] }, schema)).toEqual(["'p[1]' is not a string or boolean"]); - }); - - test("objects with specified shape", () => { - const schema: Schema = { p: { type: Object, shape: { id: Number, url: String } } }; - expect(validateSchema({ p: [] }, schema)).toEqual(["'p' is not an object"]); - expect(validateSchema({ p: {} }, schema)).toEqual([ - "'p' doesn't have the correct shape ('id' is missing (should be a number), 'url' is missing (should be a string))", + expect(validateType(undefined, t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType([], t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType(() => {}, t.object({}))).toMatchObject([ + { message: "value is not an object", path: [] }, ]); - expect(validateSchema({ p: { id: 1, url: "asf" } }, schema)).toEqual([]); - expect(validateSchema({ p: { id: 1, url: 1 } }, schema)).toEqual([ - "'p' doesn't have the correct shape ('url' is not a string)", + expect(validateType({}, t.object({}))).toEqual([]); + expect(validateType({ a: 1 }, t.object({}))).toEqual([]); + expect(validateType({ a: 1 }, t.object({ a: t.number }))).toEqual([]); + expect(validateType({ a: 1 }, t.object({ a: t.string }))).toMatchObject([ + { message: "value is not a string", path: ["a"] }, ]); - expect(validateSchema({ p: undefined }, schema)).toEqual([ - "'p' is undefined (should be a object)", + expect(validateType({ b: 1 }, t.object({ a: t.string }))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a"] }, ]); + expect(validateType({ a: 1, b: "b" }, t.object({ b: t.string }))).toEqual([]); }); - test("objects with a values schema", () => { - const schema: Schema = { - p: { type: Object, values: { type: Object, shape: { id: Number, url: String } } }, - }; - expect(validateSchema({ p: [] }, schema)).toEqual(["'p' is not an object"]); - expect(validateSchema({ p: {} }, schema)).toEqual([]); - expect(validateSchema({ p: { id: 1, url: "asf" } }, schema)).toEqual([ - "some of the values in 'p' are invalid ('id' is not an object, 'url' is not an object)", + test("shaped object with optional key", () => { + expect(validateType({}, t.object({ a: t.number }))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a"] }, ]); - expect( - validateSchema( - { - p: { - a: { id: 1, url: "asf" }, - }, - }, - schema - ) - ).toEqual([]); - expect( - validateSchema( - { - p: { - a: { id: 1, url: "asf" }, - b: { id: 1, url: 1 }, - }, - }, - schema - ) - ).toEqual([ - "some of the values in 'p' are invalid ('b' doesn't have the correct shape ('url' is not a string))", + expect(validateType({}, t.object({ "a?": t.number }))).toEqual([]); + expect(validateType({}, t.object({ a: t.number, "b?": t.number }))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a"] }, ]); + expect(validateType({ a: 1 }, t.object({ a: t.number, "b?": t.number }))).toEqual([]); + expect(validateType({ a: 1, b: 1 }, t.object({ a: t.number, "b?": t.number }))).toMatchObject( + [] + ); + expect( + validateType({ a: 1, b: "abc" }, t.object({ a: t.number, "b?": t.number })) + ).toMatchObject([{ message: "value is not a number", path: ["b"] }]); }); - test("objects with more complex shape", () => { - const schema: Schema = { - p: { - type: Object, - shape: { - id: Number, - url: [Boolean, { type: Array, element: Number }], - }, - }, - }; - expect(validateSchema({ p: [] }, schema)).toEqual(["'p' is not an object"]); - expect(validateSchema({ p: {} }, schema)).toEqual([ - "'p' doesn't have the correct shape ('id' is missing (should be a number), 'url' is missing (should be a boolean or list of numbers))", + test("shaped object with nested object", () => { + const type = t.object({ + a: t.number, + b: t.object({ + c: t.string, + }), + }); + + expect(validateType({}, type)).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a", "b"] }, ]); - expect(validateSchema({ p: { id: 1, url: "asf" } }, schema)).toEqual([ - "'p' doesn't have the correct shape ('url' is not a boolean or list of numbers)", + expect(validateType({ a: 1 }, type)).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["b"] }, ]); - expect(validateSchema({ p: { id: 1, url: true } }, schema)).toEqual([]); - expect(validateSchema({ p: undefined }, schema)).toEqual([ - "'p' is undefined (should be a object)", + expect(validateType({ a: 1, b: 1 }, type)).toMatchObject([ + { message: "value is not an object", path: ["b"] }, ]); - }); - - test("objects with shape and *", () => { - const schema: Schema = { p: { type: Object, shape: { id: Number, "*": true } } }; - expect(validateSchema({ p: [] }, schema)).toEqual(["'p' is not an object"]); - expect(validateSchema({ p: {} }, schema)).toEqual([ - "'p' doesn't have the correct shape ('id' is missing (should be a number))", + expect(validateType({ a: 1, b: {} }, type)).toMatchObject([ + { message: "object value have missing keys", path: ["b"], missingKeys: ["c"] }, ]); - expect(validateSchema({ p: { id: 1 } }, schema)).toEqual([]); - expect(validateSchema({ p: { id: "asdf" } }, schema)).toEqual([ - "'p' doesn't have the correct shape ('id' is not a number)", + expect(validateType({ a: 1, b: { c: "" } }, type)).toEqual([]); + expect(validateType({ a: "", b: { c: "" } }, type)).toMatchObject([ + { message: "value is not a number", path: ["a"] }, ]); - expect(validateSchema({ p: { id: 1, url: 1 } }, schema)).toEqual([]); - expect(validateSchema({ p: undefined }, schema)).toEqual([ - "'p' is undefined (should be a object)", + expect(validateType({ a: 1, b: { c: 123 } }, type)).toMatchObject([ + { message: "value is not a string", path: ["b", "c"] }, ]); }); - test("can specify that additional keys are allowed", () => { - const schema: Schema = { - message: String, - "*": true, - }; - expect(validateSchema({ message: "hey" }, schema)).toEqual([]); - expect(validateSchema({ message: "hey", otherKey: true }, schema)).toEqual([]); + test("keyed object", () => { + expect(validateType("abc", t.object(["a", "b"]))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType(123, t.object(["a", "b"]))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType(true, t.object(["a", "b"]))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType({}, t.object(["a", "b"]))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a", "b"] }, + ]); + expect(validateType({ a: "abc" }, t.object(["a", "b"]))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["b"] }, + ]); + expect(validateType({ a: "abc", b: "def" }, t.object(["a", "b"]))).toEqual([]); + expect(validateType({ a: 123 }, t.object(["a", "b"]))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["b"] }, + ]); + expect(validateType({ a: 123, b: "def" }, t.object(["a", "b"]))).toEqual([]); + expect(validateType({ a: 123, b: 123 }, t.object(["a", "b"]))).toEqual([]); }); - test("array with element with shape", () => { - const schema: Schema = { - p: { - type: Array, - element: { - type: Object, - shape: { - num: { type: Number, optional: true }, - }, - }, - }, - }; - expect(validateSchema({ p: 1 }, schema)).toEqual(["'p' is not a list of objects"]); - expect(validateSchema({ p: {} }, schema)).toEqual(["'p' is not a list of objects"]); - expect(validateSchema({ p: [] }, schema)).toEqual([]); - expect(validateSchema({ p: [{}] }, schema)).toEqual([]); - expect(validateSchema({ p: [{ num: 1 }] }, schema)).toEqual([]); - expect(validateSchema({ p: [{ num: true }] }, schema)).toEqual([ - "'p[0]' doesn't have the correct shape ('num' is not a number)", + test("keyed object with optional keys", () => { + expect(validateType({}, t.object(["a", "b?"]))).toMatchObject([ + { message: "object value have missing keys", path: [], missingKeys: ["a"] }, ]); + expect(validateType({ a: "abc" }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: "abc", b: "def" }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: 123 }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: 123, b: "def" }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: 123, b: 123 }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: 123, b: 123 }, t.object(["a", "b?"]))).toEqual([]); }); - test("schema with custom validate function", () => { - const schema: Schema = { - size: { - validate: (e: string) => ["small", "medium", "large"].includes(e), - }, - }; - expect(validateSchema({ size: "small" }, schema)).toEqual([]); - expect(validateSchema({ size: "sall" }, schema)).toEqual(["'size' is not valid"]); - expect(validateSchema({ size: 1 }, schema)).toEqual(["'size' is not valid"]); + test("keyed object with additional keys", () => { + expect(validateType({ a: "abc", b: "def", c: "ghi" }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: "abc", c: "ghi" }, t.object(["a", "b?"]))).toEqual([]); + expect(validateType({ a: "abc", d: "jkl" }, t.object(["a", "b?"]))).toEqual([]); }); +}); - test("schema with custom validate function and type", () => { - const schema: Schema = { - size: { - type: String, - validate: (e: string) => ["small", "medium", "large"].includes(e), - }, - }; - expect(validateSchema({ size: "small" }, schema)).toEqual([]); - expect(validateSchema({ size: "sall" }, schema)).toEqual(["'size' is not valid"]); - expect(validateSchema({ size: 1 }, schema)).toEqual(["'size' is not a string"]); +describe("promise", () => { + test("promise", () => { + const issue = { message: "value is not a promise" }; + expect(validateType(123, t.promise())).toMatchObject([issue]); + expect(validateType("abc", t.promise())).toMatchObject([issue]); + expect(validateType(true, t.promise())).toMatchObject([issue]); + expect(validateType(Promise.resolve(), t.promise())).toEqual([]); }); - test("value as type", () => { - expect(validateSchema({ a: false }, { a: { value: false } })).toEqual([]); - expect(validateSchema({ a: true }, { a: { value: false } })).toEqual([ - "'a' is not equal to 'false'", - ]); + test("return type is not checked", () => { + expect(validateType(Promise.resolve(""), t.promise(t.string))).toEqual([]); + expect(validateType(Promise.resolve(123), t.promise(t.string))).toEqual([]); + expect(validateType(Promise.resolve(true), t.promise(t.string))).toEqual([]); }); +}); - test("value as type (some other values)", () => { - expect(validateSchema({ a: null }, { a: { value: null } })).toEqual([]); - expect(validateSchema({ a: false }, { a: { value: null } })).toEqual([ - "'a' is not equal to 'null'", - ]); - expect(validateSchema({ a: "hey" }, { a: { value: "hey" } })).toEqual([]); - expect(validateSchema({ a: true }, { a: { value: "hey" } })).toEqual([ - "'a' is not equal to 'hey'", - ]); - }); +test("signal", () => { + const issue = { message: "value is not a reactive value" }; + expect(validateType(123, t.signal(t.string))).toMatchObject([issue]); + expect(validateType("abc", t.signal(t.string))).toMatchObject([issue]); + expect(validateType(true, t.signal(t.string))).toMatchObject([issue]); + expect(validateType(() => {}, t.signal(t.string))).toMatchObject([issue]); + expect(validateType(function () {}, t.signal(t.string))).toMatchObject([issue]); + expect(validateType(A, t.signal(t.string))).toMatchObject([issue]); + class B { + set() {} + } + expect(validateType(B, t.signal(t.string))).toMatchObject([issue]); + expect(validateType(signal(1), t.signal(t.number))).toEqual([]); + expect( + validateType( + computed(() => 1), + t.signal(t.number) + ) + ).toEqual([]); +}); - test("value as type work in union type", () => { - expect(validateSchema({ a: false }, { a: [String, { value: false }] })).toEqual([]); - expect(validateSchema({ a: true }, { a: [String, { value: false }] })).toEqual([ - "'a' is not a string or false", - ]); - expect(validateSchema({ a: "string" }, { a: [String, { value: false }] })).toEqual([]); +test("record", () => { + expect(validateType("abc", t.record(t.string))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType(123, t.record(t.string))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType(true, t.record(t.string))).toMatchObject([ + { message: "value is not an object", path: [] }, + ]); + expect(validateType({}, t.record(t.string))).toEqual([]); + expect(validateType({ a: "abc" }, t.record(t.string))).toEqual([]); + expect(validateType({ a: "abc", b: "def" }, t.record(t.string))).toEqual([]); + expect(validateType({ a: 123 }, t.record(t.string))).toMatchObject([ + { message: "value is not a string", path: ["a"] }, + ]); + expect(validateType({ a: 123, b: "def" }, t.record(t.string))).toMatchObject([ + { message: "value is not a string", path: ["a"] }, + ]); + expect(validateType({ a: 123, b: 123 }, t.record(t.string))).toMatchObject([ + { message: "value is not a string", path: ["a"] }, + { message: "value is not a string", path: ["b"] }, + ]); + expect(validateType({ a: 123, b: 123 }, t.record(t.number))).toEqual([]); +}); + +test("string", () => { + const issue = { message: "value is not a string" }; + expect(validateType("", t.string)).toEqual([]); + expect(validateType("abc", t.string)).toEqual([]); + expect(validateType(123, t.string)).toMatchObject([issue]); + expect(validateType(987, t.string)).toMatchObject([issue]); + expect(validateType(true, t.string)).toMatchObject([issue]); + expect(validateType(false, t.string)).toMatchObject([issue]); + expect(validateType(undefined, t.string)).toMatchObject([issue]); + expect(validateType(null, t.string)).toMatchObject([issue]); + expect(validateType({}, t.string)).toMatchObject([issue]); + expect(validateType([], t.string)).toMatchObject([issue]); + expect(validateType(A, t.string)).toMatchObject([issue]); + expect(validateType(new A(), t.string)).toMatchObject([issue]); +}); + +test("tuple", () => { + expect(validateType(["abc"], t.tuple([t.string]))).toEqual([]); + expect(validateType([], t.tuple([t.string]))).toMatchObject([ + { message: "tuple value does not have the correct length" }, + ]); + expect(validateType([123], t.tuple([t.string]))).toMatchObject([ + { message: "value is not a string", path: [0] }, + ]); + expect(validateType(["abc", 123], t.tuple([t.string]))).toMatchObject([ + { message: "tuple value does not have the correct length" }, + ]); + expect(validateType("", t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType("abc", t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType(123, t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType(987, t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType(true, t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType({}, t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not an array" }, + ]); + expect(validateType(["abc", 123], t.tuple([t.string, t.number]))).toEqual([]); + expect(validateType([123, "abc"], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not a string", path: [0] }, + { message: "value is not a number", path: [1] }, + ]); + expect(validateType(["abc"], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "tuple value does not have the correct length" }, + ]); + expect(validateType([123], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "tuple value does not have the correct length" }, + ]); + expect(validateType(["abc", true], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not a number", path: [1] }, + ]); + expect(validateType([true, 123], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "value is not a string", path: [0] }, + ]); + expect(validateType(["abc", 123, true], t.tuple([t.string, t.number]))).toMatchObject([ + { message: "tuple value does not have the correct length" }, + ]); + expect(validateType(["abc", 123, true], t.tuple([t.string, t.number, t.boolean]))).toEqual([]); + expect(validateType(["abc", 123, 123], t.tuple([t.string, t.number, t.boolean]))).toMatchObject([ + { message: "value is not a boolean", path: [2] }, + ]); +}); + +test("or", () => { + expect(validateType("", t.or([t.string, t.number]))).toEqual([]); + expect(validateType("abc", t.or([t.string, t.number]))).toEqual([]); + expect(validateType(123, t.or([t.string, t.number]))).toEqual([]); + expect(validateType(987, t.or([t.string, t.number]))).toEqual([]); + expect(validateType(true, t.or([t.string, t.number]))).toMatchObject([ + { + message: "value does not match union type", + subIssues: [{ message: "value is not a string" }, { message: "value is not a number" }], + }, + ]); + expect(validateType({}, t.or([t.string, t.number]))).toMatchObject([ + { + message: "value does not match union type", + subIssues: [{ message: "value is not a string" }, { message: "value is not a number" }], + }, + ]); + expect(validateType([], t.or([t.string, t.number]))).toMatchObject([ + { + message: "value does not match union type", + subIssues: [{ message: "value is not a string" }, { message: "value is not a number" }], + }, + ]); + expect(validateType([], t.or([t.string, t.array(t.number)]))).toEqual([]); + expect(validateType([""], t.or([t.string, t.array(t.number)]))).toMatchObject([ + { message: "value is not a number", path: [0] }, + ]); +}); + +test("complex type", () => { + const complexType = t.object({ + "a?": t.number, + b: t.array( + t.object({ + a: t.instanceOf(A), + "b?": t.or([t.number, t.literal(false)]), + c: t.tuple([t.string, t.string]), + }) + ), }); + + expect(validateType(1, complexType)).toMatchObject([{ message: "value is not an object" }]); + expect(validateType("", complexType)).toMatchObject([{ message: "value is not an object" }]); + expect(validateType([], complexType)).toMatchObject([{ message: "value is not an object" }]); + expect(validateType(null, complexType)).toMatchObject([{ message: "value is not an object" }]); + expect(validateType({}, complexType)).toMatchObject([ + { message: "object value have missing keys", missingKeys: ["b"] }, + ]); + expect(validateType({ a: "" }, complexType)).toMatchObject([ + { message: "value is not a number", path: ["a"] }, + { message: "object value have missing keys", missingKeys: ["b"], path: [] }, + ]); + expect(validateType({ a: 1 }, complexType)).toMatchObject([ + { message: "object value have missing keys", missingKeys: ["b"] }, + ]); + expect(validateType({ b: {} }, complexType)).toMatchObject([ + { message: "value is not an array", path: ["b"] }, + ]); + expect( + validateType( + { + b: [{ a: 1, c: ["a", "b", "c"] }], + }, + complexType + ) + ).toMatchObject([ + { message: "value is not an instance of 'A'", path: ["b", 0, "a"] }, + { message: "tuple value does not have the correct length", path: ["b", 0, "c"] }, + ]); + expect( + validateType( + { + b: [{ a: new A(), c: ["a", "b"] }], + }, + complexType + ) + ).toEqual([]); + expect( + validateType( + { + a: 123, + b: [{ a: new A(), c: ["a", "b"] }], + }, + complexType + ) + ).toEqual([]); + expect( + validateType( + { + a: 123, + b: [{ a: new A(), b: false, c: ["a", "b"] }], + }, + complexType + ) + ).toEqual([]); + expect( + validateType( + { + a: 123, + b: [{ a: new A(), b: 123, c: ["a", "b"] }], + }, + complexType + ) + ).toEqual([]); }); diff --git a/tools/devtools/src/page_scripts/owl_devtools_global_hook.js b/tools/devtools/src/page_scripts/owl_devtools_global_hook.js index ad9d39227..129cd7dfa 100644 --- a/tools/devtools/src/page_scripts/owl_devtools_global_hook.js +++ b/tools/devtools/src/page_scripts/owl_devtools_global_hook.js @@ -1396,8 +1396,8 @@ subscription.target.contentType === "object" ? Object.keys(rawSubscription.target).length > 0 : subscription.target.contentType === "array" - ? rawSubscription.target.length > 0 - : false; + ? rawSubscription.target.length > 0 + : false; } subscription.target.children = []; if (subscription.target.toggled) { diff --git a/tsconfig.json b/tsconfig.json index 4092bef3a..4370819ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,9 +13,9 @@ // "compileOnSave": false,                   // Signals to the IDE to generate all files for a given tsconfig.json upon saving. "compilerOptions": {                                                             // Main options - "target": "es2019",                                         // Specify ECMAScript target version: 'es3' (default), 'es5', 'es2015', 'es2016', 'es2017','es2018' or 'esnext'. + "target": "ES2022",                                         // Specify ECMAScript target version: 'es3' (default), 'es5', 'es2015', 'es2016', 'es2017','es2018' or 'esnext'. "module": "es6",                                         // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. - // "lib": ["esnext", "dom"],                 // Specify library files to be included in the compilation. + "lib": ["ES2022", "DOM"],                 // Specify library files to be included in the compilation. // "allowJs": false,                 // Allow javascript files to be compiled. // "checkJs": false,                 // Report errors in .js files. // "outFile": "./",                 // Concatenate and emit output to single file.