From eed3986a83770583865f771cd870818c093f50a2 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 09:01:43 +0700 Subject: [PATCH 01/71] Initial v3 commit stripping out element stuff --- README.md | 1 + package.json | 1 - src/elementary.js | 309 ------------------------ src/index.js | 1 - src/reactor.js | 2 + test/elementary.test.html | 34 --- test/elementary.test.js | 492 -------------------------------------- 7 files changed, 3 insertions(+), 837 deletions(-) delete mode 100644 src/elementary.js delete mode 100644 test/elementary.test.html delete mode 100644 test/elementary.test.js diff --git a/README.md b/README.md index 044bab4..1507d7c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ Reactor.js ========== + Reactor.js is a simple reactive front-end library. It provides - `Reactor` objects that store reactive variables - `Observer` functions that automatically track the reactive variables that they use and retrigger if any of these variables are updated. The function `ob` is shorthand for `new Observer` diff --git a/package.json b/package.json index c70fec8..956acb9 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "prepare": "npm run build", "pretest": "npm run build", "test": "standard && mocha test/reactor.test.js", - "browserTest": "npm run pretest && parcel serve test/elementary.test.html", "prepublishOnly": "npm test" }, "repository": { diff --git a/src/elementary.js b/src/elementary.js deleted file mode 100644 index e28a3af..0000000 --- a/src/elementary.js +++ /dev/null @@ -1,309 +0,0 @@ -/* eslint-env browser */ - -// Provides a function `el` that enables a declarative syntax for DOM generation -// in plain javascript. The first argument is what type of element to create. -// The subsequent arguments are appended as child nodes. If the "child" argument -// is a function, it is executed in the context of the parent node. - -// By nesting `el` calls we have a plain javascript alternative to HTML that -// also allows for inline logic. This unifies the DOM and closure hierarchy, -// creating a single consistent context for UI creation. - -// When an Observer from reactor.js is passed as a child argument, it's return -// is automatically attached to the parent each time the observer triggers, -// replacing the previous iterations if any. Attached Observers are also -// automatically disabled when their parent element is removed from the DOM. - -import { Observer, shuck } from './reactor.js' - -// Manually compiled list of valid HTML tags. Used when creating a new `el` -// If the string matches a named tag it will create that element -// If it does not match it will just make a div with the string as a class name -const VALID_HTML_TAGS = Object.freeze([ - 'a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', - 'b', 'bdi', 'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', - 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', - 'data', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', - 'em', 'embed', 'eventsource', - 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', - 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', - 'i', 'iframe', 'img', 'input', 'ins', 'isindex', - 'kbd', 'keygen', - 'label', 'legend', 'li', 'link', - 'mark', 'map', 'menu', 'meta', 'meter', - 'nav', - 'noframes', 'noscript', - 'object', 'ol', 'optgroup', 'option', 'output', - 'p', 'param', 'pre', 'progress', - 'q', - 'ruby', 'rp', 'rt', - 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', - 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', - 'u', 'ul', - 'var', 'video', - 'wbr' -]) - -// Whenever an element is added to the DOM turn its observers on -// Whenever an element is removed from the DOM turn its observers off -// This avoids leaking "orphan" observers that stay alive updating nodes that -// no longer are relevant. -// Note: MutationObserver is native class and unrelated to reactor.js observers -const docObserver = new MutationObserver((mutationList, mutationObserver) => { - for (const mutationRecord of mutationList) { - for (const addedNode of Array.from(mutationRecord.addedNodes)) { - const comments = getAllComments(addedNode) - for (const comment of comments) { - observerTrios.get(comment)?.observer.start() - } - } - for (const removedNode of Array.from(mutationRecord.removedNodes)) { - const comments = getAllComments(removedNode) - for (const comment of comments) { - observerTrios.get(comment)?.observer.stop() - } - } - } -}) -docObserver.observe(document, { subtree: true, childList: true }) - -// When an observer is attached to an element, a pair of comment nodes are -// created to mark the "location" of the observer within the parent. -// These comments are meant to act as proxies for the observer within the DOM. -// When a comment is removed, so is its partner and the observer they represent -// This defines the MutationObserver but it is only activated on the creation of -// each `el` element. -const observerTrios = new WeakMap() -const bookmarkObserver = new MutationObserver((mutationList, mutationObserver) => { - for (const mutationRecord of mutationList) { - for (const removedNode of Array.from(mutationRecord.removedNodes)) { - observerTrios.get(removedNode)?.clear() - } - } -}) - -// Helper function to get all comment nodes for a given subtree -function getAllComments (root) { - const commentIterator = document.createNodeIterator( - root, - NodeFilter.SHOW_COMMENT, - () => NodeFilter.FILTER_ACCEPT - ) - const commentList = [] - let nextComment = commentIterator.nextNode() - while (nextComment !== null) { - commentList.push(nextComment) - nextComment = commentIterator.nextNode() - } - return commentList -} - -// Helper function to get all nodes between 2 nodes -function getNodesBetween (startNode, endNode) { - if ( - startNode.parentNode === null || - endNode.parentNode === null || - startNode.parentNode !== endNode.parentNode - ) throw new RangeError('endNode could not be reached from startNode') - const result = [] - let currentNode = startNode.nextSibling - while (currentNode !== endNode) { - if (currentNode === null) { - throw new RangeError('endNode could not be reached from startNode') - } - result.push(currentNode) - currentNode = currentNode.nextSibling - } - return result -} - -// Simple check for a query selector over creating a tag -// Problem is that a plain text string is a valid tag search -// We check for the common cases of . # and [ -// Just skip starting with tag search -// TODO improve this to actually detect valid query selector -const isQuerySelector = (testString) => ( - typeof testString === 'string' && ( - testString.startsWith('.') || - testString.startsWith('#') || - testString.startsWith('[') - ) -) - -// Main magic element wrapping function -// First argument is the element to create or wrap -// Subsequent arguments are children to attach -// Returns the element with all the stuff attached -const el = (descriptor, ...children) => { - // Create the new element or wrap an existing one - // If its an existing element dont do anything - let self - // Trivial case when given an element - if (descriptor instanceof Element) { - self = descriptor - // If its a selector then find the thing - } else if (isQuerySelector(descriptor)) { - self = document.querySelector(descriptor) - // If its a valid html tag, then make a new html tag and add classes - // Default to div otherwise - } else if (typeof descriptor === 'string') { - const firstWord = descriptor.split(' ')[0] - const tag = VALID_HTML_TAGS.includes(firstWord) ? firstWord : 'div' - const newElement = document.createElement(tag) - newElement.className = descriptor - self = newElement - } else { - throw new TypeError('el descriptor expects a string or an existing Element') - } - - // Attach the MutationObserver to cleanly remove observer markers - bookmarkObserver.observe(self, { childList: true }) - - // For the children - // If its a string, then just append it as a text node child - // If its an existing element, then append it as a child - // If its a function, execute it in the context. Append return values - // If its an observer then append a pair of comment nodes as placeholders - // The contents of the observer will be inserted between the placeholders - // If it is an array, decompose it and try to add each of its elements - // If it is a Promise, add a comment placeholder which will be replaced - // when the promise returns - function append (child, insertionPoint) { - // If the insertion point given is no longer attached - // Then abort the insertion - if (insertionPoint && insertionPoint.parentElement !== self) return false - // Handle the null case - if (typeof child === 'undefined' || child === null) return false - // Strings are just appended as text - if (typeof child === 'string') { - const textNode = document.createTextNode(child) - self.insertBefore(textNode, insertionPoint) - // Existing elements are just appended - } else if (child instanceof Element || child instanceof DocumentFragment) { - self.insertBefore(shuck(child), insertionPoint) - // Promises get an immediate placeholder before they resolve - // If the placeholder is removed before the promise resolves. Nothing happens - // With observers, this means only the latest promise will get handled - } else if (child instanceof Promise) { - const promisePlaceholder = document.createComment('promisePlaceholder') - self.insertBefore(promisePlaceholder, insertionPoint) - child.then(value => { - append(value, promisePlaceholder) - promisePlaceholder.remove() - }) - // When an Observers is appended we insert comment nodes as "bookends" to - // mark its position. On initial commitment Observers work like normal - // functions. They execute and the return value if any is appended between - // the bookends. On subsequent triggers, everything between the bookends - // is first cleared before the new result is appended - } else if (child instanceof Observer) { - // Start with the bookends marking the observer domain - // Keep a mapping of the bookends to the observer - // Lets the observer be cleaned up later when the any comment is removed - const observerStartNode = document.createComment('observerStart') - const observerEndNode = document.createComment('observerEnd') - self.insertBefore(observerStartNode, insertionPoint) - self.insertBefore(observerEndNode, insertionPoint) - const observerTrio = { - start: observerStartNode, - end: observerEndNode, - observer: child, - clear: function () { - this.start.remove() - this.end.remove() - this.observer.stop() - } - } - observerTrios.set(observerStartNode, observerTrio) - observerTrios.set(observerEndNode, observerTrio) - observerTrios.set(child, observerTrio) - // Create meta-observer to observe the observer - // When the observer returns a new value - // The meta-observer appends the results - // This pattern is used so that the library user can write observers - // just returning a value and not worry about the attachment logic - // TODO - group meta-observer with the rest of it to be cleared together - new Observer(() => { - // Since the child is an Observer and Observers values are Signals - // reading the value here binds the meta-observer to retrigger whenever - // the child observer retriggers - const result = child.value - // Check if the bookmarks are still attached before acting - if ( - observerStartNode.parentNode === self && - observerEndNode.parentNode === self - ) { - // Clear everything between the bookmarks - const oldChildren = getNodesBetween(observerStartNode, observerEndNode) - for (const oldChild of oldChildren) oldChild.remove() - // Then insert new content between them - append(result, observerEndNode) - } - // If either of the bookmarks is missing or no longer attached something - // weird has happened so do nothing - // In theory the comment observer should detect the missing comment and - // remove the other one and disable the observer - }).start() - // Kickoff the child observer with a context of self - // If it is not yet in the document then stop observer from triggering further - child.setThisContext(self) - child.setArgsContext(self) - child.stop() - child.start() - if (!document.contains(self)) child.stop() - - // When a normal function is provided it is executed immediately and its - // output (if any) is appended. - // The function has access to the parent element via either `this` for - // traditional functions or by the first argument for arrow functions - // e.g. (ctx) => {...} - // Need this condition to come after Observers since they are functions too - } else if (typeof child === 'function') { - const result = child.call(self, self) - append(result, insertionPoint) - // Arrays are handled recursively - // Works for any sort of iterable - } else if (typeof child?.[Symbol.iterator] === 'function') { - for (const grandChild of child) { - append(grandChild, insertionPoint) - } - // Anything else isnt meant to be appended - } else { - throw new TypeError('expects string, function, an Element, or an Array of them') - } - // If it successfully appended something return true - return true - } - children.forEach((child) => append(child)) - - // Return the raw DOM element - // Magic wrapping held in a pocket dimension outside of time and space - return self -} - -// Shorthand for setting an attribute -// el('foo', attr('id', 'bar')) -function attr (attribute, value) { - return ($) => { - $.setAttribute(attribute, value) - } -} - -// Shorthand for 2-way binding to a reactor -// el('input', attr('type', 'text'), bind(rx, 'foo')) -function bind (reactor, key) { - return ($) => { - $.oninput = () => { reactor[key] = $.value } - return new Observer(() => { $.value = reactor[key] }) - } -} - -// Shorthand for making new observers -const ob = (x) => new Observer(x) - -export { - el, - ob, - attr, - bind -} diff --git a/src/index.js b/src/index.js index f048253..ad4f233 100644 --- a/src/index.js +++ b/src/index.js @@ -1,2 +1 @@ export * from './reactor.js' -export * from './elementary.js' diff --git a/src/reactor.js b/src/reactor.js index e935b14..a94a0a6 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -628,6 +628,7 @@ const batch = (execute) => { // Execute the given block and collect the triggerd observers try { result = execute() + // TODO Catch the error and throw it after the batching is done } finally { // Clear the batching mode // This needs to be done before observer triggering in case any observers @@ -643,6 +644,7 @@ const batch = (execute) => { // Trigger the collected observers // If an error occurs, collect it and keep going // A conslidated error will be thrown at the end of propagation + // TODO consider: batch wrap the subsequent triggers as well? const errorList = [] batchedObservers.forEach(observer => { try { observer.trigger() } catch (error) { errorList.push(error) } diff --git a/test/elementary.test.html b/test/elementary.test.html deleted file mode 100644 index b2152f0..0000000 --- a/test/elementary.test.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - Mocha Tests - - - - -
- - - - - - - diff --git a/test/elementary.test.js b/test/elementary.test.js deleted file mode 100644 index e8f2da2..0000000 --- a/test/elementary.test.js +++ /dev/null @@ -1,492 +0,0 @@ -/* eslint-env mocha */ -/* global assert */ -import { el, attr, bind, Observer, Reactor } from '../dist/index.js' - -const ob = (x) => new Observer(x) - -describe('Element creation', () => { - it('can create a basic div', () => { - const result = el('foo') - assert.equal(result.outerHTML, '
') - }) - - it('can create a valid HTML tag', () => { - const result = el('h1') - assert(result.outerHTML === '

') - }) - - it('can wrap an existing element', () => { - const base = document.createElement('div') - const result = el(base) - assert(result === base) - assert(result.outerHTML === '
') - }) - - it('can grab an existing element by query', () => { - const base = document.createElement('div') - base.className = 'foo' - assert.equal(base.outerHTML, '
') - document.body.appendChild(base) - const result = el('.foo') - assert(result === base) - }) - - it('can fill an element with text', () => { - const result = el('foo', 'bar') - assert.equal(result.outerHTML, '
bar
') - }) - - it('can fill an element with another element', () => { - const innerElement = el('foo') - const result = el('bar', innerElement) - assert(result.outerHTML === '
') - }) - - it('can fill an element with a DocumentFragment', () => { - const fragment = document.createDocumentFragment() - fragment.appendChild(el('foo')) - fragment.appendChild(el('bar')) - const result = el('div', fragment) - assert(result.outerHTML === '
') - }) - - it('can fill an element with a function', () => { - const result = el('foo', $ => { - $.innerHTML = 'bar' - }) - assert(result.outerHTML === '
bar
') - }) - - it('can fill an element with a function using this', () => { - const result = el('foo', function () { - this.innerHTML = 'bar' - }) - assert(result.outerHTML === '
bar
') - }) - - it('can fill an element with a function return', () => { - const result = el('foo', () => 'bar') - assert(result.outerHTML === '
bar
') - }) - - it('can fill an element with a Promise', (done) => { - const result = el('foo', new Promise(resolve => { - setTimeout(() => { - resolve('bar') - }, 10) - })) - assert(result.outerHTML === '
') - setTimeout(() => { - assert(result.outerHTML === '
bar
') - done() - }, 20) - }) - - it('can fill an element with arrays', () => { - const result = el('foo', [ - 'bar', - 'baz', - 'qux' - ]) - assert(result.outerHTML === '
barbazqux
') - }) - - it('can fill an element with nested arrays', () => { - const result = el('foo', [ - 'bar', [ - 'baz', [ - 'qux' - ] - ] - ]) - assert(result.outerHTML === '
barbazqux
') - }) - - it('can fill an element with multiple arguments', () => { - const result = el('foo', - 'bar', - 'baz', - 'qux' - ) - assert(result.outerHTML === '
barbazqux
') - }) - - it('can do all of the above', () => { - const base = document.createElement('div') - const result = el('foo', [ - el('h1'), [ - el(base), - 'bar' - ], - $ => { $.setAttribute('name', 'baz') }, - function () { this.id = 'qux' }, - $ => 'corge' - ]) - assert(result.outerHTML === '

barcorge
') - }) - - it('can nest el elegantly', () => { - const result = el('foo', - el('bar', - el('baz', $ => { - el($, 'qux') - }) - ) - ) - assert(result.outerHTML === '
qux
') - }) -}) - -describe('Reactivity', () => { - it('can take an observer', (done) => { - const result = el('foo', ob(() => {})) - assert.equal(result.outerHTML, '
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
') - result.remove() - done() - }, 10) - }) - - it('can take an observer modifying a property', (done) => { - const result = el('foo', ob(($) => { - $.setAttribute('name', 'bar') - })) - assert.equal( - result.outerHTML, - '
' - ) - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
') - result.remove() - done() - }, 10) - }) - - it('can take an observer returning a string', (done) => { - const result = el('foo', ob(() => 'bar')) - assert.equal(result.outerHTML, '
bar
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
bar
') - result.remove() - done() - }, 10) - }) - - it('can take an observer returning an element', (done) => { - const result = el('foo', ob(() => el('bar', 'baz'))) - assert.equal(result.outerHTML, '
baz
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
baz
') - result.remove() - done() - }, 10) - }) - - it('can take an observer returning an array', (done) => { - const result = el('foo', ob(() => ['bar', 'baz', 'qux'])) - assert.equal(result.outerHTML, '
barbazqux
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
barbazqux
') - result.remove() - done() - }, 10) - }) - - it('can take nested observers', (done) => { - const result = el('foo', ob(() => { - return ob(() => { - return 'bar' - }) - })) - assert.equal(result.outerHTML, '
bar
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
bar
') - result.remove() - done() - }, 10) - }) - - it('can take a complex nested set of observers', (done) => { - const result = el('foo', ob(() => { - return [ - ob(() => { - return [ - ob(() => { - return 'bar' - }), - ob(() => { - return 'baz' - }) - ] - }), - ob(() => { - return ob(() => { - return 'qux' - }) - }) - ] - })) - assert.equal(result.outerHTML, '
barbazqux
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
barbazqux
') - result.remove() - done() - }, 10) - }) - - it('updates an observer property', (done) => { - const rx = new Reactor() - rx.bar = 'baz' - const result = el('foo', ob(($) => { - $.setAttribute('name', rx.bar) - })) - assert.equal( - result.outerHTML, - '
' - ) - rx.bar = 'qux' - assert.equal( - result.outerHTML, - '
' - ) - document.body.appendChild(result) - setTimeout(() => { - assert.equal( - result.outerHTML, - '
' - ) - rx.bar = 'corge' - assert.equal( - result.outerHTML, - '
' - ) - result.remove() - done() - }, 10) - }) - - it('updates an observer string', (done) => { - const rx = new Reactor() - rx.bar = 'baz' - const result = el('foo', ob(() => rx.bar)) - assert.equal(result.outerHTML, '
baz
') - rx.bar = 'qux' - assert.equal(result.outerHTML, '
baz
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
qux
') - rx.bar = 'corge' - assert.equal(result.outerHTML, '
corge
') - result.remove() - done() - }, 10) - }) - - it('updates an observer element', (done) => { - const rx = new Reactor() - rx.foo = 'foo' - rx.bar = 'bar' - const result = el('div', ob(() => el(rx.foo, rx.bar))) - assert.equal(result.outerHTML, '
bar
') - rx.foo = 'baz' - rx.bar = 'qux' - assert.equal(result.outerHTML, '
bar
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
qux
') - rx.foo = 'corge' - assert.equal(result.outerHTML, '
qux
') - rx.bar = 'grault' - assert.equal(result.outerHTML, '
grault
') - result.remove() - done() - }, 10) - }) - it('test for a simple element triggering', (done) => { - const rx = new Reactor() - rx.title = 'foo' - const result = el('article', ob(() => { - return ob(() => { - return rx.title - }) - })) - assert.equal( - result.outerHTML, - '
foo
' - ) - rx.title = 'bar' - document.body.appendChild(result) - setTimeout(() => { - assert.equal( - result.outerHTML, - '
bar
' - ) - rx.title = 'baz' - result.remove() - done() - }, 10) - }) - - it('updates a complex element', (done) => { - const rx = new Reactor() - rx.title = 'foo' - rx.paragraphs = [ - { id: 'bar', content: 'Lorem ipsum dolor sit amet', time: '123' }, - { id: 'baz', content: 'Ut enim ad minim veniam', time: '456' }, - { id: 'qux', content: 'Duis aute irure dolor in reprehenderit', time: '789' } - ] - const result = el('article', - el('h1', ob(() => rx.title)), - ob(() => rx.paragraphs.map((paragraph) => [ - el('p', ob(($) => { - $.setAttribute('id', paragraph.id) - return paragraph.content - })), - ob(() => { - return el('h3', ob(() => { - return paragraph.time - })) - }) - ])) - ) - assert.equal( - result.outerHTML, - '

foo

Lorem ipsum dolor sit amet

123

Ut enim ad minim veniam

456

Duis aute irure dolor in reprehenderit

789

' - ) - document.body.appendChild(result) - rx.title = 'corge' - assert.equal( - result.outerHTML, - '

foo

Lorem ipsum dolor sit amet

123

Ut enim ad minim veniam

456

Duis aute irure dolor in reprehenderit

789

' - ) - setTimeout(() => { - assert.equal( - result.outerHTML, - '

corge

Lorem ipsum dolor sit amet

123

Ut enim ad minim veniam

456

Duis aute irure dolor in reprehenderit

789

' - ) - rx.paragraphs[0].content = 'bloop bloop bloop' - assert.equal( - result.outerHTML, - '

corge

bloop bloop bloop

123

Ut enim ad minim veniam

456

Duis aute irure dolor in reprehenderit

789

' - ) - rx.paragraphs[2].time = '987' - assert.equal( - result.outerHTML, - '

corge

bloop bloop bloop

123

Ut enim ad minim veniam

456

Duis aute irure dolor in reprehenderit

987

' - ) - result.remove() - done() - }, 10) - }) -}) - -describe('Shorthands', () => { - it('set attributes using attr', () => { - const result = el('foo', attr('id', 'bar')) - assert.equal(result.outerHTML, '
') - }) - - it('set multiple attributes using attr', () => { - const result = el('foo', - attr('id', 'bar'), - attr('name', 'baz') - ) - assert.equal(result.outerHTML, '
') - }) - - it('set attributes reactively using attr', (done) => { - const rx = new Reactor() - rx.foo = 'bar' - const result = el('foo', ob(() => attr('id', rx.foo))) - assert.equal(result.outerHTML, '
') - rx.foo = 'baz' - assert.equal(result.outerHTML, '
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
') - rx.foo = 'corge' - assert.equal(result.outerHTML, '
') - result.remove() - done() - }, 10) - }) - - it.skip('does 2 way binding', () => { - // Need to automate this with puppeteer - const rx = new Reactor() - rx.foo = 'bar' - const display = el('h1', ob(() => rx.foo)) - const input = el('input', - attr('type', 'text'), - bind(rx, 'foo') - ) - const input2 = el('input', - attr('type', 'text'), - bind(rx, 'foo') - ) - el(document.body, display, input, input2) - }) -}) - -describe('Clean up', () => { - it('disables observer when removed from DOM', (done) => { - const rx = new Reactor() - rx.bar = 'baz' - const result = el('foo', ob(() => rx.bar)) - assert.equal(result.outerHTML, '
baz
') - rx.bar = 'qux' - assert.equal(result.outerHTML, '
baz
') - document.body.appendChild(result) - setTimeout(() => { - assert.equal(result.outerHTML, '
qux
') - rx.bar = 'corge' - assert.equal(result.outerHTML, '
corge
') - result.remove() - setTimeout(() => { - rx.bar = 'grault' - assert.equal(result.outerHTML, '
corge
') - done() - }, 10) - }, 10) - }) - - it('removes comment pair together', (done) => { - const rx = new Reactor() - rx.bar = 'baz' - const result = el('foo', ob(() => rx.bar)) - assert.equal(result.outerHTML, '
baz
') - result.childNodes[0].remove() - setTimeout(() => { - assert.equal(result.outerHTML, '
baz
') - done() - }, 10) - }) - - it('disables observer when comment placeholder is removed', (done) => { - const rx = new Reactor() - rx.bar = 'baz' - const result = el('foo', ob(() => rx.bar)) - assert.equal(result.outerHTML, '
baz
') - document.body.appendChild(result) - setTimeout(() => { - rx.bar = 'qux' - assert.equal(result.outerHTML, '
qux
') - result.childNodes[0].remove() - setTimeout(() => { - assert.equal(result.outerHTML, '
qux
') - rx.bar = 'corge' - assert.equal(result.outerHTML, '
qux
') - result.remove() - done() - }, 10) - }, 10) - }) -}) From fec45032659df5de8b0c736c3f1c7a7e7dc4c690 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 09:03:37 +0700 Subject: [PATCH 02/71] gitignoring notes file --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3076c78..459aac1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store .parcel-cache dist -node_modules \ No newline at end of file +node_modules +notes.js From 99a2cc67c7505e5b6c68154de636ba95990fee4d Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 09:15:39 +0700 Subject: [PATCH 03/71] rename test.js --- package.json | 2 +- test/{reactor.test.js => test.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{reactor.test.js => test.js} (100%) diff --git a/package.json b/package.json index 956acb9..eb93b3a 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "build": "rm -rf dist/ && parcel build", "prepare": "npm run build", "pretest": "npm run build", - "test": "standard && mocha test/reactor.test.js", + "test": "standard && mocha test/test.js", "prepublishOnly": "npm test" }, "repository": { diff --git a/test/reactor.test.js b/test/test.js similarity index 100% rename from test/reactor.test.js rename to test/test.js From 0c5eb770ffe6a730227f5d7dba13957f4085e1d2 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 09:51:35 +0700 Subject: [PATCH 04/71] Strip out docker dev environment stuff since it no longer works --- compose-dev.yaml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 compose-dev.yaml diff --git a/compose-dev.yaml b/compose-dev.yaml deleted file mode 100644 index ca48d01..0000000 --- a/compose-dev.yaml +++ /dev/null @@ -1,12 +0,0 @@ -services: - app: - entrypoint: - - sleep - - infinity - image: node:20.5.0 - init: true - volumes: - - type: bind - source: /var/run/docker.sock - target: /var/run/docker.sock - From 1637d9617d6a7d3979f085741858137c4a9a7394 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 10:45:37 +0700 Subject: [PATCH 05/71] Added more testability for observers --- src/reactor.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/reactor.js b/src/reactor.js index a94a0a6..4cabd2d 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -16,6 +16,7 @@ const dependencyStack = [] // to their internal cores const signalCoreExtractor = new WeakMap() const reactorCoreExtractor = new WeakMap() +const observerCoreExtractor = new WeakMap() // A batcher is used to postpone observer triggers and batch them together // When "batch" is called it adds sets a batcher to this global variable @@ -49,6 +50,7 @@ class Signal extends Function { // - The core: The properties & methods which lets signals work // - The interface: The function returned to the user to use constructor (initialValue) { + // The "guts" of a Signal containing properties and methods // All actual functionality & state should be built into the core // Should be completely agnostic to syntactic sugar @@ -450,6 +452,7 @@ class Reactor { // and allow updates again // // observer.start() Does nothing since already started +const Observers = new WeakSet() class Observer extends Function { constructor (execute) { // Parameter validation @@ -599,6 +602,11 @@ class Observer extends Function { Object.defineProperty(observerInterface, 'value', { get () { return observerCore.value() } }) + + // Register the observer for debugging/typechecking purposes + observerCoreExtractor.set(observerInterface, observerCore) + Observers.add(observerInterface) + // Does not trigger on initialization until () or .start() are called return observerInterface } @@ -695,9 +703,13 @@ class CompoundError extends Error { } export { + Signal, Reactor, Observer, hide, batch, - shuck + shuck, + signalCoreExtractor, + reactorCoreExtractor, + observerCoreExtractor } From 7e39ee3f2dfac0a4f5360e512ae04bdeeb1a678a Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 10:46:31 +0700 Subject: [PATCH 06/71] Minor change to signal constructor to just use write directly. Semantic difference for an empty initialization --- src/reactor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reactor.js b/src/reactor.js index 4cabd2d..95188e4 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -160,7 +160,7 @@ class Signal extends Function { Signals.add(signalInterface) // Initialize with the provided value before returning - signalInterface(initialValue) + signalCore.write(initialValue) return signalInterface } } From 8a9883726e3d3e9a4318bf0db8a8ff2f8cf20232 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 14:37:19 +0700 Subject: [PATCH 07/71] Initial Signal tests --- test/test.js | 540 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 540 insertions(+) diff --git a/test/test.js b/test/test.js index 2b73e30..7a4293e 100644 --- a/test/test.js +++ b/test/test.js @@ -1,13 +1,553 @@ /* eslint-env mocha */ import assert from 'assert' import { + Signal, Reactor, Observer, + // Signals, + Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, hide, batch, shuck } from '../src/reactor.js' +describe('Signal', () => { + describe('Initializes with a value', () => { + it('should initialize with a string', () => { + assert.doesNotThrow(new Signal('foo')) + }) + + it('should initialize with a number', () => { + assert.doesNotThrow(new Signal(123)) + }) + + it('should initialize with a bigint', () => { + assert.doesNotThrow(new Signal(123456789123456789n)) + }) + + it('should initialize with a symbol', () => { + assert.doesNotThrow(new Signal(Symbol('foo'))) + }) + + it('should initialize with true', () => { + assert.doesNotThrow(new Signal(true)) + }) + + it('should initialize with false', () => { + assert.doesNotThrow(new Signal(false)) + }) + + it('should initialize with null', () => { + assert.doesNotThrow(new Signal(null)) + }) + + it('should initialize with undefined', () => { + assert.doesNotThrow(new Signal(undefined)) + }) + + it('should initialize with an Object', () => { + assert.doesNotThrow(new Signal({})) + }) + + it('should initialize with a Function', () => { + assert.doesNotThrow(new Signal(() => {})) + }) + + // TODO: Figure out promises + it('should initialize with a Promise') + + describe('Edge cases', () => { + it('should initialize empty', () => { + assert.doesNotThrow(new Signal()) + }) + it.skip('should not initialize with multiple arguments', () => { + assert.throws(new Signal('foo', 'bar')) + }) + }) + }) + + describe('Returns the initial value when called with no arguments', () => { + it('should return the initial string', () => { + const value = 'foo' + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial number', () => { + const value = 123 + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial bigint', () => { + const value = 123456789123456789n + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial symbol', () => { + const value = Symbol('foo') + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial true', () => { + const value = true + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial false', () => { + const value = false + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial null', () => { + const value = null + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial undefined', () => { + const value = undefined + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + describe('Object are returned wrapped in a Reactor', () => { + it('should return the initial Object wrapped in a Reactor', () => { + const dummyObject = {} + const signal = new Signal(dummyObject) + const result = signal() + assert(Reactors.has(result)) + assert.strictEqual(shuck(result), dummyObject) + }) + + it('should return the initial Function wrapped in a Reactor', () => { + const dummyFunction = () => {} + const signal = new Signal(dummyFunction) + const result = signal() + assert(Reactors.has(result)) + assert.strictEqual(shuck(result), dummyFunction) + }) + + // TODO figure out promises + it('should return the initial Promise') + }) + }) + + describe('Replaces the stored value when called with an argument while returning the new value', () => { + it('should update with a new string', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 'foo' + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with a new number', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 123 + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with a new bigint', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 123456789123456789n + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with a new symbol', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = Symbol('foo') + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with true', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = true + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with false', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = false + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with null', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = null + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with undefined', () => { + const signal = new Signal('foo') + assert.strictEqual(signal(), 'foo') + const value = undefined + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + it('should update with an Object', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) + it('should update with a Function', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = () => {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) + it('should update with a Promise') + }) + + it('can be updated with undefined', () => { + const signal = new Signal('foo') + signal(undefined) + assert.equal(signal(), undefined) + }) + + it('can be updated with null', () => { + const signal = new Signal('foo') + signal(null) + assert.equal(signal(), null) + }) + + it('can be updated with false', () => { + const signal = new Signal('foo') + signal(false) + assert.equal(signal(), false) + }) + + it('can be updated with zero', () => { + const signal = new Signal('foo') + signal(0) + assert.equal(signal(), 0) + }) + + it('can be updated with empty string', () => { + const signal = new Signal('foo') + signal('') + assert.equal(signal(), '') + }) + + it.skip('can be updated with function definition', () => { + const signal = new Signal(5) + const dummyFunction = () => {} + signal(dummyFunction) + console.log('dummyFunction', dummyFunction) + console.log('signal', signal()) + assert.equal(signal(), signal()) + }) + + it('can be updated with function that returns undefined', () => { + const signal = new Signal(5) + signal(() => undefined) + // Function definitions are not supported in current implementation + // The signal should store the function itself + assert.equal(typeof signal(), 'function') + }) + + it('tracks dependencies when read by an observer', () => { + const signal = new Signal(100) + let readValue = null + + const observer = new Observer(() => { + readValue = signal() + }) + + // Trigger the observer to read the signal + observer() + assert.equal(readValue, 100) + + // Update the signal and trigger again + signal(200) + observer() + assert.equal(readValue, 200) + }) + + it('wraps object values in Reactors', () => { + const obj = { foo: 'bar' } + const signal = new Signal(obj) + const result = signal() + + // The result should be a Reactor, not the original object + assert.notEqual(result, obj) + assert.equal(result.foo, 'bar') + }) + + it('does not wrap primitive values in Reactors', () => { + const signal = new Signal('hello') + const result = signal() + + // String should be returned as-is + assert.equal(result, 'hello') + assert.equal(typeof result, 'string') + }) + + it('does not wrap null in Reactors', () => { + const signal = new Signal(null) + const result = signal() + + // null should be returned as-is + assert.equal(result, null) + }) + + it('does not wrap functions in Reactors', () => { + const func = () => 'test' + const signal = new Signal(func) + const result = signal() + + // Function should be returned as-is (not wrapped in a Reactor) + assert.equal(typeof result, 'function') + assert.equal(result(), 'test') + }) + + it('does not wrap existing Reactors in new Reactors', () => { + const reactor = new Reactor({ foo: 'bar' }) + const signal = new Signal(reactor) + const result = signal() + + // Should return the same Reactor instance + assert.equal(result, reactor) + }) + + it('triggers observers when value changes', () => { + const signal = new Signal(1) + let triggerCount = 0 + + const observer = new Observer(() => { + signal() // Read the signal + triggerCount++ + }) + + observer() // Initial trigger + assert.equal(triggerCount, 1) + + signal(2) // Update signal + assert.equal(triggerCount, 2) + + signal(3) // Update signal again + assert.equal(triggerCount, 3) + }) + + it('does not trigger observers when same value is written', () => { + const signal = new Signal(1) + let triggerCount = 0 + + const observer = new Observer(() => { + signal() // Read the signal + triggerCount++ + }) + + observer() // Initial trigger + assert.equal(triggerCount, 1) + + signal(1) // Write same value + assert.equal(triggerCount, 1) // Should not trigger + + signal(2) // Write different value + assert.equal(triggerCount, 2) // Should trigger + }) + + it('handles multiple observers correctly', () => { + const signal = new Signal(1) + let observer1Count = 0 + let observer2Count = 0 + + const observer1 = new Observer(() => { + signal() // Read the signal + observer1Count++ + }) + + const observer2 = new Observer(() => { + signal() // Read the signal + observer2Count++ + }) + + observer1() // Initial trigger + observer2() // Initial trigger + assert.equal(observer1Count, 1) + assert.equal(observer2Count, 1) + + signal(2) // Update signal + assert.equal(observer1Count, 2) + assert.equal(observer2Count, 2) + }) + + it('removes observers when they are stopped', () => { + const signal = new Signal(1) + let triggerCount = 0 + + const observer = new Observer(() => { + signal() // Read the signal + triggerCount++ + }) + + observer() // Initial trigger + assert.equal(triggerCount, 1) + + observer.stop() // Stop the observer + signal(2) // Update signal + assert.equal(triggerCount, 1) // Should not trigger + + observer.start() // Start the observer again + signal(3) // Update signal + assert.equal(triggerCount, 3) // Should trigger again (total count) + }) + + it('works with batching', () => { + const signal = new Signal(1) + let triggerCount = 0 + + const observer = new Observer(() => { + signal() // Read the signal + triggerCount++ + }) + + observer() // Initial trigger + assert.equal(triggerCount, 1) + + // Use batching to update multiple times + batch(() => { + signal(2) + signal(3) + signal(4) + }) + + // Should only trigger once due to batching + assert.equal(triggerCount, 2) + assert.equal(signal(), 4) + }) + + it('handles nested signals correctly', () => { + const outerSignal = new Signal(1) + const innerSignal = new Signal(10) + + let outerCount = 0 + let innerCount = 0 + + const outerObserver = new Observer(() => { + outerSignal() // Read outer signal + innerSignal() // Read inner signal + outerCount++ + }) + + const innerObserver = new Observer(() => { + innerSignal() // Read only inner signal + innerCount++ + }) + + outerObserver() // Initial trigger + innerObserver() // Initial trigger + assert.equal(outerCount, 1) + assert.equal(innerCount, 1) + + innerSignal(20) // Update inner signal + assert.equal(outerCount, 2) // Outer observer should trigger + assert.equal(innerCount, 2) // Inner observer should trigger + + outerSignal(2) // Update outer signal + assert.equal(outerCount, 3) // Outer observer should trigger + assert.equal(innerCount, 2) // Inner observer should not trigger + }) + + it('can be used as a function with no arguments to read', () => { + const signal = new Signal(42) + assert.equal(signal(), 42) + }) + + it('can be used as a function with one argument to write', () => { + const signal = new Signal(42) + signal(100) + assert.equal(signal(), 100) + }) + + it('can be used as a function with multiple arguments (ignores extras)', () => { + const signal = new Signal(42) + signal(100, 'extra', 'args') + assert.equal(signal(), 100) + }) + + it('works with hide function to prevent dependency tracking', () => { + const signal = new Signal(1) + let triggerCount = 0 + + // eslint-disable-next-line no-new + new Observer(() => { + triggerCount++ + }) + + // Use hide to read signal without creating dependency + const result = hide(() => signal()) + assert.equal(result, 1) + + // Observer should not be triggered when signal changes + signal(2) + assert.equal(triggerCount, 0) + }) + + it('handles Symbol values correctly', () => { + const symbol = Symbol('test') + const signal = new Signal(symbol) + const result = signal() + + // Symbol should be returned as-is (not wrapped) + assert.equal(result, symbol) + assert.equal(typeof result, 'symbol') + }) + + it('handles BigInt values correctly', () => { + const bigint = BigInt(123) + const signal = new Signal(bigint) + const result = signal() + + // BigInt should be returned as-is (not wrapped) + assert.equal(result, bigint) + assert.equal(typeof result, 'bigint') + }) +}) + describe('Reactor', () => { it('initializes without error', () => new Reactor()) From 48c85162bdeec943d96fe5ef9f24f95e9323d873 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 14:37:55 +0700 Subject: [PATCH 08/71] Changing behaviour so that write calls to a signal return reactor wrapped objects (same as read behaviour) --- src/reactor.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 95188e4..14a2b8b 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -50,7 +50,6 @@ class Signal extends Function { // - The core: The properties & methods which lets signals work // - The interface: The function returned to the user to use constructor (initialValue) { - // The "guts" of a Signal containing properties and methods // All actual functionality & state should be built into the core // Should be completely agnostic to syntactic sugar @@ -129,7 +128,23 @@ class Signal extends Function { const errorMessage = 'Multiple errors from signal write' throw new CompoundError(errorMessage, errorList) } - return output + + // If it's not an object then just return it right away + // Cleaner and faster than the alternative approach of constructing a Reactor + // and catching an error + if ( + // Need to do this because typeof null is object for some reason + output === null || ( + typeof output !== 'function' && + typeof output !== 'object' + ) + ) return output + + // Wrap the output in a Reactor if it's an object + // No need to wrap it if its already a Reactor + if (Reactors.has(output)) return output + // If not then wrap and store it for future reads + return new Reactor(output) }, // Used by observers to remove themselves from this as dependents // Also removesSelf from any owners if there are no more dependents @@ -706,10 +721,13 @@ export { Signal, Reactor, Observer, - hide, - batch, - shuck, + Signals, + Reactors, + Observers, signalCoreExtractor, reactorCoreExtractor, - observerCoreExtractor + observerCoreExtractor, + hide, + batch, + shuck } From 5023dd062bc3689d2b43426384e7c4ba0bb4103e Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 15:18:10 +0700 Subject: [PATCH 09/71] Synchronized the reactor rejection function to a common isObject --- src/reactor.js | 46 ++++++++++++++++++++-------------------------- test/test.js | 18 +++++++++--------- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 14a2b8b..6945941 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -32,6 +32,15 @@ let batcher = null // across multiple reads of the same object const reactorCache = new WeakMap() +// Helper function for checking if something is an object +function isObject (x) { + // functions are objects also but typeof to function + // nulls are not objects but typeof to objects + // the last bit is to check for nulls + const type = typeof (x) + return ((type === 'function' || type === 'object') && !!x) +} + // Signals are observable functions representing values // - Read a signal by calling it with no arguments // - Write to a signal by calling it with the desired value as an argument @@ -82,19 +91,8 @@ class Signal extends Function { // If it's not an object then just return it right away // Cleaner and faster than the alternative approach of constructing a Reactor // and catching an error - if ( - // Need to do this because typeof null is object for some reason - output === null || ( - typeof output !== 'function' && - typeof output !== 'object' - ) - ) return output - - // Wrap the output in a Reactor if it's an object - // No need to wrap it if its already a Reactor - if (Reactors.has(output)) return output - // If not then wrap and store it for future reads - return new Reactor(output) + if (isObject(output)) return new Reactor(output) + else return output }, // Life of a write @@ -132,19 +130,8 @@ class Signal extends Function { // If it's not an object then just return it right away // Cleaner and faster than the alternative approach of constructing a Reactor // and catching an error - if ( - // Need to do this because typeof null is object for some reason - output === null || ( - typeof output !== 'function' && - typeof output !== 'object' - ) - ) return output - - // Wrap the output in a Reactor if it's an object - // No need to wrap it if its already a Reactor - if (Reactors.has(output)) return output - // If not then wrap and store it for future reads - return new Reactor(output) + if (isObject(output)) return new Reactor(output) + else return output }, // Used by observers to remove themselves from this as dependents // Also removesSelf from any owners if there are no more dependents @@ -216,6 +203,13 @@ class Reactor { // If no source is provided then provide a new default object if (arguments.length === 0) initializedSource = this + // Early rejection for non-objects + // Could be handled later by proxy creation, but cleaner to have the logic here + // Can use the same function as Signal does for it's wrapping + if (!isObject(initializedSource)) { + throw new TypeError('Reactor source must be an Object') + } + // The "guts" of a Reactor containing properties and methods // All actual functionality & state should be built into the core // Should be completely agnostic to syntactic sugar diff --git a/test/test.js b/test/test.js index 7a4293e..d7863db 100644 --- a/test/test.js +++ b/test/test.js @@ -556,39 +556,39 @@ describe('Reactor', () => { it('fails to initialize with non-object', () => { assert.throws(() => new Reactor(true), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(false), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(null), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(undefined), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(1), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(0), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor('a'), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(''), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) assert.throws(() => new Reactor(Symbol('dummyTest')), { name: 'TypeError', - message: 'Cannot create proxy with a non-object as target or handler' + message: 'Reactor source must be an Object' }) }) From 8d8ba2ac68316650d394a5c166f11a93a00e98ff Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 15:20:45 +0700 Subject: [PATCH 10/71] Minor test name fix --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index d7863db..a67e903 100644 --- a/test/test.js +++ b/test/test.js @@ -61,7 +61,7 @@ describe('Signal', () => { it('should initialize with a Promise') describe('Edge cases', () => { - it('should initialize empty', () => { + it('should initialize with no arguments', () => { assert.doesNotThrow(new Signal()) }) it.skip('should not initialize with multiple arguments', () => { From 910f09f619151fb966dc21614c17d4183b3327ff Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 15:27:52 +0700 Subject: [PATCH 11/71] Added input validation for Signals --- src/reactor.js | 5 +++++ test/test.js | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 6945941..9c3ceb5 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -59,6 +59,11 @@ class Signal extends Function { // - The core: The properties & methods which lets signals work // - The interface: The function returned to the user to use constructor (initialValue) { + // Early rejection for multiple arguments + if (arguments.length > 1) { + throw new Error('Signal constructor takes at most one argument') + } + // The "guts" of a Signal containing properties and methods // All actual functionality & state should be built into the core // Should be completely agnostic to syntactic sugar diff --git a/test/test.js b/test/test.js index a67e903..112b8d7 100644 --- a/test/test.js +++ b/test/test.js @@ -64,8 +64,11 @@ describe('Signal', () => { it('should initialize with no arguments', () => { assert.doesNotThrow(new Signal()) }) - it.skip('should not initialize with multiple arguments', () => { - assert.throws(new Signal('foo', 'bar')) + it('should not initialize with multiple arguments', () => { + assert.throws(() => new Signal('foo', 'bar'), { + name: 'Error', + message: 'Signal constructor takes at most one argument' + }) }) }) }) From 13d78794ddb19764cce434ade5f9ca88e353a362 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 17:42:59 +0800 Subject: [PATCH 12/71] Cleaned up signal tests and added check for too many args --- src/reactor.js | 4 + test/test.js | 408 ++++++++++--------------------------------------- 2 files changed, 88 insertions(+), 324 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 9c3ceb5..faf8c9b 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -155,6 +155,10 @@ class Signal extends Function { super() const signalInterface = new Proxy(this, { apply (target, thisArg, args) { + // Early rejection for multiple arguments + if (args.length > 1) { + throw new Error('Signal objects take at most one argument for writes and zero arguments for reads') + } // An empty call is treated as a read if (args.length === 0) return signalCore.read() // A non empty call is treated as a write diff --git a/test/test.js b/test/test.js index 112b8d7..6ede4e0 100644 --- a/test/test.js +++ b/test/test.js @@ -15,7 +15,7 @@ import { shuck } from '../src/reactor.js' -describe('Signal', () => { +describe.only('Signal', () => { describe('Initializes with a value', () => { it('should initialize with a string', () => { assert.doesNotThrow(new Signal('foo')) @@ -41,6 +41,14 @@ describe('Signal', () => { assert.doesNotThrow(new Signal(false)) }) + it('should initialize with zero', () => { + assert.doesNotThrow(new Signal(0)) + }) + + it('should initialize with an empty string', () => { + assert.doesNotThrow(new Signal('')) + }) + it('should initialize with null', () => { assert.doesNotThrow(new Signal(null)) }) @@ -110,6 +118,18 @@ describe('Signal', () => { assert.strictEqual(signal(), value) }) + it('should return the initial zero', () => { + const value = 0 + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial empty string', () => { + const value = '' + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + it('should return the initial null', () => { const value = null const signal = new Signal(value) @@ -154,6 +174,7 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) + it('should update with a new number', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -163,6 +184,7 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) + it('should update with a new bigint', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -172,6 +194,7 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) + it('should update with a new symbol', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -181,6 +204,7 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) + it('should update with true', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -190,6 +214,7 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) + it('should update with false', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -199,355 +224,86 @@ describe('Signal', () => { const readReturn = signal() assert.strictEqual(readReturn, value) }) - it('should update with null', () => { + + it('should update with zero', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) - const value = null + const value = 0 const writeReturn = signal(value) assert.strictEqual(writeReturn, value) const readReturn = signal() assert.strictEqual(readReturn, value) }) - it('should update with undefined', () => { - const signal = new Signal('foo') - assert.strictEqual(signal(), 'foo') - const value = undefined + + it('should update with an empty string', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = '' const writeReturn = signal(value) assert.strictEqual(writeReturn, value) const readReturn = signal() assert.strictEqual(readReturn, value) }) - it('should update with an Object', () => { + + it('should update with null', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) - const value = {} + const value = null const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) + assert.strictEqual(writeReturn, value) const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) + assert.strictEqual(readReturn, value) }) - it('should update with a Function', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = () => {} + + it('should update with undefined', () => { + const signal = new Signal('foo') + assert.strictEqual(signal(), 'foo') + const value = undefined const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) + assert.strictEqual(writeReturn, value) const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) - }) - it('should update with a Promise') - }) - - it('can be updated with undefined', () => { - const signal = new Signal('foo') - signal(undefined) - assert.equal(signal(), undefined) - }) - - it('can be updated with null', () => { - const signal = new Signal('foo') - signal(null) - assert.equal(signal(), null) - }) - - it('can be updated with false', () => { - const signal = new Signal('foo') - signal(false) - assert.equal(signal(), false) - }) - - it('can be updated with zero', () => { - const signal = new Signal('foo') - signal(0) - assert.equal(signal(), 0) - }) - - it('can be updated with empty string', () => { - const signal = new Signal('foo') - signal('') - assert.equal(signal(), '') - }) - - it.skip('can be updated with function definition', () => { - const signal = new Signal(5) - const dummyFunction = () => {} - signal(dummyFunction) - console.log('dummyFunction', dummyFunction) - console.log('signal', signal()) - assert.equal(signal(), signal()) - }) - - it('can be updated with function that returns undefined', () => { - const signal = new Signal(5) - signal(() => undefined) - // Function definitions are not supported in current implementation - // The signal should store the function itself - assert.equal(typeof signal(), 'function') - }) - - it('tracks dependencies when read by an observer', () => { - const signal = new Signal(100) - let readValue = null - - const observer = new Observer(() => { - readValue = signal() - }) - - // Trigger the observer to read the signal - observer() - assert.equal(readValue, 100) - - // Update the signal and trigger again - signal(200) - observer() - assert.equal(readValue, 200) - }) - - it('wraps object values in Reactors', () => { - const obj = { foo: 'bar' } - const signal = new Signal(obj) - const result = signal() - - // The result should be a Reactor, not the original object - assert.notEqual(result, obj) - assert.equal(result.foo, 'bar') - }) - - it('does not wrap primitive values in Reactors', () => { - const signal = new Signal('hello') - const result = signal() - - // String should be returned as-is - assert.equal(result, 'hello') - assert.equal(typeof result, 'string') - }) - - it('does not wrap null in Reactors', () => { - const signal = new Signal(null) - const result = signal() - - // null should be returned as-is - assert.equal(result, null) - }) - - it('does not wrap functions in Reactors', () => { - const func = () => 'test' - const signal = new Signal(func) - const result = signal() - - // Function should be returned as-is (not wrapped in a Reactor) - assert.equal(typeof result, 'function') - assert.equal(result(), 'test') - }) - - it('does not wrap existing Reactors in new Reactors', () => { - const reactor = new Reactor({ foo: 'bar' }) - const signal = new Signal(reactor) - const result = signal() - - // Should return the same Reactor instance - assert.equal(result, reactor) - }) - - it('triggers observers when value changes', () => { - const signal = new Signal(1) - let triggerCount = 0 - - const observer = new Observer(() => { - signal() // Read the signal - triggerCount++ - }) - - observer() // Initial trigger - assert.equal(triggerCount, 1) - - signal(2) // Update signal - assert.equal(triggerCount, 2) - - signal(3) // Update signal again - assert.equal(triggerCount, 3) - }) - - it('does not trigger observers when same value is written', () => { - const signal = new Signal(1) - let triggerCount = 0 - - const observer = new Observer(() => { - signal() // Read the signal - triggerCount++ - }) - - observer() // Initial trigger - assert.equal(triggerCount, 1) - - signal(1) // Write same value - assert.equal(triggerCount, 1) // Should not trigger - - signal(2) // Write different value - assert.equal(triggerCount, 2) // Should trigger - }) - - it('handles multiple observers correctly', () => { - const signal = new Signal(1) - let observer1Count = 0 - let observer2Count = 0 - - const observer1 = new Observer(() => { - signal() // Read the signal - observer1Count++ - }) - - const observer2 = new Observer(() => { - signal() // Read the signal - observer2Count++ - }) - - observer1() // Initial trigger - observer2() // Initial trigger - assert.equal(observer1Count, 1) - assert.equal(observer2Count, 1) - - signal(2) // Update signal - assert.equal(observer1Count, 2) - assert.equal(observer2Count, 2) - }) - - it('removes observers when they are stopped', () => { - const signal = new Signal(1) - let triggerCount = 0 - - const observer = new Observer(() => { - signal() // Read the signal - triggerCount++ - }) - - observer() // Initial trigger - assert.equal(triggerCount, 1) - - observer.stop() // Stop the observer - signal(2) // Update signal - assert.equal(triggerCount, 1) // Should not trigger - - observer.start() // Start the observer again - signal(3) // Update signal - assert.equal(triggerCount, 3) // Should trigger again (total count) - }) - - it('works with batching', () => { - const signal = new Signal(1) - let triggerCount = 0 - - const observer = new Observer(() => { - signal() // Read the signal - triggerCount++ - }) - - observer() // Initial trigger - assert.equal(triggerCount, 1) - - // Use batching to update multiple times - batch(() => { - signal(2) - signal(3) - signal(4) + assert.strictEqual(readReturn, value) }) - // Should only trigger once due to batching - assert.equal(triggerCount, 2) - assert.equal(signal(), 4) - }) - - it('handles nested signals correctly', () => { - const outerSignal = new Signal(1) - const innerSignal = new Signal(10) - - let outerCount = 0 - let innerCount = 0 + describe('Objects are returned wrapped in a Reactor', () => { + it('should update with an Object', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) - const outerObserver = new Observer(() => { - outerSignal() // Read outer signal - innerSignal() // Read inner signal - outerCount++ - }) + it('should update with a Function', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = () => {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) - const innerObserver = new Observer(() => { - innerSignal() // Read only inner signal - innerCount++ + it('should update with a Promise') }) - outerObserver() // Initial trigger - innerObserver() // Initial trigger - assert.equal(outerCount, 1) - assert.equal(innerCount, 1) - - innerSignal(20) // Update inner signal - assert.equal(outerCount, 2) // Outer observer should trigger - assert.equal(innerCount, 2) // Inner observer should trigger - - outerSignal(2) // Update outer signal - assert.equal(outerCount, 3) // Outer observer should trigger - assert.equal(innerCount, 2) // Inner observer should not trigger - }) - - it('can be used as a function with no arguments to read', () => { - const signal = new Signal(42) - assert.equal(signal(), 42) - }) - - it('can be used as a function with one argument to write', () => { - const signal = new Signal(42) - signal(100) - assert.equal(signal(), 100) - }) - - it('can be used as a function with multiple arguments (ignores extras)', () => { - const signal = new Signal(42) - signal(100, 'extra', 'args') - assert.equal(signal(), 100) - }) - - it('works with hide function to prevent dependency tracking', () => { - const signal = new Signal(1) - let triggerCount = 0 - - // eslint-disable-next-line no-new - new Observer(() => { - triggerCount++ + describe('Edge cases', () => { + it('should throw an Error when called multiple arguments', () => { + const signal = new Signal() + assert.throws(() => signal(1, 2), { + name: 'Error', + message: 'Signal objects take at most one argument for writes and zero arguments for reads' + }) + }) }) - - // Use hide to read signal without creating dependency - const result = hide(() => signal()) - assert.equal(result, 1) - - // Observer should not be triggered when signal changes - signal(2) - assert.equal(triggerCount, 0) - }) - - it('handles Symbol values correctly', () => { - const symbol = Symbol('test') - const signal = new Signal(symbol) - const result = signal() - - // Symbol should be returned as-is (not wrapped) - assert.equal(result, symbol) - assert.equal(typeof result, 'symbol') - }) - - it('handles BigInt values correctly', () => { - const bigint = BigInt(123) - const signal = new Signal(bigint) - const result = signal() - - // BigInt should be returned as-is (not wrapped) - assert.equal(result, bigint) - assert.equal(typeof result, 'bigint') }) }) @@ -1471,3 +1227,7 @@ describe('Observer', () => { }) }) }) + +describe('Triggering', () => { + +}) From 8520ff4da01e0d30da03e1c6e40a490366b97260 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 18:45:33 +0800 Subject: [PATCH 13/71] Added Reactor initialization tests --- test/test.js | 201 +++++++++++++++++++++++++++++---------------------- 1 file changed, 115 insertions(+), 86 deletions(-) diff --git a/test/test.js b/test/test.js index 6ede4e0..f0aed93 100644 --- a/test/test.js +++ b/test/test.js @@ -17,61 +17,21 @@ import { describe.only('Signal', () => { describe('Initializes with a value', () => { - it('should initialize with a string', () => { - assert.doesNotThrow(new Signal('foo')) - }) - - it('should initialize with a number', () => { - assert.doesNotThrow(new Signal(123)) - }) - - it('should initialize with a bigint', () => { - assert.doesNotThrow(new Signal(123456789123456789n)) - }) - - it('should initialize with a symbol', () => { - assert.doesNotThrow(new Signal(Symbol('foo'))) - }) - - it('should initialize with true', () => { - assert.doesNotThrow(new Signal(true)) - }) - - it('should initialize with false', () => { - assert.doesNotThrow(new Signal(false)) - }) - - it('should initialize with zero', () => { - assert.doesNotThrow(new Signal(0)) - }) - - it('should initialize with an empty string', () => { - assert.doesNotThrow(new Signal('')) - }) - - it('should initialize with null', () => { - assert.doesNotThrow(new Signal(null)) - }) - - it('should initialize with undefined', () => { - assert.doesNotThrow(new Signal(undefined)) - }) - - it('should initialize with an Object', () => { - assert.doesNotThrow(new Signal({})) - }) - - it('should initialize with a Function', () => { - assert.doesNotThrow(new Signal(() => {})) - }) - - // TODO: Figure out promises - it('should initialize with a Promise') - + it('should initialize with a string', () => new Signal('foo')) + it('should initialize with a number', () => new Signal(123)) + it('should initialize with a bigint', () => new Signal(123456789123456789n)) + it('should initialize with a symbol', () => new Signal(Symbol('foo'))) + it('should initialize with true', () => new Signal(true)) + it('should initialize with false', () => new Signal(false)) + it('should initialize with zero', () => new Signal(0)) + it('should initialize with an empty string', () => new Signal('')) + it('should initialize with null', () => new Signal(null)) + it('should initialize with undefined', () => new Signal(undefined)) + it('should initialize with an Object', () => new Signal({})) + it('should initialize with a Function', () => new Signal(() => {})) + it('should initialize with a Promise') // TODO: Figure out promises describe('Edge cases', () => { - it('should initialize with no arguments', () => { - assert.doesNotThrow(new Signal()) - }) + it('should initialize with no arguments', () => new Signal()) it('should not initialize with multiple arguments', () => { assert.throws(() => new Signal('foo', 'bar'), { name: 'Error', @@ -164,7 +124,7 @@ describe.only('Signal', () => { }) }) - describe('Replaces the stored value when called with an argument while returning the new value', () => { + describe('Replaces the stored value when called with an argument and returns the new value', () => { it('should update with a new string', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) @@ -307,50 +267,119 @@ describe.only('Signal', () => { }) }) -describe('Reactor', () => { - it('initializes without error', () => new Reactor()) +describe.only('Reactor', () => { + describe('Initializes with no argument returning a new Reactor wrapped Object', () => { + it('should initialize with no argument', () => new Reactor()) + it('should return a Reactor Object', () => { + const reactor = new Reactor() + assert(Reactors.has(reactor)) + }) + }) - it('initializes exsting object without error', () => new Reactor({})) + describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { + it('should initialize with an Object', () => new Reactor({})) + it('should initialize with an Function', () => new Reactor(() => {})) + it('should initialize with a Promise') // TODO: Figure out promises + it('should return a Reactor Object wrapping the original', () => { + const object = {} + const reactor = new Reactor(object) + assert(Reactors.has(reactor)) + assert.notEqual(reactor, object) + assert.strictEqual(shuck(reactor), object) + }) + describe('Edge cases', () => { + it('should not wrap a Reactor around an existing Reactor', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(reactor) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) - it('fails to initialize with non-object', () => { - assert.throws(() => new Reactor(true), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should return the same Reactor when wrapping the same object', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(object) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) }) - assert.throws(() => new Reactor(false), { - name: 'TypeError', - message: 'Reactor source must be an Object' + }) + + describe('Fails to initialize with values which are not Objects', () => { + it('should fail to initialize with a string', () => { + assert.throws(() => new Reactor('foo'), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(null), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a number', () => { + assert.throws(() => new Reactor(123), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(undefined), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a bigint', () => { + assert.throws(() => new Reactor(123456789123456789n), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(1), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a symbol', () => { + assert.throws(() => new Reactor(Symbol('foo')), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(0), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with true', () => { + assert.throws(() => new Reactor(true), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor('a'), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with false', () => { + assert.throws(() => new Reactor(false), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(''), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with zero', () => { + assert.throws(() => new Reactor(0), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - assert.throws(() => new Reactor(Symbol('dummyTest')), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with an empty string', () => { + assert.throws(() => new Reactor(''), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with null', () => { + assert.throws(() => new Reactor(null), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with undefined', () => { + assert.throws(() => new Reactor(undefined), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) }) + it('writes without error', () => { const reactor = new Reactor() reactor.foo = 'bar' From d6ed6931e111b53dd0bffc8074e0bd31db11d17a Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 21:14:13 +0800 Subject: [PATCH 14/71] Cleaned up Signal and Reactor tests --- test/test.js | 403 +++++++++++++++++++++++++++------------------------ 1 file changed, 215 insertions(+), 188 deletions(-) diff --git a/test/test.js b/test/test.js index f0aed93..109bb9e 100644 --- a/test/test.js +++ b/test/test.js @@ -15,7 +15,7 @@ import { shuck } from '../src/reactor.js' -describe.only('Signal', () => { +describe('Signal', () => { describe('Initializes with a value', () => { it('should initialize with a string', () => new Signal('foo')) it('should initialize with a number', () => new Signal(123)) @@ -267,246 +267,246 @@ describe.only('Signal', () => { }) }) -describe.only('Reactor', () => { - describe('Initializes with no argument returning a new Reactor wrapped Object', () => { - it('should initialize with no argument', () => new Reactor()) - it('should return a Reactor Object', () => { - const reactor = new Reactor() - assert(Reactors.has(reactor)) +describe('Reactor', () => { + describe('Initialization', () => { + describe('Initializes with no argument returning a new Reactor wrapped Object', () => { + it('should initialize with no argument', () => new Reactor()) + it('should return a Reactor Object', () => { + const reactor = new Reactor() + assert(Reactors.has(reactor)) + }) }) - }) - describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { - it('should initialize with an Object', () => new Reactor({})) - it('should initialize with an Function', () => new Reactor(() => {})) - it('should initialize with a Promise') // TODO: Figure out promises - it('should return a Reactor Object wrapping the original', () => { - const object = {} - const reactor = new Reactor(object) - assert(Reactors.has(reactor)) - assert.notEqual(reactor, object) - assert.strictEqual(shuck(reactor), object) - }) - describe('Edge cases', () => { - it('should not wrap a Reactor around an existing Reactor', () => { + describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { + it('should initialize with an Object', () => new Reactor({})) + it('should initialize with an Function', () => new Reactor(() => {})) + it('should initialize with a Promise') // TODO: Figure out promises + it('should return a Reactor Object wrapping the original', () => { const object = {} const reactor = new Reactor(object) - const reactor2 = new Reactor(reactor) - assert(!Reactors.has(object)) assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.notEqual(reactor, object) assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) }) + describe('Edge cases', () => { + it('should not wrap a Reactor around an existing Reactor', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(reactor) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) - it('should return the same Reactor when wrapping the same object', () => { - const object = {} - const reactor = new Reactor(object) - const reactor2 = new Reactor(object) - assert(!Reactors.has(object)) - assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) - assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) + it('should return the same Reactor when wrapping the same object', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(object) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) }) }) - }) - describe('Fails to initialize with values which are not Objects', () => { - it('should fail to initialize with a string', () => { - assert.throws(() => new Reactor('foo'), { - name: 'TypeError', - message: 'Reactor source must be an Object' + describe('Fails to initialize with values which are not Objects', () => { + it('should fail to initialize with a string', () => { + assert.throws(() => new Reactor('foo'), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with a number', () => { - assert.throws(() => new Reactor(123), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a number', () => { + assert.throws(() => new Reactor(123), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with a bigint', () => { - assert.throws(() => new Reactor(123456789123456789n), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a bigint', () => { + assert.throws(() => new Reactor(123456789123456789n), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with a symbol', () => { - assert.throws(() => new Reactor(Symbol('foo')), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with a symbol', () => { + assert.throws(() => new Reactor(Symbol('foo')), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with true', () => { - assert.throws(() => new Reactor(true), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with true', () => { + assert.throws(() => new Reactor(true), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with false', () => { - assert.throws(() => new Reactor(false), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with false', () => { + assert.throws(() => new Reactor(false), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with zero', () => { - assert.throws(() => new Reactor(0), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with zero', () => { + assert.throws(() => new Reactor(0), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with an empty string', () => { - assert.throws(() => new Reactor(''), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with an empty string', () => { + assert.throws(() => new Reactor(''), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with null', () => { - assert.throws(() => new Reactor(null), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with null', () => { + assert.throws(() => new Reactor(null), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) - }) - it('should fail to initialize with undefined', () => { - assert.throws(() => new Reactor(undefined), { - name: 'TypeError', - message: 'Reactor source must be an Object' + it('should fail to initialize with undefined', () => { + assert.throws(() => new Reactor(undefined), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) }) }) }) - - it('writes without error', () => { - const reactor = new Reactor() - reactor.foo = 'bar' - }) - - it('reads without error', () => { - const reactor = new Reactor() - reactor.foo = 'bar' - assert.equal(reactor.foo, 'bar') - }) - - it('reads from existing object without error', () => { - const reactor = new Reactor({ - foo: 'bar' + describe('Reads properties from the proxied Object', () => { + it('should return primitive values from the proxied Object', () => { + const reactor = new Reactor({ + foo: 'bar' + }) + assert.strictEqual(reactor.foo, 'bar') + }) + it('should return object values from the proxied Object as a Reactor', () => { + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + const readResult = reactor.foo + assert.notStrictEqual(dummyObject, readResult) + assert(Reactors.has(readResult)) + assert.strictEqual(dummyObject, shuck(readResult)) }) - assert.equal(reactor.foo, 'bar') }) - it('can defineProperty without error', () => { - const reactor = new Reactor() - Object.defineProperty(reactor, 'foo', { - get () { return 'bar' } + describe('Writes through to the proxied Object when assigning properties', () => { + it('should write values through to the proxied Object', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + reactor.foo = 'bar' + assert.strictEqual(proxiedObject.foo, 'bar') + assert.strictEqual(reactor.foo, 'bar') }) - assert.equal(reactor.foo, 'bar') - }) - it('fails write after defineProperty non-writable', () => { - const reactor = new Reactor() - Object.defineProperty(reactor, 'foo', { - value: 'bar', - writable: false + it('should return the written values', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + const writeReturn = (reactor.foo = 'bar') + assert.strictEqual(writeReturn, 'bar') }) - assert.throws(() => (reactor.foo = 'baz'), { - name: 'TypeError' + + it('should work with defineProperty', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + const result = Object.defineProperty(reactor, 'foo', { + get () { return 'bar' } + }) + assert.strictEqual(proxiedObject.foo, 'bar') + assert.strictEqual(reactor.foo, 'bar') + assert.strictEqual(result, reactor) }) - }) - it('can deleteProperty without error', () => { - const reactor = new Reactor({ - foo: 'bar' + it('should not be writable if defineProperty sets writable to false', () => { + const reactor = new Reactor() + Object.defineProperty(reactor, 'foo', { + value: 'bar', + writable: false + }) + assert.strictEqual(reactor.foo, 'bar') + assert.throws(() => { + reactor.foo = 'baz' + }, { + name: 'TypeError', + message: "Cannot assign to read only property 'foo' of object '#'" + }) }) - delete reactor.foo - assert.equal(reactor.foo, undefined) - }) - it('can call map on Array Reactor without error', () => { - const reactor = new Reactor(['0', '1', '2']) - reactor.map(x => 'this is ' + x) + it('should delete properties from the proxied Object', () => { + const proxiedObject = { foo: 'bar' } + const reactor = new Reactor(proxiedObject) + delete reactor.foo + assert.equal(proxiedObject.foo, undefined) + assert.equal(reactor.foo, undefined) + }) }) - describe('Misc', () => { - it('respects receiver context for prototype inheritors', () => { - const reactor = new Reactor() - reactor.foo = 'bar' - Object.defineProperty(reactor, 'getFoo', { - get () { - return this.foo - } - }) - assert.equal(reactor.getFoo, 'bar') - reactor.foo = 'quu' - assert.equal(reactor.getFoo, 'quu') - const inheritor = Object.create(reactor) - assert.equal(inheritor.foo, 'quu') - assert.equal(inheritor.getFoo, 'quu') - inheritor.foo = 'mux' - assert.equal(inheritor.getFoo, 'mux') + describe('Works with native object properties and methods', () => { + it('should work with Array map', () => { + const reactor = new Reactor(['0', '1', '2']) + const result = reactor.map(x => 'this is ' + x) + assert.deepStrictEqual(result, ['this is 0', 'this is 1', 'this is 2']) }) - it('allows Reactor wrapping of native object properties', () => { - const native = new Map() - const proxy = new Reactor(native) + it('should be able to read native properties', () => { + const map = new Map() + const reactor = new Reactor(map) // Normaly proxy wrapping will fail // This check to see if we redirect the call `this` // to the wrapped object instead of the wrapper when appropriate - assert.equal(proxy.size, 0) + assert.strictEqual(reactor.size, 0) + map.set('foo', 'bar') + assert.strictEqual(reactor.size, 1) }) - it('allows Reactor wrapping of native objects methods', () => { + it('should be able to call native objects methods', () => { const reactor = new Reactor(new Map()) // Normal proxy wrapping will fail // since .keys() cannot be called on a Proxy - reactor.keys() + const result = reactor.keys() + assert(typeof result[Symbol.iterator] === 'function') }) + }) - it('allows shucking of a Reactor to get the underlying object', () => { - const reactor = new Reactor(new Map()) - assert.throws(() => Map.prototype.keys.call(reactor), { - name: 'TypeError', - message: 'Method Map.prototype.keys called on incompatible receiver #' - }) - const source = shuck(reactor) - Map.prototype.keys.call(source) + describe('Misc', () => { + it('should maintain instanceof checks for the wrapped object', () => { + const reactor = new Reactor([]) + assert(reactor instanceof Array) + // Sadly no way to also pass instanceof Reactor while maintaining the original instanceof checks + // An object can only have one class inheritance chain + // Would be great if we had some sort of in }) - it('Wraps the same object to the same Reactor', () => { - const outerDummy = {} - const reactorA = new Reactor(outerDummy) - const reactorB = new Reactor(outerDummy) - const innerDummy = {} - reactorA.foo = innerDummy - reactorB.bar = innerDummy - assert.equal(reactorA, reactorB) - assert.equal(reactorA.foo, reactorB.bar) + it('should pass instanceof Reactor if no object was provided', () => { + const reactor = new Reactor() + assert(reactor instanceof Reactor) }) - it('does not read an observer when calling start', () => { - let counter = 0 - const reactor = new Reactor({ - foo: 'bar' + it('should respect receiver this context for prototype inheritors', () => { + const reactor = new Reactor() + reactor.foo = 'bar' + Object.defineProperty(reactor, 'getFoo', { + get () { + return this.foo + } }) - const innerObserver = new Observer(() => reactor.foo) - new Observer(() => { - innerObserver.start() - counter += 1 - })() - assert.equal(counter, 1) - reactor.foo = 'baz' - assert.equal(counter, 1) - }) - - it('passes instanceof checks', () => { - const a = new Reactor() - assert(a instanceof Reactor) - const b = new Reactor([]) - assert(b instanceof Array) - // assert(b instanceof Reactor) + const inheritor = Object.create(reactor) + assert.strictEqual(inheritor.getFoo, 'bar') + // The inheritor is still using its inherited getter + // But it is being executed with the inheritor as `this` + // So it should return the inheritor's foo property instead of the original + inheritor.foo = 'qux' + assert.strictEqual(inheritor.getFoo, 'qux') }) }) }) @@ -1260,3 +1260,30 @@ describe('Observer', () => { describe('Triggering', () => { }) + +describe('Misc', () => { + it('allows shucking of a Reactor to get the underlying object', () => { + const reactor = new Reactor(new Map()) + assert.throws(() => Map.prototype.keys.call(reactor), { + name: 'TypeError', + message: 'Method Map.prototype.keys called on incompatible receiver #' + }) + const source = shuck(reactor) + Map.prototype.keys.call(source) + }) + + it('does not read an observer when calling start', () => { + let counter = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + const innerObserver = new Observer(() => reactor.foo) + new Observer(() => { + innerObserver.start() + counter += 1 + })() + assert.equal(counter, 1) + reactor.foo = 'baz' + assert.equal(counter, 1) + }) +}) From a2642ae95ce43b5c4f3940560ddbff896485cf29 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 21:26:32 +0800 Subject: [PATCH 15/71] Added error for Reactor constructor being called with multiple arguments --- src/reactor.js | 4 ++++ test/test.js | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/src/reactor.js b/src/reactor.js index faf8c9b..c1643d5 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -208,6 +208,10 @@ class Reactor { const existingReactor = reactorCache.get(initializedSource) if (existingReactor) return existingReactor + if (arguments.length > 1) { + throw new Error('Reactor constructor takes at most one argument') + } + // The source is the internal proxied object // If no source is provided then provide a new default object if (arguments.length === 0) initializedSource = this diff --git a/test/test.js b/test/test.js index 109bb9e..7b532b9 100644 --- a/test/test.js +++ b/test/test.js @@ -379,6 +379,13 @@ describe('Reactor', () => { }) }) }) + + it('should fail to initialize with multiple arguments', () => { + assert.throws(() => new Reactor({}, {}), { + name: 'Error', + message: 'Reactor constructor takes at most one argument' + }) + }) }) describe('Reads properties from the proxied Object', () => { From 252db259d5e0717428cfd3f31fddad56dfb06995 Mon Sep 17 00:00:00 2001 From: fynyky Date: Fri, 15 Aug 2025 22:09:52 +0800 Subject: [PATCH 16/71] Refined check on native object call error --- src/reactor.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index c1643d5..b96fa7c 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -250,7 +250,7 @@ class Reactor { try { return Reflect.apply(this.source, thisArg, argumentsList) } catch (error) { - if (error.name === 'TypeError') { + if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { const core = reactorCoreExtractor.get(thisArg) if (typeof core !== 'undefined') { // Note that this.source and core.source are different @@ -310,9 +310,9 @@ class Reactor { try { return Reflect.get(this.source, property, receiver) } catch (error) { - // We trim to TypeError to minimize unnecessary double retries to actual proxy problems + // We trim to specific "incompatible receiver" TypeErrors to minimize unnecessary double retries to actual proxy problems // but it could still happen for other TypeErrors - if (error.name === 'TypeError') return Reflect.get(this.source, property, this.source) + if (error.name === 'TypeError' && error.message.includes('incompatible receiver')) return Reflect.get(this.source, property, this.source) throw error } })() From 9b39954be22d1e92f007e11ff92f0ced4cd71a06 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 00:11:01 +0800 Subject: [PATCH 17/71] Cleaned up basic observer tests --- src/reactor.js | 4 + test/test.js | 642 +++++++++++++++++++++++++++++-------------------- 2 files changed, 379 insertions(+), 267 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index b96fa7c..dc6eb10 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -477,6 +477,10 @@ class Reactor { const Observers = new WeakSet() class Observer extends Function { constructor (execute) { + if (arguments.length !== 1) { + throw new Error('Observer constructor requires exactly one argument') + } + // Parameter validation if (typeof execute !== 'function') { throw new TypeError('Cannot create observer with a non-function') diff --git a/test/test.js b/test/test.js index 7b532b9..b055b13 100644 --- a/test/test.js +++ b/test/test.js @@ -380,10 +380,12 @@ describe('Reactor', () => { }) }) - it('should fail to initialize with multiple arguments', () => { - assert.throws(() => new Reactor({}, {}), { - name: 'Error', - message: 'Reactor constructor takes at most one argument' + describe('Edge cases', () => { + it('should fail to initialize with multiple arguments', () => { + assert.throws(() => new Reactor({}, {}), { + name: 'Error', + message: 'Reactor constructor takes at most one argument' + }) }) }) }) @@ -519,141 +521,292 @@ describe('Reactor', () => { }) describe('Observer', () => { - it('passes instanceof checks', () => { - const a = new Observer(() => {}) - assert(a instanceof Observer) - assert(a instanceof Function) - }) + describe('Initializes wrapping a function', () => { + it('should initialize with a function argument', () => new Observer(() => {})) - it('can be used as a constructor', () => { - const A = new Observer(function (arg) { - this.foo = 'bar' + arg - return this + it('should fail to initialize with no argument', () => { + assert.throws(() => new Observer(), { + name: 'Error', + message: 'Observer constructor requires exactly one argument' + }) }) - const a = new A('baz') - assert.equal(JSON.stringify(a), '{"foo":"barbaz"}') - }) - it('initializes function without error', () => new Observer(() => {})) - - it('passed correct value of this to observer', () => { - let aResult - const a = new Observer(function () { aResult = this }) - let barResult - const foo = { - a, - bar: function () { barResult = this } - } - foo.a() - foo.bar() - assert.equal(foo, aResult) - assert.equal(foo, barResult) - assert.equal(aResult, barResult) - }) + it('should fail to initialize with multiple arguments', () => { + assert.throws(() => new Observer(() => {}, () => {}), { + name: 'Error', + message: 'Observer constructor requires exactly one argument' + }) + }) - it('fails to initialize with no argument', () => { - assert.throws(() => new Observer(), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + it('should be an Observer object', () => { + const observer = new Observer(() => {}) + assert(observer instanceof Observer) }) - }) - it('fails to initialize with non-function', () => { - assert.throws(() => new Observer(true), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + describe('Fails to initialize with an argument that is not a Function', () => { + it('should fail to initialize with a string', () => { + assert.throws(() => new Observer('foo'), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a number', () => { + assert.throws(() => new Observer(123), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a bigint', () => { + assert.throws(() => new Observer(123456789123456789n), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a symbol', () => { + assert.throws(() => new Observer(Symbol('foo')), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with true', () => { + assert.throws(() => new Observer(true), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with false', () => { + assert.throws(() => new Observer(false), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with zero', () => { + assert.throws(() => new Observer(0), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an empty string', () => { + assert.throws(() => new Observer(''), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with null', () => { + assert.throws(() => new Observer(null), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with undefined', () => { + assert.throws(() => new Observer(undefined), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an Object', () => { + assert.throws(() => new Observer({}), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an Array', () => { + assert.throws(() => new Observer([]), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) }) - assert.throws(() => new Observer(false), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + }) + + describe('Can be used like a normal function', () => { + it('should be callable', () => { + const observer = new Observer(() => {}) + observer() }) - assert.throws(() => new Observer(null), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should return the function return value', () => { + const observer = new Observer(() => 'foo') + assert.strictEqual(observer(), 'foo') }) - assert.throws(() => new Observer(undefined), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should be callable with arguments', () => { + const observer = new Observer((a, b, c) => { + return a + b + c + }) + assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') }) - assert.throws(() => new Observer(1), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should have access to its arguments array', () => { + const observer = new Observer(function () { + let output = '' + for (const arg of arguments) { + output += arg + } + return output + }) + assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') }) - assert.throws(() => new Observer(0), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should have access to its this context', () => { + let context + const object = {} + const observer = new Observer(function () { + context = this + }) + object.observer = observer + object.observer() + assert.strictEqual(context, object) }) - assert.throws(() => new Observer('a'), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should be able to use bind to create a new function with this context and arguments', () => { + let context + const object = { foo: 42 } + const observer = new Observer(function (a) { + context = this + return this.foo + a + }) + const boundFunction = observer.bind(object, 10) + const result = boundFunction() + assert.strictEqual(context, object) + assert.strictEqual(result, 52) }) - assert.throws(() => new Observer(''), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should be able to use call to execute with specified this context and arguments', () => { + const object = { foo: 'bar' } + const observer = new Observer(function (a, b) { + return this.foo + a + b + }) + const result = observer.call(object, 'baz', 'qux') + assert.strictEqual(result, 'barbazqux') }) - assert.throws(() => new Observer(Symbol('dummyTest')), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should be able to use apply to execute with specified this context and arguments', () => { + const object = { foo: 'bar' } + const observer = new Observer(function (a, b) { + return this.foo + a + b + }) + const result = observer.apply(object, ['baz', 'qux']) + assert.strictEqual(result, 'barbazqux') }) - assert.throws(() => new Observer({}), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it.skip('should be usable as a constructor', () => { + const DummyClass = new Observer(function (arg) { + this.foo = 'bar' + arg + return this + }) + const instance = new DummyClass('baz') + // TODO this is failing + // The constructor is the execute function rather than the wrapped observer + // Need to figure out how to interject + assert(instance instanceof DummyClass.execute) // This works but shouldn't + assert(instance instanceof DummyClass) // This doesn't work but should + assert.strictEqual(instance.foo, 'barbaz') }) - assert.throws(() => new Observer([]), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' + + it('should be a type of Function', () => { + const observer = new Observer(() => {}) + assert(observer instanceof Function) + assert(typeof observer === 'function') }) }) - it('exposes the raw function as execute', () => { - const dummyFunction = function () { - return 'foo' - } - const observer = new Observer(dummyFunction) - assert.equal(observer.execute, dummyFunction) + describe('Wraps returned Object values in Reactors', () => { + it('', () => { + const object = {} + const observer = new Observer(() => object) + const result = observer() + assert(Reactors.has(result)) + assert.notStrictEqual(result, object) + assert.strictEqual(shuck(result), object) + }) }) - it('exposes the last derived value', () => { - const rx = new Reactor({ - foo: 'foo' + describe('Exposes the wrapped function through execute', () => { + it('', () => { + const dummyFunction = function () {} + const observer = new Observer(dummyFunction) + assert.strictEqual(observer.execute, dummyFunction) }) - const observer = new Observer(() => { - return rx.foo - }) - assert(typeof observer.value === 'undefined') - observer() - assert.equal(observer.value, 'foo') - rx.foo = 'bar' - assert.equal(observer.value, 'bar') }) - it('returns the function return value', () => { - const observer = new Observer(() => 'foo') - assert.equal(observer(), 'foo') + describe('Exposes the last derived value through value', () => { + it('should keep the last derived value for primitive values', () => { + let counter = 0 + const dummyFunction = () => (counter += 1) + const observer = new Observer(dummyFunction) + let result = observer() + assert.strictEqual(result, 1) + assert.strictEqual(observer.value, 1) + assert.strictEqual(result, observer.value) + result = observer() + assert.strictEqual(result, 2) + assert.strictEqual(observer.value, 2) + assert.strictEqual(result, observer.value) + }) + + it('should keep the last derived value for Object values', () => { + let counter = 0 + const dummyFunction = () => { + counter += 1 + return { count: counter } + } + const observer = new Observer(dummyFunction) + let result = observer() + assert.strictEqual(JSON.stringify(result), '{"count":1}') + assert.strictEqual(JSON.stringify(observer.value), '{"count":1}') + assert.strictEqual(result, observer.value) + result = observer() + assert.strictEqual(JSON.stringify(result), '{"count":2}') + assert.strictEqual(JSON.stringify(observer.value), '{"count":2}') + assert.strictEqual(result, observer.value) + }) }) - it('can observe an observer', () => { - let outcome - const rx = new Reactor({ - foo: 'foo' - }) - const a = new Observer(() => rx.foo + 'bar') - a() - const b = new Observer(() => (outcome = a.value + 'baz')) - b() - assert.equal(outcome, 'foobarbaz') - rx.foo = 'qux' - assert.equal(outcome, 'quxbarbaz') + describe('Observer chaining and dependencies', () => { + it('should observe an observer', () => { + let outcome + const rx = new Reactor({ + foo: 'foo' + }) + const a = new Observer(() => rx.foo + 'bar') + a() + const b = new Observer(() => (outcome = a.value + 'baz')) + b() + assert.equal(outcome, 'foobarbaz') + rx.foo = 'qux' + assert.equal(outcome, 'quxbarbaz') + }) + + it('should trigger chained observers', () => { + let tracker + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + reactor.bigFoo = reactor.foo.toUpperCase() + })() + assert.equal(reactor.bigFoo, 'BAR') + new Observer(() => { + tracker = reactor.bigFoo + })() + assert.equal(tracker, 'BAR') + reactor.foo = 'qux' + assert.equal(reactor.bigFoo, 'QUX') + assert.equal(tracker, 'QUX') + }) }) +}) +describe('Reactivity', () => { describe('Triggering', () => { - it('triggers once on initialization', () => { + it('should trigger once on initialization', () => { let counter = 0 new Observer(() => { counter += 1 })() assert.equal(counter, 1) }) - it('triggers once on Reactor dependency write', () => { + it('should trigger once on Reactor dependency write', () => { let counter = 0 let tracker const reactor = new Reactor({ @@ -670,7 +823,7 @@ describe('Observer', () => { assert.equal(tracker, 'mux') }) - it('triggers once on nested Reactor dependency write', () => { + it('should trigger once on nested Reactor dependency write', () => { let counter = 0 let tracker const reactor = new Reactor({ @@ -689,7 +842,7 @@ describe('Observer', () => { assert.equal(tracker, 'moo') }) - it('triggers on defineProperty', () => { + it('should trigger on defineProperty', () => { let tracker const reactor = new Reactor({ foo: 'bar' @@ -702,7 +855,7 @@ describe('Observer', () => { assert.equal(tracker, 'baz') }) - it('trigger on deleteProperty', () => { + it('should trigger on deleteProperty', () => { let tracker const reactor = new Reactor({ foo: 'bar' @@ -713,7 +866,7 @@ describe('Observer', () => { assert.equal(tracker, undefined) }) - it('triggers on array update methods', () => { + it('should trigger on array update methods', () => { let counter = 0 let tracker const reactor = new Reactor([]) @@ -731,7 +884,7 @@ describe('Observer', () => { assert.equal(tracker, 'bar') }) - it('triggers only once despite multiple dependencies', () => { + it('should trigger only once despite multiple dependencies', () => { let counter = 0 let hasTracker let getTracker @@ -756,7 +909,7 @@ describe('Observer', () => { assert.equal(JSON.stringify(ownKeysTracker), '["foo"]') }) - it('triggers only once even for functions with multiple changes', () => { + it('should trigger only once even for functions with multiple changes', () => { let counter = 0 let lengthTracker let firstTracker @@ -775,7 +928,7 @@ describe('Observer', () => { assert.equal(firstTracker, 'bar') }) - it('triggers correctly on nested observer definitions', () => { + it('should trigger correctly on nested observer definitions', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' @@ -810,7 +963,7 @@ describe('Observer', () => { assert.equal(innerTracker, 'baz') }) - it('subscribes on Object.keys', () => { + it('should subscribe on Object.keys', () => { let counter = 0 let tracker const reactor = new Reactor({ foo: 'bar' }) @@ -825,7 +978,7 @@ describe('Observer', () => { assert.equal(JSON.stringify(tracker), '["foo","moo"]') }) - it('subscribes on in operator', () => { + it('should subscribe on in operator', () => { let counter = 0 let tracker const reactor = new Reactor() @@ -840,7 +993,7 @@ describe('Observer', () => { assert.equal(tracker, true) }) - it('subscribes using observe keyword', () => { + it('should subscribe using observe keyword', () => { let counter = 0 let tracker const reactor = new Reactor({ value: 'foo' }) @@ -855,7 +1008,7 @@ describe('Observer', () => { assert.equal(tracker, 'bar') }) - it('does not subscribe in hide block', () => { + it('should not subscribe in hide block', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' @@ -888,7 +1041,7 @@ describe('Observer', () => { assert.equal(innerTracker, 'baz') }) - it('returns output of hide block', () => { + it('should return output of hide block', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' @@ -921,116 +1074,14 @@ describe('Observer', () => { assert.equal(innerTracker, 'baz') }) - it('does not self trigger in an hide block', () => { + it('should not self trigger in an hide block', () => { const reactor = new Reactor(['a', 'b', 'c']) new Observer(() => { hide(() => reactor.pop()) })() }) - it('can redefine an observer', () => { - const reactor = new Reactor({ - first: 'foo', - second: 'bar' - }) - let firstCounter = 0 - let secondCounter = 0 - let firstTracker - let secondTracker - const observer = new Observer(() => { - firstCounter += 1 - firstTracker = reactor.first - }) - observer() - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 0) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, undefined) - observer.execute = () => { - secondCounter += 1 - secondTracker = reactor.second - } - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.first = 'moo' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.second = 'baz' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 2) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'baz') - }) - - it('delays and combines observer triggers when using batch', () => { - const reactor = new Reactor({ value: 'foo' }) - let counter = 0 - new Observer(() => { - counter += 1 - return reactor.value - })() - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bleep' - assert.equal(counter, 1) - reactor.value = 'bloop' - assert.equal(counter, 1) - reactor.value = 'blarp' - assert.equal(counter, 1) - }) - assert.equal(counter, 2) - }) - - it('can nest batchers with no consequence', () => { - const reactor = new Reactor({ value: 'foo' }) - let counter = 0 - new Observer(() => { - counter += 1 - return reactor.value - })() - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bleep' - assert.equal(counter, 1) - reactor.value = 'bloop' - assert.equal(counter, 1) - reactor.value = 'blarp' - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bink' - assert.equal(counter, 1) - reactor.value = 'bonk' - assert.equal(counter, 1) - reactor.value = 'bup' - assert.equal(counter, 1) - }) - }) - assert.equal(counter, 2) - }) - - it('triggers chained observers', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - reactor.bigFoo = reactor.foo.toUpperCase() - })() - assert.equal(reactor.bigFoo, 'BAR') - new Observer(() => { - tracker = reactor.bigFoo - })() - assert.equal(tracker, 'BAR') - reactor.foo = 'qux' - assert.equal(reactor.bigFoo, 'QUX') - assert.equal(tracker, 'QUX') - }) - - it('does not redundantly trigger on setting identical values', () => { + it('should not redundantly trigger on setting identical values', () => { let counter = 0 let tracker const reactor = new Reactor({ @@ -1047,7 +1098,7 @@ describe('Observer', () => { assert.equal(tracker, 'bar') }) - it('does not redundantly trigger if has check remains the same', () => { + it('should not redundantly trigger if has check remains the same', () => { let counter = 0 let tracker const reactor = new Reactor({ @@ -1064,7 +1115,7 @@ describe('Observer', () => { assert.equal(tracker, true) }) - it('does not redundantly trigger if ownKeys check is the same', () => { + it('should not redundantly trigger if ownKeys check is the same', () => { let counter = 0 const reactor = new Reactor({ foo: 'bar' @@ -1084,8 +1135,56 @@ describe('Observer', () => { }) }) - describe('Start Stop', () => { - it('can stop observing', () => { + describe('Batching', () => { + it('should delay and combine observer triggers when using batch', () => { + const reactor = new Reactor({ value: 'foo' }) + let counter = 0 + new Observer(() => { + counter += 1 + return reactor.value + })() + assert.equal(counter, 1) + batch(() => { + reactor.value = 'bleep' + assert.equal(counter, 1) + reactor.value = 'bloop' + assert.equal(counter, 1) + reactor.value = 'blarp' + assert.equal(counter, 1) + }) + assert.equal(counter, 2) + }) + + it('should nest batchers with no consequence', () => { + const reactor = new Reactor({ value: 'foo' }) + let counter = 0 + new Observer(() => { + counter += 1 + return reactor.value + })() + assert.equal(counter, 1) + batch(() => { + reactor.value = 'bleep' + assert.equal(counter, 1) + reactor.value = 'bloop' + assert.equal(counter, 1) + reactor.value = 'blarp' + assert.equal(counter, 1) + batch(() => { + reactor.value = 'bink' + assert.equal(counter, 1) + reactor.value = 'bonk' + assert.equal(counter, 1) + reactor.value = 'bup' + assert.equal(counter, 1) + }) + }) + assert.equal(counter, 2) + }) + }) + + describe('Start and Stop', () => { + it('should stop observing', () => { let counter = 0 let tracker const reactor = new Reactor({ value: 'foo' }) @@ -1105,7 +1204,7 @@ describe('Observer', () => { assert.equal(tracker, 'bar') }) - it('can start after stopping', () => { + it('should start after stopping', () => { let counter = 0 let tracker = null const reactor = new Reactor({ value: 'foo' }) @@ -1125,7 +1224,7 @@ describe('Observer', () => { assert.equal(tracker, 'moo') }) - it('has no effect with repeated starts', () => { + it('should have no effect with repeated starts', () => { let counter = 0 let tracker = null const reactor = new Reactor({ value: 'foo' }) @@ -1149,8 +1248,8 @@ describe('Observer', () => { }) }) - describe('Context & Subscriptions', () => { - it('context defaults to undefined', () => { + describe('Context and Subscriptions', () => { + it('should default context to undefined', () => { let contextChecker = 'foo' new Observer((context) => { contextChecker = context @@ -1158,7 +1257,7 @@ describe('Observer', () => { assert(typeof contextChecker === 'undefined') }) - it('can set context', () => { + it('should set context', () => { let contextChecker const observer = new Observer((context) => { contextChecker = context @@ -1170,7 +1269,7 @@ describe('Observer', () => { assert.equal(contextChecker, dummyObject) }) - it('can set context with multiple params', () => { + it('should set context with multiple params', () => { let contextChecker const observer = new Observer((a, b, c) => { contextChecker = '' + a + b + c @@ -1182,7 +1281,7 @@ describe('Observer', () => { assert.equal(contextChecker, 'undefinedundefinedundefined') }) - it('can set context and react to it', () => { + it('should set context and react to it', () => { const reactor = new Reactor() const contextChecker = {} const observer = new Observer(function (...args) { @@ -1207,8 +1306,48 @@ describe('Observer', () => { }) }) + describe('Observer redefinition', () => { + it('should redefine an observer', () => { + const reactor = new Reactor({ + first: 'foo', + second: 'bar' + }) + let firstCounter = 0 + let secondCounter = 0 + let firstTracker + let secondTracker + const observer = new Observer(() => { + firstCounter += 1 + firstTracker = reactor.first + }) + observer() + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 0) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, undefined) + observer.execute = () => { + secondCounter += 1 + secondTracker = reactor.second + } + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 1) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'bar') + reactor.first = 'moo' + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 1) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'bar') + reactor.second = 'baz' + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 2) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'baz') + }) + }) + describe('Error Handling', () => { - it('throws an error on a write if there is an Observer error', () => { + it('should throw an error on a write if there is an Observer error', () => { const reactor = new Reactor({ value: 'foo' }) new Observer(() => { if (reactor.value > 1) throw new Error('dummy error') @@ -1219,7 +1358,7 @@ describe('Observer', () => { }) }) - it('throws a CompoundError if there are multiple Observer errors', () => { + it('should throw a CompoundError if there are multiple Observer errors', () => { const reactor = new Reactor({ value: 1 }) new Observer(() => { if (reactor.value > 1) throw new Error('dummy error 1') @@ -1232,7 +1371,7 @@ describe('Observer', () => { }) }) - it('throws a flattened compound error with chained observers', () => { + it('should throw a flattened compound error with chained observers', () => { const reactor = new Reactor({ foo: 'Bar' }) @@ -1241,7 +1380,7 @@ describe('Observer', () => { reactor.passthrough = reactor.foo })() assert.equal(reactor.passthrough, 'Bar') - // Initial error failrues to create an initial compound error + // Initial error failures to create an initial compound error new Observer(() => { if (reactor.foo === 'error') throw new Error('BIG ERROR 1') })() @@ -1263,34 +1402,3 @@ describe('Observer', () => { }) }) }) - -describe('Triggering', () => { - -}) - -describe('Misc', () => { - it('allows shucking of a Reactor to get the underlying object', () => { - const reactor = new Reactor(new Map()) - assert.throws(() => Map.prototype.keys.call(reactor), { - name: 'TypeError', - message: 'Method Map.prototype.keys called on incompatible receiver #' - }) - const source = shuck(reactor) - Map.prototype.keys.call(source) - }) - - it('does not read an observer when calling start', () => { - let counter = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - const innerObserver = new Observer(() => reactor.foo) - new Observer(() => { - innerObserver.start() - counter += 1 - })() - assert.equal(counter, 1) - reactor.foo = 'baz' - assert.equal(counter, 1) - }) -}) From ce8338dfaaa9bacd0ed7a68be3fad3a39cb25c04 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 00:36:13 +0800 Subject: [PATCH 18/71] Fixed inheritance when an observer is used as a constructor --- src/reactor.js | 2 +- test/test.js | 70 ++++++++++++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index dc6eb10..8a54a01 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -599,7 +599,7 @@ class Observer extends Function { return observerCore.value() }, construct (target, args, receiver) { - return Reflect.construct(observerCore.execute, args) + return Reflect.construct(observerCore.execute, args, observerInterface) } }) observerInterface.start = () => observerCore.start() diff --git a/test/test.js b/test/test.js index b055b13..3170e6e 100644 --- a/test/test.js +++ b/test/test.js @@ -690,17 +690,13 @@ describe('Observer', () => { assert.strictEqual(result, 'barbazqux') }) - it.skip('should be usable as a constructor', () => { + it('should be usable as a constructor', () => { const DummyClass = new Observer(function (arg) { this.foo = 'bar' + arg return this }) const instance = new DummyClass('baz') - // TODO this is failing - // The constructor is the execute function rather than the wrapped observer - // Need to figure out how to interject - assert(instance instanceof DummyClass.execute) // This works but shouldn't - assert(instance instanceof DummyClass) // This doesn't work but should + assert(instance instanceof DummyClass) assert.strictEqual(instance.foo, 'barbaz') }) @@ -762,39 +758,39 @@ describe('Observer', () => { assert.strictEqual(result, observer.value) }) }) +}) - describe('Observer chaining and dependencies', () => { - it('should observe an observer', () => { - let outcome - const rx = new Reactor({ - foo: 'foo' - }) - const a = new Observer(() => rx.foo + 'bar') - a() - const b = new Observer(() => (outcome = a.value + 'baz')) - b() - assert.equal(outcome, 'foobarbaz') - rx.foo = 'qux' - assert.equal(outcome, 'quxbarbaz') - }) +describe('Observer chaining and dependencies', () => { + it('should observe an observer', () => { + let outcome + const rx = new Reactor({ + foo: 'foo' + }) + const a = new Observer(() => rx.foo + 'bar') + a() + const b = new Observer(() => (outcome = a.value + 'baz')) + b() + assert.equal(outcome, 'foobarbaz') + rx.foo = 'qux' + assert.equal(outcome, 'quxbarbaz') + }) - it('should trigger chained observers', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - reactor.bigFoo = reactor.foo.toUpperCase() - })() - assert.equal(reactor.bigFoo, 'BAR') - new Observer(() => { - tracker = reactor.bigFoo - })() - assert.equal(tracker, 'BAR') - reactor.foo = 'qux' - assert.equal(reactor.bigFoo, 'QUX') - assert.equal(tracker, 'QUX') - }) + it('should trigger chained observers', () => { + let tracker + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + reactor.bigFoo = reactor.foo.toUpperCase() + })() + assert.equal(reactor.bigFoo, 'BAR') + new Observer(() => { + tracker = reactor.bigFoo + })() + assert.equal(tracker, 'BAR') + reactor.foo = 'qux' + assert.equal(reactor.bigFoo, 'QUX') + assert.equal(tracker, 'QUX') }) }) From 67befd48d22ab490aa0a7ca45972223eaa76cb32 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 12:28:27 +0800 Subject: [PATCH 19/71] Updated basic Reactivity tests --- test/test.js | 297 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 236 insertions(+), 61 deletions(-) diff --git a/test/test.js b/test/test.js index 3170e6e..1e697a1 100644 --- a/test/test.js +++ b/test/test.js @@ -538,6 +538,13 @@ describe('Observer', () => { }) }) + it('should not run upon initialization', () => { + let triggerCount = 0 + // eslint-disable-next-line no-new + new Observer(() => { triggerCount += 1 }) + assert.strictEqual(triggerCount, 0) + }) + it('should be an Observer object', () => { const observer = new Observer(() => {}) assert(observer instanceof Observer) @@ -760,84 +767,218 @@ describe('Observer', () => { }) }) -describe('Observer chaining and dependencies', () => { - it('should observe an observer', () => { - let outcome - const rx = new Reactor({ - foo: 'foo' - }) - const a = new Observer(() => rx.foo + 'bar') - a() - const b = new Observer(() => (outcome = a.value + 'baz')) - b() - assert.equal(outcome, 'foobarbaz') - rx.foo = 'qux' - assert.equal(outcome, 'quxbarbaz') +// TODO test for observer starting and stopping + +describe.only('Reactivity', () => { + describe('Observers do not trigger before being run', () => { + it('should not trigger if reading a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + // eslint-disable-next-line no-new + new Observer(() => { + runCount += 1 + runValue = signal() + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + assert.strictEqual(signal(), 'foo') + signal('bar') + assert.strictEqual(signal(), 'bar') + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + }) + it('should not trigger if reading a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + // eslint-disable-next-line no-new + new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + assert.strictEqual(reactor.foo, 'bar') + reactor.foo = 'baz' + assert.strictEqual(reactor.foo, 'baz') + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + }) }) - it('should trigger chained observers', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - reactor.bigFoo = reactor.foo.toUpperCase() - })() - assert.equal(reactor.bigFoo, 'BAR') - new Observer(() => { - tracker = reactor.bigFoo - })() - assert.equal(tracker, 'BAR') - reactor.foo = 'qux' - assert.equal(reactor.bigFoo, 'QUX') - assert.equal(tracker, 'QUX') + describe('Observers trigger on dependency updates after being run', () => { + it('should trigger if reading a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + new Observer(() => { + runCount += 1 + runValue = signal() + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + assert.strictEqual(signal(), 'foo') + signal('bar') + assert.strictEqual(signal(), 'bar') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + }) + it('should trigger if reading a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.foo, 'bar') + reactor.foo = 'baz' + assert.strictEqual(reactor.foo, 'baz') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + it('should trigger if reading another Observer', () => { + let runCount = 0 + let runValue + const headObserver = new Observer((x) => x) + const tailObserver = new Observer(() => { + runCount += 1 + runValue = headObserver.value + }) + tailObserver() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + headObserver('foo') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + }) + // TODO trigger if reading another Observer via observer() instead of observer.value }) -}) -describe('Reactivity', () => { - describe('Triggering', () => { - it('should trigger once on initialization', () => { - let counter = 0 - new Observer(() => { counter += 1 })() - assert.equal(counter, 1) + describe('Observers trigger on subproperty updates', () => { + it('should trigger even if a relevant subproperty of its dependency is updated', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: {} + }) + const observer = new Observer(() => { + runCount += 1 + // Dependency is only explicitly on reactor.foo + runValue = JSON.stringify(reactor.foo) + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, '{}') + // This new property is relevant to the observer so should trigger + reactor.foo.bar = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, '{"bar":"baz"}') }) - it('should trigger once on Reactor dependency write', () => { - let counter = 0 - let tracker + it('should not trigger if an irrelevant subproperty of its dependency is updated', () => { + let runCount = 0 + let runValue const reactor = new Reactor({ - foo: 'bar' + foo: {} }) - new Observer(() => { - counter += 1 - tracker = reactor.foo - })() - assert.equal(counter, 1) - assert.equal(tracker, 'bar') - reactor.foo = 'mux' - assert.equal(counter, 2) - assert.equal(tracker, 'mux') + const observer = new Observer(() => { + runCount += 1 + // Dependency is only explicitly on reactor.foo + runValue = Array.isArray(reactor.foo) + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + // The new property is irrelevant to the observer checking isArray so should not trigger + reactor.foo.bar = 'baz' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) }) - it('should trigger once on nested Reactor dependency write', () => { - let counter = 0 - let tracker + it('should trigger if a subproperty is updated when depending on it directly', () => { + let runCount = 0 + let runValue const reactor = new Reactor({ foo: { bar: 'baz' } }) - new Observer(() => { - counter += 1 - tracker = reactor.foo.bar - })() - assert.equal(counter, 1) - assert.equal(tracker, 'baz') - reactor.foo.bar = 'moo' - assert.equal(counter, 2) - assert.equal(tracker, 'moo') + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + reactor.foo.bar = 'qux' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + }) + + it('should trigger if a parent property is updated when depending on its subproperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + // Instead of just updating bar we replace the whole object + reactor.foo = { bar: 'qux' } + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') }) + it('should not trigger if a sibling property of its dependency is updated', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + // The new sibling property is irrelevant to the observer so should not trigger + reactor.foo.qux = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + }) + }) + + it('should be dependent on other Observers') + it('should remember the last called values when triggered') + it('should break old dependencies') +}) + +describe.skip('Misc', () => { + describe('Triggering', () => { it('should trigger on defineProperty', () => { let tracker const reactor = new Reactor({ @@ -1397,4 +1538,38 @@ describe('Reactivity', () => { }) }) }) + + describe('Observer chaining and dependencies', () => { + it('should observe an observer', () => { + let outcome + const rx = new Reactor({ + foo: 'foo' + }) + const a = new Observer(() => rx.foo + 'bar') + a() + const b = new Observer(() => (outcome = a.value + 'baz')) + b() + assert.equal(outcome, 'foobarbaz') + rx.foo = 'qux' + assert.equal(outcome, 'quxbarbaz') + }) + + it('should trigger chained observers', () => { + let tracker + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + reactor.bigFoo = reactor.foo.toUpperCase() + })() + assert.equal(reactor.bigFoo, 'BAR') + new Observer(() => { + tracker = reactor.bigFoo + })() + assert.equal(tracker, 'BAR') + reactor.foo = 'qux' + assert.equal(reactor.bigFoo, 'QUX') + assert.equal(tracker, 'QUX') + }) + }) }) From 4ea8fdeeb61349d192e3f0b4fd41d57b543eaaa7 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 15:58:03 +0800 Subject: [PATCH 20/71] Added tests for array methods --- test/test.js | 404 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 360 insertions(+), 44 deletions(-) diff --git a/test/test.js b/test/test.js index 1e697a1..66e8a03 100644 --- a/test/test.js +++ b/test/test.js @@ -807,7 +807,7 @@ describe.only('Reactivity', () => { }) }) - describe('Observers trigger on dependency updates after being run', () => { + describe('Observers after being run should form dependencies and trigger on their updates', () => { it('should trigger if reading a Signal', () => { let runCount = 0 let runValue @@ -824,6 +824,7 @@ describe.only('Reactivity', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'bar') }) + it('should trigger if reading a Reactor', () => { let runCount = 0 let runValue @@ -840,6 +841,7 @@ describe.only('Reactivity', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'baz') }) + it('should trigger if reading another Observer', () => { let runCount = 0 let runValue @@ -856,6 +858,48 @@ describe.only('Reactivity', () => { assert.strictEqual(runValue, 'foo') }) // TODO trigger if reading another Observer via observer() instead of observer.value + + it('should get triggered by defineProperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + Object.defineProperty(reactor, 'foo', { + get () { return 'baz' } + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + + it('should get triggered by deleteProperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + delete reactor.foo + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, undefined) + }) }) describe('Observers trigger on subproperty updates', () => { @@ -868,6 +912,7 @@ describe.only('Reactivity', () => { const observer = new Observer(() => { runCount += 1 // Dependency is only explicitly on reactor.foo + // But depends implicitly on all its subproperties runValue = JSON.stringify(reactor.foo) }) assert.strictEqual(runCount, 0) @@ -970,57 +1015,328 @@ describe.only('Reactivity', () => { assert.strictEqual(runCount, 1) assert.strictEqual(runValue, 'baz') }) + + describe('Gets triggered by array update methods', () => { + it('should get triggered by array index assignment', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor[1] = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + assert.deepEqual(reactor, ['foo', 'baz']) + }) + + it('should get triggered by array push', () => { + let runCount = 0 + let runValue + const reactor = new Reactor([]) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + reactor.push('foo') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + }) + + it('should get triggered by array pop', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.length - 1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.pop() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + assert.strictEqual(reactor.length, 1) + }) + + it('should get triggered by array shift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.shift() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 1) + }) + + it('should get triggered by array unshift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.unshift('bar') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 2) + }) + + it('should get triggered by array splice', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.splice(1, 1, 'qux') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.strictEqual(reactor.length, 3) + }) + + it('should get triggered by array sort', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['c', 'a', 'b']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.sort() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'c']) + }) + + it('should get triggered by array reverse', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a') + reactor.reverse() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'c') + assert.deepEqual(reactor, ['c', 'b', 'a']) + }) + + it('should get triggered by array fill', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.fill('qux', 1, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.deepEqual(reactor, ['foo', 'qux', 'baz']) + }) + + it('should get triggered by array copyWithin', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c', 'd', 'e']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[2] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.copyWithin(2, 0, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'a', 'b', 'e']) + }) + + it('should get triggered by changing the array length property', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 1 + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 1) + assert.deepEqual(reactor, ['foo']) + }) + + it('should not get triggered by setting the array length property to its current value', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 2 + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + assert.deepEqual(reactor, ['foo', 'bar']) + }) + + it('should get triggered by array operations that change length', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 3) + + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 4) + + reactor.pop() + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 3) + + reactor.splice(0, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 1) + }) + + it('should get triggered by array operations that modify existing elements', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'b') + + // Modify existing element + reactor[1] = 'x' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'x') + + // Use splice to modify + reactor.splice(1, 1, 'y') + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'y') + + // Use fill to modify + reactor.fill('z', 1, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'z') + }) + }) }) - it('should be dependent on other Observers') it('should remember the last called values when triggered') it('should break old dependencies') }) describe.skip('Misc', () => { - describe('Triggering', () => { - it('should trigger on defineProperty', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => (tracker = reactor.foo))() - assert.equal(tracker, 'bar') - Object.defineProperty(reactor, 'foo', { - get () { return 'baz' } - }) - assert.equal(tracker, 'baz') - }) - - it('should trigger on deleteProperty', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => (tracker = reactor.foo))() - assert.equal(tracker, 'bar') - delete reactor.foo - assert.equal(tracker, undefined) - }) - - it('should trigger on array update methods', () => { - let counter = 0 - let tracker - const reactor = new Reactor([]) - new Observer(() => { - counter += 1 - tracker = reactor[0] - })() - assert.equal(counter, 1) - assert.equal(tracker, undefined) - reactor.push('foo') - assert.equal(counter, 2) - assert.equal(tracker, 'foo') - reactor.unshift('bar') - assert.equal(counter, 3) - assert.equal(tracker, 'bar') - }) + it('should get triggered by multiple array operations in sequence', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.join(',') + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a,b,c') + + // Multiple operations should trigger observer multiple times + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a,b,c,d') + + reactor.splice(1, 1) + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'a,c,d') + + reactor.reverse() + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'd,c,a') + }) + describe('Triggering', () => { it('should trigger only once despite multiple dependencies', () => { let counter = 0 let hasTracker From 7f3a32fe39b8570413dd9aca7b18bf306e172fde Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 17:12:10 +0800 Subject: [PATCH 21/71] Added tests for rebuilding dependencies and single triggering --- test/test.js | 193 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 147 insertions(+), 46 deletions(-) diff --git a/test/test.js b/test/test.js index 66e8a03..9acbe94 100644 --- a/test/test.js +++ b/test/test.js @@ -769,7 +769,7 @@ describe('Observer', () => { // TODO test for observer starting and stopping -describe.only('Reactivity', () => { +describe('Reactivity', () => { describe('Observers do not trigger before being run', () => { it('should not trigger if reading a Signal', () => { let runCount = 0 @@ -902,6 +902,66 @@ describe.only('Reactivity', () => { }) }) + describe('Observers rebuild dependencies each time they trigger', () => { + it('should build new dependencies on retriggers', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] + }) + // On initial run it should be depndent on foo and not baz + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify there is no dependency on baz + reactor.baz = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Switch sets new dependency on baz + reactor.switch = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Verify dependency on baz is working + reactor.baz = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'mip') + }) + it('should break old dependencies when no longer needed', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] + }) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify dependency on foo is working + reactor.foo = 'moo' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Switch builds new dependencies + reactor.switch = 'baz' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + // Verify dependency on foo is broken + reactor.foo = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + }) + }) + describe('Observers trigger on subproperty updates', () => { it('should trigger even if a relevant subproperty of its dependency is updated', () => { let runCount = 0 @@ -1303,8 +1363,93 @@ describe.only('Reactivity', () => { }) }) + describe('Observers are triggered only once per update ', () => { + it('should trigger only once despite multiple identical dependencies', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + reactor.foo + reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'barbarbar') + reactor.foo = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bazbazbaz') + }) + it('should trigger only once despite multiple different dependencies', () => { + let counter = 0 + let getTracker + let stringifyTracker + let valuesTracker + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + counter += 1 + getTracker = reactor.foo + stringifyTracker = JSON.stringify(reactor) + valuesTracker = Object.values(reactor) + })() + assert.equal(counter, 1) + assert.strictEqual(getTracker, 'bar') + assert.strictEqual(stringifyTracker, '{"foo":"bar"}') + assert.deepEqual(valuesTracker, ['bar']) + reactor.foo = 'baz' + assert.equal(counter, 2) + assert.strictEqual(getTracker, 'baz') + assert.strictEqual(stringifyTracker, '{"foo":"baz"}') + assert.deepEqual(valuesTracker, ['baz']) + }) + it('should trigger only once for native methods attached to the Reactor with multiple changes on itself', () => { + let runCount = 0 + let firstTracker + let lengthTracker + const reactor = new Reactor([]) + new Observer(() => { + runCount += 1 + firstTracker = reactor[0] + lengthTracker = reactor.length + })() + assert.equal(runCount, 1) + assert.equal(lengthTracker, 0) + assert.equal(firstTracker, undefined) + reactor.push('bar') + assert.equal(runCount, 2) + assert.equal(lengthTracker, 1) + assert.equal(firstTracker, 'bar') + }) + it('should trigger only once for custom methods attached to the Reactor with multiple changes on itself', () => { + let runCount = 0 + let fooTracker + let bazTracker + const reactor = new Reactor({ + foo: 'bar', + baz: 'qux' + }) + new Observer(() => { + runCount += 1 + fooTracker = reactor.foo + bazTracker = reactor.baz + })() + assert.equal(runCount, 1) + assert.equal(fooTracker, 'bar') + assert.equal(bazTracker, 'qux') + reactor.change = function () { + this.foo = this.foo + 'bar' + this.baz = this.baz + 'qux' + } + reactor.change() + assert.equal(runCount, 2) + assert.equal(fooTracker, 'barbar') + assert.equal(bazTracker, 'quxqux') + }) + }) + it('should remember the last called values when triggered') - it('should break old dependencies') }) describe.skip('Misc', () => { @@ -1337,50 +1482,6 @@ describe.skip('Misc', () => { }) describe('Triggering', () => { - it('should trigger only once despite multiple dependencies', () => { - let counter = 0 - let hasTracker - let getTracker - let ownKeysTracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - counter += 1 - hasTracker = ('foo' in reactor) - getTracker = reactor.foo - ownKeysTracker = Object.getOwnPropertyNames(reactor) - })() - assert.equal(counter, 1) - assert.equal(hasTracker, true) - assert.equal(getTracker, 'bar') - assert.equal(JSON.stringify(ownKeysTracker), '["foo"]') - reactor.foo = 'baz' - assert.equal(counter, 2) - assert.equal(hasTracker, true) - assert.equal(getTracker, 'baz') - assert.equal(JSON.stringify(ownKeysTracker), '["foo"]') - }) - - it('should trigger only once even for functions with multiple changes', () => { - let counter = 0 - let lengthTracker - let firstTracker - const reactor = new Reactor([]) - new Observer(() => { - counter += 1 - lengthTracker = reactor.length - firstTracker = reactor[0] - })() - assert.equal(counter, 1) - assert.equal(lengthTracker, 0) - assert.equal(firstTracker, undefined) - reactor.push('bar') - assert.equal(counter, 2) - assert.equal(lengthTracker, 1) - assert.equal(firstTracker, 'bar') - }) - it('should trigger correctly on nested observer definitions', () => { const reactor = new Reactor({ outer: 'foo', From 5b4cbf3f828ee1c21a5c386ce3ecc9119118518c Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 17:42:41 +0800 Subject: [PATCH 22/71] Added tests for avoiding redundant triggers on identical values --- test/test.js | 175 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 113 insertions(+), 62 deletions(-) diff --git a/test/test.js b/test/test.js index 9acbe94..de744f1 100644 --- a/test/test.js +++ b/test/test.js @@ -900,6 +900,36 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, undefined) }) + + it('should form a dependency when using Object.keys', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = Object.keys(reactor) + })() + assert.strictEqual(runCount, 1) + assert.deepEqual(runValue, ['foo']) + reactor.baz = 'qux' + assert.strictEqual(runCount, 2) + assert.deepEqual(runValue, ['foo', 'baz']) + }) + + it('should form a dependency when using the in operator', () => { + let runCount = 0 + let runValue + const reactor = new Reactor() + new Observer(() => { + runCount += 1 + runValue = ('foo' in reactor) + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + reactor.foo = 'bar' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, true) + }) }) describe('Observers rebuild dependencies each time they trigger', () => { @@ -1449,6 +1479,89 @@ describe('Reactivity', () => { }) }) + describe('Observers are not triggered when setting an identical value', () => { + it('should not redundantly trigger on setting an identical primitive value on a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + new Observer(() => { + runCount += 1 + runValue = signal() + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + signal('foo') + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + }) + it('should not redundantly trigger on setting an identical primitive value on a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.foo = 'bar' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + }) + it('should not redundantly trigger on setting an identical primitive value on an Observer', () => { + let runCount = 0 + let runValue + const headObserver = new Observer((x) => x) + const tailObserver = new Observer(() => { + runCount += 1 + runValue = headObserver.value + }) + headObserver('foo') + tailObserver() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + headObserver('foo') + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + }) + it('should not redundantly trigger on setting an identical object value', () => { + let runCount = 0 + let runValue + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + reactor.foo = dummyObject + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + }) + it('should trigger on setting a similar but different object', () => { + let runCount = 0 + let runValue + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + reactor.foo = {} + assert.strictEqual(runCount, 2) + assert.notStrictEqual(shuck(runValue), dummyObject) + }) + }) + it('should remember the last called values when triggered') }) @@ -1517,51 +1630,6 @@ describe.skip('Misc', () => { assert.equal(innerTracker, 'baz') }) - it('should subscribe on Object.keys', () => { - let counter = 0 - let tracker - const reactor = new Reactor({ foo: 'bar' }) - new Observer(() => { - counter += 1 - tracker = Object.keys(reactor) - })() - assert.equal(counter, 1) - assert.equal(JSON.stringify(tracker), '["foo"]') - reactor.moo = 'mux' - assert.equal(counter, 2) - assert.equal(JSON.stringify(tracker), '["foo","moo"]') - }) - - it('should subscribe on in operator', () => { - let counter = 0 - let tracker - const reactor = new Reactor() - new Observer(() => { - counter += 1 - tracker = ('foo' in reactor) - })() - assert.equal(counter, 1) - assert.equal(tracker, false) - reactor.foo = 'bar' - assert.equal(counter, 2) - assert.equal(tracker, true) - }) - - it('should subscribe using observe keyword', () => { - let counter = 0 - let tracker - const reactor = new Reactor({ value: 'foo' }) - new Observer(() => { - counter += 1 - tracker = reactor.value - })() - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - reactor.value = 'bar' - assert.equal(counter, 2) - assert.equal(tracker, 'bar') - }) - it('should not subscribe in hide block', () => { const reactor = new Reactor({ outer: 'foo', @@ -1635,23 +1703,6 @@ describe.skip('Misc', () => { })() }) - it('should not redundantly trigger on setting identical values', () => { - let counter = 0 - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - counter += 1 - tracker = reactor.foo - })() - assert.equal(counter, 1) - assert.equal(tracker, 'bar') - reactor.foo = 'bar' - assert.equal(counter, 1) - assert.equal(tracker, 'bar') - }) - it('should not redundantly trigger if has check remains the same', () => { let counter = 0 let tracker From 67ec2fec3b15fe69893cbaa8ba832037cb4921bf Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 18:22:47 +0800 Subject: [PATCH 23/71] Cleaned up tests for batching and hiding --- test/test.js | 302 ++++++++++++++++++++++++--------------------------- 1 file changed, 143 insertions(+), 159 deletions(-) diff --git a/test/test.js b/test/test.js index de744f1..d9c2e7f 100644 --- a/test/test.js +++ b/test/test.js @@ -767,8 +767,6 @@ describe('Observer', () => { }) }) -// TODO test for observer starting and stopping - describe('Reactivity', () => { describe('Observers do not trigger before being run', () => { it('should not trigger if reading a Signal', () => { @@ -1565,6 +1563,149 @@ describe('Reactivity', () => { it('should remember the last called values when triggered') }) +describe('Batching', () => { + // TODO add test and functionality for batch parameter validation + it('should delay and combine observer triggers within a batch block', () => { + const reactor = new Reactor() + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + batch(() => { + reactor.foo = 'bleep' + assert.strictEqual(runCount, 1) + reactor.foo = 'bloop' + assert.strictEqual(runCount, 1) + reactor.foo = 'blarp' + assert.strictEqual(runCount, 1) + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'blarp') + }) + + it('should nest batch blocks with no consequence', () => { + const reactor = new Reactor() + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + batch(() => { + reactor.foo = 'bleep' + assert.strictEqual(runCount, 1) + reactor.foo = 'bloop' + assert.strictEqual(runCount, 1) + reactor.foo = 'blarp' + assert.strictEqual(runCount, 1) + batch(() => { + reactor.foo = 'bink' + assert.strictEqual(runCount, 1) + reactor.foo = 'bonk' + assert.strictEqual(runCount, 1) + reactor.foo = 'bup' + assert.strictEqual(runCount, 1) + }) + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bup') + }) + // TODO should batch block return the result of the block? +}) + +describe('Hiding', () => { + // TODO add test and functionality for hide parameter validation + + it('should not create dependencies inside hide block', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' + }) + let outerRunCount = 0 + let innerRunCount = 0 + let outerRunValue + let innerRunValue + new Observer(() => { + outerRunCount += 1 + outerRunValue = reactor.outer + hide(() => { + innerRunCount += 1 + innerRunValue = reactor.inner + }) + })() + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.inner = 'baz' + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.outer = 'moo' + assert.strictEqual(outerRunCount, 2) + assert.strictEqual(innerRunCount, 2) + assert.strictEqual(outerRunValue, 'moo') + assert.strictEqual(innerRunValue, 'baz') + }) + + // TODO should hide blocks be nestable? + + it('should return the result of the hide block', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' + }) + let outerRunCount = 0 + let innerRunCount = 0 + let outerRunValue + let innerRunValue + new Observer(() => { + outerRunCount += 1 + outerRunValue = reactor.outer + innerRunValue = hide(() => { + innerRunCount += 1 + return reactor.inner + }) + })() + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.inner = 'baz' + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.outer = 'moo' + assert.strictEqual(outerRunCount, 2) + assert.strictEqual(innerRunCount, 2) + assert.strictEqual(outerRunValue, 'moo') + assert.strictEqual(innerRunValue, 'baz') + }) + + it('should not self trigger in a hide block', () => { + const reactor = new Reactor(['a', 'b', 'c']) + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + // pop reads the length of the object as well as changes it + // So calling pop normally in an observer will cause a loop + // hide allows us to call pop without creating a dependency + runValue = hide(() => reactor.pop()) + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + }) +}) + describe.skip('Misc', () => { it('should get triggered by multiple array operations in sequence', () => { let runCount = 0 @@ -1629,163 +1770,6 @@ describe.skip('Misc', () => { assert.equal(innerCounter, 3) assert.equal(innerTracker, 'baz') }) - - it('should not subscribe in hide block', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerCounter = 0 - let innerCounter = 0 - let outerTracker - let innerTracker - new Observer(() => { - outerCounter += 1 - outerTracker = reactor.outer - hide(() => { - innerCounter += 1 - innerTracker = reactor.inner - }) - })() - assert.equal(outerCounter, 1) - assert.equal(innerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerTracker, 'bar') - reactor.inner = 'baz' - assert.equal(outerCounter, 1) - assert.equal(innerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerTracker, 'bar') - reactor.outer = 'moo' - assert.equal(outerCounter, 2) - assert.equal(innerCounter, 2) - assert.equal(outerTracker, 'moo') - assert.equal(innerTracker, 'baz') - }) - - it('should return output of hide block', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerCounter = 0 - let innerCounter = 0 - let outerTracker - let innerTracker - new Observer(() => { - outerCounter += 1 - outerTracker = reactor.outer - innerTracker = hide(() => { - innerCounter += 1 - return reactor.inner - }) - })() - assert.equal(outerCounter, 1) - assert.equal(innerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerTracker, 'bar') - reactor.inner = 'baz' - assert.equal(outerCounter, 1) - assert.equal(innerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerTracker, 'bar') - reactor.outer = 'moo' - assert.equal(outerCounter, 2) - assert.equal(innerCounter, 2) - assert.equal(outerTracker, 'moo') - assert.equal(innerTracker, 'baz') - }) - - it('should not self trigger in an hide block', () => { - const reactor = new Reactor(['a', 'b', 'c']) - new Observer(() => { - hide(() => reactor.pop()) - })() - }) - - it('should not redundantly trigger if has check remains the same', () => { - let counter = 0 - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - counter += 1 - tracker = 'foo' in reactor - })() - assert.equal(counter, 1) - assert.equal(tracker, true) - reactor.foo = 'baz' - assert.equal(counter, 1) - assert.equal(tracker, true) - }) - - it('should not redundantly trigger if ownKeys check is the same', () => { - let counter = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - counter += 1 - Object.keys(reactor) - })() - reactor.foo = 'baz' - assert.equal(counter, 1) - delete reactor.boo - assert.equal(counter, 1) - delete reactor.foo - assert.equal(counter, 2) - reactor.foo = 'bar' - assert.equal(counter, 3) - }) - }) - - describe('Batching', () => { - it('should delay and combine observer triggers when using batch', () => { - const reactor = new Reactor({ value: 'foo' }) - let counter = 0 - new Observer(() => { - counter += 1 - return reactor.value - })() - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bleep' - assert.equal(counter, 1) - reactor.value = 'bloop' - assert.equal(counter, 1) - reactor.value = 'blarp' - assert.equal(counter, 1) - }) - assert.equal(counter, 2) - }) - - it('should nest batchers with no consequence', () => { - const reactor = new Reactor({ value: 'foo' }) - let counter = 0 - new Observer(() => { - counter += 1 - return reactor.value - })() - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bleep' - assert.equal(counter, 1) - reactor.value = 'bloop' - assert.equal(counter, 1) - reactor.value = 'blarp' - assert.equal(counter, 1) - batch(() => { - reactor.value = 'bink' - assert.equal(counter, 1) - reactor.value = 'bonk' - assert.equal(counter, 1) - reactor.value = 'bup' - assert.equal(counter, 1) - }) - }) - assert.equal(counter, 2) - }) }) describe('Start and Stop', () => { From 9770c6a9443c83fd3f6af830f691bd2dc10dc0bc Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 18:33:10 +0800 Subject: [PATCH 24/71] Cleaned up error handling tests --- test/test.js | 115 ++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/test/test.js b/test/test.js index d9c2e7f..a781016 100644 --- a/test/test.js +++ b/test/test.js @@ -1706,6 +1706,65 @@ describe('Hiding', () => { }) }) +describe('Error Handling', () => { + it('should throw an error on a write if there is an Observer throws an error', () => { + const reactor = new Reactor({ value: 'foo' }) + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error') + })() + assert.throws(() => (reactor.value = 2), { + name: 'Error', + message: 'dummy error' + }) + }) + + it('should throw a CompoundError if there are multiple Observer errors', () => { + const reactor = new Reactor({ value: 1 }) + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error 1') + })() + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error 2') + })() + assert.throws(() => (reactor.value = 2), { + name: 'CompoundError' + }) + }) + + it('should throw a flattened CompoundError with chained observers', () => { + const reactor = new Reactor({ + foo: 1 + }) + // Successful passthrough to create subsequent compound errors + new Observer(() => { + reactor.passthrough = reactor.foo + })() + // Initial error failures to create an initial compound error + new Observer(() => { + if (reactor.foo > 1) throw new Error('primary error 1') + })() + new Observer(() => { + if (reactor.foo > 1) throw new Error('primary error 2') + })() + // Chain off reactor.passthrough to create a subsequent compound error + new Observer(() => { + if (reactor.passthrough > 1) throw new Error('secondary error 1') + })() + new Observer(() => { + if (reactor.passthrough > 1) throw new Error('secondary error 2') + })() + // Setting foo to 2 should trigger the primary error 1 and 2 and trigger the passthrough + // The passthrough triggers secondary error 1 and 2 as well which get merged into a compound error + // This compound error should then be merged with primary error 1 and 2 + // Instead of nesting it flattens to a single compound error with 4 causes + assert.throws(() => (reactor.foo = 2), (error) => { + assert.strictEqual(error.name, 'CompoundError') + assert.strictEqual(error.cause.length, 4) + return true + }) + }) +}) + describe.skip('Misc', () => { it('should get triggered by multiple array operations in sequence', () => { let runCount = 0 @@ -1935,62 +1994,6 @@ describe.skip('Misc', () => { }) }) - describe('Error Handling', () => { - it('should throw an error on a write if there is an Observer error', () => { - const reactor = new Reactor({ value: 'foo' }) - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error') - })() - assert.throws(() => (reactor.value = 2), { - name: 'Error', - message: 'dummy error' - }) - }) - - it('should throw a CompoundError if there are multiple Observer errors', () => { - const reactor = new Reactor({ value: 1 }) - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error 1') - })() - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error 2') - })() - assert.throws(() => (reactor.value = 2), { - name: 'CompoundError' - }) - }) - - it('should throw a flattened compound error with chained observers', () => { - const reactor = new Reactor({ - foo: 'Bar' - }) - // Successful passthrough to create subsequent compound errors - new Observer(() => { - reactor.passthrough = reactor.foo - })() - assert.equal(reactor.passthrough, 'Bar') - // Initial error failures to create an initial compound error - new Observer(() => { - if (reactor.foo === 'error') throw new Error('BIG ERROR 1') - })() - new Observer(() => { - if (reactor.foo === 'error') throw new Error('BIG ERROR 2') - })() - // Chain off reactor.passthrough to create a subsequent compound error - new Observer(() => { - if (reactor.passthrough === 'error') throw new Error('small error 1') - })() - new Observer(() => { - if (reactor.passthrough === 'error') throw new Error('small error 2') - })() - assert.throws(() => (reactor.foo = 'error'), (error) => { - assert.equal(error.name, 'CompoundError') - assert.equal(error.cause.length, 4) - return true - }) - }) - }) - describe('Observer chaining and dependencies', () => { it('should observe an observer', () => { let outcome From 2188b89e98cdf9d5edfcd1597bd285ffe72d7f89 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 21:14:42 +0800 Subject: [PATCH 25/71] Finished first pass of test cleanup --- test/test.js | 335 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 213 insertions(+), 122 deletions(-) diff --git a/test/test.js b/test/test.js index a781016..335b484 100644 --- a/test/test.js +++ b/test/test.js @@ -806,7 +806,7 @@ describe('Reactivity', () => { }) describe('Observers after being run should form dependencies and trigger on their updates', () => { - it('should trigger if reading a Signal', () => { + it('should be setup to trigger if reading a Signal', () => { let runCount = 0 let runValue const signal = new Signal('foo') @@ -823,7 +823,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, 'bar') }) - it('should trigger if reading a Reactor', () => { + it('should be setup to trigger if reading a Reactor', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -840,7 +840,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, 'baz') }) - it('should trigger if reading another Observer', () => { + it('should be setup to trigger if reading another Observer', () => { let runCount = 0 let runValue const headObserver = new Observer((x) => x) @@ -857,6 +857,36 @@ describe('Reactivity', () => { }) // TODO trigger if reading another Observer via observer() instead of observer.value + it('should be setup to trigger when using Object.keys', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = Object.keys(reactor) + })() + assert.strictEqual(runCount, 1) + assert.deepEqual(runValue, ['foo']) + reactor.baz = 'qux' + assert.strictEqual(runCount, 2) + assert.deepEqual(runValue, ['foo', 'baz']) + }) + + it('should be setup to trigger when using the in operator', () => { + let runCount = 0 + let runValue + const reactor = new Reactor() + new Observer(() => { + runCount += 1 + runValue = ('foo' in reactor) + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + reactor.foo = 'bar' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, true) + }) + it('should get triggered by defineProperty', () => { let runCount = 0 let runValue @@ -899,34 +929,30 @@ describe('Reactivity', () => { assert.strictEqual(runValue, undefined) }) - it('should form a dependency when using Object.keys', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ foo: 'bar' }) - new Observer(() => { - runCount += 1 - runValue = Object.keys(reactor) - })() - assert.strictEqual(runCount, 1) - assert.deepEqual(runValue, ['foo']) - reactor.baz = 'qux' - assert.strictEqual(runCount, 2) - assert.deepEqual(runValue, ['foo', 'baz']) - }) - - it('should form a dependency when using the in operator', () => { + it('should be able to be triggered repeatedly', () => { let runCount = 0 let runValue - const reactor = new Reactor() + const reactor = new Reactor({ + foo: 'bar' + }) new Observer(() => { runCount += 1 - runValue = ('foo' in reactor) + runValue = reactor.foo })() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - reactor.foo = 'bar' + assert.strictEqual(runValue, 'bar') + reactor.foo = 'baz' assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, true) + assert.strictEqual(runValue, 'baz') + reactor.foo = 'qux' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + reactor.foo = 'moo' + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'moo') + reactor.foo = 'mip' + assert.strictEqual(runCount, 5) + assert.strictEqual(runValue, 'mip') }) }) @@ -1388,6 +1414,34 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 4) assert.strictEqual(runValue, 'z') }) + + it('should be able to be triggered repeatedly by multiple array operations', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.join(',') + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a,b,c') + + // Multiple operations should trigger observer multiple times + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a,b,c,d') + + reactor.splice(1, 1) + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'a,c,d') + + reactor.reverse() + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'd,c,a') + }) }) }) @@ -1559,8 +1613,6 @@ describe('Reactivity', () => { assert.notStrictEqual(shuck(runValue), dummyObject) }) }) - - it('should remember the last called values when triggered') }) describe('Batching', () => { @@ -1765,72 +1817,7 @@ describe('Error Handling', () => { }) }) -describe.skip('Misc', () => { - it('should get triggered by multiple array operations in sequence', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.join(',') - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'a,b,c') - - // Multiple operations should trigger observer multiple times - reactor.push('d') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a,b,c,d') - - reactor.splice(1, 1) - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'a,c,d') - - reactor.reverse() - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'd,c,a') - }) - - describe('Triggering', () => { - it('should trigger correctly on nested observer definitions', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerCounter = 0 - let innerCounter = 0 - let outerTracker - let innerTracker - let innerObserver - new Observer(() => { - outerCounter += 1 - outerTracker = reactor.outer - if (innerObserver) innerObserver.stop() - innerObserver = new Observer(() => { - innerCounter += 1 - innerTracker = reactor.inner - })() - })() - assert.equal(outerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerCounter, 1) - assert.equal(innerTracker, 'bar') - reactor.inner = 'baz' - assert.equal(outerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerCounter, 2) - assert.equal(innerTracker, 'baz') - reactor.outer = 'moo' - assert.equal(outerCounter, 2) - assert.equal(outerTracker, 'moo') - assert.equal(innerCounter, 3) - assert.equal(innerTracker, 'baz') - }) - }) - +describe('Minor Features', () => { describe('Start and Stop', () => { it('should stop observing', () => { let counter = 0 @@ -1993,38 +1980,142 @@ describe.skip('Misc', () => { assert.equal(secondTracker, 'baz') }) }) +}) - describe('Observer chaining and dependencies', () => { - it('should observe an observer', () => { - let outcome - const rx = new Reactor({ - foo: 'foo' - }) - const a = new Observer(() => rx.foo + 'bar') - a() - const b = new Observer(() => (outcome = a.value + 'baz')) - b() - assert.equal(outcome, 'foobarbaz') - rx.foo = 'qux' - assert.equal(outcome, 'quxbarbaz') - }) +describe('Complex Setups', () => { + it('should be able to chain observers off each other', () => { + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + return reactor.foo.toUpperCase() + }) + firstObserver() + assert.strictEqual(firstObserver.value, 'BAR') + const secondObserver = new Observer(() => { + return '!!!' + firstObserver.value + '!!!' + }) + secondObserver() + assert.strictEqual(secondObserver.value, '!!!BAR!!!') + const thirdObserver = new Observer(() => { + return secondObserver.value.toLowerCase() + }) + thirdObserver() + assert.strictEqual(thirdObserver.value, '!!!bar!!!') + reactor.foo = 'baz' + assert.strictEqual(firstObserver.value, 'BAZ') + assert.strictEqual(secondObserver.value, '!!!BAZ!!!') + assert.strictEqual(thirdObserver.value, '!!!baz!!!') + }) - it('should trigger chained observers', () => { - let tracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - reactor.bigFoo = reactor.foo.toUpperCase() - })() - assert.equal(reactor.bigFoo, 'BAR') - new Observer(() => { - tracker = reactor.bigFoo - })() - assert.equal(tracker, 'BAR') - reactor.foo = 'qux' - assert.equal(reactor.bigFoo, 'QUX') - assert.equal(tracker, 'QUX') + it.skip('should trigger observers once per write for triangle dependencies', () => { + // We have the following triangle dependency + // reactor -> first -> second + // reactor -> second + // Ideally we have reactor trigger first then second + // However, a naive depth first implementation would trigger first when in turn trigger second + // then go back to trigger second again because it's a dependency of reactor as well + // So we have an observer unnecessarily triggering twice off a single write + // Right now this is the naive implementation + let firstRunCount = 0 + let secondRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + firstRunCount += 1 + return reactor.foo.toUpperCase() + }) + firstObserver() + assert.strictEqual(firstRunCount, 1) + assert.strictEqual(firstObserver.value, 'BAR') + const secondObserver = new Observer(() => { + secondRunCount += 1 + return reactor.foo + firstObserver.value + }) + secondObserver() + assert.strictEqual(secondRunCount, 1) + assert.strictEqual(secondObserver.value, 'barBAR') + reactor.foo = 'baz' + assert.strictEqual(firstRunCount, 2) + assert.strictEqual(firstObserver.value, 'BAZ') + assert.strictEqual(secondRunCount, 2) + assert.strictEqual(secondObserver.value, 'bazBAZ') + }) + + it.skip('should not trivially infinite loop when using other observers like functions', () => { + // Trivial case + // observer2 = observer1() + 1 + // observer2 both calls observer1 and reads its value so is dependent on it + // So if observer1 is updated, it triggers observer2 which runs observer1 again which triggers observer 2 again + // Thus trivially causing an infinite loop + // Ideally what should happen is that observer2 should call observer1 but since it just retrieved its return value directly + // should not be subject to being triggered again + let firstRunCount = 0 + let secondRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + // By wrapping reactor.foo in an object, everytime it triggers it generates a new value + // This bypasses our "same value" trigger guard + const firstObserver = new Observer(() => { + firstRunCount += 1 + if (firstRunCount > 100) throw new Error('infinite loop') + return [reactor.foo] + }) + firstObserver() + const secondObserver = new Observer(() => { + secondRunCount += 1 + if (secondRunCount > 100) throw new Error('infinite loop') + return firstObserver() + 1 + }) + secondObserver() + // This should infinite loop but it does not right now. TBD + }) + + it('should be able to create observers inside other observers', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' }) + let outerCounter = 0 + let innerCounter = 0 + let outerTracker + let innerTracker + let innerObserver + // We have an outer observer that creates an inner observer + // The outer observer depends on reactor.outer and the inner observer + // The inner observer depends on reactor.inner + new Observer(() => { + outerCounter += 1 + outerTracker = reactor.outer + if (innerObserver) innerObserver.stop() + innerObserver = new Observer(() => { + innerCounter += 1 + innerTracker = reactor.inner + }) + innerObserver() + })() + // The outer observer runs which creates and runs the inner observer + // So both run once + assert.equal(outerCounter, 1) + assert.equal(outerTracker, 'foo') + assert.equal(innerCounter, 1) + assert.equal(innerTracker, 'bar') + // This triggers the inner observer to run again + // The outer observer is dependent on the inner observer + // but because the inner observer doesn't have a return value + // it stays as undefined and so does not trigger the outer observer + reactor.inner = 'baz' + assert.equal(outerCounter, 1) + assert.equal(outerTracker, 'foo') + assert.equal(innerCounter, 2) + assert.equal(innerTracker, 'baz') + // This triggers the outer observer which creates and runs a new inner observer + reactor.outer = 'moo' + assert.equal(outerCounter, 2) + assert.equal(outerTracker, 'moo') + assert.equal(innerCounter, 3) + assert.equal(innerTracker, 'baz') }) }) From fb938fe925bfb92881110f1ef89b0cbe84f4e0f5 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 21:59:43 +0800 Subject: [PATCH 26/71] Commented trivial infinite loop test --- test/test.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/test/test.js b/test/test.js index 335b484..ec4dfef 100644 --- a/test/test.js +++ b/test/test.js @@ -2043,14 +2043,15 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'bazBAZ') }) - it.skip('should not trivially infinite loop when using other observers like functions', () => { + it('should not trivially infinite loop when using other observers like functions', () => { // Trivial case // observer2 = observer1() + 1 // observer2 both calls observer1 and reads its value so is dependent on it // So if observer1 is updated, it triggers observer2 which runs observer1 again which triggers observer 2 again - // Thus trivially causing an infinite loop - // Ideally what should happen is that observer2 should call observer1 but since it just retrieved its return value directly - // should not be subject to being triggered again + // This is guarded against because an observer breaks all dependencies when it runs + // And a called observer sets its value before doing a read to return it + // This means that when observer2 calls observer1, it is temporarily not a dependency while it triggers its others + // Then immediately after restablishes its dependence on observer1 let firstRunCount = 0 let secondRunCount = 0 const reactor = new Reactor({ @@ -2070,7 +2071,15 @@ describe('Complex Setups', () => { return firstObserver() + 1 }) secondObserver() - // This should infinite loop but it does not right now. TBD + assert.strictEqual(firstRunCount, 2) + assert.strictEqual(secondRunCount, 1) + assert.deepEqual(firstObserver.value, ['bar']) + assert.strictEqual(secondObserver.value, 'bar1') + reactor.foo = 'baz' + assert.strictEqual(firstRunCount, 4) + assert.strictEqual(secondRunCount, 2) + assert.deepEqual(firstObserver.value, ['baz']) + assert.strictEqual(secondObserver.value, 'baz1') }) it('should be able to create observers inside other observers', () => { From ee6f9fc5d859a68f3d0785e23074683c7778c56f Mon Sep 17 00:00:00 2001 From: fynyky Date: Sat, 16 Aug 2025 22:08:06 +0800 Subject: [PATCH 27/71] Added infinite loop test for a 3 part loop --- test/test.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index ec4dfef..004d49e 100644 --- a/test/test.js +++ b/test/test.js @@ -2043,7 +2043,7 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'bazBAZ') }) - it('should not trivially infinite loop when using other observers like functions', () => { + it('should not trivially infinite loop when an observer calls another', () => { // Trivial case // observer2 = observer1() + 1 // observer2 both calls observer1 and reads its value so is dependent on it @@ -2082,6 +2082,48 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'baz1') }) + it.skip('should not infinite loop with three observers calling each other like functions', () => { + // This is a more complex case + // observer2 = observer1() + 1 + // observer3 = observer1() + observer2() + // So observer1 triggers observer2 which triggers observer3 + // Then observer3 triggers observer2 which does not loop because it is rebuilding dependencies when it sets its value + // But observer3 triggers observer1 which still triggers observer2 which still triggers observer3 + let firstRunCount = 0 + let secondRunCount = 0 + let thirdRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + firstRunCount += 1 + if (firstRunCount > 100) throw new Error('infinite loop detected') + return [reactor.foo] + }) + firstObserver() + const secondObserver = new Observer(() => { + secondRunCount += 1 + if (secondRunCount > 100) throw new Error('infinite loop detected') + return [firstObserver() + 'baz'] + }) + secondObserver() + const thirdObserver = new Observer(() => { + thirdRunCount += 1 + if (thirdRunCount > 100) throw new Error('infinite loop detected') + return [firstObserver() + secondObserver()] + }) + thirdObserver() + // assert.strictEqual(firstRunCount, 2) + // assert.strictEqual(secondRunCount, 1) + // assert.deepEqual(firstObserver.value, ['bar']) + // assert.strictEqual(secondObserver.value, 'bar1') + // reactor.foo = 'baz' + // assert.strictEqual(firstRunCount, 4) + // assert.strictEqual(secondRunCount, 2) + // assert.deepEqual(firstObserver.value, ['baz']) + // assert.strictEqual(secondObserver.value, 'baz1') + }) + it('should be able to create observers inside other observers', () => { const reactor = new Reactor({ outer: 'foo', From 0a3015a7f86c15915d57495ecbbac303e0d3974e Mon Sep 17 00:00:00 2001 From: fynyky Date: Sun, 17 Aug 2025 02:12:12 +0800 Subject: [PATCH 28/71] Made batch work to consolidate downstream observer triggers as well --- src/reactor.js | 48 +++++++++++----------- test/test.js | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 24 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 8a54a01..ec0fa49 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -119,8 +119,13 @@ class Signal extends Function { // A conslidated error will be thrown at the end of propagation Array.from(this.dependents).forEach(dependent => { try { - if (batcher) batcher.add(dependent) - else dependent.trigger() + if (batcher) { + // Do this so that the dependent is added to the end of the batcher queue + // Needed to ensure downstream observers are triggered again when necessary + // as we iterate through the batched dependents + batcher.delete(dependent) + batcher.add(dependent) + } else dependent.trigger() } catch (error) { errorList.push(error) } }) // If any errors occured during propagation @@ -653,50 +658,45 @@ const hide = (execute) => { // Method for allowing users to batch multiple observer updates together const batch = (execute) => { - let result if (batcher === null) { - // Set a global batcher so signals know not to trigger observers immediately - // Using a set allows the removal of redundant triggering in observers + // If a batcher is set then signals will not trigger observers immediately + // Instead they will be saved into the batcher to trigger after + // Using a Set allows the removal of redundant triggering in observers batcher = new Set() - let batchedObservers = [] + const errorList = [] + // Execute the given block and collect the triggerd observers - try { - result = execute() - // TODO Catch the error and throw it after the batching is done - } finally { - // Clear the batching mode - // This needs to be done before observer triggering in case any observers - // subsequently themselves trigger batches - // This also needs to be done first before throwing errors - // Otherwise the thrown errors will mean we never unset the batcher - // This will cause subsequent triggers to get stuck in this dead batcher - // Never to be executed - batchedObservers = Array.from(batcher) // Make a copy to freeze it + let result + try { result = execute() } catch (error) { + // If I want to fail forward and try to trigger the relevant observers so far + // errorList.push(error) + // If I want to fail fast instead batcher = null + throw error } // Trigger the collected observers // If an error occurs, collect it and keep going // A conslidated error will be thrown at the end of propagation - // TODO consider: batch wrap the subsequent triggers as well? - const errorList = [] - batchedObservers.forEach(observer => { + for (const observer of batcher) { try { observer.trigger() } catch (error) { errorList.push(error) } - }) + } // If any errors occured during propagation // consolidate and throw them + batcher = null if (errorList.length === 1) { throw errorList[0] } else if (errorList.length > 1) { const errorMessage = 'Multiple errors from batched reactor observers' throw new CompoundError(errorMessage, errorList) } + + return result // No need to do anything if batching is already taking place } } else { - result = execute() + return execute() } - return result } // Method for extracting a the internal object from the Reactor diff --git a/test/test.js b/test/test.js index 004d49e..0e42628 100644 --- a/test/test.js +++ b/test/test.js @@ -1668,7 +1668,114 @@ describe('Batching', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'bup') }) + + // What should happen when a batch hits an error? + // Fail out straight away? (unsetting batcher of course) + // Or should it collect the error and try to trigger the observers it got to so far? + // The later might seem like a fail forward action, but it's actually more consistent + // since the semantic we have is that writing to a signal triggers all observers synchronously + // It is more consistent with what happens outside of the batch block + it.skip('should trigger observers from the batch block even if there is an error', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.throws(() => { + batch(() => { + reactor.foo = 'baz' + throw new Error('dummy error') + }) + }, { + name: 'Error', + message: 'dummy error' + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) // TODO should batch block return the result of the block? + + // -> a -> c + // -> b -> c + // Used to be batch would trigger a and b together + // which would then double trigger c + // Ideally a batch would only trigger c once + it('should consolidate redundant downstream triggers', () => { + const reactor = new Reactor({ + a: 'foo', + b: 'bar' + }) + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return reactor.a + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return reactor.b + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + batch(() => { + reactor.a = 'baz' + reactor.b = 'qux' + }) + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // Without batch this would be triggered an additional time + // Once from observerA and another time from observerB + // With batch these are consolidated into a single trigger + assert.strictEqual(runCountC, 2) + }) + + // -> a -> d + // -> b -> c -> d + // In this case you might need to trigger d twice by the discover process + // the batch first queues up [ab] + // then it discovers [abdc] + // after triggering d it discovers that it needs to update c again [abdcd] + // If we don't queue d to be be triggered again, it will have an outdated value for c + // Anyway around it? + it('should not skip essential downstream triggers', () => { + const reactor = new Reactor({ + a: 'foo', + b: 'bar' + }) + const observerA = new Observer(() => { + return reactor.a + }) + observerA() + const observerB = new Observer(() => { + return reactor.b + }) + observerB() + const observerC = new Observer(() => { + return observerB.value + }) + observerC() + const observerD = new Observer(() => { + return observerA.value + observerC.value + }) + observerD() + assert.strictEqual(observerD.value, 'foobar') + batch(() => { + reactor.a = 'baz' + reactor.b = 'qux' + }) + assert.strictEqual(observerD.value, 'bazqux') + }) }) describe('Hiding', () => { From 6c7d15d7219a7f26527a55d300c3c0a0d6c9bff5 Mon Sep 17 00:00:00 2001 From: fynyky Date: Sun, 17 Aug 2025 02:18:05 +0800 Subject: [PATCH 29/71] Batch now triggers the dependent oberservers if there was an error --- src/reactor.js | 9 +++++---- test/test.js | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index ec0fa49..5c8dae4 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -668,11 +668,12 @@ const batch = (execute) => { // Execute the given block and collect the triggerd observers let result try { result = execute() } catch (error) { - // If I want to fail forward and try to trigger the relevant observers so far - // errorList.push(error) + // If I want to fail forward store the error + // and try to trigger the relevant observers so far + errorList.push(error) // If I want to fail fast instead - batcher = null - throw error + // batcher = null + // throw error } // Trigger the collected observers diff --git a/test/test.js b/test/test.js index 0e42628..621ee32 100644 --- a/test/test.js +++ b/test/test.js @@ -1675,7 +1675,7 @@ describe('Batching', () => { // The later might seem like a fail forward action, but it's actually more consistent // since the semantic we have is that writing to a signal triggers all observers synchronously // It is more consistent with what happens outside of the batch block - it.skip('should trigger observers from the batch block even if there is an error', () => { + it('should trigger dependent observers from the batch block even if there is an error', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -1695,7 +1695,6 @@ describe('Batching', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'baz') }) - // TODO should batch block return the result of the block? // -> a -> c // -> b -> c From f881f6d9ea8ff0d1d1ccc7093d30a3821e18c7cf Mon Sep 17 00:00:00 2001 From: fynyky Date: Sun, 17 Aug 2025 11:32:23 +0800 Subject: [PATCH 30/71] Automatic batching for signals for consistency --- src/reactor.js | 80 +++++++++++++++++--------------- test/test.js | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 36 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 5c8dae4..30b3a50 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -105,43 +105,51 @@ class Signal extends Function { // - Trigger any dependent Observers while collecting errors thrown // - Throw a CompoundError if necessary write (newValue) { - // Avoid triggering observers if same value is written - if (this.value === newValue) return (this.value = newValue) - // Save the new value/definition - const output = (this.value = newValue) - // Trigger dependents - // Need to do an array copy to avoid an infinite loop - // Triggering a dependent will remove it from the dependent set - // Then re-add it when it is execute - // This will cause the iterator to trigger again - const errorList = [] - // If an error occurs, collect it and keep going - // A conslidated error will be thrown at the end of propagation - Array.from(this.dependents).forEach(dependent => { - try { - if (batcher) { - // Do this so that the dependent is added to the end of the batcher queue - // Needed to ensure downstream observers are triggered again when necessary - // as we iterate through the batched dependents - batcher.delete(dependent) - batcher.add(dependent) - } else dependent.trigger() - } catch (error) { errorList.push(error) } - }) - // If any errors occured during propagation - // consolidate and throw them - if (errorList.length === 1) { - throw errorList[0] - } else if (errorList.length > 1) { - const errorMessage = 'Multiple errors from signal write' - throw new CompoundError(errorMessage, errorList) - } + // Design decision to wrap even individual signal writes in a batch + // This allows for consistency with all dependent triggering + // since Reactor writes are also batched + return batch(() => { + // Avoid triggering observers if same value is written + if (this.value === newValue) return (this.value = newValue) + // Save the new value/definition + const output = (this.value = newValue) + // Trigger dependents + // Need to do an array copy to avoid an infinite loop + // Triggering a dependent will remove it from the dependent set + // Then re-add it when it is execute + // This will cause the iterator to trigger again + const errorList = [] + // If an error occurs, collect it and keep going + // A conslidated error will be thrown at the end of propagation + Array.from(this.dependents).forEach(dependent => { + try { + if (batcher) { + // Do this so that the dependent is added to the end of the batcher queue + // Needed to ensure downstream observers are triggered again when necessary + // as we iterate through the batched dependents + batcher.delete(dependent) + batcher.add(dependent) + // Technically this is dead code now that we're batching + // But leaving it in for now for semantic clarity + // Could consider throwing an error here instead since the batcher should always be set + } else dependent.trigger() + } catch (error) { errorList.push(error) } + }) + // If any errors occured during propagation + // consolidate and throw them + if (errorList.length === 1) { + throw errorList[0] + } else if (errorList.length > 1) { + const errorMessage = 'Multiple errors from signal write' + throw new CompoundError(errorMessage, errorList) + } - // If it's not an object then just return it right away - // Cleaner and faster than the alternative approach of constructing a Reactor - // and catching an error - if (isObject(output)) return new Reactor(output) - else return output + // If it's not an object then just return it right away + // Cleaner and faster than the alternative approach of constructing a Reactor + // and catching an error + if (isObject(output)) return new Reactor(output) + else return output + }) }, // Used by observers to remove themselves from this as dependents // Also removesSelf from any owners if there are no more dependents diff --git a/test/test.js b/test/test.js index 621ee32..70c5fdd 100644 --- a/test/test.js +++ b/test/test.js @@ -1775,6 +1775,128 @@ describe('Batching', () => { }) assert.strictEqual(observerD.value, 'bazqux') }) + + // foo -> a -> c + // foo -> b -> c + // Auto batching for signals should trigger c once + it('should automatically batch Signal writes', () => { + const signal = new Signal('foo') + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return signal() + 'A' + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return signal() + 'B' + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + assert.strictEqual(observerA.value, 'fooA') + assert.strictEqual(observerB.value, 'fooB') + assert.strictEqual(observerC.value, 'fooAfooB') + signal('bar') + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // If not auto batched this would be 3 + // As observerC would be trigger from both A and B + assert.strictEqual(runCountC, 2) + assert.strictEqual(observerA.value, 'barA') + assert.strictEqual(observerB.value, 'barB') + assert.strictEqual(observerC.value, 'barAbarB') + }) + // This should be the same as Signal since Observer values are a Signal + // But testing it anyway for completeness + it('should automatically batch Observer writes', () => { + const rootObserver = new Observer((x) => x) + rootObserver('foo') + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return rootObserver.value + 'A' + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return rootObserver.value + 'B' + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + assert.strictEqual(observerA.value, 'fooA') + assert.strictEqual(observerB.value, 'fooB') + assert.strictEqual(observerC.value, 'fooAfooB') + rootObserver('bar') + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // If not auto batched this would be 3 + // As observerC would be trigger from both A and B + assert.strictEqual(runCountC, 2) + assert.strictEqual(observerA.value, 'barA') + assert.strictEqual(observerB.value, 'barB') + assert.strictEqual(observerC.value, 'barAbarB') + }) + + // foo -> a -> c + // foo -> b -> c + // Auto batching for signals should trigger c once + // Even if signals are batched, some reactor writes are compound operations + // So need to batch at this level as well + it.skip('should automatically batch Reactor writes', () => { + const signal = new Signal('foo') + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return signal() + 'A' + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return signal() + 'B' + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + assert.strictEqual(observerA.value, 'fooA') + assert.strictEqual(observerB.value, 'fooB') + assert.strictEqual(observerC.value, 'fooAfooB') + signal('bar') + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // If not auto batched this would be 3 + // As observerC would be trigger from both A and B + assert.strictEqual(runCountC, 2) + assert.strictEqual(observerA.value, 'barA') + assert.strictEqual(observerB.value, 'barB') + assert.strictEqual(observerC.value, 'barAbarB') + }) + }) describe('Hiding', () => { From a80328a74e731d48da34a00d4ec080463c71a568 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 18 Aug 2025 00:03:05 +0800 Subject: [PATCH 31/71] Added test for reactor write batching --- test/test.js | 52 +++++++++++----------------------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/test/test.js b/test/test.js index 70c5fdd..2c10d4c 100644 --- a/test/test.js +++ b/test/test.js @@ -1855,48 +1855,18 @@ describe('Batching', () => { assert.strictEqual(observerC.value, 'barAbarB') }) - // foo -> a -> c - // foo -> b -> c - // Auto batching for signals should trigger c once - // Even if signals are batched, some reactor writes are compound operations - // So need to batch at this level as well - it.skip('should automatically batch Reactor writes', () => { - const signal = new Signal('foo') - let runCountA = 0 - let runCountB = 0 - let runCountC = 0 - const observerA = new Observer(() => { - runCountA += 1 - return signal() + 'A' - }) - observerA() - const observerB = new Observer(() => { - runCountB += 1 - return signal() + 'B' - }) - observerB() - const observerC = new Observer(() => { - runCountC += 1 - return observerA.value + observerB.value - }) - observerC() - assert.strictEqual(runCountA, 1) - assert.strictEqual(runCountB, 1) - assert.strictEqual(runCountC, 1) - assert.strictEqual(observerA.value, 'fooA') - assert.strictEqual(observerB.value, 'fooB') - assert.strictEqual(observerC.value, 'fooAfooB') - signal('bar') - assert.strictEqual(runCountA, 2) - assert.strictEqual(runCountB, 2) - // If not auto batched this would be 3 - // As observerC would be trigger from both A and B - assert.strictEqual(runCountC, 2) - assert.strictEqual(observerA.value, 'barA') - assert.strictEqual(observerB.value, 'barB') - assert.strictEqual(observerC.value, 'barAbarB') + it('should automatically batch Reactor writes', () => { + let runCount = 0 + const reactor = new Reactor(['foo', 'bar']) + new Observer(() => { + runCount += 1 + return JSON.stringify(reactor) + })() + assert.strictEqual(runCount, 1) + // Call pop because it's a compound operation + reactor.pop() + assert.strictEqual(runCount, 2) }) - }) describe('Hiding', () => { From 3d08f92db0837e7eb9d3319ebe3cce79d529f2f7 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 18 Aug 2025 00:43:36 +0800 Subject: [PATCH 32/71] Refactor signal dependency handling in batch processing to improve clarity and maintainability. Removed redundant error handling and streamlined the process of triggering dependents, ensuring consistency in observer updates. --- src/reactor.js | 51 +++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 30b3a50..de0fda4 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -108,42 +108,25 @@ class Signal extends Function { // Design decision to wrap even individual signal writes in a batch // This allows for consistency with all dependent triggering // since Reactor writes are also batched + // Wrap the whole function so we catch potential triggers + // from defining internal object values and wrapping output as a Reactor return batch(() => { // Avoid triggering observers if same value is written if (this.value === newValue) return (this.value = newValue) // Save the new value/definition const output = (this.value = newValue) - // Trigger dependents - // Need to do an array copy to avoid an infinite loop - // Triggering a dependent will remove it from the dependent set - // Then re-add it when it is execute - // This will cause the iterator to trigger again - const errorList = [] - // If an error occurs, collect it and keep going - // A conslidated error will be thrown at the end of propagation + + // Build dependency queue + // Do not trigger dependents directly and leave it to be handled by the batcher Array.from(this.dependents).forEach(dependent => { - try { - if (batcher) { - // Do this so that the dependent is added to the end of the batcher queue - // Needed to ensure downstream observers are triggered again when necessary - // as we iterate through the batched dependents - batcher.delete(dependent) - batcher.add(dependent) - // Technically this is dead code now that we're batching - // But leaving it in for now for semantic clarity - // Could consider throwing an error here instead since the batcher should always be set - } else dependent.trigger() - } catch (error) { errorList.push(error) } + // Do this so that the dependent is added to the end of the batcher queue + // Needed to ensure downstream observers are triggered again when necessary + // as we iterate through the batched dependents + // Generally modifying an iterable while iterating through it is a bad idea + // But in this case it's necessary as we can't know all the downstream dependents ahead of time + batcher.delete(dependent) + batcher.add(dependent) }) - // If any errors occured during propagation - // consolidate and throw them - if (errorList.length === 1) { - throw errorList[0] - } else if (errorList.length > 1) { - const errorMessage = 'Multiple errors from signal write' - throw new CompoundError(errorMessage, errorList) - } - // If it's not an object then just return it right away // Cleaner and faster than the alternative approach of constructing a Reactor // and catching an error @@ -245,10 +228,10 @@ class Reactor { // but for the reactor overall selfSignal: new Signal(null), - // Function calls on reactor properties are automatically batched - // This allows compound function calls like "Array.push" - // to only trigger one round of observer updates apply (thisArg, argumentsList) { + // Function calls on reactor properties are automatically batched + // This allows compound function calls like "Array.push" + // to only trigger one round of observer updates return batch(() => { // For native object methods which cant use a Proxy as `this` // try again with the underlying object @@ -384,8 +367,6 @@ class Reactor { // Force dependencies to trigger // Hack to do this by trivially "redefining" the signal - // The proper accessor will be materialized "just in time" on the getter - // so it doesn't matter that we're swapping it with a filler Symbol trigger (property) { // Calculate the actual new values observers will receive // This avoids redundant triggering if they were the same @@ -404,6 +385,8 @@ class Reactor { return false })() // Batch together to avoid redundant triggering for shared observers + // This might be redundant because the only way this happens is by calling native methods + // which are already batched anyway. But keeping for safety batch(() => { if (this.getSignals[property]) this.getSignals[property](getValue) if (this.hasSignals[property]) this.hasSignals[property](hasValue) From 9f84ca08326404fd6fb0ecdd053801aefe9f984e Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 18 Aug 2025 01:28:09 +0800 Subject: [PATCH 33/71] Split tests out into separate files for easier handling --- test/batching.test.js | 270 +++++ test/complex.test.js | 205 ++++ test/errors.test.js | 75 ++ test/features.test.js | 181 +++ test/hiding.test.js | 103 ++ test/observer.test.js | 263 +++++ test/reactivity.test.js | 864 ++++++++++++++ test/reactor.test.js | 269 +++++ test/signal.test.js | 268 +++++ test/test.js | 2378 +-------------------------------------- 10 files changed, 2507 insertions(+), 2369 deletions(-) create mode 100644 test/batching.test.js create mode 100644 test/complex.test.js create mode 100644 test/errors.test.js create mode 100644 test/features.test.js create mode 100644 test/hiding.test.js create mode 100644 test/observer.test.js create mode 100644 test/reactivity.test.js create mode 100644 test/reactor.test.js create mode 100644 test/signal.test.js diff --git a/test/batching.test.js b/test/batching.test.js new file mode 100644 index 0000000..d51cf93 --- /dev/null +++ b/test/batching.test.js @@ -0,0 +1,270 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + Signal, + Reactor, + Observer, + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + batch + // shuck +} from '../src/reactor.js' + +describe('Batching', () => { + // TODO add test and functionality for batch parameter validation + it('should delay and combine observer triggers within a batch block', () => { + const reactor = new Reactor() + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + batch(() => { + reactor.foo = 'bleep' + assert.strictEqual(runCount, 1) + reactor.foo = 'bloop' + assert.strictEqual(runCount, 1) + reactor.foo = 'blarp' + assert.strictEqual(runCount, 1) + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'blarp') + }) + + it('should nest batch blocks with no consequence', () => { + const reactor = new Reactor() + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + batch(() => { + reactor.foo = 'bleep' + assert.strictEqual(runCount, 1) + reactor.foo = 'bloop' + assert.strictEqual(runCount, 1) + reactor.foo = 'blarp' + assert.strictEqual(runCount, 1) + batch(() => { + reactor.foo = 'bink' + assert.strictEqual(runCount, 1) + reactor.foo = 'bonk' + assert.strictEqual(runCount, 1) + reactor.foo = 'bup' + assert.strictEqual(runCount, 1) + }) + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bup') + }) + + // What should happen when a batch hits an error? + // Fail out straight away? (unsetting batcher of course) + // Or should it collect the error and try to trigger the observers it got to so far? + // The later might seem like a fail forward action, but it's actually more consistent + // since the semantic we have is that writing to a signal triggers all observers synchronously + // It is more consistent with what happens outside of the batch block + it('should trigger dependent observers from the batch block even if there is an error', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.throws(() => { + batch(() => { + reactor.foo = 'baz' + throw new Error('dummy error') + }) + }, { + name: 'Error', + message: 'dummy error' + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + + // -> a -> c + // -> b -> c + // Used to be batch would trigger a and b together + // which would then double trigger c + // Ideally a batch would only trigger c once + it('should consolidate redundant downstream triggers', () => { + const reactor = new Reactor({ + a: 'foo', + b: 'bar' + }) + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return reactor.a + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return reactor.b + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + batch(() => { + reactor.a = 'baz' + reactor.b = 'qux' + }) + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // Without batch this would be triggered an additional time + // Once from observerA and another time from observerB + // With batch these are consolidated into a single trigger + assert.strictEqual(runCountC, 2) + }) + + // -> a -> d + // -> b -> c -> d + // In this case you might need to trigger d twice by the discover process + // the batch first queues up [ab] + // then it discovers [abdc] + // after triggering d it discovers that it needs to update c again [abdcd] + // If we don't queue d to be be triggered again, it will have an outdated value for c + // Anyway around it? + it('should not skip essential downstream triggers', () => { + const reactor = new Reactor({ + a: 'foo', + b: 'bar' + }) + const observerA = new Observer(() => { + return reactor.a + }) + observerA() + const observerB = new Observer(() => { + return reactor.b + }) + observerB() + const observerC = new Observer(() => { + return observerB.value + }) + observerC() + const observerD = new Observer(() => { + return observerA.value + observerC.value + }) + observerD() + assert.strictEqual(observerD.value, 'foobar') + batch(() => { + reactor.a = 'baz' + reactor.b = 'qux' + }) + assert.strictEqual(observerD.value, 'bazqux') + }) + + // foo -> a -> c + // foo -> b -> c + // Auto batching for signals should trigger c once + it('should automatically batch Signal writes', () => { + const signal = new Signal('foo') + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return signal() + 'A' + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return signal() + 'B' + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + assert.strictEqual(observerA.value, 'fooA') + assert.strictEqual(observerB.value, 'fooB') + assert.strictEqual(observerC.value, 'fooAfooB') + signal('bar') + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // If not auto batched this would be 3 + // As observerC would be trigger from both A and B + assert.strictEqual(runCountC, 2) + assert.strictEqual(observerA.value, 'barA') + assert.strictEqual(observerB.value, 'barB') + assert.strictEqual(observerC.value, 'barAbarB') + }) + // This should be the same as Signal since Observer values are a Signal + // But testing it anyway for completeness + it('should automatically batch Observer writes', () => { + const rootObserver = new Observer((x) => x) + rootObserver('foo') + let runCountA = 0 + let runCountB = 0 + let runCountC = 0 + const observerA = new Observer(() => { + runCountA += 1 + return rootObserver.value + 'A' + }) + observerA() + const observerB = new Observer(() => { + runCountB += 1 + return rootObserver.value + 'B' + }) + observerB() + const observerC = new Observer(() => { + runCountC += 1 + return observerA.value + observerB.value + }) + observerC() + assert.strictEqual(runCountA, 1) + assert.strictEqual(runCountB, 1) + assert.strictEqual(runCountC, 1) + assert.strictEqual(observerA.value, 'fooA') + assert.strictEqual(observerB.value, 'fooB') + assert.strictEqual(observerC.value, 'fooAfooB') + rootObserver('bar') + assert.strictEqual(runCountA, 2) + assert.strictEqual(runCountB, 2) + // If not auto batched this would be 3 + // As observerC would be trigger from both A and B + assert.strictEqual(runCountC, 2) + assert.strictEqual(observerA.value, 'barA') + assert.strictEqual(observerB.value, 'barB') + assert.strictEqual(observerC.value, 'barAbarB') + }) + + it('should automatically batch Reactor writes', () => { + let runCount = 0 + const reactor = new Reactor(['foo', 'bar']) + new Observer(() => { + runCount += 1 + return JSON.stringify(reactor) + })() + assert.strictEqual(runCount, 1) + // Call pop because it's a compound operation + reactor.pop() + assert.strictEqual(runCount, 2) + }) +}) diff --git a/test/complex.test.js b/test/complex.test.js new file mode 100644 index 0000000..5ea0557 --- /dev/null +++ b/test/complex.test.js @@ -0,0 +1,205 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + Reactor, + Observer + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + // shuck +} from '../src/reactor.js' + +describe('Complex Setups', () => { + it('should be able to chain observers off each other', () => { + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + return reactor.foo.toUpperCase() + }) + firstObserver() + assert.strictEqual(firstObserver.value, 'BAR') + const secondObserver = new Observer(() => { + return '!!!' + firstObserver.value + '!!!' + }) + secondObserver() + assert.strictEqual(secondObserver.value, '!!!BAR!!!') + const thirdObserver = new Observer(() => { + return secondObserver.value.toLowerCase() + }) + thirdObserver() + assert.strictEqual(thirdObserver.value, '!!!bar!!!') + reactor.foo = 'baz' + assert.strictEqual(firstObserver.value, 'BAZ') + assert.strictEqual(secondObserver.value, '!!!BAZ!!!') + assert.strictEqual(thirdObserver.value, '!!!baz!!!') + }) + + it.skip('should trigger observers once per write for triangle dependencies', () => { + // We have the following triangle dependency + // reactor -> first -> second + // reactor -> second + // Ideally we have reactor trigger first then second + // However, a naive depth first implementation would trigger first when in turn trigger second + // then go back to trigger second again because it's a dependency of reactor as well + // So we have an observer unnecessarily triggering twice off a single write + // Right now this is the naive implementation + let firstRunCount = 0 + let secondRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + firstRunCount += 1 + return reactor.foo.toUpperCase() + }) + firstObserver() + assert.strictEqual(firstRunCount, 1) + assert.strictEqual(firstObserver.value, 'BAR') + const secondObserver = new Observer(() => { + secondRunCount += 1 + return reactor.foo + firstObserver.value + }) + secondObserver() + assert.strictEqual(secondRunCount, 1) + assert.strictEqual(secondObserver.value, 'barBAR') + reactor.foo = 'baz' + assert.strictEqual(firstRunCount, 2) + assert.strictEqual(firstObserver.value, 'BAZ') + assert.strictEqual(secondRunCount, 2) + assert.strictEqual(secondObserver.value, 'bazBAZ') + }) + + it('should not trivially infinite loop when an observer calls another', () => { + // Trivial case + // observer2 = observer1() + 1 + // observer2 both calls observer1 and reads its value so is dependent on it + // So if observer1 is updated, it triggers observer2 which runs observer1 again which triggers observer 2 again + // This is guarded against because an observer breaks all dependencies when it runs + // And a called observer sets its value before doing a read to return it + // This means that when observer2 calls observer1, it is temporarily not a dependency while it triggers its others + // Then immediately after restablishes its dependence on observer1 + let firstRunCount = 0 + let secondRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + // By wrapping reactor.foo in an object, everytime it triggers it generates a new value + // This bypasses our "same value" trigger guard + const firstObserver = new Observer(() => { + firstRunCount += 1 + if (firstRunCount > 100) throw new Error('infinite loop') + return [reactor.foo] + }) + firstObserver() + const secondObserver = new Observer(() => { + secondRunCount += 1 + if (secondRunCount > 100) throw new Error('infinite loop') + return firstObserver() + 1 + }) + secondObserver() + assert.strictEqual(firstRunCount, 2) + assert.strictEqual(secondRunCount, 1) + assert.deepEqual(firstObserver.value, ['bar']) + assert.strictEqual(secondObserver.value, 'bar1') + reactor.foo = 'baz' + assert.strictEqual(firstRunCount, 4) + assert.strictEqual(secondRunCount, 2) + assert.deepEqual(firstObserver.value, ['baz']) + assert.strictEqual(secondObserver.value, 'baz1') + }) + + it.skip('should not infinite loop with three observers calling each other like functions', () => { + // This is a more complex case + // observer2 = observer1() + 1 + // observer3 = observer1() + observer2() + // So observer1 triggers observer2 which triggers observer3 + // Then observer3 triggers observer2 which does not loop because it is rebuilding dependencies when it sets its value + // But observer3 triggers observer1 which still triggers observer2 which still triggers observer3 + let firstRunCount = 0 + let secondRunCount = 0 + let thirdRunCount = 0 + const reactor = new Reactor({ + foo: 'bar' + }) + const firstObserver = new Observer(() => { + firstRunCount += 1 + if (firstRunCount > 100) throw new Error('infinite loop detected') + return [reactor.foo] + }) + firstObserver() + const secondObserver = new Observer(() => { + secondRunCount += 1 + if (secondRunCount > 100) throw new Error('infinite loop detected') + return [firstObserver() + 'baz'] + }) + secondObserver() + const thirdObserver = new Observer(() => { + thirdRunCount += 1 + if (thirdRunCount > 100) throw new Error('infinite loop detected') + return [firstObserver() + secondObserver()] + }) + thirdObserver() + // assert.strictEqual(firstRunCount, 2) + // assert.strictEqual(secondRunCount, 1) + // assert.deepEqual(firstObserver.value, ['bar']) + // assert.strictEqual(secondObserver.value, 'bar1') + // reactor.foo = 'baz' + // assert.strictEqual(firstRunCount, 4) + // assert.strictEqual(secondRunCount, 2) + // assert.deepEqual(firstObserver.value, ['baz']) + // assert.strictEqual(secondObserver.value, 'baz1') + }) + + it('should be able to create observers inside other observers', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' + }) + let outerCounter = 0 + let innerCounter = 0 + let outerTracker + let innerTracker + let innerObserver + // We have an outer observer that creates an inner observer + // The outer observer depends on reactor.outer and the inner observer + // The inner observer depends on reactor.inner + new Observer(() => { + outerCounter += 1 + outerTracker = reactor.outer + if (innerObserver) innerObserver.stop() + innerObserver = new Observer(() => { + innerCounter += 1 + innerTracker = reactor.inner + }) + innerObserver() + })() + // The outer observer runs which creates and runs the inner observer + // So both run once + assert.equal(outerCounter, 1) + assert.equal(outerTracker, 'foo') + assert.equal(innerCounter, 1) + assert.equal(innerTracker, 'bar') + // This triggers the inner observer to run again + // The outer observer is dependent on the inner observer + // but because the inner observer doesn't have a return value + // it stays as undefined and so does not trigger the outer observer + reactor.inner = 'baz' + assert.equal(outerCounter, 1) + assert.equal(outerTracker, 'foo') + assert.equal(innerCounter, 2) + assert.equal(innerTracker, 'baz') + // This triggers the outer observer which creates and runs a new inner observer + reactor.outer = 'moo' + assert.equal(outerCounter, 2) + assert.equal(outerTracker, 'moo') + assert.equal(innerCounter, 3) + assert.equal(innerTracker, 'baz') + }) +}) diff --git a/test/errors.test.js b/test/errors.test.js new file mode 100644 index 0000000..2785935 --- /dev/null +++ b/test/errors.test.js @@ -0,0 +1,75 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + Reactor, + Observer + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + // shuck +} from '../src/reactor.js' + +describe('Error Handling', () => { + it('should throw an error on a write if there is an Observer throws an error', () => { + const reactor = new Reactor({ value: 'foo' }) + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error') + })() + assert.throws(() => (reactor.value = 2), { + name: 'Error', + message: 'dummy error' + }) + }) + + it('should throw a CompoundError if there are multiple Observer errors', () => { + const reactor = new Reactor({ value: 1 }) + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error 1') + })() + new Observer(() => { + if (reactor.value > 1) throw new Error('dummy error 2') + })() + assert.throws(() => (reactor.value = 2), { + name: 'CompoundError' + }) + }) + + it('should throw a flattened CompoundError with chained observers', () => { + const reactor = new Reactor({ + foo: 1 + }) + // Successful passthrough to create subsequent compound errors + new Observer(() => { + reactor.passthrough = reactor.foo + })() + // Initial error failures to create an initial compound error + new Observer(() => { + if (reactor.foo > 1) throw new Error('primary error 1') + })() + new Observer(() => { + if (reactor.foo > 1) throw new Error('primary error 2') + })() + // Chain off reactor.passthrough to create a subsequent compound error + new Observer(() => { + if (reactor.passthrough > 1) throw new Error('secondary error 1') + })() + new Observer(() => { + if (reactor.passthrough > 1) throw new Error('secondary error 2') + })() + // Setting foo to 2 should trigger the primary error 1 and 2 and trigger the passthrough + // The passthrough triggers secondary error 1 and 2 as well which get merged into a compound error + // This compound error should then be merged with primary error 1 and 2 + // Instead of nesting it flattens to a single compound error with 4 causes + assert.throws(() => (reactor.foo = 2), (error) => { + assert.strictEqual(error.name, 'CompoundError') + assert.strictEqual(error.cause.length, 4) + return true + }) + }) +}) diff --git a/test/features.test.js b/test/features.test.js new file mode 100644 index 0000000..1e3c388 --- /dev/null +++ b/test/features.test.js @@ -0,0 +1,181 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + Reactor, + Observer + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + // shuck +} from '../src/reactor.js' + +describe('Minor Features', () => { + describe('Start and Stop', () => { + it('should stop observing', () => { + let counter = 0 + let tracker + const reactor = new Reactor({ value: 'foo' }) + const observer = new Observer(() => { + counter += 1 + tracker = reactor.value + }) + observer() + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + reactor.value = 'bar' + assert.equal(counter, 2) + assert.equal(tracker, 'bar') + observer.stop() + reactor.value = 'moo' + assert.equal(counter, 2) + assert.equal(tracker, 'bar') + }) + + it('should start after stopping', () => { + let counter = 0 + let tracker = null + const reactor = new Reactor({ value: 'foo' }) + const observer = new Observer(() => { + counter += 1 + tracker = reactor.value + }) + observer() + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + observer.stop() + reactor.value = 'moo' + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + observer.start() + assert.equal(counter, 2) + assert.equal(tracker, 'moo') + }) + + it('should have no effect with repeated starts', () => { + let counter = 0 + let tracker = null + const reactor = new Reactor({ value: 'foo' }) + const observer = new Observer(() => { + counter += 1 + tracker = reactor.value + }) + observer() + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + observer.stop() + reactor.value = 'moo' + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + observer.start() + assert.equal(counter, 2) + assert.equal(tracker, 'moo') + observer.start() + assert.equal(counter, 2) + assert.equal(tracker, 'moo') + }) + }) + + describe('Context and Subscriptions', () => { + it('should default context to undefined', () => { + let contextChecker = 'foo' + new Observer((context) => { + contextChecker = context + })() + assert(typeof contextChecker === 'undefined') + }) + + it('should set context', () => { + let contextChecker + const observer = new Observer((context) => { + contextChecker = context + }) + observer('foo') + assert.equal(contextChecker, 'foo') + const dummyObject = {} + observer(dummyObject) + assert.equal(contextChecker, dummyObject) + }) + + it('should set context with multiple params', () => { + let contextChecker + const observer = new Observer((a, b, c) => { + contextChecker = '' + a + b + c + }) + observer('foo', 'bar', 'baz') + assert.equal(contextChecker, 'foobarbaz') + contextChecker = null + observer() + assert.equal(contextChecker, 'undefinedundefinedundefined') + }) + + it('should set context and react to it', () => { + const reactor = new Reactor() + const contextChecker = {} + const observer = new Observer(function (...args) { + contextChecker.this = this + contextChecker.args = args + contextChecker.result = reactor.foo + }) + const bar = { + baz: observer + } + assert(typeof contextChecker.this === 'undefined') + assert(typeof contextChecker.args === 'undefined') + assert(typeof contextChecker.result === 'undefined') + bar.baz('qux') + assert.equal(contextChecker.this, bar) + assert.equal(contextChecker.args[0], 'qux') + assert(typeof contextChecker.result === 'undefined') + reactor.foo = 'bop' + assert.equal(contextChecker.this, bar) + assert.equal(contextChecker.args[0], 'qux') + assert.equal(contextChecker.result, 'bop') + }) + }) + + describe('Observer redefinition', () => { + it('should redefine an observer', () => { + const reactor = new Reactor({ + first: 'foo', + second: 'bar' + }) + let firstCounter = 0 + let secondCounter = 0 + let firstTracker + let secondTracker + const observer = new Observer(() => { + firstCounter += 1 + firstTracker = reactor.first + }) + observer() + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 0) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, undefined) + observer.execute = () => { + secondCounter += 1 + secondTracker = reactor.second + } + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 1) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'bar') + reactor.first = 'moo' + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 1) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'bar') + reactor.second = 'baz' + assert.equal(firstCounter, 1) + assert.equal(secondCounter, 2) + assert.equal(firstTracker, 'foo') + assert.equal(secondTracker, 'baz') + }) + }) +}) diff --git a/test/hiding.test.js b/test/hiding.test.js new file mode 100644 index 0000000..f0c45e2 --- /dev/null +++ b/test/hiding.test.js @@ -0,0 +1,103 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + Reactor, + Observer, + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + hide + // batch, + // shuck +} from '../src/reactor.js' + +describe('Hiding', () => { + // TODO add test and functionality for hide parameter validation + + it('should not create dependencies inside hide block', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' + }) + let outerRunCount = 0 + let innerRunCount = 0 + let outerRunValue + let innerRunValue + new Observer(() => { + outerRunCount += 1 + outerRunValue = reactor.outer + hide(() => { + innerRunCount += 1 + innerRunValue = reactor.inner + }) + })() + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.inner = 'baz' + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.outer = 'moo' + assert.strictEqual(outerRunCount, 2) + assert.strictEqual(innerRunCount, 2) + assert.strictEqual(outerRunValue, 'moo') + assert.strictEqual(innerRunValue, 'baz') + }) + + // TODO should hide blocks be nestable? + + it('should return the result of the hide block', () => { + const reactor = new Reactor({ + outer: 'foo', + inner: 'bar' + }) + let outerRunCount = 0 + let innerRunCount = 0 + let outerRunValue + let innerRunValue + new Observer(() => { + outerRunCount += 1 + outerRunValue = reactor.outer + innerRunValue = hide(() => { + innerRunCount += 1 + return reactor.inner + }) + })() + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.inner = 'baz' + assert.strictEqual(outerRunCount, 1) + assert.strictEqual(innerRunCount, 1) + assert.strictEqual(outerRunValue, 'foo') + assert.strictEqual(innerRunValue, 'bar') + reactor.outer = 'moo' + assert.strictEqual(outerRunCount, 2) + assert.strictEqual(innerRunCount, 2) + assert.strictEqual(outerRunValue, 'moo') + assert.strictEqual(innerRunValue, 'baz') + }) + + it('should not self trigger in a hide block', () => { + const reactor = new Reactor(['a', 'b', 'c']) + let runCount = 0 + let runValue + new Observer(() => { + runCount += 1 + // pop reads the length of the object as well as changes it + // So calling pop normally in an observer will cause a loop + // hide allows us to call pop without creating a dependency + runValue = hide(() => reactor.pop()) + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + }) +}) diff --git a/test/observer.test.js b/test/observer.test.js new file mode 100644 index 0000000..eced497 --- /dev/null +++ b/test/observer.test.js @@ -0,0 +1,263 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + // Reactor, + Observer, + // Signals, + Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + shuck +} from '../src/reactor.js' + +describe('Observer', () => { + describe('Initializes wrapping a function', () => { + it('should initialize with a function argument', () => new Observer(() => {})) + + it('should fail to initialize with no argument', () => { + assert.throws(() => new Observer(), { + name: 'Error', + message: 'Observer constructor requires exactly one argument' + }) + }) + + it('should fail to initialize with multiple arguments', () => { + assert.throws(() => new Observer(() => {}, () => {}), { + name: 'Error', + message: 'Observer constructor requires exactly one argument' + }) + }) + + it('should not run upon initialization', () => { + let triggerCount = 0 + // eslint-disable-next-line no-new + new Observer(() => { triggerCount += 1 }) + assert.strictEqual(triggerCount, 0) + }) + + it('should be an Observer object', () => { + const observer = new Observer(() => {}) + assert(observer instanceof Observer) + }) + + describe('Fails to initialize with an argument that is not a Function', () => { + it('should fail to initialize with a string', () => { + assert.throws(() => new Observer('foo'), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a number', () => { + assert.throws(() => new Observer(123), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a bigint', () => { + assert.throws(() => new Observer(123456789123456789n), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with a symbol', () => { + assert.throws(() => new Observer(Symbol('foo')), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with true', () => { + assert.throws(() => new Observer(true), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with false', () => { + assert.throws(() => new Observer(false), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with zero', () => { + assert.throws(() => new Observer(0), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an empty string', () => { + assert.throws(() => new Observer(''), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with null', () => { + assert.throws(() => new Observer(null), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with undefined', () => { + assert.throws(() => new Observer(undefined), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an Object', () => { + assert.throws(() => new Observer({}), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + it('should fail to initialize with an Array', () => { + assert.throws(() => new Observer([]), { + name: 'TypeError', + message: 'Cannot create observer with a non-function' + }) + }) + }) + }) + + describe('Can be used like a normal function', () => { + it('should be callable', () => { + const observer = new Observer(() => {}) + observer() + }) + + it('should return the function return value', () => { + const observer = new Observer(() => 'foo') + assert.strictEqual(observer(), 'foo') + }) + + it('should be callable with arguments', () => { + const observer = new Observer((a, b, c) => { + return a + b + c + }) + assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') + }) + + it('should have access to its arguments array', () => { + const observer = new Observer(function () { + let output = '' + for (const arg of arguments) { + output += arg + } + return output + }) + assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') + }) + + it('should have access to its this context', () => { + let context + const object = {} + const observer = new Observer(function () { + context = this + }) + object.observer = observer + object.observer() + assert.strictEqual(context, object) + }) + + it('should be able to use bind to create a new function with this context and arguments', () => { + let context + const object = { foo: 42 } + const observer = new Observer(function (a) { + context = this + return this.foo + a + }) + const boundFunction = observer.bind(object, 10) + const result = boundFunction() + assert.strictEqual(context, object) + assert.strictEqual(result, 52) + }) + + it('should be able to use call to execute with specified this context and arguments', () => { + const object = { foo: 'bar' } + const observer = new Observer(function (a, b) { + return this.foo + a + b + }) + const result = observer.call(object, 'baz', 'qux') + assert.strictEqual(result, 'barbazqux') + }) + + it('should be able to use apply to execute with specified this context and arguments', () => { + const object = { foo: 'bar' } + const observer = new Observer(function (a, b) { + return this.foo + a + b + }) + const result = observer.apply(object, ['baz', 'qux']) + assert.strictEqual(result, 'barbazqux') + }) + + it('should be usable as a constructor', () => { + const DummyClass = new Observer(function (arg) { + this.foo = 'bar' + arg + return this + }) + const instance = new DummyClass('baz') + assert(instance instanceof DummyClass) + assert.strictEqual(instance.foo, 'barbaz') + }) + + it('should be a type of Function', () => { + const observer = new Observer(() => {}) + assert(observer instanceof Function) + assert(typeof observer === 'function') + }) + }) + + describe('Wraps returned Object values in Reactors', () => { + it('', () => { + const object = {} + const observer = new Observer(() => object) + const result = observer() + assert(Reactors.has(result)) + assert.notStrictEqual(result, object) + assert.strictEqual(shuck(result), object) + }) + }) + + describe('Exposes the wrapped function through execute', () => { + it('', () => { + const dummyFunction = function () {} + const observer = new Observer(dummyFunction) + assert.strictEqual(observer.execute, dummyFunction) + }) + }) + + describe('Exposes the last derived value through value', () => { + it('should keep the last derived value for primitive values', () => { + let counter = 0 + const dummyFunction = () => (counter += 1) + const observer = new Observer(dummyFunction) + let result = observer() + assert.strictEqual(result, 1) + assert.strictEqual(observer.value, 1) + assert.strictEqual(result, observer.value) + result = observer() + assert.strictEqual(result, 2) + assert.strictEqual(observer.value, 2) + assert.strictEqual(result, observer.value) + }) + + it('should keep the last derived value for Object values', () => { + let counter = 0 + const dummyFunction = () => { + counter += 1 + return { count: counter } + } + const observer = new Observer(dummyFunction) + let result = observer() + assert.strictEqual(JSON.stringify(result), '{"count":1}') + assert.strictEqual(JSON.stringify(observer.value), '{"count":1}') + assert.strictEqual(result, observer.value) + result = observer() + assert.strictEqual(JSON.stringify(result), '{"count":2}') + assert.strictEqual(JSON.stringify(observer.value), '{"count":2}') + assert.strictEqual(result, observer.value) + }) + }) +}) diff --git a/test/reactivity.test.js b/test/reactivity.test.js new file mode 100644 index 0000000..a0f7e11 --- /dev/null +++ b/test/reactivity.test.js @@ -0,0 +1,864 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + Signal, + Reactor, + Observer, + // Signals, + // Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + shuck +} from '../src/reactor.js' + +describe('Reactivity', () => { + describe('Observers do not trigger before being run', () => { + it('should not trigger if reading a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + // eslint-disable-next-line no-new + new Observer(() => { + runCount += 1 + runValue = signal() + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + assert.strictEqual(signal(), 'foo') + signal('bar') + assert.strictEqual(signal(), 'bar') + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + }) + it('should not trigger if reading a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + // eslint-disable-next-line no-new + new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + assert.strictEqual(reactor.foo, 'bar') + reactor.foo = 'baz' + assert.strictEqual(reactor.foo, 'baz') + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + }) + }) + + describe('Observers after being run should form dependencies and trigger on their updates', () => { + it('should be setup to trigger if reading a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + new Observer(() => { + runCount += 1 + runValue = signal() + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + assert.strictEqual(signal(), 'foo') + signal('bar') + assert.strictEqual(signal(), 'bar') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + }) + + it('should be setup to trigger if reading a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.foo, 'bar') + reactor.foo = 'baz' + assert.strictEqual(reactor.foo, 'baz') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + + it('should be setup to trigger if reading another Observer', () => { + let runCount = 0 + let runValue + const headObserver = new Observer((x) => x) + const tailObserver = new Observer(() => { + runCount += 1 + runValue = headObserver.value + }) + tailObserver() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + headObserver('foo') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + }) + // TODO trigger if reading another Observer via observer() instead of observer.value + + it('should be setup to trigger when using Object.keys', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + new Observer(() => { + runCount += 1 + runValue = Object.keys(reactor) + })() + assert.strictEqual(runCount, 1) + assert.deepEqual(runValue, ['foo']) + reactor.baz = 'qux' + assert.strictEqual(runCount, 2) + assert.deepEqual(runValue, ['foo', 'baz']) + }) + + it('should be setup to trigger when using the in operator', () => { + let runCount = 0 + let runValue + const reactor = new Reactor() + new Observer(() => { + runCount += 1 + runValue = ('foo' in reactor) + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + reactor.foo = 'bar' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, true) + }) + + it('should get triggered by defineProperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + Object.defineProperty(reactor, 'foo', { + get () { return 'baz' } + }) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + + it('should get triggered by deleteProperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + delete reactor.foo + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, undefined) + }) + + it('should be able to be triggered repeatedly', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.foo = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + reactor.foo = 'qux' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + reactor.foo = 'moo' + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'moo') + reactor.foo = 'mip' + assert.strictEqual(runCount, 5) + assert.strictEqual(runValue, 'mip') + }) + }) + + describe('Observers rebuild dependencies each time they trigger', () => { + it('should build new dependencies on retriggers', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] + }) + // On initial run it should be depndent on foo and not baz + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify there is no dependency on baz + reactor.baz = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Switch sets new dependency on baz + reactor.switch = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Verify dependency on baz is working + reactor.baz = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'mip') + }) + it('should break old dependencies when no longer needed', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] + }) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify dependency on foo is working + reactor.foo = 'moo' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Switch builds new dependencies + reactor.switch = 'baz' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + // Verify dependency on foo is broken + reactor.foo = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + }) + }) + + describe('Observers trigger on subproperty updates', () => { + it('should trigger even if a relevant subproperty of its dependency is updated', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: {} + }) + const observer = new Observer(() => { + runCount += 1 + // Dependency is only explicitly on reactor.foo + // But depends implicitly on all its subproperties + runValue = JSON.stringify(reactor.foo) + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, '{}') + // This new property is relevant to the observer so should trigger + reactor.foo.bar = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, '{"bar":"baz"}') + }) + + it('should not trigger if an irrelevant subproperty of its dependency is updated', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: {} + }) + const observer = new Observer(() => { + runCount += 1 + // Dependency is only explicitly on reactor.foo + runValue = Array.isArray(reactor.foo) + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + // The new property is irrelevant to the observer checking isArray so should not trigger + reactor.foo.bar = 'baz' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, false) + }) + + it('should trigger if a subproperty is updated when depending on it directly', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + reactor.foo.bar = 'qux' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + }) + + it('should trigger if a parent property is updated when depending on its subproperty', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + // Instead of just updating bar we replace the whole object + reactor.foo = { bar: 'qux' } + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + }) + + it('should not trigger if a sibling property of its dependency is updated', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.foo.bar + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + // The new sibling property is irrelevant to the observer so should not trigger + reactor.foo.qux = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') + }) + + describe('Gets triggered by array update methods', () => { + it('should get triggered by array index assignment', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor[1] = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + assert.deepEqual(reactor, ['foo', 'baz']) + }) + + it('should get triggered by array push', () => { + let runCount = 0 + let runValue + const reactor = new Reactor([]) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + reactor.push('foo') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + }) + + it('should get triggered by array pop', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.length - 1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.pop() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + assert.strictEqual(reactor.length, 1) + }) + + it('should get triggered by array shift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.shift() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 1) + }) + + it('should get triggered by array unshift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.unshift('bar') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 2) + }) + + it('should get triggered by array splice', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.splice(1, 1, 'qux') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.strictEqual(reactor.length, 3) + }) + + it('should get triggered by array sort', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['c', 'a', 'b']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.sort() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'c']) + }) + + it('should get triggered by array reverse', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a') + reactor.reverse() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'c') + assert.deepEqual(reactor, ['c', 'b', 'a']) + }) + + it('should get triggered by array fill', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.fill('qux', 1, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.deepEqual(reactor, ['foo', 'qux', 'baz']) + }) + + it('should get triggered by array copyWithin', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c', 'd', 'e']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[2] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.copyWithin(2, 0, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'a', 'b', 'e']) + }) + + it('should get triggered by changing the array length property', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 1 + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 1) + assert.deepEqual(reactor, ['foo']) + }) + + it('should not get triggered by setting the array length property to its current value', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 2 + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + assert.deepEqual(reactor, ['foo', 'bar']) + }) + + it('should get triggered by array operations that change length', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 3) + + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 4) + + reactor.pop() + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 3) + + reactor.splice(0, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 1) + }) + + it('should get triggered by array operations that modify existing elements', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'b') + + // Modify existing element + reactor[1] = 'x' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'x') + + // Use splice to modify + reactor.splice(1, 1, 'y') + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'y') + + // Use fill to modify + reactor.fill('z', 1, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'z') + }) + + it('should be able to be triggered repeatedly by multiple array operations', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.join(',') + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a,b,c') + + // Multiple operations should trigger observer multiple times + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a,b,c,d') + + reactor.splice(1, 1) + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'a,c,d') + + reactor.reverse() + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'd,c,a') + }) + }) + }) + + describe('Observers are triggered only once per update ', () => { + it('should trigger only once despite multiple identical dependencies', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + reactor.foo + reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'barbarbar') + reactor.foo = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bazbazbaz') + }) + it('should trigger only once despite multiple different dependencies', () => { + let counter = 0 + let getTracker + let stringifyTracker + let valuesTracker + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + counter += 1 + getTracker = reactor.foo + stringifyTracker = JSON.stringify(reactor) + valuesTracker = Object.values(reactor) + })() + assert.equal(counter, 1) + assert.strictEqual(getTracker, 'bar') + assert.strictEqual(stringifyTracker, '{"foo":"bar"}') + assert.deepEqual(valuesTracker, ['bar']) + reactor.foo = 'baz' + assert.equal(counter, 2) + assert.strictEqual(getTracker, 'baz') + assert.strictEqual(stringifyTracker, '{"foo":"baz"}') + assert.deepEqual(valuesTracker, ['baz']) + }) + it('should trigger only once for native methods attached to the Reactor with multiple changes on itself', () => { + let runCount = 0 + let firstTracker + let lengthTracker + const reactor = new Reactor([]) + new Observer(() => { + runCount += 1 + firstTracker = reactor[0] + lengthTracker = reactor.length + })() + assert.equal(runCount, 1) + assert.equal(lengthTracker, 0) + assert.equal(firstTracker, undefined) + reactor.push('bar') + assert.equal(runCount, 2) + assert.equal(lengthTracker, 1) + assert.equal(firstTracker, 'bar') + }) + it('should trigger only once for custom methods attached to the Reactor with multiple changes on itself', () => { + let runCount = 0 + let fooTracker + let bazTracker + const reactor = new Reactor({ + foo: 'bar', + baz: 'qux' + }) + new Observer(() => { + runCount += 1 + fooTracker = reactor.foo + bazTracker = reactor.baz + })() + assert.equal(runCount, 1) + assert.equal(fooTracker, 'bar') + assert.equal(bazTracker, 'qux') + reactor.change = function () { + this.foo = this.foo + 'bar' + this.baz = this.baz + 'qux' + } + reactor.change() + assert.equal(runCount, 2) + assert.equal(fooTracker, 'barbar') + assert.equal(bazTracker, 'quxqux') + }) + }) + + describe('Observers are not triggered when setting an identical value', () => { + it('should not redundantly trigger on setting an identical primitive value on a Signal', () => { + let runCount = 0 + let runValue + const signal = new Signal('foo') + new Observer(() => { + runCount += 1 + runValue = signal() + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + signal('foo') + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + }) + it('should not redundantly trigger on setting an identical primitive value on a Reactor', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + foo: 'bar' + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.foo = 'bar' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + }) + it('should not redundantly trigger on setting an identical primitive value on an Observer', () => { + let runCount = 0 + let runValue + const headObserver = new Observer((x) => x) + const tailObserver = new Observer(() => { + runCount += 1 + runValue = headObserver.value + }) + headObserver('foo') + tailObserver() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + headObserver('foo') + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + }) + it('should not redundantly trigger on setting an identical object value', () => { + let runCount = 0 + let runValue + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + reactor.foo = dummyObject + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + }) + it('should trigger on setting a similar but different object', () => { + let runCount = 0 + let runValue + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + new Observer(() => { + runCount += 1 + runValue = reactor.foo + })() + assert.strictEqual(runCount, 1) + assert.strictEqual(shuck(runValue), dummyObject) + reactor.foo = {} + assert.strictEqual(runCount, 2) + assert.notStrictEqual(shuck(runValue), dummyObject) + }) + }) +}) diff --git a/test/reactor.test.js b/test/reactor.test.js new file mode 100644 index 0000000..29389c4 --- /dev/null +++ b/test/reactor.test.js @@ -0,0 +1,269 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + // Signal, + Reactor, + // Observer, + // Signals, + Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + shuck +} from '../src/reactor.js' + +describe('Reactor', () => { + describe('Initialization', () => { + describe('Initializes with no argument returning a new Reactor wrapped Object', () => { + it('should initialize with no argument', () => new Reactor()) + it('should return a Reactor Object', () => { + const reactor = new Reactor() + assert(Reactors.has(reactor)) + }) + }) + + describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { + it('should initialize with an Object', () => new Reactor({})) + it('should initialize with an Function', () => new Reactor(() => {})) + it('should initialize with a Promise') // TODO: Figure out promises + it('should return a Reactor Object wrapping the original', () => { + const object = {} + const reactor = new Reactor(object) + assert(Reactors.has(reactor)) + assert.notEqual(reactor, object) + assert.strictEqual(shuck(reactor), object) + }) + describe('Edge cases', () => { + it('should not wrap a Reactor around an existing Reactor', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(reactor) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) + + it('should return the same Reactor when wrapping the same object', () => { + const object = {} + const reactor = new Reactor(object) + const reactor2 = new Reactor(object) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor, reactor2) + assert.strictEqual(shuck(reactor), shuck(reactor2)) + assert.strictEqual(shuck(reactor), object) + assert.strictEqual(shuck(reactor2), object) + }) + }) + }) + + describe('Fails to initialize with values which are not Objects', () => { + it('should fail to initialize with a string', () => { + assert.throws(() => new Reactor('foo'), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with a number', () => { + assert.throws(() => new Reactor(123), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with a bigint', () => { + assert.throws(() => new Reactor(123456789123456789n), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with a symbol', () => { + assert.throws(() => new Reactor(Symbol('foo')), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with true', () => { + assert.throws(() => new Reactor(true), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with false', () => { + assert.throws(() => new Reactor(false), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with zero', () => { + assert.throws(() => new Reactor(0), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with an empty string', () => { + assert.throws(() => new Reactor(''), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with null', () => { + assert.throws(() => new Reactor(null), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + it('should fail to initialize with undefined', () => { + assert.throws(() => new Reactor(undefined), { + name: 'TypeError', + message: 'Reactor source must be an Object' + }) + }) + }) + + describe('Edge cases', () => { + it('should fail to initialize with multiple arguments', () => { + assert.throws(() => new Reactor({}, {}), { + name: 'Error', + message: 'Reactor constructor takes at most one argument' + }) + }) + }) + }) + + describe('Reads properties from the proxied Object', () => { + it('should return primitive values from the proxied Object', () => { + const reactor = new Reactor({ + foo: 'bar' + }) + assert.strictEqual(reactor.foo, 'bar') + }) + it('should return object values from the proxied Object as a Reactor', () => { + const dummyObject = {} + const reactor = new Reactor({ + foo: dummyObject + }) + const readResult = reactor.foo + assert.notStrictEqual(dummyObject, readResult) + assert(Reactors.has(readResult)) + assert.strictEqual(dummyObject, shuck(readResult)) + }) + }) + + describe('Writes through to the proxied Object when assigning properties', () => { + it('should write values through to the proxied Object', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + reactor.foo = 'bar' + assert.strictEqual(proxiedObject.foo, 'bar') + assert.strictEqual(reactor.foo, 'bar') + }) + + it('should return the written values', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + const writeReturn = (reactor.foo = 'bar') + assert.strictEqual(writeReturn, 'bar') + }) + + it('should work with defineProperty', () => { + const proxiedObject = {} + const reactor = new Reactor(proxiedObject) + const result = Object.defineProperty(reactor, 'foo', { + get () { return 'bar' } + }) + assert.strictEqual(proxiedObject.foo, 'bar') + assert.strictEqual(reactor.foo, 'bar') + assert.strictEqual(result, reactor) + }) + + it('should not be writable if defineProperty sets writable to false', () => { + const reactor = new Reactor() + Object.defineProperty(reactor, 'foo', { + value: 'bar', + writable: false + }) + assert.strictEqual(reactor.foo, 'bar') + assert.throws(() => { + reactor.foo = 'baz' + }, { + name: 'TypeError', + message: "Cannot assign to read only property 'foo' of object '#'" + }) + }) + + it('should delete properties from the proxied Object', () => { + const proxiedObject = { foo: 'bar' } + const reactor = new Reactor(proxiedObject) + delete reactor.foo + assert.equal(proxiedObject.foo, undefined) + assert.equal(reactor.foo, undefined) + }) + }) + + describe('Works with native object properties and methods', () => { + it('should work with Array map', () => { + const reactor = new Reactor(['0', '1', '2']) + const result = reactor.map(x => 'this is ' + x) + assert.deepStrictEqual(result, ['this is 0', 'this is 1', 'this is 2']) + }) + + it('should be able to read native properties', () => { + const map = new Map() + const reactor = new Reactor(map) + // Normaly proxy wrapping will fail + // This check to see if we redirect the call `this` + // to the wrapped object instead of the wrapper when appropriate + assert.strictEqual(reactor.size, 0) + map.set('foo', 'bar') + assert.strictEqual(reactor.size, 1) + }) + + it('should be able to call native objects methods', () => { + const reactor = new Reactor(new Map()) + // Normal proxy wrapping will fail + // since .keys() cannot be called on a Proxy + const result = reactor.keys() + assert(typeof result[Symbol.iterator] === 'function') + }) + }) + + describe('Misc', () => { + it('should maintain instanceof checks for the wrapped object', () => { + const reactor = new Reactor([]) + assert(reactor instanceof Array) + // Sadly no way to also pass instanceof Reactor while maintaining the original instanceof checks + // An object can only have one class inheritance chain + // Would be great if we had some sort of in + }) + + it('should pass instanceof Reactor if no object was provided', () => { + const reactor = new Reactor() + assert(reactor instanceof Reactor) + }) + + it('should respect receiver this context for prototype inheritors', () => { + const reactor = new Reactor() + reactor.foo = 'bar' + Object.defineProperty(reactor, 'getFoo', { + get () { + return this.foo + } + }) + const inheritor = Object.create(reactor) + assert.strictEqual(inheritor.getFoo, 'bar') + // The inheritor is still using its inherited getter + // But it is being executed with the inheritor as `this` + // So it should return the inheritor's foo property instead of the original + inheritor.foo = 'qux' + assert.strictEqual(inheritor.getFoo, 'qux') + }) + }) +}) diff --git a/test/signal.test.js b/test/signal.test.js new file mode 100644 index 0000000..0c72b30 --- /dev/null +++ b/test/signal.test.js @@ -0,0 +1,268 @@ +/* eslint-env mocha */ +import assert from 'assert' +import { + Signal, + // Reactor, + // Observer, + // Signals, + Reactors, + // Observers, + // signalCoreExtractor, + // reactorCoreExtractor, + // observerCoreExtractor, + // hide, + // batch, + shuck +} from '../src/reactor.js' + +describe('Signal', () => { + describe('Initializes with a value', () => { + it('should initialize with a string', () => new Signal('foo')) + it('should initialize with a number', () => new Signal(123)) + it('should initialize with a bigint', () => new Signal(123456789123456789n)) + it('should initialize with a symbol', () => new Signal(Symbol('foo'))) + it('should initialize with true', () => new Signal(true)) + it('should initialize with false', () => new Signal(false)) + it('should initialize with zero', () => new Signal(0)) + it('should initialize with an empty string', () => new Signal('')) + it('should initialize with null', () => new Signal(null)) + it('should initialize with undefined', () => new Signal(undefined)) + it('should initialize with an Object', () => new Signal({})) + it('should initialize with a Function', () => new Signal(() => {})) + it('should initialize with a Promise') // TODO: Figure out promises + describe('Edge cases', () => { + it('should initialize with no arguments', () => new Signal()) + it('should not initialize with multiple arguments', () => { + assert.throws(() => new Signal('foo', 'bar'), { + name: 'Error', + message: 'Signal constructor takes at most one argument' + }) + }) + }) + }) + + describe('Returns the initial value when called with no arguments', () => { + it('should return the initial string', () => { + const value = 'foo' + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial number', () => { + const value = 123 + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial bigint', () => { + const value = 123456789123456789n + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial symbol', () => { + const value = Symbol('foo') + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial true', () => { + const value = true + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial false', () => { + const value = false + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial zero', () => { + const value = 0 + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial empty string', () => { + const value = '' + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial null', () => { + const value = null + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + it('should return the initial undefined', () => { + const value = undefined + const signal = new Signal(value) + assert.strictEqual(signal(), value) + }) + + describe('Object are returned wrapped in a Reactor', () => { + it('should return the initial Object wrapped in a Reactor', () => { + const dummyObject = {} + const signal = new Signal(dummyObject) + const result = signal() + assert(Reactors.has(result)) + assert.strictEqual(shuck(result), dummyObject) + }) + + it('should return the initial Function wrapped in a Reactor', () => { + const dummyFunction = () => {} + const signal = new Signal(dummyFunction) + const result = signal() + assert(Reactors.has(result)) + assert.strictEqual(shuck(result), dummyFunction) + }) + + // TODO figure out promises + it('should return the initial Promise') + }) + }) + + describe('Replaces the stored value when called with an argument and returns the new value', () => { + it('should update with a new string', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 'foo' + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with a new number', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 123 + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with a new bigint', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 123456789123456789n + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with a new symbol', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = Symbol('foo') + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with true', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = true + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with false', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = false + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with zero', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = 0 + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with an empty string', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = '' + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with null', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = null + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + it('should update with undefined', () => { + const signal = new Signal('foo') + assert.strictEqual(signal(), 'foo') + const value = undefined + const writeReturn = signal(value) + assert.strictEqual(writeReturn, value) + const readReturn = signal() + assert.strictEqual(readReturn, value) + }) + + describe('Objects are returned wrapped in a Reactor', () => { + it('should update with an Object', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) + + it('should update with a Function', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = () => {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) + + it('should update with a Promise') + }) + + describe('Edge cases', () => { + it('should throw an Error when called multiple arguments', () => { + const signal = new Signal() + assert.throws(() => signal(1, 2), { + name: 'Error', + message: 'Signal objects take at most one argument for writes and zero arguments for reads' + }) + }) + }) + }) +}) diff --git a/test/test.js b/test/test.js index 2c10d4c..c57a389 100644 --- a/test/test.js +++ b/test/test.js @@ -1,2370 +1,10 @@ /* eslint-env mocha */ -import assert from 'assert' -import { - Signal, - Reactor, - Observer, - // Signals, - Reactors, - // Observers, - // signalCoreExtractor, - // reactorCoreExtractor, - // observerCoreExtractor, - hide, - batch, - shuck -} from '../src/reactor.js' - -describe('Signal', () => { - describe('Initializes with a value', () => { - it('should initialize with a string', () => new Signal('foo')) - it('should initialize with a number', () => new Signal(123)) - it('should initialize with a bigint', () => new Signal(123456789123456789n)) - it('should initialize with a symbol', () => new Signal(Symbol('foo'))) - it('should initialize with true', () => new Signal(true)) - it('should initialize with false', () => new Signal(false)) - it('should initialize with zero', () => new Signal(0)) - it('should initialize with an empty string', () => new Signal('')) - it('should initialize with null', () => new Signal(null)) - it('should initialize with undefined', () => new Signal(undefined)) - it('should initialize with an Object', () => new Signal({})) - it('should initialize with a Function', () => new Signal(() => {})) - it('should initialize with a Promise') // TODO: Figure out promises - describe('Edge cases', () => { - it('should initialize with no arguments', () => new Signal()) - it('should not initialize with multiple arguments', () => { - assert.throws(() => new Signal('foo', 'bar'), { - name: 'Error', - message: 'Signal constructor takes at most one argument' - }) - }) - }) - }) - - describe('Returns the initial value when called with no arguments', () => { - it('should return the initial string', () => { - const value = 'foo' - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial number', () => { - const value = 123 - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial bigint', () => { - const value = 123456789123456789n - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial symbol', () => { - const value = Symbol('foo') - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial true', () => { - const value = true - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial false', () => { - const value = false - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial zero', () => { - const value = 0 - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial empty string', () => { - const value = '' - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial null', () => { - const value = null - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - it('should return the initial undefined', () => { - const value = undefined - const signal = new Signal(value) - assert.strictEqual(signal(), value) - }) - - describe('Object are returned wrapped in a Reactor', () => { - it('should return the initial Object wrapped in a Reactor', () => { - const dummyObject = {} - const signal = new Signal(dummyObject) - const result = signal() - assert(Reactors.has(result)) - assert.strictEqual(shuck(result), dummyObject) - }) - - it('should return the initial Function wrapped in a Reactor', () => { - const dummyFunction = () => {} - const signal = new Signal(dummyFunction) - const result = signal() - assert(Reactors.has(result)) - assert.strictEqual(shuck(result), dummyFunction) - }) - - // TODO figure out promises - it('should return the initial Promise') - }) - }) - - describe('Replaces the stored value when called with an argument and returns the new value', () => { - it('should update with a new string', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = 'foo' - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with a new number', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = 123 - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with a new bigint', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = 123456789123456789n - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with a new symbol', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = Symbol('foo') - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with true', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = true - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with false', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = false - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with zero', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = 0 - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with an empty string', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = '' - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with null', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = null - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - it('should update with undefined', () => { - const signal = new Signal('foo') - assert.strictEqual(signal(), 'foo') - const value = undefined - const writeReturn = signal(value) - assert.strictEqual(writeReturn, value) - const readReturn = signal() - assert.strictEqual(readReturn, value) - }) - - describe('Objects are returned wrapped in a Reactor', () => { - it('should update with an Object', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = {} - const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) - const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) - }) - - it('should update with a Function', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = () => {} - const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) - const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) - }) - - it('should update with a Promise') - }) - - describe('Edge cases', () => { - it('should throw an Error when called multiple arguments', () => { - const signal = new Signal() - assert.throws(() => signal(1, 2), { - name: 'Error', - message: 'Signal objects take at most one argument for writes and zero arguments for reads' - }) - }) - }) - }) -}) - -describe('Reactor', () => { - describe('Initialization', () => { - describe('Initializes with no argument returning a new Reactor wrapped Object', () => { - it('should initialize with no argument', () => new Reactor()) - it('should return a Reactor Object', () => { - const reactor = new Reactor() - assert(Reactors.has(reactor)) - }) - }) - - describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { - it('should initialize with an Object', () => new Reactor({})) - it('should initialize with an Function', () => new Reactor(() => {})) - it('should initialize with a Promise') // TODO: Figure out promises - it('should return a Reactor Object wrapping the original', () => { - const object = {} - const reactor = new Reactor(object) - assert(Reactors.has(reactor)) - assert.notEqual(reactor, object) - assert.strictEqual(shuck(reactor), object) - }) - describe('Edge cases', () => { - it('should not wrap a Reactor around an existing Reactor', () => { - const object = {} - const reactor = new Reactor(object) - const reactor2 = new Reactor(reactor) - assert(!Reactors.has(object)) - assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) - assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) - }) - - it('should return the same Reactor when wrapping the same object', () => { - const object = {} - const reactor = new Reactor(object) - const reactor2 = new Reactor(object) - assert(!Reactors.has(object)) - assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) - assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) - }) - }) - }) - - describe('Fails to initialize with values which are not Objects', () => { - it('should fail to initialize with a string', () => { - assert.throws(() => new Reactor('foo'), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with a number', () => { - assert.throws(() => new Reactor(123), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with a bigint', () => { - assert.throws(() => new Reactor(123456789123456789n), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with a symbol', () => { - assert.throws(() => new Reactor(Symbol('foo')), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with true', () => { - assert.throws(() => new Reactor(true), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with false', () => { - assert.throws(() => new Reactor(false), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with zero', () => { - assert.throws(() => new Reactor(0), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with an empty string', () => { - assert.throws(() => new Reactor(''), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with null', () => { - assert.throws(() => new Reactor(null), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - it('should fail to initialize with undefined', () => { - assert.throws(() => new Reactor(undefined), { - name: 'TypeError', - message: 'Reactor source must be an Object' - }) - }) - }) - - describe('Edge cases', () => { - it('should fail to initialize with multiple arguments', () => { - assert.throws(() => new Reactor({}, {}), { - name: 'Error', - message: 'Reactor constructor takes at most one argument' - }) - }) - }) - }) - - describe('Reads properties from the proxied Object', () => { - it('should return primitive values from the proxied Object', () => { - const reactor = new Reactor({ - foo: 'bar' - }) - assert.strictEqual(reactor.foo, 'bar') - }) - it('should return object values from the proxied Object as a Reactor', () => { - const dummyObject = {} - const reactor = new Reactor({ - foo: dummyObject - }) - const readResult = reactor.foo - assert.notStrictEqual(dummyObject, readResult) - assert(Reactors.has(readResult)) - assert.strictEqual(dummyObject, shuck(readResult)) - }) - }) - - describe('Writes through to the proxied Object when assigning properties', () => { - it('should write values through to the proxied Object', () => { - const proxiedObject = {} - const reactor = new Reactor(proxiedObject) - reactor.foo = 'bar' - assert.strictEqual(proxiedObject.foo, 'bar') - assert.strictEqual(reactor.foo, 'bar') - }) - - it('should return the written values', () => { - const proxiedObject = {} - const reactor = new Reactor(proxiedObject) - const writeReturn = (reactor.foo = 'bar') - assert.strictEqual(writeReturn, 'bar') - }) - - it('should work with defineProperty', () => { - const proxiedObject = {} - const reactor = new Reactor(proxiedObject) - const result = Object.defineProperty(reactor, 'foo', { - get () { return 'bar' } - }) - assert.strictEqual(proxiedObject.foo, 'bar') - assert.strictEqual(reactor.foo, 'bar') - assert.strictEqual(result, reactor) - }) - - it('should not be writable if defineProperty sets writable to false', () => { - const reactor = new Reactor() - Object.defineProperty(reactor, 'foo', { - value: 'bar', - writable: false - }) - assert.strictEqual(reactor.foo, 'bar') - assert.throws(() => { - reactor.foo = 'baz' - }, { - name: 'TypeError', - message: "Cannot assign to read only property 'foo' of object '#'" - }) - }) - - it('should delete properties from the proxied Object', () => { - const proxiedObject = { foo: 'bar' } - const reactor = new Reactor(proxiedObject) - delete reactor.foo - assert.equal(proxiedObject.foo, undefined) - assert.equal(reactor.foo, undefined) - }) - }) - - describe('Works with native object properties and methods', () => { - it('should work with Array map', () => { - const reactor = new Reactor(['0', '1', '2']) - const result = reactor.map(x => 'this is ' + x) - assert.deepStrictEqual(result, ['this is 0', 'this is 1', 'this is 2']) - }) - - it('should be able to read native properties', () => { - const map = new Map() - const reactor = new Reactor(map) - // Normaly proxy wrapping will fail - // This check to see if we redirect the call `this` - // to the wrapped object instead of the wrapper when appropriate - assert.strictEqual(reactor.size, 0) - map.set('foo', 'bar') - assert.strictEqual(reactor.size, 1) - }) - - it('should be able to call native objects methods', () => { - const reactor = new Reactor(new Map()) - // Normal proxy wrapping will fail - // since .keys() cannot be called on a Proxy - const result = reactor.keys() - assert(typeof result[Symbol.iterator] === 'function') - }) - }) - - describe('Misc', () => { - it('should maintain instanceof checks for the wrapped object', () => { - const reactor = new Reactor([]) - assert(reactor instanceof Array) - // Sadly no way to also pass instanceof Reactor while maintaining the original instanceof checks - // An object can only have one class inheritance chain - // Would be great if we had some sort of in - }) - - it('should pass instanceof Reactor if no object was provided', () => { - const reactor = new Reactor() - assert(reactor instanceof Reactor) - }) - - it('should respect receiver this context for prototype inheritors', () => { - const reactor = new Reactor() - reactor.foo = 'bar' - Object.defineProperty(reactor, 'getFoo', { - get () { - return this.foo - } - }) - const inheritor = Object.create(reactor) - assert.strictEqual(inheritor.getFoo, 'bar') - // The inheritor is still using its inherited getter - // But it is being executed with the inheritor as `this` - // So it should return the inheritor's foo property instead of the original - inheritor.foo = 'qux' - assert.strictEqual(inheritor.getFoo, 'qux') - }) - }) -}) - -describe('Observer', () => { - describe('Initializes wrapping a function', () => { - it('should initialize with a function argument', () => new Observer(() => {})) - - it('should fail to initialize with no argument', () => { - assert.throws(() => new Observer(), { - name: 'Error', - message: 'Observer constructor requires exactly one argument' - }) - }) - - it('should fail to initialize with multiple arguments', () => { - assert.throws(() => new Observer(() => {}, () => {}), { - name: 'Error', - message: 'Observer constructor requires exactly one argument' - }) - }) - - it('should not run upon initialization', () => { - let triggerCount = 0 - // eslint-disable-next-line no-new - new Observer(() => { triggerCount += 1 }) - assert.strictEqual(triggerCount, 0) - }) - - it('should be an Observer object', () => { - const observer = new Observer(() => {}) - assert(observer instanceof Observer) - }) - - describe('Fails to initialize with an argument that is not a Function', () => { - it('should fail to initialize with a string', () => { - assert.throws(() => new Observer('foo'), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with a number', () => { - assert.throws(() => new Observer(123), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with a bigint', () => { - assert.throws(() => new Observer(123456789123456789n), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with a symbol', () => { - assert.throws(() => new Observer(Symbol('foo')), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with true', () => { - assert.throws(() => new Observer(true), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with false', () => { - assert.throws(() => new Observer(false), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with zero', () => { - assert.throws(() => new Observer(0), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with an empty string', () => { - assert.throws(() => new Observer(''), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with null', () => { - assert.throws(() => new Observer(null), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with undefined', () => { - assert.throws(() => new Observer(undefined), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with an Object', () => { - assert.throws(() => new Observer({}), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - it('should fail to initialize with an Array', () => { - assert.throws(() => new Observer([]), { - name: 'TypeError', - message: 'Cannot create observer with a non-function' - }) - }) - }) - }) - - describe('Can be used like a normal function', () => { - it('should be callable', () => { - const observer = new Observer(() => {}) - observer() - }) - - it('should return the function return value', () => { - const observer = new Observer(() => 'foo') - assert.strictEqual(observer(), 'foo') - }) - - it('should be callable with arguments', () => { - const observer = new Observer((a, b, c) => { - return a + b + c - }) - assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') - }) - - it('should have access to its arguments array', () => { - const observer = new Observer(function () { - let output = '' - for (const arg of arguments) { - output += arg - } - return output - }) - assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') - }) - - it('should have access to its this context', () => { - let context - const object = {} - const observer = new Observer(function () { - context = this - }) - object.observer = observer - object.observer() - assert.strictEqual(context, object) - }) - - it('should be able to use bind to create a new function with this context and arguments', () => { - let context - const object = { foo: 42 } - const observer = new Observer(function (a) { - context = this - return this.foo + a - }) - const boundFunction = observer.bind(object, 10) - const result = boundFunction() - assert.strictEqual(context, object) - assert.strictEqual(result, 52) - }) - - it('should be able to use call to execute with specified this context and arguments', () => { - const object = { foo: 'bar' } - const observer = new Observer(function (a, b) { - return this.foo + a + b - }) - const result = observer.call(object, 'baz', 'qux') - assert.strictEqual(result, 'barbazqux') - }) - - it('should be able to use apply to execute with specified this context and arguments', () => { - const object = { foo: 'bar' } - const observer = new Observer(function (a, b) { - return this.foo + a + b - }) - const result = observer.apply(object, ['baz', 'qux']) - assert.strictEqual(result, 'barbazqux') - }) - - it('should be usable as a constructor', () => { - const DummyClass = new Observer(function (arg) { - this.foo = 'bar' + arg - return this - }) - const instance = new DummyClass('baz') - assert(instance instanceof DummyClass) - assert.strictEqual(instance.foo, 'barbaz') - }) - - it('should be a type of Function', () => { - const observer = new Observer(() => {}) - assert(observer instanceof Function) - assert(typeof observer === 'function') - }) - }) - - describe('Wraps returned Object values in Reactors', () => { - it('', () => { - const object = {} - const observer = new Observer(() => object) - const result = observer() - assert(Reactors.has(result)) - assert.notStrictEqual(result, object) - assert.strictEqual(shuck(result), object) - }) - }) - - describe('Exposes the wrapped function through execute', () => { - it('', () => { - const dummyFunction = function () {} - const observer = new Observer(dummyFunction) - assert.strictEqual(observer.execute, dummyFunction) - }) - }) - - describe('Exposes the last derived value through value', () => { - it('should keep the last derived value for primitive values', () => { - let counter = 0 - const dummyFunction = () => (counter += 1) - const observer = new Observer(dummyFunction) - let result = observer() - assert.strictEqual(result, 1) - assert.strictEqual(observer.value, 1) - assert.strictEqual(result, observer.value) - result = observer() - assert.strictEqual(result, 2) - assert.strictEqual(observer.value, 2) - assert.strictEqual(result, observer.value) - }) - - it('should keep the last derived value for Object values', () => { - let counter = 0 - const dummyFunction = () => { - counter += 1 - return { count: counter } - } - const observer = new Observer(dummyFunction) - let result = observer() - assert.strictEqual(JSON.stringify(result), '{"count":1}') - assert.strictEqual(JSON.stringify(observer.value), '{"count":1}') - assert.strictEqual(result, observer.value) - result = observer() - assert.strictEqual(JSON.stringify(result), '{"count":2}') - assert.strictEqual(JSON.stringify(observer.value), '{"count":2}') - assert.strictEqual(result, observer.value) - }) - }) -}) - -describe('Reactivity', () => { - describe('Observers do not trigger before being run', () => { - it('should not trigger if reading a Signal', () => { - let runCount = 0 - let runValue - const signal = new Signal('foo') - // eslint-disable-next-line no-new - new Observer(() => { - runCount += 1 - runValue = signal() - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - assert.strictEqual(signal(), 'foo') - signal('bar') - assert.strictEqual(signal(), 'bar') - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - }) - it('should not trigger if reading a Reactor', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ foo: 'bar' }) - // eslint-disable-next-line no-new - new Observer(() => { - runCount += 1 - runValue = reactor.foo - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - assert.strictEqual(reactor.foo, 'bar') - reactor.foo = 'baz' - assert.strictEqual(reactor.foo, 'baz') - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - }) - }) - - describe('Observers after being run should form dependencies and trigger on their updates', () => { - it('should be setup to trigger if reading a Signal', () => { - let runCount = 0 - let runValue - const signal = new Signal('foo') - new Observer(() => { - runCount += 1 - runValue = signal() - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - assert.strictEqual(signal(), 'foo') - signal('bar') - assert.strictEqual(signal(), 'bar') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bar') - }) - - it('should be setup to trigger if reading a Reactor', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ foo: 'bar' }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - assert.strictEqual(reactor.foo, 'bar') - reactor.foo = 'baz' - assert.strictEqual(reactor.foo, 'baz') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - }) - - it('should be setup to trigger if reading another Observer', () => { - let runCount = 0 - let runValue - const headObserver = new Observer((x) => x) - const tailObserver = new Observer(() => { - runCount += 1 - runValue = headObserver.value - }) - tailObserver() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) - headObserver('foo') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'foo') - }) - // TODO trigger if reading another Observer via observer() instead of observer.value - - it('should be setup to trigger when using Object.keys', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ foo: 'bar' }) - new Observer(() => { - runCount += 1 - runValue = Object.keys(reactor) - })() - assert.strictEqual(runCount, 1) - assert.deepEqual(runValue, ['foo']) - reactor.baz = 'qux' - assert.strictEqual(runCount, 2) - assert.deepEqual(runValue, ['foo', 'baz']) - }) - - it('should be setup to trigger when using the in operator', () => { - let runCount = 0 - let runValue - const reactor = new Reactor() - new Observer(() => { - runCount += 1 - runValue = ('foo' in reactor) - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - reactor.foo = 'bar' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, true) - }) - - it('should get triggered by defineProperty', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: 'bar' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - Object.defineProperty(reactor, 'foo', { - get () { return 'baz' } - }) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - }) - - it('should get triggered by deleteProperty', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: 'bar' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - delete reactor.foo - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, undefined) - }) - - it('should be able to be triggered repeatedly', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.foo = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - reactor.foo = 'qux' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'qux') - reactor.foo = 'moo' - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'moo') - reactor.foo = 'mip' - assert.strictEqual(runCount, 5) - assert.strictEqual(runValue, 'mip') - }) - }) - - describe('Observers rebuild dependencies each time they trigger', () => { - it('should build new dependencies on retriggers', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - switch: 'foo', - foo: 'bar', - baz: 'qux' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.switch] - }) - // On initial run it should be depndent on foo and not baz - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Verify there is no dependency on baz - reactor.baz = 'moo' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Switch sets new dependency on baz - reactor.switch = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'moo') - // Verify dependency on baz is working - reactor.baz = 'mip' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'mip') - }) - it('should break old dependencies when no longer needed', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - switch: 'foo', - foo: 'bar', - baz: 'qux' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.switch] - }) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Verify dependency on foo is working - reactor.foo = 'moo' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'moo') - // Switch builds new dependencies - reactor.switch = 'baz' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'qux') - // Verify dependency on foo is broken - reactor.foo = 'mip' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'qux') - }) - }) - - describe('Observers trigger on subproperty updates', () => { - it('should trigger even if a relevant subproperty of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: {} - }) - const observer = new Observer(() => { - runCount += 1 - // Dependency is only explicitly on reactor.foo - // But depends implicitly on all its subproperties - runValue = JSON.stringify(reactor.foo) - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, '{}') - // This new property is relevant to the observer so should trigger - reactor.foo.bar = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, '{"bar":"baz"}') - }) - - it('should not trigger if an irrelevant subproperty of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: {} - }) - const observer = new Observer(() => { - runCount += 1 - // Dependency is only explicitly on reactor.foo - runValue = Array.isArray(reactor.foo) - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - // The new property is irrelevant to the observer checking isArray so should not trigger - reactor.foo.bar = 'baz' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - }) - - it('should trigger if a subproperty is updated when depending on it directly', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - reactor.foo.bar = 'qux' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - }) - - it('should trigger if a parent property is updated when depending on its subproperty', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - // Instead of just updating bar we replace the whole object - reactor.foo = { bar: 'qux' } - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - }) - - it('should not trigger if a sibling property of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - // The new sibling property is irrelevant to the observer so should not trigger - reactor.foo.qux = 'moo' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - }) - - describe('Gets triggered by array update methods', () => { - it('should get triggered by array index assignment', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor[1] = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - assert.deepEqual(reactor, ['foo', 'baz']) - }) - - it('should get triggered by array push', () => { - let runCount = 0 - let runValue - const reactor = new Reactor([]) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) - reactor.push('foo') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'foo') - }) - - it('should get triggered by array pop', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.length - 1] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.pop() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'foo') - assert.strictEqual(reactor.length, 1) - }) - - it('should get triggered by array shift', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - reactor.shift() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bar') - assert.strictEqual(reactor.length, 1) - }) - - it('should get triggered by array unshift', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - reactor.unshift('bar') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bar') - assert.strictEqual(reactor.length, 2) - }) - - it('should get triggered by array splice', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar', 'baz']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.splice(1, 1, 'qux') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - assert.strictEqual(reactor.length, 3) - }) - - it('should get triggered by array sort', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['c', 'a', 'b']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'c') - reactor.sort() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a') - assert.deepEqual(reactor, ['a', 'b', 'c']) - }) - - it('should get triggered by array reverse', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'a') - reactor.reverse() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'c') - assert.deepEqual(reactor, ['c', 'b', 'a']) - }) - - it('should get triggered by array fill', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar', 'baz']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.fill('qux', 1, 2) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - assert.deepEqual(reactor, ['foo', 'qux', 'baz']) - }) - - it('should get triggered by array copyWithin', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c', 'd', 'e']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[2] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'c') - reactor.copyWithin(2, 0, 2) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a') - assert.deepEqual(reactor, ['a', 'b', 'a', 'b', 'e']) - }) - - it('should get triggered by changing the array length property', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - reactor.length = 1 - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 1) - assert.deepEqual(reactor, ['foo']) - }) - - it('should not get triggered by setting the array length property to its current value', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - reactor.length = 2 - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - assert.deepEqual(reactor, ['foo', 'bar']) - }) - - it('should get triggered by array operations that change length', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 3) - - reactor.push('d') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 4) - - reactor.pop() - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 3) - - reactor.splice(0, 2) - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 1) - }) - - it('should get triggered by array operations that modify existing elements', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'b') - - // Modify existing element - reactor[1] = 'x' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'x') - - // Use splice to modify - reactor.splice(1, 1, 'y') - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'y') - - // Use fill to modify - reactor.fill('z', 1, 2) - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'z') - }) - - it('should be able to be triggered repeatedly by multiple array operations', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.join(',') - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'a,b,c') - - // Multiple operations should trigger observer multiple times - reactor.push('d') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a,b,c,d') - - reactor.splice(1, 1) - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'a,c,d') - - reactor.reverse() - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'd,c,a') - }) - }) - }) - - describe('Observers are triggered only once per update ', () => { - it('should trigger only once despite multiple identical dependencies', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo + reactor.foo + reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'barbarbar') - reactor.foo = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bazbazbaz') - }) - it('should trigger only once despite multiple different dependencies', () => { - let counter = 0 - let getTracker - let stringifyTracker - let valuesTracker - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - counter += 1 - getTracker = reactor.foo - stringifyTracker = JSON.stringify(reactor) - valuesTracker = Object.values(reactor) - })() - assert.equal(counter, 1) - assert.strictEqual(getTracker, 'bar') - assert.strictEqual(stringifyTracker, '{"foo":"bar"}') - assert.deepEqual(valuesTracker, ['bar']) - reactor.foo = 'baz' - assert.equal(counter, 2) - assert.strictEqual(getTracker, 'baz') - assert.strictEqual(stringifyTracker, '{"foo":"baz"}') - assert.deepEqual(valuesTracker, ['baz']) - }) - it('should trigger only once for native methods attached to the Reactor with multiple changes on itself', () => { - let runCount = 0 - let firstTracker - let lengthTracker - const reactor = new Reactor([]) - new Observer(() => { - runCount += 1 - firstTracker = reactor[0] - lengthTracker = reactor.length - })() - assert.equal(runCount, 1) - assert.equal(lengthTracker, 0) - assert.equal(firstTracker, undefined) - reactor.push('bar') - assert.equal(runCount, 2) - assert.equal(lengthTracker, 1) - assert.equal(firstTracker, 'bar') - }) - it('should trigger only once for custom methods attached to the Reactor with multiple changes on itself', () => { - let runCount = 0 - let fooTracker - let bazTracker - const reactor = new Reactor({ - foo: 'bar', - baz: 'qux' - }) - new Observer(() => { - runCount += 1 - fooTracker = reactor.foo - bazTracker = reactor.baz - })() - assert.equal(runCount, 1) - assert.equal(fooTracker, 'bar') - assert.equal(bazTracker, 'qux') - reactor.change = function () { - this.foo = this.foo + 'bar' - this.baz = this.baz + 'qux' - } - reactor.change() - assert.equal(runCount, 2) - assert.equal(fooTracker, 'barbar') - assert.equal(bazTracker, 'quxqux') - }) - }) - - describe('Observers are not triggered when setting an identical value', () => { - it('should not redundantly trigger on setting an identical primitive value on a Signal', () => { - let runCount = 0 - let runValue - const signal = new Signal('foo') - new Observer(() => { - runCount += 1 - runValue = signal() - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - signal('foo') - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - }) - it('should not redundantly trigger on setting an identical primitive value on a Reactor', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: 'bar' - }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.foo = 'bar' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - }) - it('should not redundantly trigger on setting an identical primitive value on an Observer', () => { - let runCount = 0 - let runValue - const headObserver = new Observer((x) => x) - const tailObserver = new Observer(() => { - runCount += 1 - runValue = headObserver.value - }) - headObserver('foo') - tailObserver() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - headObserver('foo') - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - }) - it('should not redundantly trigger on setting an identical object value', () => { - let runCount = 0 - let runValue - const dummyObject = {} - const reactor = new Reactor({ - foo: dummyObject - }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(shuck(runValue), dummyObject) - reactor.foo = dummyObject - assert.strictEqual(runCount, 1) - assert.strictEqual(shuck(runValue), dummyObject) - }) - it('should trigger on setting a similar but different object', () => { - let runCount = 0 - let runValue - const dummyObject = {} - const reactor = new Reactor({ - foo: dummyObject - }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(shuck(runValue), dummyObject) - reactor.foo = {} - assert.strictEqual(runCount, 2) - assert.notStrictEqual(shuck(runValue), dummyObject) - }) - }) -}) - -describe('Batching', () => { - // TODO add test and functionality for batch parameter validation - it('should delay and combine observer triggers within a batch block', () => { - const reactor = new Reactor() - let runCount = 0 - let runValue - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) - batch(() => { - reactor.foo = 'bleep' - assert.strictEqual(runCount, 1) - reactor.foo = 'bloop' - assert.strictEqual(runCount, 1) - reactor.foo = 'blarp' - assert.strictEqual(runCount, 1) - }) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'blarp') - }) - - it('should nest batch blocks with no consequence', () => { - const reactor = new Reactor() - let runCount = 0 - let runValue - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) - batch(() => { - reactor.foo = 'bleep' - assert.strictEqual(runCount, 1) - reactor.foo = 'bloop' - assert.strictEqual(runCount, 1) - reactor.foo = 'blarp' - assert.strictEqual(runCount, 1) - batch(() => { - reactor.foo = 'bink' - assert.strictEqual(runCount, 1) - reactor.foo = 'bonk' - assert.strictEqual(runCount, 1) - reactor.foo = 'bup' - assert.strictEqual(runCount, 1) - }) - }) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bup') - }) - - // What should happen when a batch hits an error? - // Fail out straight away? (unsetting batcher of course) - // Or should it collect the error and try to trigger the observers it got to so far? - // The later might seem like a fail forward action, but it's actually more consistent - // since the semantic we have is that writing to a signal triggers all observers synchronously - // It is more consistent with what happens outside of the batch block - it('should trigger dependent observers from the batch block even if there is an error', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ foo: 'bar' }) - new Observer(() => { - runCount += 1 - runValue = reactor.foo - })() - assert.throws(() => { - batch(() => { - reactor.foo = 'baz' - throw new Error('dummy error') - }) - }, { - name: 'Error', - message: 'dummy error' - }) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - }) - - // -> a -> c - // -> b -> c - // Used to be batch would trigger a and b together - // which would then double trigger c - // Ideally a batch would only trigger c once - it('should consolidate redundant downstream triggers', () => { - const reactor = new Reactor({ - a: 'foo', - b: 'bar' - }) - let runCountA = 0 - let runCountB = 0 - let runCountC = 0 - const observerA = new Observer(() => { - runCountA += 1 - return reactor.a - }) - observerA() - const observerB = new Observer(() => { - runCountB += 1 - return reactor.b - }) - observerB() - const observerC = new Observer(() => { - runCountC += 1 - return observerA.value + observerB.value - }) - observerC() - assert.strictEqual(runCountA, 1) - assert.strictEqual(runCountB, 1) - assert.strictEqual(runCountC, 1) - batch(() => { - reactor.a = 'baz' - reactor.b = 'qux' - }) - assert.strictEqual(runCountA, 2) - assert.strictEqual(runCountB, 2) - // Without batch this would be triggered an additional time - // Once from observerA and another time from observerB - // With batch these are consolidated into a single trigger - assert.strictEqual(runCountC, 2) - }) - - // -> a -> d - // -> b -> c -> d - // In this case you might need to trigger d twice by the discover process - // the batch first queues up [ab] - // then it discovers [abdc] - // after triggering d it discovers that it needs to update c again [abdcd] - // If we don't queue d to be be triggered again, it will have an outdated value for c - // Anyway around it? - it('should not skip essential downstream triggers', () => { - const reactor = new Reactor({ - a: 'foo', - b: 'bar' - }) - const observerA = new Observer(() => { - return reactor.a - }) - observerA() - const observerB = new Observer(() => { - return reactor.b - }) - observerB() - const observerC = new Observer(() => { - return observerB.value - }) - observerC() - const observerD = new Observer(() => { - return observerA.value + observerC.value - }) - observerD() - assert.strictEqual(observerD.value, 'foobar') - batch(() => { - reactor.a = 'baz' - reactor.b = 'qux' - }) - assert.strictEqual(observerD.value, 'bazqux') - }) - - // foo -> a -> c - // foo -> b -> c - // Auto batching for signals should trigger c once - it('should automatically batch Signal writes', () => { - const signal = new Signal('foo') - let runCountA = 0 - let runCountB = 0 - let runCountC = 0 - const observerA = new Observer(() => { - runCountA += 1 - return signal() + 'A' - }) - observerA() - const observerB = new Observer(() => { - runCountB += 1 - return signal() + 'B' - }) - observerB() - const observerC = new Observer(() => { - runCountC += 1 - return observerA.value + observerB.value - }) - observerC() - assert.strictEqual(runCountA, 1) - assert.strictEqual(runCountB, 1) - assert.strictEqual(runCountC, 1) - assert.strictEqual(observerA.value, 'fooA') - assert.strictEqual(observerB.value, 'fooB') - assert.strictEqual(observerC.value, 'fooAfooB') - signal('bar') - assert.strictEqual(runCountA, 2) - assert.strictEqual(runCountB, 2) - // If not auto batched this would be 3 - // As observerC would be trigger from both A and B - assert.strictEqual(runCountC, 2) - assert.strictEqual(observerA.value, 'barA') - assert.strictEqual(observerB.value, 'barB') - assert.strictEqual(observerC.value, 'barAbarB') - }) - // This should be the same as Signal since Observer values are a Signal - // But testing it anyway for completeness - it('should automatically batch Observer writes', () => { - const rootObserver = new Observer((x) => x) - rootObserver('foo') - let runCountA = 0 - let runCountB = 0 - let runCountC = 0 - const observerA = new Observer(() => { - runCountA += 1 - return rootObserver.value + 'A' - }) - observerA() - const observerB = new Observer(() => { - runCountB += 1 - return rootObserver.value + 'B' - }) - observerB() - const observerC = new Observer(() => { - runCountC += 1 - return observerA.value + observerB.value - }) - observerC() - assert.strictEqual(runCountA, 1) - assert.strictEqual(runCountB, 1) - assert.strictEqual(runCountC, 1) - assert.strictEqual(observerA.value, 'fooA') - assert.strictEqual(observerB.value, 'fooB') - assert.strictEqual(observerC.value, 'fooAfooB') - rootObserver('bar') - assert.strictEqual(runCountA, 2) - assert.strictEqual(runCountB, 2) - // If not auto batched this would be 3 - // As observerC would be trigger from both A and B - assert.strictEqual(runCountC, 2) - assert.strictEqual(observerA.value, 'barA') - assert.strictEqual(observerB.value, 'barB') - assert.strictEqual(observerC.value, 'barAbarB') - }) - - it('should automatically batch Reactor writes', () => { - let runCount = 0 - const reactor = new Reactor(['foo', 'bar']) - new Observer(() => { - runCount += 1 - return JSON.stringify(reactor) - })() - assert.strictEqual(runCount, 1) - // Call pop because it's a compound operation - reactor.pop() - assert.strictEqual(runCount, 2) - }) -}) - -describe('Hiding', () => { - // TODO add test and functionality for hide parameter validation - - it('should not create dependencies inside hide block', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerRunCount = 0 - let innerRunCount = 0 - let outerRunValue - let innerRunValue - new Observer(() => { - outerRunCount += 1 - outerRunValue = reactor.outer - hide(() => { - innerRunCount += 1 - innerRunValue = reactor.inner - }) - })() - assert.strictEqual(outerRunCount, 1) - assert.strictEqual(innerRunCount, 1) - assert.strictEqual(outerRunValue, 'foo') - assert.strictEqual(innerRunValue, 'bar') - reactor.inner = 'baz' - assert.strictEqual(outerRunCount, 1) - assert.strictEqual(innerRunCount, 1) - assert.strictEqual(outerRunValue, 'foo') - assert.strictEqual(innerRunValue, 'bar') - reactor.outer = 'moo' - assert.strictEqual(outerRunCount, 2) - assert.strictEqual(innerRunCount, 2) - assert.strictEqual(outerRunValue, 'moo') - assert.strictEqual(innerRunValue, 'baz') - }) - - // TODO should hide blocks be nestable? - - it('should return the result of the hide block', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerRunCount = 0 - let innerRunCount = 0 - let outerRunValue - let innerRunValue - new Observer(() => { - outerRunCount += 1 - outerRunValue = reactor.outer - innerRunValue = hide(() => { - innerRunCount += 1 - return reactor.inner - }) - })() - assert.strictEqual(outerRunCount, 1) - assert.strictEqual(innerRunCount, 1) - assert.strictEqual(outerRunValue, 'foo') - assert.strictEqual(innerRunValue, 'bar') - reactor.inner = 'baz' - assert.strictEqual(outerRunCount, 1) - assert.strictEqual(innerRunCount, 1) - assert.strictEqual(outerRunValue, 'foo') - assert.strictEqual(innerRunValue, 'bar') - reactor.outer = 'moo' - assert.strictEqual(outerRunCount, 2) - assert.strictEqual(innerRunCount, 2) - assert.strictEqual(outerRunValue, 'moo') - assert.strictEqual(innerRunValue, 'baz') - }) - - it('should not self trigger in a hide block', () => { - const reactor = new Reactor(['a', 'b', 'c']) - let runCount = 0 - let runValue - new Observer(() => { - runCount += 1 - // pop reads the length of the object as well as changes it - // So calling pop normally in an observer will cause a loop - // hide allows us to call pop without creating a dependency - runValue = hide(() => reactor.pop()) - })() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'c') - }) -}) - -describe('Error Handling', () => { - it('should throw an error on a write if there is an Observer throws an error', () => { - const reactor = new Reactor({ value: 'foo' }) - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error') - })() - assert.throws(() => (reactor.value = 2), { - name: 'Error', - message: 'dummy error' - }) - }) - - it('should throw a CompoundError if there are multiple Observer errors', () => { - const reactor = new Reactor({ value: 1 }) - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error 1') - })() - new Observer(() => { - if (reactor.value > 1) throw new Error('dummy error 2') - })() - assert.throws(() => (reactor.value = 2), { - name: 'CompoundError' - }) - }) - - it('should throw a flattened CompoundError with chained observers', () => { - const reactor = new Reactor({ - foo: 1 - }) - // Successful passthrough to create subsequent compound errors - new Observer(() => { - reactor.passthrough = reactor.foo - })() - // Initial error failures to create an initial compound error - new Observer(() => { - if (reactor.foo > 1) throw new Error('primary error 1') - })() - new Observer(() => { - if (reactor.foo > 1) throw new Error('primary error 2') - })() - // Chain off reactor.passthrough to create a subsequent compound error - new Observer(() => { - if (reactor.passthrough > 1) throw new Error('secondary error 1') - })() - new Observer(() => { - if (reactor.passthrough > 1) throw new Error('secondary error 2') - })() - // Setting foo to 2 should trigger the primary error 1 and 2 and trigger the passthrough - // The passthrough triggers secondary error 1 and 2 as well which get merged into a compound error - // This compound error should then be merged with primary error 1 and 2 - // Instead of nesting it flattens to a single compound error with 4 causes - assert.throws(() => (reactor.foo = 2), (error) => { - assert.strictEqual(error.name, 'CompoundError') - assert.strictEqual(error.cause.length, 4) - return true - }) - }) -}) - -describe('Minor Features', () => { - describe('Start and Stop', () => { - it('should stop observing', () => { - let counter = 0 - let tracker - const reactor = new Reactor({ value: 'foo' }) - const observer = new Observer(() => { - counter += 1 - tracker = reactor.value - }) - observer() - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - reactor.value = 'bar' - assert.equal(counter, 2) - assert.equal(tracker, 'bar') - observer.stop() - reactor.value = 'moo' - assert.equal(counter, 2) - assert.equal(tracker, 'bar') - }) - - it('should start after stopping', () => { - let counter = 0 - let tracker = null - const reactor = new Reactor({ value: 'foo' }) - const observer = new Observer(() => { - counter += 1 - tracker = reactor.value - }) - observer() - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - observer.stop() - reactor.value = 'moo' - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - observer.start() - assert.equal(counter, 2) - assert.equal(tracker, 'moo') - }) - - it('should have no effect with repeated starts', () => { - let counter = 0 - let tracker = null - const reactor = new Reactor({ value: 'foo' }) - const observer = new Observer(() => { - counter += 1 - tracker = reactor.value - }) - observer() - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - observer.stop() - reactor.value = 'moo' - assert.equal(counter, 1) - assert.equal(tracker, 'foo') - observer.start() - assert.equal(counter, 2) - assert.equal(tracker, 'moo') - observer.start() - assert.equal(counter, 2) - assert.equal(tracker, 'moo') - }) - }) - - describe('Context and Subscriptions', () => { - it('should default context to undefined', () => { - let contextChecker = 'foo' - new Observer((context) => { - contextChecker = context - })() - assert(typeof contextChecker === 'undefined') - }) - - it('should set context', () => { - let contextChecker - const observer = new Observer((context) => { - contextChecker = context - }) - observer('foo') - assert.equal(contextChecker, 'foo') - const dummyObject = {} - observer(dummyObject) - assert.equal(contextChecker, dummyObject) - }) - - it('should set context with multiple params', () => { - let contextChecker - const observer = new Observer((a, b, c) => { - contextChecker = '' + a + b + c - }) - observer('foo', 'bar', 'baz') - assert.equal(contextChecker, 'foobarbaz') - contextChecker = null - observer() - assert.equal(contextChecker, 'undefinedundefinedundefined') - }) - - it('should set context and react to it', () => { - const reactor = new Reactor() - const contextChecker = {} - const observer = new Observer(function (...args) { - contextChecker.this = this - contextChecker.args = args - contextChecker.result = reactor.foo - }) - const bar = { - baz: observer - } - assert(typeof contextChecker.this === 'undefined') - assert(typeof contextChecker.args === 'undefined') - assert(typeof contextChecker.result === 'undefined') - bar.baz('qux') - assert.equal(contextChecker.this, bar) - assert.equal(contextChecker.args[0], 'qux') - assert(typeof contextChecker.result === 'undefined') - reactor.foo = 'bop' - assert.equal(contextChecker.this, bar) - assert.equal(contextChecker.args[0], 'qux') - assert.equal(contextChecker.result, 'bop') - }) - }) - - describe('Observer redefinition', () => { - it('should redefine an observer', () => { - const reactor = new Reactor({ - first: 'foo', - second: 'bar' - }) - let firstCounter = 0 - let secondCounter = 0 - let firstTracker - let secondTracker - const observer = new Observer(() => { - firstCounter += 1 - firstTracker = reactor.first - }) - observer() - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 0) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, undefined) - observer.execute = () => { - secondCounter += 1 - secondTracker = reactor.second - } - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.first = 'moo' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.second = 'baz' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 2) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'baz') - }) - }) -}) - -describe('Complex Setups', () => { - it('should be able to chain observers off each other', () => { - const reactor = new Reactor({ - foo: 'bar' - }) - const firstObserver = new Observer(() => { - return reactor.foo.toUpperCase() - }) - firstObserver() - assert.strictEqual(firstObserver.value, 'BAR') - const secondObserver = new Observer(() => { - return '!!!' + firstObserver.value + '!!!' - }) - secondObserver() - assert.strictEqual(secondObserver.value, '!!!BAR!!!') - const thirdObserver = new Observer(() => { - return secondObserver.value.toLowerCase() - }) - thirdObserver() - assert.strictEqual(thirdObserver.value, '!!!bar!!!') - reactor.foo = 'baz' - assert.strictEqual(firstObserver.value, 'BAZ') - assert.strictEqual(secondObserver.value, '!!!BAZ!!!') - assert.strictEqual(thirdObserver.value, '!!!baz!!!') - }) - - it.skip('should trigger observers once per write for triangle dependencies', () => { - // We have the following triangle dependency - // reactor -> first -> second - // reactor -> second - // Ideally we have reactor trigger first then second - // However, a naive depth first implementation would trigger first when in turn trigger second - // then go back to trigger second again because it's a dependency of reactor as well - // So we have an observer unnecessarily triggering twice off a single write - // Right now this is the naive implementation - let firstRunCount = 0 - let secondRunCount = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - const firstObserver = new Observer(() => { - firstRunCount += 1 - return reactor.foo.toUpperCase() - }) - firstObserver() - assert.strictEqual(firstRunCount, 1) - assert.strictEqual(firstObserver.value, 'BAR') - const secondObserver = new Observer(() => { - secondRunCount += 1 - return reactor.foo + firstObserver.value - }) - secondObserver() - assert.strictEqual(secondRunCount, 1) - assert.strictEqual(secondObserver.value, 'barBAR') - reactor.foo = 'baz' - assert.strictEqual(firstRunCount, 2) - assert.strictEqual(firstObserver.value, 'BAZ') - assert.strictEqual(secondRunCount, 2) - assert.strictEqual(secondObserver.value, 'bazBAZ') - }) - - it('should not trivially infinite loop when an observer calls another', () => { - // Trivial case - // observer2 = observer1() + 1 - // observer2 both calls observer1 and reads its value so is dependent on it - // So if observer1 is updated, it triggers observer2 which runs observer1 again which triggers observer 2 again - // This is guarded against because an observer breaks all dependencies when it runs - // And a called observer sets its value before doing a read to return it - // This means that when observer2 calls observer1, it is temporarily not a dependency while it triggers its others - // Then immediately after restablishes its dependence on observer1 - let firstRunCount = 0 - let secondRunCount = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - // By wrapping reactor.foo in an object, everytime it triggers it generates a new value - // This bypasses our "same value" trigger guard - const firstObserver = new Observer(() => { - firstRunCount += 1 - if (firstRunCount > 100) throw new Error('infinite loop') - return [reactor.foo] - }) - firstObserver() - const secondObserver = new Observer(() => { - secondRunCount += 1 - if (secondRunCount > 100) throw new Error('infinite loop') - return firstObserver() + 1 - }) - secondObserver() - assert.strictEqual(firstRunCount, 2) - assert.strictEqual(secondRunCount, 1) - assert.deepEqual(firstObserver.value, ['bar']) - assert.strictEqual(secondObserver.value, 'bar1') - reactor.foo = 'baz' - assert.strictEqual(firstRunCount, 4) - assert.strictEqual(secondRunCount, 2) - assert.deepEqual(firstObserver.value, ['baz']) - assert.strictEqual(secondObserver.value, 'baz1') - }) - - it.skip('should not infinite loop with three observers calling each other like functions', () => { - // This is a more complex case - // observer2 = observer1() + 1 - // observer3 = observer1() + observer2() - // So observer1 triggers observer2 which triggers observer3 - // Then observer3 triggers observer2 which does not loop because it is rebuilding dependencies when it sets its value - // But observer3 triggers observer1 which still triggers observer2 which still triggers observer3 - let firstRunCount = 0 - let secondRunCount = 0 - let thirdRunCount = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - const firstObserver = new Observer(() => { - firstRunCount += 1 - if (firstRunCount > 100) throw new Error('infinite loop detected') - return [reactor.foo] - }) - firstObserver() - const secondObserver = new Observer(() => { - secondRunCount += 1 - if (secondRunCount > 100) throw new Error('infinite loop detected') - return [firstObserver() + 'baz'] - }) - secondObserver() - const thirdObserver = new Observer(() => { - thirdRunCount += 1 - if (thirdRunCount > 100) throw new Error('infinite loop detected') - return [firstObserver() + secondObserver()] - }) - thirdObserver() - // assert.strictEqual(firstRunCount, 2) - // assert.strictEqual(secondRunCount, 1) - // assert.deepEqual(firstObserver.value, ['bar']) - // assert.strictEqual(secondObserver.value, 'bar1') - // reactor.foo = 'baz' - // assert.strictEqual(firstRunCount, 4) - // assert.strictEqual(secondRunCount, 2) - // assert.deepEqual(firstObserver.value, ['baz']) - // assert.strictEqual(secondObserver.value, 'baz1') - }) - - it('should be able to create observers inside other observers', () => { - const reactor = new Reactor({ - outer: 'foo', - inner: 'bar' - }) - let outerCounter = 0 - let innerCounter = 0 - let outerTracker - let innerTracker - let innerObserver - // We have an outer observer that creates an inner observer - // The outer observer depends on reactor.outer and the inner observer - // The inner observer depends on reactor.inner - new Observer(() => { - outerCounter += 1 - outerTracker = reactor.outer - if (innerObserver) innerObserver.stop() - innerObserver = new Observer(() => { - innerCounter += 1 - innerTracker = reactor.inner - }) - innerObserver() - })() - // The outer observer runs which creates and runs the inner observer - // So both run once - assert.equal(outerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerCounter, 1) - assert.equal(innerTracker, 'bar') - // This triggers the inner observer to run again - // The outer observer is dependent on the inner observer - // but because the inner observer doesn't have a return value - // it stays as undefined and so does not trigger the outer observer - reactor.inner = 'baz' - assert.equal(outerCounter, 1) - assert.equal(outerTracker, 'foo') - assert.equal(innerCounter, 2) - assert.equal(innerTracker, 'baz') - // This triggers the outer observer which creates and runs a new inner observer - reactor.outer = 'moo' - assert.equal(outerCounter, 2) - assert.equal(outerTracker, 'moo') - assert.equal(innerCounter, 3) - assert.equal(innerTracker, 'baz') - }) -}) +import './signal.test.js' +import './reactor.test.js' +import './observer.test.js' +import './reactivity.test.js' +import './batching.test.js' +import './hiding.test.js' +import './errors.test.js' +import './features.test.js' +import './complex.test.js' From e43d5fa3d027118db617fface126cbf7a16f61cd Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 02:17:10 +0800 Subject: [PATCH 34/71] Cleaned up wording for some tests --- test/observer.test.js | 87 ++++---- test/reactor.test.js | 462 ++++++++++++++++++++++++++++++++---------- test/signal.test.js | 164 ++++++++------- 3 files changed, 484 insertions(+), 229 deletions(-) diff --git a/test/observer.test.js b/test/observer.test.js index eced497..53a46d8 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -16,103 +16,103 @@ import { } from '../src/reactor.js' describe('Observer', () => { - describe('Initializes wrapping a function', () => { - it('should initialize with a function argument', () => new Observer(() => {})) + describe('initializes with a function and returns it wrapped in an observer', () => { + it('initializes with a function argument', () => new Observer(() => {})) - it('should fail to initialize with no argument', () => { + it('throws an error when initialized with no arguments', () => { assert.throws(() => new Observer(), { name: 'Error', message: 'Observer constructor requires exactly one argument' }) }) - it('should fail to initialize with multiple arguments', () => { + it('throws an error when initialized with multiple arguments', () => { assert.throws(() => new Observer(() => {}, () => {}), { name: 'Error', message: 'Observer constructor requires exactly one argument' }) }) - it('should not run upon initialization', () => { + it('does not run upon initialization', () => { let triggerCount = 0 // eslint-disable-next-line no-new new Observer(() => { triggerCount += 1 }) assert.strictEqual(triggerCount, 0) }) - it('should be an Observer object', () => { + it('is an Observer object', () => { const observer = new Observer(() => {}) assert(observer instanceof Observer) }) - describe('Fails to initialize with an argument that is not a Function', () => { - it('should fail to initialize with a string', () => { + describe('throws an error when initialized with invalid parameters', () => { + it('throws an error when initialized with a string', () => { assert.throws(() => new Observer('foo'), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with a number', () => { + it('throws an error when initialized with a number', () => { assert.throws(() => new Observer(123), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with a bigint', () => { + it('throws an error when initialized with a bigint', () => { assert.throws(() => new Observer(123456789123456789n), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with a symbol', () => { + it('throws an error when initialized with a symbol', () => { assert.throws(() => new Observer(Symbol('foo')), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with true', () => { + it('throws an error when initialized with true', () => { assert.throws(() => new Observer(true), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with false', () => { + it('throws an error when initialized with false', () => { assert.throws(() => new Observer(false), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with zero', () => { + it('throws an error when initialized with zero', () => { assert.throws(() => new Observer(0), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with an empty string', () => { + it('throws an error when initialized with an empty string', () => { assert.throws(() => new Observer(''), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with null', () => { + it('throws an error when initialized with null', () => { assert.throws(() => new Observer(null), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with undefined', () => { + it('throws an error when initialized with undefined', () => { assert.throws(() => new Observer(undefined), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with an Object', () => { + it('throws an error when initialized with a non-function object', () => { assert.throws(() => new Observer({}), { name: 'TypeError', message: 'Cannot create observer with a non-function' }) }) - it('should fail to initialize with an Array', () => { + it('fails to initialize with an array', () => { assert.throws(() => new Observer([]), { name: 'TypeError', message: 'Cannot create observer with a non-function' @@ -121,25 +121,32 @@ describe('Observer', () => { }) }) - describe('Can be used like a normal function', () => { - it('should be callable', () => { + describe('behaves the same as the wrapped function', () => { + it('is callable', () => { const observer = new Observer(() => {}) observer() }) - it('should return the function return value', () => { + it('runs the wrapped function when called', () => { + let runCount = 0 + const observer = new Observer(() => { runCount += 1 }) + observer() + assert.strictEqual(runCount, 1) + }) + + it('returns the wrapped function return value', () => { const observer = new Observer(() => 'foo') assert.strictEqual(observer(), 'foo') }) - it('should be callable with arguments', () => { + it('is callable with arguments', () => { const observer = new Observer((a, b, c) => { return a + b + c }) assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') }) - it('should have access to its arguments array', () => { + it('has access to its arguments array', () => { const observer = new Observer(function () { let output = '' for (const arg of arguments) { @@ -150,18 +157,18 @@ describe('Observer', () => { assert.strictEqual(observer('foo', 'bar', 'baz'), 'foobarbaz') }) - it('should have access to its this context', () => { + it('has access to its this context', () => { let context - const object = {} - const observer = new Observer(function () { - context = this - }) - object.observer = observer + const object = { + observer: new Observer(function () { + context = this + }) + } object.observer() assert.strictEqual(context, object) }) - it('should be able to use bind to create a new function with this context and arguments', () => { + it('can use bind to create a new function with the specified this context and arguments', () => { let context const object = { foo: 42 } const observer = new Observer(function (a) { @@ -174,7 +181,7 @@ describe('Observer', () => { assert.strictEqual(result, 52) }) - it('should be able to use call to execute with specified this context and arguments', () => { + it('can use call to run with the specified this context and arguments', () => { const object = { foo: 'bar' } const observer = new Observer(function (a, b) { return this.foo + a + b @@ -183,7 +190,7 @@ describe('Observer', () => { assert.strictEqual(result, 'barbazqux') }) - it('should be able to use apply to execute with specified this context and arguments', () => { + it('can use apply to run with the specified this context and arguments', () => { const object = { foo: 'bar' } const observer = new Observer(function (a, b) { return this.foo + a + b @@ -192,7 +199,7 @@ describe('Observer', () => { assert.strictEqual(result, 'barbazqux') }) - it('should be usable as a constructor', () => { + it('can be used as a constructor', () => { const DummyClass = new Observer(function (arg) { this.foo = 'bar' + arg return this @@ -202,14 +209,14 @@ describe('Observer', () => { assert.strictEqual(instance.foo, 'barbaz') }) - it('should be a type of Function', () => { + it('is an instance of Function', () => { const observer = new Observer(() => {}) assert(observer instanceof Function) assert(typeof observer === 'function') }) }) - describe('Wraps returned Object values in Reactors', () => { + describe('returns object values wrapped in a reactor', () => { it('', () => { const object = {} const observer = new Observer(() => object) @@ -220,7 +227,7 @@ describe('Observer', () => { }) }) - describe('Exposes the wrapped function through execute', () => { + describe('exposes the wrapped function through the execute property', () => { it('', () => { const dummyFunction = function () {} const observer = new Observer(dummyFunction) @@ -228,8 +235,8 @@ describe('Observer', () => { }) }) - describe('Exposes the last derived value through value', () => { - it('should keep the last derived value for primitive values', () => { + describe('exposes the last return value throught the value property', () => { + it('exposes the last derived value for primitive values', () => { let counter = 0 const dummyFunction = () => (counter += 1) const observer = new Observer(dummyFunction) @@ -243,7 +250,7 @@ describe('Observer', () => { assert.strictEqual(result, observer.value) }) - it('should keep the last derived value for Object values', () => { + it('exposes the last derived value for object values', () => { let counter = 0 const dummyFunction = () => { counter += 1 diff --git a/test/reactor.test.js b/test/reactor.test.js index 29389c4..4e155f0 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -16,120 +16,116 @@ import { } from '../src/reactor.js' describe('Reactor', () => { - describe('Initialization', () => { - describe('Initializes with no argument returning a new Reactor wrapped Object', () => { - it('should initialize with no argument', () => new Reactor()) - it('should return a Reactor Object', () => { - const reactor = new Reactor() - assert(Reactors.has(reactor)) - }) + describe('initializes with an object and returns it wrapped in a reactor', () => { + it('initializes with an object returning it wrapped in a reactor', () => { + const object = {} + const reactor = new Reactor(object) + assert(Reactors.has(reactor)) + assert.strictEqual(shuck(reactor), object) }) - describe('Initializes with an existing Object returning it wrapped in a Reactor', () => { - it('should initialize with an Object', () => new Reactor({})) - it('should initialize with an Function', () => new Reactor(() => {})) - it('should initialize with a Promise') // TODO: Figure out promises - it('should return a Reactor Object wrapping the original', () => { - const object = {} - const reactor = new Reactor(object) - assert(Reactors.has(reactor)) - assert.notEqual(reactor, object) - assert.strictEqual(shuck(reactor), object) - }) - describe('Edge cases', () => { - it('should not wrap a Reactor around an existing Reactor', () => { - const object = {} - const reactor = new Reactor(object) - const reactor2 = new Reactor(reactor) - assert(!Reactors.has(object)) - assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) - assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) - }) + it('initializes with a function returning it wrapped in a reactor', () => { + const func = () => {} + const reactor = new Reactor(func) + assert(Reactors.has(reactor)) + assert.strictEqual(shuck(reactor), func) + }) - it('should return the same Reactor when wrapping the same object', () => { - const object = {} - const reactor = new Reactor(object) - const reactor2 = new Reactor(object) - assert(!Reactors.has(object)) - assert(Reactors.has(reactor)) - assert(Reactors.has(reactor2)) - assert.strictEqual(reactor, reactor2) - assert.strictEqual(shuck(reactor), shuck(reactor2)) - assert.strictEqual(shuck(reactor), object) - assert.strictEqual(shuck(reactor2), object) - }) - }) + it('initializes with a promise') // TODO: Figure out promises + + it('initializes with no arguments automatically making an object and returning it wrapped in a reactor', () => { + const reactor = new Reactor() + assert(Reactors.has(reactor)) + assert.deepEqual(shuck(reactor), {}) }) - describe('Fails to initialize with values which are not Objects', () => { - it('should fail to initialize with a string', () => { + it('returns the same reactor when initialized with an existing reactor', () => { + const object = {} + const reactor1 = new Reactor(object) + const reactor2 = new Reactor(reactor1) + assert(Reactors.has(reactor1)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor1, reactor2) + assert.strictEqual(shuck(reactor1), shuck(reactor2)) + assert.strictEqual(shuck(reactor1), object) + assert.strictEqual(shuck(reactor2), object) + }) + + it('returns the same reactor when initialized with the same object', () => { + const object = {} + const reactor1 = new Reactor(object) + const reactor2 = new Reactor(object) + assert(!Reactors.has(object)) + assert(Reactors.has(reactor1)) + assert(Reactors.has(reactor2)) + assert.strictEqual(reactor1, reactor2) + assert.strictEqual(shuck(reactor1), shuck(reactor2)) + assert.strictEqual(shuck(reactor1), object) + assert.strictEqual(shuck(reactor2), object) + }) + + describe('throws an error when initialized with invalid parameters', () => { + it('throws an error when initialized with a string', () => { assert.throws(() => new Reactor('foo'), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with a number', () => { + it('throws an error when initialized with a number', () => { assert.throws(() => new Reactor(123), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with a bigint', () => { + it('throws an error when initialized with a bigint', () => { assert.throws(() => new Reactor(123456789123456789n), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with a symbol', () => { + it('throws an error when initialized with a symbol', () => { assert.throws(() => new Reactor(Symbol('foo')), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with true', () => { + it('throws an error when initialized with a boolean true value', () => { assert.throws(() => new Reactor(true), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with false', () => { + it('throws an error when initialized with a boolean false value', () => { assert.throws(() => new Reactor(false), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with zero', () => { + it('throws an error when initialized with a zero value', () => { assert.throws(() => new Reactor(0), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with an empty string', () => { + it('throws an error when initialized with an empty string', () => { assert.throws(() => new Reactor(''), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with null', () => { + it('throws an error when initialized with a null value', () => { assert.throws(() => new Reactor(null), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - it('should fail to initialize with undefined', () => { + it('throws an error when initialized with an undefined value', () => { assert.throws(() => new Reactor(undefined), { name: 'TypeError', message: 'Reactor source must be an Object' }) }) - }) - - describe('Edge cases', () => { - it('should fail to initialize with multiple arguments', () => { + it('throws an error when initialized with multiple arguments', () => { assert.throws(() => new Reactor({}, {}), { name: 'Error', message: 'Reactor constructor takes at most one argument' @@ -138,42 +134,81 @@ describe('Reactor', () => { }) }) - describe('Reads properties from the proxied Object', () => { - it('should return primitive values from the proxied Object', () => { - const reactor = new Reactor({ - foo: 'bar' - }) + describe('exposes the same properties and returns values from the wrapped object', () => { + it('reads the same primitive values as the wrapped object when initialized', () => { + const reactor = new Reactor({ foo: 'bar' }) assert.strictEqual(reactor.foo, 'bar') }) - it('should return object values from the proxied Object as a Reactor', () => { - const dummyObject = {} + it('reads the same primitive values from the wrapped object when it is modified', () => { + const object = { foo: 'bar' } + const reactor = new Reactor(object) + object.foo = 'baz' + assert.strictEqual(reactor.foo, 'baz') + }) + }) + + describe('returns object values recursively wrapped in reactors', () => { + it('returns an object value as a reactor', () => { + const object = {} const reactor = new Reactor({ - foo: dummyObject + foo: object }) const readResult = reactor.foo - assert.notStrictEqual(dummyObject, readResult) + assert.notStrictEqual(object, readResult) + assert(Reactors.has(readResult)) + assert.strictEqual(object, shuck(readResult)) + }) + it('returns a nested object value as a reactor', () => { + const object = {} + const reactor = new Reactor({ + foo: { + bar: object + } + }) + const readResult = reactor.foo.bar + assert.notStrictEqual(object, readResult) assert(Reactors.has(readResult)) - assert.strictEqual(dummyObject, shuck(readResult)) + assert.strictEqual(object, shuck(readResult)) }) }) - describe('Writes through to the proxied Object when assigning properties', () => { - it('should write values through to the proxied Object', () => { - const proxiedObject = {} - const reactor = new Reactor(proxiedObject) + describe('can set properties and get what was set', () => { + it('sets values through to the wrapped object', () => { + const object = {} + const reactor = new Reactor(object) reactor.foo = 'bar' - assert.strictEqual(proxiedObject.foo, 'bar') - assert.strictEqual(reactor.foo, 'bar') + assert.strictEqual(object.foo, 'bar') }) - it('should return the written values', () => { - const proxiedObject = {} - const reactor = new Reactor(proxiedObject) + it('returns the set values', () => { + const object = {} + const reactor = new Reactor(object) const writeReturn = (reactor.foo = 'bar') assert.strictEqual(writeReturn, 'bar') }) - it('should work with defineProperty', () => { + it('gets the value that was set', () => { + const object = {} + const reactor = new Reactor(object) + reactor.foo = 'bar' + assert.strictEqual(reactor.foo, 'bar') + }) + + it('deletes properties from the wrapped object', () => { + const object = { foo: 'bar' } + const reactor = new Reactor(object) + delete reactor.foo + assert.equal(object.foo, undefined) + }) + + it('deletes properties from itself', () => { + const object = { foo: 'bar' } + const reactor = new Reactor(object) + delete reactor.foo + assert.equal(reactor.foo, undefined) + }) + + it('works with Object.defineProperty', () => { const proxiedObject = {} const reactor = new Reactor(proxiedObject) const result = Object.defineProperty(reactor, 'foo', { @@ -184,7 +219,7 @@ describe('Reactor', () => { assert.strictEqual(result, reactor) }) - it('should not be writable if defineProperty sets writable to false', () => { + it('respects the writable property descriptor', () => { const reactor = new Reactor() Object.defineProperty(reactor, 'foo', { value: 'bar', @@ -198,58 +233,277 @@ describe('Reactor', () => { message: "Cannot assign to read only property 'foo' of object '#'" }) }) - - it('should delete properties from the proxied Object', () => { - const proxiedObject = { foo: 'bar' } - const reactor = new Reactor(proxiedObject) - delete reactor.foo - assert.equal(proxiedObject.foo, undefined) - assert.equal(reactor.foo, undefined) - }) }) - describe('Works with native object properties and methods', () => { - it('should work with Array map', () => { + describe('maintains compatibility with native object behavior', () => { + it('works with Array.prototype.map()', () => { const reactor = new Reactor(['0', '1', '2']) const result = reactor.map(x => 'this is ' + x) assert.deepStrictEqual(result, ['this is 0', 'this is 1', 'this is 2']) }) - it('should be able to read native properties', () => { + it('works with Array.prototype.filter()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5, 6]) + const result = reactor.filter(x => x % 2 === 0) + assert.deepStrictEqual(result, [2, 4, 6]) + }) + + it('works with Array.prototype.reduce()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.reduce((sum, x) => sum + x, 0) + assert.strictEqual(result, 15) + }) + + it('works with Array.prototype.reduceRight()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.reduceRight((sum, x) => sum + x, 0) + assert.strictEqual(result, 15) + }) + + it('works with Array.prototype.find()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.find(x => x > 3) + assert.strictEqual(result, 4) + }) + + it('works with Array.prototype.findIndex()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.findIndex(x => x > 3) + assert.strictEqual(result, 3) + }) + + it('works with Array.prototype.some()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.some(x => x > 3) + assert.strictEqual(result, true) + }) + + it('works with Array.prototype.every()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.every(x => x > 0) + assert.strictEqual(result, true) + }) + + it('works with Array.prototype.forEach()', () => { + const reactor = new Reactor([1, 2, 3]) + const results = [] + reactor.forEach(x => results.push(x * 2)) + assert.deepStrictEqual(results, [2, 4, 6]) + }) + + it('works with Array.prototype.slice()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.slice(1, 4) + assert.deepStrictEqual(result, [2, 3, 4]) + }) + + it('works with Array.prototype.splice()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const removed = reactor.splice(1, 2, 'a', 'b') + assert.deepStrictEqual(removed, [2, 3]) + assert.deepStrictEqual(shuck(reactor), [1, 'a', 'b', 4, 5]) + }) + + it('works with Array.prototype.concat()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.concat([4, 5], [6]) + assert.deepStrictEqual(result, [1, 2, 3, 4, 5, 6]) + }) + + it('works with Array.prototype.join()', () => { + const reactor = new Reactor(['a', 'b', 'c']) + const result = reactor.join('-') + assert.strictEqual(result, 'a-b-c') + }) + + it('works with Array.prototype.reverse()', () => { + const reactor = new Reactor([1, 2, 3, 4]) + const result = reactor.reverse() + assert.deepStrictEqual(shuck(result), [4, 3, 2, 1]) + assert.deepStrictEqual(shuck(reactor), [4, 3, 2, 1]) // reverse modifies in place + }) + + it('works with Array.prototype.sort()', () => { + const reactor = new Reactor([3, 1, 4, 1, 5]) + const result = reactor.sort() + assert.deepStrictEqual(shuck(result), [1, 1, 3, 4, 5]) + assert.deepStrictEqual(shuck(reactor), [1, 1, 3, 4, 5]) // sort modifies in place + }) + + it('works with Array.prototype.sort() with comparator', () => { + const reactor = new Reactor([3, 1, 4, 1, 5]) + const result = reactor.sort((a, b) => b - a) + assert.deepStrictEqual(shuck(result), [5, 4, 3, 1, 1]) + }) + + it.skip('works with Array.prototype.flat()', () => { + const reactor = new Reactor([1, [2, 3], [4, [5, 6]]]) + const result = reactor.flat() + // Interesting edge case here + // Flat returns a new array with the subarrays being reactor wrapped too + // But the subarrays are reactor wrapped even in the internal object + // This is because flat is constructing them from reactor reads + // Making the apply call use the internal object as `this` solves this + // but it breaks a bunch of other stuff + // TODO find a way to fix this + assert.deepStrictEqual(shuck(result), [1, 2, 3, 4, [5, 6]]) + }) + + // it('test flat', () => { + // const array = [1, [2, 3], [4, [5, 6]]] + // const result = array.flat() + // const original56 = array[2][1] + // const result56 = result[4] + // console.log(original56, result56) + // assert(original56 === result56) + // assert.strictEqual(array[2][1], result[4]) + // }) + + it('works with Array.prototype.flatMap()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.flatMap(x => [x, x * 2]) + assert.deepStrictEqual(result, [1, 2, 2, 4, 3, 6]) + }) + + it('works with Array.prototype.includes()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + assert.strictEqual(reactor.includes(3), true) + assert.strictEqual(reactor.includes(6), false) + }) + + it('works with Array.prototype.indexOf()', () => { + const reactor = new Reactor([1, 2, 3, 2, 5]) + assert.strictEqual(reactor.indexOf(2), 1) + assert.strictEqual(reactor.indexOf(6), -1) + }) + + it('works with Array.prototype.lastIndexOf()', () => { + const reactor = new Reactor([1, 2, 3, 2, 5]) + assert.strictEqual(reactor.lastIndexOf(2), 3) + assert.strictEqual(reactor.lastIndexOf(6), -1) + }) + + it('works with Array.prototype.entries()', () => { + const reactor = new Reactor(['a', 'b', 'c']) + const result = Array.from(reactor.entries()) + assert.deepStrictEqual(result, [[0, 'a'], [1, 'b'], [2, 'c']]) + }) + + it('works with Array.prototype.keys()', () => { + const reactor = new Reactor(['a', 'b', 'c']) + const result = Array.from(reactor.keys()) + assert.deepStrictEqual(result, [0, 1, 2]) + }) + + it('works with Array.prototype.values()', () => { + const reactor = new Reactor(['a', 'b', 'c']) + const result = Array.from(reactor.values()) + assert.deepStrictEqual(result, ['a', 'b', 'c']) + }) + + it('works with Array.prototype.fill()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.fill(0, 1, 4) + assert.deepStrictEqual(shuck(result), [1, 0, 0, 0, 5]) + assert.deepStrictEqual(shuck(reactor), [1, 0, 0, 0, 5]) // fill modifies in place + }) + + it('works with Array.prototype.copyWithin()', () => { + const reactor = new Reactor([1, 2, 3, 4, 5]) + const result = reactor.copyWithin(0, 3, 5) + assert.deepStrictEqual(shuck(result), [4, 5, 3, 4, 5]) + assert.deepStrictEqual(shuck(reactor), [4, 5, 3, 4, 5]) // copyWithin modifies in place + }) + + it('works with Array.prototype.push()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.push(4, 5) + assert.strictEqual(result, 5) + assert.deepStrictEqual(shuck(reactor), [1, 2, 3, 4, 5]) + }) + + it('works with Array.prototype.pop()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.pop() + assert.strictEqual(result, 3) + assert.deepStrictEqual(shuck(reactor), [1, 2]) + }) + + it('works with Array.prototype.shift()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.shift() + assert.strictEqual(result, 1) + assert.deepStrictEqual(shuck(reactor), [2, 3]) + }) + + it('works with Array.prototype.unshift()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = reactor.unshift(0, -1) + assert.strictEqual(result, 5) + assert.deepStrictEqual(shuck(reactor), [0, -1, 1, 2, 3]) + }) + + it('works with Array.prototype.length property', () => { + const reactor = new Reactor([1, 2, 3]) + assert.strictEqual(reactor.length, 3) + reactor.push(4) + assert.strictEqual(reactor.length, 4) + }) + + it('works with Array.prototype.isArray()', () => { + const reactor = new Reactor([1, 2, 3]) + assert.strictEqual(Array.isArray(reactor), true) + }) + + it('works with Array.prototype.from()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = Array.from(reactor, x => x * 2) + assert.deepStrictEqual(result, [2, 4, 6]) + }) + + it('works with Array.prototype.of()', () => { + const reactor = new Reactor([1, 2, 3]) + const result = Array.of(...reactor, 4, 5) + assert.deepStrictEqual(result, [1, 2, 3, 4, 5]) + }) + + it('can read native properties', () => { const map = new Map() const reactor = new Reactor(map) - // Normaly proxy wrapping will fail - // This check to see if we redirect the call `this` + // Normally proxy wrapping will fail + // This checks to see if we redirect the call `this` // to the wrapped object instead of the wrapper when appropriate assert.strictEqual(reactor.size, 0) map.set('foo', 'bar') assert.strictEqual(reactor.size, 1) }) - it('should be able to call native objects methods', () => { + it('can call native object methods', () => { const reactor = new Reactor(new Map()) - // Normal proxy wrapping will fail + // Normally proxy wrapping will fail // since .keys() cannot be called on a Proxy const result = reactor.keys() assert(typeof result[Symbol.iterator] === 'function') }) }) - describe('Misc', () => { - it('should maintain instanceof checks for the wrapped object', () => { - const reactor = new Reactor([]) - assert(reactor instanceof Array) - // Sadly no way to also pass instanceof Reactor while maintaining the original instanceof checks - // An object can only have one class inheritance chain - // Would be great if we had some sort of in + describe('preserves object identity and inheritance behavior', () => { + // When initialized with an existing object, it has reactor behaviours but is not a Reactor instance + // This is because we maintain the original class inheritance chain instead + // and javascript does not support multiple inheritance + it('is an instance of its original class when initialized with an existing object', () => { + const object = new Date() + const reactor = new Reactor(object) + const originalClass = object.constructor + assert(reactor instanceof originalClass) }) - it('should pass instanceof Reactor if no object was provided', () => { + it('is an instance of Reactor when initialized with no arguments', () => { const reactor = new Reactor() assert(reactor instanceof Reactor) }) - it('should respect receiver this context for prototype inheritors', () => { + it('respects receiver this context for prototype inheritors', () => { const reactor = new Reactor() reactor.foo = 'bar' Object.defineProperty(reactor, 'getFoo', { diff --git a/test/signal.test.js b/test/signal.test.js index 0c72b30..c911a4e 100644 --- a/test/signal.test.js +++ b/test/signal.test.js @@ -16,94 +16,92 @@ import { } from '../src/reactor.js' describe('Signal', () => { - describe('Initializes with a value', () => { - it('should initialize with a string', () => new Signal('foo')) - it('should initialize with a number', () => new Signal(123)) - it('should initialize with a bigint', () => new Signal(123456789123456789n)) - it('should initialize with a symbol', () => new Signal(Symbol('foo'))) - it('should initialize with true', () => new Signal(true)) - it('should initialize with false', () => new Signal(false)) - it('should initialize with zero', () => new Signal(0)) - it('should initialize with an empty string', () => new Signal('')) - it('should initialize with null', () => new Signal(null)) - it('should initialize with undefined', () => new Signal(undefined)) - it('should initialize with an Object', () => new Signal({})) - it('should initialize with a Function', () => new Signal(() => {})) - it('should initialize with a Promise') // TODO: Figure out promises - describe('Edge cases', () => { - it('should initialize with no arguments', () => new Signal()) - it('should not initialize with multiple arguments', () => { - assert.throws(() => new Signal('foo', 'bar'), { - name: 'Error', - message: 'Signal constructor takes at most one argument' - }) + describe('initializes with any single value', () => { + it('initializes with a string', () => new Signal('foo')) + it('initializes with a number', () => new Signal(123)) + it('initializes with a bigint', () => new Signal(123456789123456789n)) + it('initializes with a symbol', () => new Signal(Symbol('foo'))) + it('initializes with true', () => new Signal(true)) + it('initializes with false', () => new Signal(false)) + it('initializes with an empty string', () => new Signal('')) + it('initializes with zero', () => new Signal(0)) + it('initializes with null', () => new Signal(null)) + it('initializes with undefined', () => new Signal(undefined)) + it('initializes with an object', () => new Signal({})) + it('initializes with a function', () => new Signal(() => {})) + it('initializes with a promise') // TODO: Figure out promises + it('initializes with no arguments', () => new Signal()) + it('throws an error when initialized with multiple arguments', () => { + assert.throws(() => new Signal('foo', 'bar'), { + name: 'Error', + message: 'Signal constructor takes at most one argument' }) }) }) - describe('Returns the initial value when called with no arguments', () => { - it('should return the initial string', () => { + describe('returns the initial value when called with no arguments', () => { + it('returns a string', () => { const value = 'foo' const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial number', () => { + it('returns a number', () => { const value = 123 const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial bigint', () => { + it('returns a bigint', () => { const value = 123456789123456789n const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial symbol', () => { + it('returns a symbol', () => { const value = Symbol('foo') const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial true', () => { + it('returns true', () => { const value = true const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial false', () => { + it('returns false', () => { const value = false const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial zero', () => { - const value = 0 + it('returns an empty string', () => { + const value = '' const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial empty string', () => { - const value = '' + it('returns zero', () => { + const value = 0 const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial null', () => { + it('returns null', () => { const value = null const signal = new Signal(value) assert.strictEqual(signal(), value) }) - it('should return the initial undefined', () => { + it('returns undefined', () => { const value = undefined const signal = new Signal(value) assert.strictEqual(signal(), value) }) - describe('Object are returned wrapped in a Reactor', () => { - it('should return the initial Object wrapped in a Reactor', () => { + describe('returns objects wrapped in a reactor', () => { + it('returns an object wrapped in a reactor', () => { const dummyObject = {} const signal = new Signal(dummyObject) const result = signal() @@ -111,7 +109,7 @@ describe('Signal', () => { assert.strictEqual(shuck(result), dummyObject) }) - it('should return the initial Function wrapped in a Reactor', () => { + it('returns a function wrapped in a reactor', () => { const dummyFunction = () => {} const signal = new Signal(dummyFunction) const result = signal() @@ -120,12 +118,12 @@ describe('Signal', () => { }) // TODO figure out promises - it('should return the initial Promise') + it('returns a promise') }) }) - describe('Replaces the stored value when called with an argument and returns the new value', () => { - it('should update with a new string', () => { + describe('updates its stored value when called with an argument then returns the new value', () => { + it('updates with a string', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = 'foo' @@ -135,7 +133,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with a new number', () => { + it('updates with a number', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = 123 @@ -145,7 +143,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with a new bigint', () => { + it('updates with a bigint', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = 123456789123456789n @@ -155,7 +153,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with a new symbol', () => { + it('updates with a symbol', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = Symbol('foo') @@ -165,7 +163,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with true', () => { + it('updates with true', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = true @@ -175,7 +173,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with false', () => { + it('updates with false', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = false @@ -185,27 +183,27 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with zero', () => { + it('updates with an empty string', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) - const value = 0 + const value = '' const writeReturn = signal(value) assert.strictEqual(writeReturn, value) const readReturn = signal() assert.strictEqual(readReturn, value) }) - it('should update with an empty string', () => { + it('updates with zero', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) - const value = '' + const value = 0 const writeReturn = signal(value) assert.strictEqual(writeReturn, value) const readReturn = signal() assert.strictEqual(readReturn, value) }) - it('should update with null', () => { + it('updates with null', () => { const signal = new Signal() assert.strictEqual(signal(), undefined) const value = null @@ -215,7 +213,7 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - it('should update with undefined', () => { + it('updates with undefined', () => { const signal = new Signal('foo') assert.strictEqual(signal(), 'foo') const value = undefined @@ -225,43 +223,39 @@ describe('Signal', () => { assert.strictEqual(readReturn, value) }) - describe('Objects are returned wrapped in a Reactor', () => { - it('should update with an Object', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = {} - const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) - const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) - }) - - it('should update with a Function', () => { - const signal = new Signal() - assert.strictEqual(signal(), undefined) - const value = () => {} - const writeReturn = signal(value) - assert(Reactors.has(writeReturn)) - assert.strictEqual(shuck(writeReturn), value) - const readReturn = signal() - assert(Reactors.has(readReturn)) - assert.strictEqual(shuck(readReturn), value) - assert.strictEqual(writeReturn, readReturn) - }) + it('updates with an object and returns it wrapped in a reactor', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) + }) - it('should update with a Promise') + it('updates with a function and returns it wrapped in a reactor', () => { + const signal = new Signal() + assert.strictEqual(signal(), undefined) + const value = () => {} + const writeReturn = signal(value) + assert(Reactors.has(writeReturn)) + assert.strictEqual(shuck(writeReturn), value) + const readReturn = signal() + assert(Reactors.has(readReturn)) + assert.strictEqual(shuck(readReturn), value) + assert.strictEqual(writeReturn, readReturn) }) - describe('Edge cases', () => { - it('should throw an Error when called multiple arguments', () => { - const signal = new Signal() - assert.throws(() => signal(1, 2), { - name: 'Error', - message: 'Signal objects take at most one argument for writes and zero arguments for reads' - }) + it('updates with a Promise') // TODO: Figure out promises + + it('throws an error when called with multiple arguments', () => { + const signal = new Signal() + assert.throws(() => signal(1, 2), { + name: 'Error', + message: 'Signal objects take at most one argument for writes and zero arguments for reads' }) }) }) From 179867b4368b8b9ed7fd866dbd9d83697a6b8a95 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:02:37 +0800 Subject: [PATCH 35/71] Cleaned up reactivity tests --- test/reactivity.test.js | 868 ++++++++++++++++++++-------------------- 1 file changed, 442 insertions(+), 426 deletions(-) diff --git a/test/reactivity.test.js b/test/reactivity.test.js index a0f7e11..4e0cc33 100644 --- a/test/reactivity.test.js +++ b/test/reactivity.test.js @@ -16,8 +16,8 @@ import { } from '../src/reactor.js' describe('Reactivity', () => { - describe('Observers do not trigger before being run', () => { - it('should not trigger if reading a Signal', () => { + describe('Observers are inactive until they are run', () => { + it('does not trigger on a signal update if it has not been run', () => { let runCount = 0 let runValue const signal = new Signal('foo') @@ -34,7 +34,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) }) - it('should not trigger if reading a Reactor', () => { + it('does not trigger on a reactor update if it has not been run', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -53,8 +53,8 @@ describe('Reactivity', () => { }) }) - describe('Observers after being run should form dependencies and trigger on their updates', () => { - it('should be setup to trigger if reading a Signal', () => { + describe('Observers form dependencies when run and trigger on their updates', () => { + it('builds a dependency when reading a signal', () => { let runCount = 0 let runValue const signal = new Signal('foo') @@ -71,7 +71,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, 'bar') }) - it('should be setup to trigger if reading a Reactor', () => { + it('builds a dependency when reading a reactor', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -88,7 +88,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, 'baz') }) - it('should be setup to trigger if reading another Observer', () => { + it('builds a dependency when reading another observer value', () => { let runCount = 0 let runValue const headObserver = new Observer((x) => x) @@ -103,9 +103,25 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'foo') }) - // TODO trigger if reading another Observer via observer() instead of observer.value - it('should be setup to trigger when using Object.keys', () => { + it('builds a dependency when calling another observer', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar' }) + const headObserver = new Observer(() => reactor.foo) + const tailObserver = new Observer(() => { + runCount += 1 + runValue = headObserver() + }) + tailObserver() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.foo = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + }) + + it('builds a dependency when using Object.keys', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -120,7 +136,7 @@ describe('Reactivity', () => { assert.deepEqual(runValue, ['foo', 'baz']) }) - it('should be setup to trigger when using the in operator', () => { + it('builds a dependency when using the in operator', () => { let runCount = 0 let runValue const reactor = new Reactor() @@ -135,7 +151,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, true) }) - it('should get triggered by defineProperty', () => { + it('builds a dependency when using defineProperty', () => { let runCount = 0 let runValue const reactor = new Reactor({ @@ -157,7 +173,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, 'baz') }) - it('should get triggered by deleteProperty', () => { + it('builds a dependency when using deleteProperty', () => { let runCount = 0 let runValue const reactor = new Reactor({ @@ -177,7 +193,7 @@ describe('Reactivity', () => { assert.strictEqual(runValue, undefined) }) - it('should be able to be triggered repeatedly', () => { + it('is able to be triggered repeatedly', () => { let runCount = 0 let runValue const reactor = new Reactor({ @@ -202,499 +218,499 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 5) assert.strictEqual(runValue, 'mip') }) - }) - describe('Observers rebuild dependencies each time they trigger', () => { - it('should build new dependencies on retriggers', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - switch: 'foo', - foo: 'bar', - baz: 'qux' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.switch] - }) - // On initial run it should be depndent on foo and not baz - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Verify there is no dependency on baz - reactor.baz = 'moo' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Switch sets new dependency on baz - reactor.switch = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'moo') - // Verify dependency on baz is working - reactor.baz = 'mip' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'mip') - }) - it('should break old dependencies when no longer needed', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - switch: 'foo', - foo: 'bar', - baz: 'qux' - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.switch] - }) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - // Verify dependency on foo is working - reactor.foo = 'moo' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'moo') - // Switch builds new dependencies - reactor.switch = 'baz' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'qux') - // Verify dependency on foo is broken - reactor.foo = 'mip' - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'qux') - }) - }) - - describe('Observers trigger on subproperty updates', () => { - it('should trigger even if a relevant subproperty of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: {} - }) - const observer = new Observer(() => { - runCount += 1 - // Dependency is only explicitly on reactor.foo - // But depends implicitly on all its subproperties - runValue = JSON.stringify(reactor.foo) - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, '{}') - // This new property is relevant to the observer so should trigger - reactor.foo.bar = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, '{"bar":"baz"}') - }) - - it('should not trigger if an irrelevant subproperty of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: {} - }) - const observer = new Observer(() => { - runCount += 1 - // Dependency is only explicitly on reactor.foo - runValue = Array.isArray(reactor.foo) - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - // The new property is irrelevant to the observer checking isArray so should not trigger - reactor.foo.bar = 'baz' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, false) - }) - - it('should trigger if a subproperty is updated when depending on it directly', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - reactor.foo.bar = 'qux' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - }) - - it('should trigger if a parent property is updated when depending on its subproperty', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - // Instead of just updating bar we replace the whole object - reactor.foo = { bar: 'qux' } - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - }) - - it('should not trigger if a sibling property of its dependency is updated', () => { - let runCount = 0 - let runValue - const reactor = new Reactor({ - foo: { - bar: 'baz' - } - }) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.foo.bar - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - // The new sibling property is irrelevant to the observer so should not trigger - reactor.foo.qux = 'moo' - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'baz') - }) - - describe('Gets triggered by array update methods', () => { - it('should get triggered by array index assignment', () => { + describe('Observers can form dependencies on subproperties and trigger on their updates', () => { + it('triggers if a relevant subproperty of its dependency is updated', () => { let runCount = 0 let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] + const reactor = new Reactor({ + foo: {} }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor[1] = 'baz' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'baz') - assert.deepEqual(reactor, ['foo', 'baz']) - }) - - it('should get triggered by array push', () => { - let runCount = 0 - let runValue - const reactor = new Reactor([]) const observer = new Observer(() => { runCount += 1 - runValue = reactor[0] + // Dependency is only explicitly on reactor.foo + // But depends implicitly on all its subproperties + runValue = JSON.stringify(reactor.foo) }) assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) observer() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) - reactor.push('foo') + assert.strictEqual(runValue, '{}') + // This new property is relevant to the observer so should trigger + reactor.foo.bar = 'baz' assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'foo') + assert.strictEqual(runValue, '{"bar":"baz"}') }) - it('should get triggered by array pop', () => { + it('does not trigger if an irrelevant subproperty of its dependency is updated', () => { let runCount = 0 let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[reactor.length - 1] + const reactor = new Reactor({ + foo: {} }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.pop() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'foo') - assert.strictEqual(reactor.length, 1) - }) - - it('should get triggered by array shift', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) const observer = new Observer(() => { runCount += 1 - runValue = reactor[0] + // Dependency is only explicitly on reactor.foo + runValue = Array.isArray(reactor.foo) }) assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) observer() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - reactor.shift() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bar') - assert.strictEqual(reactor.length, 1) - }) - - it('should get triggered by array unshift', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[0] - }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() + assert.strictEqual(runValue, false) + // The new property is irrelevant to the observer checking isArray so should not trigger + reactor.foo.bar = 'baz' assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'foo') - reactor.unshift('bar') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bar') - assert.strictEqual(reactor.length, 2) + assert.strictEqual(runValue, false) }) - it('should get triggered by array splice', () => { + it('triggers if a subproperty it depends on directly is updated', () => { let runCount = 0 let runValue - const reactor = new Reactor(['foo', 'bar', 'baz']) + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) const observer = new Observer(() => { runCount += 1 - runValue = reactor[1] + runValue = reactor.foo.bar }) assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) observer() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.splice(1, 1, 'qux') + assert.strictEqual(runValue, 'baz') + reactor.foo.bar = 'qux' assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'qux') - assert.strictEqual(reactor.length, 3) }) - it('should get triggered by array sort', () => { + it('triggers if a parent of a subproperty it depends on is updated', () => { let runCount = 0 let runValue - const reactor = new Reactor(['c', 'a', 'b']) + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) const observer = new Observer(() => { runCount += 1 - runValue = reactor[0] + runValue = reactor.foo.bar }) assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) observer() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'c') - reactor.sort() + assert.strictEqual(runValue, 'baz') + // Instead of just updating bar we replace the whole object + reactor.foo = { bar: 'qux' } assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a') - assert.deepEqual(reactor, ['a', 'b', 'c']) + assert.strictEqual(runValue, 'qux') }) - it('should get triggered by array reverse', () => { + it('does not trigger if an irrelevant sibling subproperty of its subproperty dependency is updated', () => { let runCount = 0 let runValue - const reactor = new Reactor(['a', 'b', 'c']) + const reactor = new Reactor({ + foo: { + bar: 'baz' + } + }) const observer = new Observer(() => { runCount += 1 - runValue = reactor[0] + runValue = reactor.foo.bar }) assert.strictEqual(runCount, 0) assert.strictEqual(runValue, undefined) observer() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'a') - reactor.reverse() - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'c') - assert.deepEqual(reactor, ['c', 'b', 'a']) + assert.strictEqual(runValue, 'baz') + // The new sibling property is irrelevant to the observer so should not trigger + reactor.foo.qux = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'baz') }) - it('should get triggered by array fill', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar', 'baz']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] + describe('triggers on array update methods', () => { + it('triggers on an array index assignment', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor[1] = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'baz') + assert.deepEqual(reactor, ['foo', 'baz']) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'bar') - reactor.fill('qux', 1, 2) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'qux') - assert.deepEqual(reactor, ['foo', 'qux', 'baz']) - }) - it('should get triggered by array copyWithin', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c', 'd', 'e']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[2] + it('triggers on an array push', () => { + let runCount = 0 + let runValue + const reactor = new Reactor([]) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, undefined) + reactor.push('foo') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'c') - reactor.copyWithin(2, 0, 2) - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a') - assert.deepEqual(reactor, ['a', 'b', 'a', 'b', 'e']) - }) - it('should get triggered by changing the array length property', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length + it('triggers on an array pop', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.length - 1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.pop() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'foo') + assert.strictEqual(reactor.length, 1) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - reactor.length = 1 - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 1) - assert.deepEqual(reactor, ['foo']) - }) - it('should not get triggered by setting the array length property to its current value', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['foo', 'bar']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length + it('triggers on an array shift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.shift() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 1) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - reactor.length = 2 - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 2) - assert.deepEqual(reactor, ['foo', 'bar']) - }) - it('should get triggered by array operations that change length', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.length + it('triggers on an array unshift', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'foo') + reactor.unshift('bar') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'bar') + assert.strictEqual(reactor.length, 2) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 3) - reactor.push('d') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 4) + it('triggers on an array splice', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.splice(1, 1, 'qux') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.strictEqual(reactor.length, 3) + }) - reactor.pop() - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 3) + it('triggers on an array sort', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['c', 'a', 'b']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.sort() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'c']) + }) - reactor.splice(0, 2) - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 1) - }) + it('triggers on an array reverse', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[0] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a') + reactor.reverse() + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'c') + assert.deepEqual(reactor, ['c', 'b', 'a']) + }) - it('should get triggered by array operations that modify existing elements', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor[1] + it('triggers on an array fill', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar', 'baz']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + reactor.fill('qux', 1, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'qux') + assert.deepEqual(reactor, ['foo', 'qux', 'baz']) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'b') - // Modify existing element - reactor[1] = 'x' - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'x') + it('triggers on an array copyWithin', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c', 'd', 'e']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[2] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'c') + reactor.copyWithin(2, 0, 2) + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a') + assert.deepEqual(reactor, ['a', 'b', 'a', 'b', 'e']) + }) - // Use splice to modify - reactor.splice(1, 1, 'y') - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'y') + it('triggers on an array length change', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 1 + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 1) + assert.deepEqual(reactor, ['foo']) + }) - // Use fill to modify - reactor.fill('z', 1, 2) - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'z') - }) + it('does not trigger on an array length set to its current value', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['foo', 'bar']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + reactor.length = 2 + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 2) + assert.deepEqual(reactor, ['foo', 'bar']) + }) - it('should be able to be triggered repeatedly by multiple array operations', () => { - let runCount = 0 - let runValue - const reactor = new Reactor(['a', 'b', 'c']) - const observer = new Observer(() => { - runCount += 1 - runValue = reactor.join(',') + it('triggers on array operations that change length', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.length + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 3) + + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 4) + + reactor.pop() + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 3) + + reactor.splice(0, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 1) }) - assert.strictEqual(runCount, 0) - assert.strictEqual(runValue, undefined) - observer() - assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, 'a,b,c') - // Multiple operations should trigger observer multiple times - reactor.push('d') - assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'a,b,c,d') + it('triggers on array operations that modify existing elements', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[1] + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'b') + + // Modify existing element + reactor[1] = 'x' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'x') + + // Use splice to modify + reactor.splice(1, 1, 'y') + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'y') + + // Use fill to modify + reactor.fill('z', 1, 2) + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'z') + }) - reactor.splice(1, 1) - assert.strictEqual(runCount, 3) - assert.strictEqual(runValue, 'a,c,d') + it('is able to be triggered repeatedly by multiple array operations', () => { + let runCount = 0 + let runValue + const reactor = new Reactor(['a', 'b', 'c']) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor.join(',') + }) + assert.strictEqual(runCount, 0) + assert.strictEqual(runValue, undefined) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'a,b,c') + + // Multiple operations should trigger observer multiple times + reactor.push('d') + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'a,b,c,d') + + reactor.splice(1, 1) + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'a,c,d') + + reactor.reverse() + assert.strictEqual(runCount, 4) + assert.strictEqual(runValue, 'd,c,a') + }) + }) + }) + }) - reactor.reverse() - assert.strictEqual(runCount, 4) - assert.strictEqual(runValue, 'd,c,a') + describe('Observers rebuild dependencies each time they run', () => { + it('builds new dependencies on retriggers', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] + }) + // On initial run it should be depndent on foo and not baz + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify there is no dependency on baz + reactor.baz = 'moo' + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Switch sets new dependency on baz + reactor.switch = 'baz' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Verify dependency on baz is working + reactor.baz = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'mip') + }) + it('breaks old dependencies when no longer needed', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ + switch: 'foo', + foo: 'bar', + baz: 'qux' + }) + const observer = new Observer(() => { + runCount += 1 + runValue = reactor[reactor.switch] }) + observer() + assert.strictEqual(runCount, 1) + assert.strictEqual(runValue, 'bar') + // Verify dependency on foo is working + reactor.foo = 'moo' + assert.strictEqual(runCount, 2) + assert.strictEqual(runValue, 'moo') + // Switch builds new dependencies + reactor.switch = 'baz' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') + // Verify dependency on foo is broken + reactor.foo = 'mip' + assert.strictEqual(runCount, 3) + assert.strictEqual(runValue, 'qux') }) }) - describe('Observers are triggered only once per update ', () => { - it('should trigger only once despite multiple identical dependencies', () => { + describe('Observers trigger only once per update', () => { + it('triggers only once despite multiple identical dependencies', () => { let runCount = 0 let runValue const reactor = new Reactor({ @@ -710,7 +726,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 2) assert.strictEqual(runValue, 'bazbazbaz') }) - it('should trigger only once despite multiple different dependencies', () => { + it('triggers only once despite multiple different dependencies', () => { let counter = 0 let getTracker let stringifyTracker @@ -734,7 +750,7 @@ describe('Reactivity', () => { assert.strictEqual(stringifyTracker, '{"foo":"baz"}') assert.deepEqual(valuesTracker, ['baz']) }) - it('should trigger only once for native methods attached to the Reactor with multiple changes on itself', () => { + it('triggers only once for native methods attached to the Reactor with multiple changes on itself', () => { let runCount = 0 let firstTracker let lengthTracker @@ -752,7 +768,7 @@ describe('Reactivity', () => { assert.equal(lengthTracker, 1) assert.equal(firstTracker, 'bar') }) - it('should trigger only once for custom methods attached to the Reactor with multiple changes on itself', () => { + it('triggers only once for custom methods attached to the Reactor with multiple changes on itself', () => { let runCount = 0 let fooTracker let bazTracker @@ -779,8 +795,8 @@ describe('Reactivity', () => { }) }) - describe('Observers are not triggered when setting an identical value', () => { - it('should not redundantly trigger on setting an identical primitive value on a Signal', () => { + describe('Signals do not trigger observers when updated to an identical value', () => { + it('does not redundantly trigger on setting an identical primitive value on a Signal', () => { let runCount = 0 let runValue const signal = new Signal('foo') @@ -794,7 +810,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 1) assert.strictEqual(runValue, 'foo') }) - it('should not redundantly trigger on setting an identical primitive value on a Reactor', () => { + it('does not redundantly trigger on setting an identical primitive value on a Reactor', () => { let runCount = 0 let runValue const reactor = new Reactor({ @@ -810,7 +826,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 1) assert.strictEqual(runValue, 'bar') }) - it('should not redundantly trigger on setting an identical primitive value on an Observer', () => { + it('does not redundantly trigger on setting an identical primitive value on an Observer', () => { let runCount = 0 let runValue const headObserver = new Observer((x) => x) @@ -826,7 +842,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 1) assert.strictEqual(runValue, 'foo') }) - it('should not redundantly trigger on setting an identical object value', () => { + it('does not redundantly trigger on setting an identical object value', () => { let runCount = 0 let runValue const dummyObject = {} @@ -843,7 +859,7 @@ describe('Reactivity', () => { assert.strictEqual(runCount, 1) assert.strictEqual(shuck(runValue), dummyObject) }) - it('should trigger on setting a similar but different object', () => { + it('triggers on setting an identical but different object', () => { let runCount = 0 let runValue const dummyObject = {} From ed7652cef62661411f1fdc0320c9a103dc30f032 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:22:43 +0800 Subject: [PATCH 36/71] Added parameter validation for batch and updated batching tests --- src/reactor.js | 6 +++- test/batching.test.js | 83 +++++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index de0fda4..ef80b32 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -648,7 +648,11 @@ const hide = (execute) => { } // Method for allowing users to batch multiple observer updates together -const batch = (execute) => { +const batch = function (execute) { + if (arguments.length !== 1 || typeof execute !== 'function') { + throw new Error('batch requires exactly one function argument') + } + if (batcher === null) { // If a batcher is set then signals will not trigger observers immediately // Instead they will be saved into the batcher to trigger after diff --git a/test/batching.test.js b/test/batching.test.js index d51cf93..83809c5 100644 --- a/test/batching.test.js +++ b/test/batching.test.js @@ -16,8 +16,7 @@ import { } from '../src/reactor.js' describe('Batching', () => { - // TODO add test and functionality for batch parameter validation - it('should delay and combine observer triggers within a batch block', () => { + it('consolidates duplicate observer triggers within a batch', () => { const reactor = new Reactor() let runCount = 0 let runValue @@ -39,43 +38,52 @@ describe('Batching', () => { assert.strictEqual(runValue, 'blarp') }) - it('should nest batch blocks with no consequence', () => { - const reactor = new Reactor() + it('postpones observer triggers within a batch till after the block is complete', () => { + const reactor = new Reactor({ foo: 'bar' }) + const triggerOrder = [] + new Observer(() => { + triggerOrder.push(reactor.foo) + })() + assert.deepStrictEqual(triggerOrder, ['bar']) + batch(() => { + reactor.foo = 'baz' + triggerOrder.push('qux') + }) + assert.deepStrictEqual(triggerOrder, ['bar', 'qux', 'baz']) + }) + + it('flattens nested batches to the outermost batch', () => { + const reactor = new Reactor({ foo: 'bar' }) let runCount = 0 - let runValue + const triggerOrder = [] new Observer(() => { runCount += 1 - runValue = reactor.foo + triggerOrder.push(reactor.foo) })() assert.strictEqual(runCount, 1) - assert.strictEqual(runValue, undefined) + assert.deepStrictEqual(triggerOrder, ['bar']) batch(() => { - reactor.foo = 'bleep' - assert.strictEqual(runCount, 1) - reactor.foo = 'bloop' - assert.strictEqual(runCount, 1) - reactor.foo = 'blarp' - assert.strictEqual(runCount, 1) batch(() => { - reactor.foo = 'bink' - assert.strictEqual(runCount, 1) - reactor.foo = 'bonk' - assert.strictEqual(runCount, 1) - reactor.foo = 'bup' - assert.strictEqual(runCount, 1) + reactor.foo = 'baz' + triggerOrder.push('qux') }) + reactor.foo = 'moo' + triggerOrder.push('mip') }) assert.strictEqual(runCount, 2) - assert.strictEqual(runValue, 'bup') + // The 'baz' update never gets seen by the observer + // Because the 'moo' update overrides it later + // The inner batch gets flattened to the outer batch + // so the observer triggers after 'mip' + assert.deepStrictEqual(triggerOrder, ['bar', 'qux', 'mip', 'moo']) }) - // What should happen when a batch hits an error? // Fail out straight away? (unsetting batcher of course) // Or should it collect the error and try to trigger the observers it got to so far? // The later might seem like a fail forward action, but it's actually more consistent // since the semantic we have is that writing to a signal triggers all observers synchronously // It is more consistent with what happens outside of the batch block - it('should trigger dependent observers from the batch block even if there is an error', () => { + it('triggers the dependent observers found before the error even if there is an error in a batch', () => { let runCount = 0 let runValue const reactor = new Reactor({ foo: 'bar' }) @@ -101,7 +109,7 @@ describe('Batching', () => { // Used to be batch would trigger a and b together // which would then double trigger c // Ideally a batch would only trigger c once - it('should consolidate redundant downstream triggers', () => { + it('consolidates redundant downstream triggers from chain dependencies', () => { const reactor = new Reactor({ a: 'foo', b: 'bar' @@ -147,7 +155,7 @@ describe('Batching', () => { // after triggering d it discovers that it needs to update c again [abdcd] // If we don't queue d to be be triggered again, it will have an outdated value for c // Anyway around it? - it('should not skip essential downstream triggers', () => { + it('does not skip essential downstream triggers from chain dependencies', () => { const reactor = new Reactor({ a: 'foo', b: 'bar' @@ -179,7 +187,7 @@ describe('Batching', () => { // foo -> a -> c // foo -> b -> c // Auto batching for signals should trigger c once - it('should automatically batch Signal writes', () => { + it('automatically batches signal writes', () => { const signal = new Signal('foo') let runCountA = 0 let runCountB = 0 @@ -217,7 +225,7 @@ describe('Batching', () => { }) // This should be the same as Signal since Observer values are a Signal // But testing it anyway for completeness - it('should automatically batch Observer writes', () => { + it('automatically batches observer writes', () => { const rootObserver = new Observer((x) => x) rootObserver('foo') let runCountA = 0 @@ -255,7 +263,7 @@ describe('Batching', () => { assert.strictEqual(observerC.value, 'barAbarB') }) - it('should automatically batch Reactor writes', () => { + it('automatically batches reactor writes', () => { let runCount = 0 const reactor = new Reactor(['foo', 'bar']) new Observer(() => { @@ -267,4 +275,25 @@ describe('Batching', () => { reactor.pop() assert.strictEqual(runCount, 2) }) + + it('throws an error if the batch function it is called with no arguments', () => { + assert.throws(() => batch(), { + name: 'Error', + message: 'batch requires exactly one function argument' + }) + }) + + it('throws an error if the batch function it is called a non-function argument', () => { + assert.throws(() => batch(1), { + name: 'Error', + message: 'batch requires exactly one function argument' + }) + }) + + it('throws an error if the batch function it is called with multiple arguments', () => { + assert.throws(() => batch(() => {}, () => {}), { + name: 'Error', + message: 'batch requires exactly one function argument' + }) + }) }) From fe57c821ad77bbe71039c1f78f88de4ca7007e58 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:26:58 +0800 Subject: [PATCH 37/71] Added parameter vaildation to hide and updates test naming --- src/reactor.js | 5 ++++- test/hiding.test.js | 31 ++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index ef80b32..2de3b8a 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -636,7 +636,10 @@ class Observer extends Function { // Unobserve is syntactic sugar to create a dummy observer to block the triggers // While also returning the contents of the block -const hide = (execute) => { +const hide = function (execute) { + if (arguments.length !== 1 || typeof execute !== 'function') { + throw new Error('hide requires exactly one function argument') + } let result dependencyStack.push(null) try { diff --git a/test/hiding.test.js b/test/hiding.test.js index f0c45e2..0812c1e 100644 --- a/test/hiding.test.js +++ b/test/hiding.test.js @@ -16,9 +16,7 @@ import { } from '../src/reactor.js' describe('Hiding', () => { - // TODO add test and functionality for hide parameter validation - - it('should not create dependencies inside hide block', () => { + it('does not create dependencies inside hide block', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' @@ -51,9 +49,7 @@ describe('Hiding', () => { assert.strictEqual(innerRunValue, 'baz') }) - // TODO should hide blocks be nestable? - - it('should return the result of the hide block', () => { + it('returns the result of the hide block', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' @@ -86,7 +82,7 @@ describe('Hiding', () => { assert.strictEqual(innerRunValue, 'baz') }) - it('should not self trigger in a hide block', () => { + it('avoids self triggering an observer by using a hide block', () => { const reactor = new Reactor(['a', 'b', 'c']) let runCount = 0 let runValue @@ -100,4 +96,25 @@ describe('Hiding', () => { assert.strictEqual(runCount, 1) assert.strictEqual(runValue, 'c') }) + + it('throws an error if the hide function is not called with a function', () => { + assert.throws(() => hide(), { + name: 'Error', + message: 'hide requires exactly one function argument' + }) + }) + + it('throws an error if the hide function is not called with a non-function argument', () => { + assert.throws(() => hide(1), { + name: 'Error', + message: 'hide requires exactly one function argument' + }) + }) + + it('throws an error if the hide function is called with multiple arguments', () => { + assert.throws(() => hide(() => {}, () => {}), { + name: 'Error', + message: 'hide requires exactly one function argument' + }) + }) }) From 8a874ddba157084df8f7c14a04e59a4d1de82f51 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:29:26 +0800 Subject: [PATCH 38/71] Updated error handling test naming --- test/errors.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/errors.test.js b/test/errors.test.js index 2785935..f83fd73 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -16,7 +16,7 @@ import { } from '../src/reactor.js' describe('Error Handling', () => { - it('should throw an error on a write if there is an Observer throws an error', () => { + it('throws an error on an update if there is an observer throws an error', () => { const reactor = new Reactor({ value: 'foo' }) new Observer(() => { if (reactor.value > 1) throw new Error('dummy error') @@ -27,7 +27,7 @@ describe('Error Handling', () => { }) }) - it('should throw a CompoundError if there are multiple Observer errors', () => { + it('throws a CompoundError if there are multiple errors from direct observers', () => { const reactor = new Reactor({ value: 1 }) new Observer(() => { if (reactor.value > 1) throw new Error('dummy error 1') @@ -40,7 +40,7 @@ describe('Error Handling', () => { }) }) - it('should throw a flattened CompoundError with chained observers', () => { + it('throws a flattened CompoundError if there are multiple errors from chained observers', () => { const reactor = new Reactor({ foo: 1 }) From 97987c6cb1d7708073ad28dd212b8170c15db987 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:36:08 +0800 Subject: [PATCH 39/71] Updated the features tests --- test/features.test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/features.test.js b/test/features.test.js index 1e3c388..2aee7be 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -17,7 +17,7 @@ import { describe('Minor Features', () => { describe('Start and Stop', () => { - it('should stop observing', () => { + it('deactivates observers with stop', () => { let counter = 0 let tracker const reactor = new Reactor({ value: 'foo' }) @@ -37,7 +37,7 @@ describe('Minor Features', () => { assert.equal(tracker, 'bar') }) - it('should start after stopping', () => { + it('reactivates observers with start after stopping', () => { let counter = 0 let tracker = null const reactor = new Reactor({ value: 'foo' }) @@ -57,7 +57,7 @@ describe('Minor Features', () => { assert.equal(tracker, 'moo') }) - it('should have no effect with repeated starts', () => { + it('has no effect with repeated start calls', () => { let counter = 0 let tracker = null const reactor = new Reactor({ value: 'foo' }) @@ -82,7 +82,7 @@ describe('Minor Features', () => { }) describe('Context and Subscriptions', () => { - it('should default context to undefined', () => { + it('defaults context to undefined', () => { let contextChecker = 'foo' new Observer((context) => { contextChecker = context @@ -90,7 +90,7 @@ describe('Minor Features', () => { assert(typeof contextChecker === 'undefined') }) - it('should set context', () => { + it('sets context by calling the observer with an argument', () => { let contextChecker const observer = new Observer((context) => { contextChecker = context @@ -102,7 +102,7 @@ describe('Minor Features', () => { assert.equal(contextChecker, dummyObject) }) - it('should set context with multiple params', () => { + it('sets context by calling the observer with multiple params', () => { let contextChecker const observer = new Observer((a, b, c) => { contextChecker = '' + a + b + c @@ -114,7 +114,7 @@ describe('Minor Features', () => { assert.equal(contextChecker, 'undefinedundefinedundefined') }) - it('should set context and react to it', () => { + it('retains the set context on an observer when getting triggered later', () => { const reactor = new Reactor() const contextChecker = {} const observer = new Observer(function (...args) { @@ -140,7 +140,7 @@ describe('Minor Features', () => { }) describe('Observer redefinition', () => { - it('should redefine an observer', () => { + it('redefines an observer by setting the execute property', () => { const reactor = new Reactor({ first: 'foo', second: 'bar' From 559e867796e6434bcf96654593c780914200956f Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 19 Aug 2025 03:38:06 +0800 Subject: [PATCH 40/71] updated complex test names --- test/complex.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/complex.test.js b/test/complex.test.js index 5ea0557..0793986 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -16,7 +16,7 @@ import { } from '../src/reactor.js' describe('Complex Setups', () => { - it('should be able to chain observers off each other', () => { + it('can chain observers off each other', () => { const reactor = new Reactor({ foo: 'bar' }) @@ -41,7 +41,7 @@ describe('Complex Setups', () => { assert.strictEqual(thirdObserver.value, '!!!baz!!!') }) - it.skip('should trigger observers once per write for triangle dependencies', () => { + it.skip('triggers observers once per write for triangle dependencies', () => { // We have the following triangle dependency // reactor -> first -> second // reactor -> second @@ -76,7 +76,7 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'bazBAZ') }) - it('should not trivially infinite loop when an observer calls another', () => { + it('does not trivially infinite loop when an observer calls another', () => { // Trivial case // observer2 = observer1() + 1 // observer2 both calls observer1 and reads its value so is dependent on it @@ -115,7 +115,7 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'baz1') }) - it.skip('should not infinite loop with three observers calling each other like functions', () => { + it.skip('does not infinite loop with three observers calling each other like functions', () => { // This is a more complex case // observer2 = observer1() + 1 // observer3 = observer1() + observer2() @@ -157,7 +157,7 @@ describe('Complex Setups', () => { // assert.strictEqual(secondObserver.value, 'baz1') }) - it('should be able to create observers inside other observers', () => { + it('can create observers inside other observers', () => { const reactor = new Reactor({ outer: 'foo', inner: 'bar' From 4b6c41cab066910aacbf9bfcd36c785d3b2c4978 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 20 Aug 2025 01:45:40 +0800 Subject: [PATCH 41/71] Cleaned up context tests and an outdated comment --- src/reactor.js | 3 +- test/features.test.js | 148 +++++++++++++++++++++++++++++------------- 2 files changed, 104 insertions(+), 47 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index 2de3b8a..bbbdb10 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -611,9 +611,8 @@ class Observer extends Function { observerInterface.setArgsContext = (...args) => { observerCore.argsContext = args } - // Expose the wrapped execute function + // Expose the wrapped execute function and restart the observer // Setting it keeps the context and dependents - // but puts the observer back to sleep Object.defineProperty(observerInterface, 'execute', { get () { return observerCore.execute }, set (newValue) { return observerCore.redefine(newValue) } diff --git a/test/features.test.js b/test/features.test.js index 2aee7be..14004ea 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -15,8 +15,26 @@ import { // shuck } from '../src/reactor.js' -describe('Minor Features', () => { - describe('Start and Stop', () => { +describe.only('Minor Features', () => { + describe('Starting and stopping observers', () => { + it('activates observers with start', () => { + let counter = 0 + let tracker + const reactor = new Reactor({ value: 'foo' }) + const observer = new Observer(() => { + counter += 1 + tracker = reactor.value + }) + assert.equal(counter, 0) + assert.equal(tracker, undefined) + observer.start() + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + reactor.value = 'bar' + assert.equal(counter, 2) + assert.equal(tracker, 'bar') + }) + it('deactivates observers with stop', () => { let counter = 0 let tracker @@ -25,7 +43,7 @@ describe('Minor Features', () => { counter += 1 tracker = reactor.value }) - observer() + observer.start() assert.equal(counter, 1) assert.equal(tracker, 'foo') reactor.value = 'bar' @@ -45,7 +63,7 @@ describe('Minor Features', () => { counter += 1 tracker = reactor.value }) - observer() + observer.start() assert.equal(counter, 1) assert.equal(tracker, 'foo') observer.stop() @@ -57,7 +75,7 @@ describe('Minor Features', () => { assert.equal(tracker, 'moo') }) - it('has no effect with repeated start calls', () => { + it('does nothing calling start on an active observer', () => { let counter = 0 let tracker = null const reactor = new Reactor({ value: 'foo' }) @@ -65,7 +83,10 @@ describe('Minor Features', () => { counter += 1 tracker = reactor.value }) - observer() + observer.start() + assert.equal(counter, 1) + assert.equal(tracker, 'foo') + observer.start() assert.equal(counter, 1) assert.equal(tracker, 'foo') observer.stop() @@ -81,65 +102,102 @@ describe('Minor Features', () => { }) }) - describe('Context and Subscriptions', () => { - it('defaults context to undefined', () => { + describe('Observer context setting', () => { + it('defaults single argument context to undefined', () => { + let contextChecker = 'foo' + new Observer((parameter) => { + contextChecker = parameter + })() + assert(typeof contextChecker === 'undefined') + }) + + it('defaults arguments context to an empty array', () => { + let contextChecker = 'foo' + new Observer(function () { + contextChecker = Array.from(arguments) + })() + assert.deepEqual(contextChecker, []) + }) + + it('defaults this context to undefined', () => { let contextChecker = 'foo' - new Observer((context) => { - contextChecker = context + new Observer(() => { + contextChecker = this })() assert(typeof contextChecker === 'undefined') }) - it('sets context by calling the observer with an argument', () => { + it('sets single argument context by calling the observer with an argument', () => { let contextChecker + const reactor = new Reactor({ foo: 'bar' }) const observer = new Observer((context) => { - contextChecker = context + contextChecker = reactor.foo + context }) - observer('foo') - assert.equal(contextChecker, 'foo') - const dummyObject = {} - observer(dummyObject) - assert.equal(contextChecker, dummyObject) + observer('baz') + assert.equal(contextChecker, 'barbaz') + reactor.foo = 'qux' + assert.equal(contextChecker, 'quxbaz') + observer() + assert.equal(contextChecker, 'quxundefined') }) - it('sets context by calling the observer with multiple params', () => { + it('sets multiple arguments context by calling the observer with multiple arguments', () => { let contextChecker + const reactor = new Reactor({ foo: 'bar' }) const observer = new Observer((a, b, c) => { - contextChecker = '' + a + b + c + contextChecker = reactor.foo + a + b + c }) - observer('foo', 'bar', 'baz') - assert.equal(contextChecker, 'foobarbaz') - contextChecker = null + observer('apple', 'banana', 'cherry') + assert.equal(contextChecker, 'barapplebananacherry') + reactor.foo = 'baz' + assert.equal(contextChecker, 'bazapplebananacherry') observer() - assert.equal(contextChecker, 'undefinedundefinedundefined') + assert.equal(contextChecker, 'bazundefinedundefinedundefined') }) - it('retains the set context on an observer when getting triggered later', () => { - const reactor = new Reactor() - const contextChecker = {} - const observer = new Observer(function (...args) { - contextChecker.this = this - contextChecker.args = args - contextChecker.result = reactor.foo + it('sets arguments context by calling the observer with arguments', () => { + let contextChecker + const reactor = new Reactor({ foo: 'bar' }) + const observer = new Observer(function (a, b, c) { + contextChecker = Array.from(arguments).join(reactor.foo) }) - const bar = { - baz: observer - } - assert(typeof contextChecker.this === 'undefined') - assert(typeof contextChecker.args === 'undefined') - assert(typeof contextChecker.result === 'undefined') - bar.baz('qux') - assert.equal(contextChecker.this, bar) - assert.equal(contextChecker.args[0], 'qux') - assert(typeof contextChecker.result === 'undefined') - reactor.foo = 'bop' - assert.equal(contextChecker.this, bar) - assert.equal(contextChecker.args[0], 'qux') - assert.equal(contextChecker.result, 'bop') + observer('apple', 'banana', 'cherry') + assert.equal(contextChecker, 'applebarbananabarcherry') + reactor.foo = 'baz' + assert.equal(contextChecker, 'applebazbananabazcherry') + observer() + assert.equal(contextChecker, '') }) }) - describe('Observer redefinition', () => { + describe('Observer execute setting', () => { + it('exposes the wrapped function through the execute property', () => { + const dummyFunction = function () {} + const observer = new Observer(dummyFunction) + assert.strictEqual(observer.execute, dummyFunction) + }) + it.only('deactivates the observer when setting the execute property', () => { + let runCounter = 0 + let runValue = null + const reactor = new Reactor({ foo: 'bar' }) + const observer = new Observer(() => { + runCounter += 1 + runValue = reactor.foo + }) + observer() + assert.equal(runCounter, 1) + assert.equal(runValue, 'bar') + reactor.foo = 'baz' + assert.equal(runCounter, 2) + assert.equal(runValue, 'baz') + observer.execute = () => { + runCounter += 1 + runValue = 'new' + reactor.foo + } + assert.equal(runCounter, 3) + assert.equal(runValue, 'newbaz') + }) + it('uses the new execute after being restarted') it('redefines an observer by setting the execute property', () => { const reactor = new Reactor({ first: 'foo', From 3a5a75eb97741a1fbdcd7db011efb5a738983762 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 20 Aug 2025 11:19:03 +0800 Subject: [PATCH 42/71] Can shuck observers to retrieve internal function --- src/reactor.js | 14 ++++++++------ test/features.test.js | 4 ++-- test/observer.test.js | 9 +++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/reactor.js b/src/reactor.js index bbbdb10..c1b59fc 100644 --- a/src/reactor.js +++ b/src/reactor.js @@ -605,6 +605,7 @@ class Observer extends Function { // Named setContext instead of exposing context property for cleaner syntax // `context` property is an array but trivial case of giving a single context argument // Should be expected to work but it doesnt + // TODO: Consider removing these features to maintain the purity of calling the observer as a function observerInterface.setThisContext = (that) => { observerCore.thisContext = that } @@ -697,12 +698,13 @@ const batch = function (execute) { } } -// Method for extracting a the internal object from the Reactor -const shuck = (reactor) => { - const core = reactorCoreExtractor.get(reactor) - if (core) return core.source - // In this case its a normal object. No need to shuck - return reactor +// Method for extracting the internal object from a Reactor +// or extracting the internal function from an Observer +const shuck = (shuckee) => { + let output = shuckee + if (Reactors.has(output)) output = reactorCoreExtractor.get(output).source + if (Observers.has(output)) output = observerCoreExtractor.get(output).execute + return output } // Custom Error to consolidate multiple errors together diff --git a/test/features.test.js b/test/features.test.js index 14004ea..8bf8aff 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -15,7 +15,7 @@ import { // shuck } from '../src/reactor.js' -describe.only('Minor Features', () => { +describe('Minor Features', () => { describe('Starting and stopping observers', () => { it('activates observers with start', () => { let counter = 0 @@ -176,7 +176,7 @@ describe.only('Minor Features', () => { const observer = new Observer(dummyFunction) assert.strictEqual(observer.execute, dummyFunction) }) - it.only('deactivates the observer when setting the execute property', () => { + it('deactivates the observer when setting the execute property', () => { let runCounter = 0 let runValue = null const reactor = new Reactor({ foo: 'bar' }) diff --git a/test/observer.test.js b/test/observer.test.js index 53a46d8..0135146 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -6,7 +6,7 @@ import { Observer, // Signals, Reactors, - // Observers, + Observers, // signalCoreExtractor, // reactorCoreExtractor, // observerCoreExtractor, @@ -17,7 +17,12 @@ import { describe('Observer', () => { describe('initializes with a function and returns it wrapped in an observer', () => { - it('initializes with a function argument', () => new Observer(() => {})) + it('initializes with a function returning it wrapped in an observer', () => { + const func = () => {} + const observer = new Observer(func) + assert(Observers.has(observer)) + assert.strictEqual(shuck(observer), func) + }) it('throws an error when initialized with no arguments', () => { assert.throws(() => new Observer(), { From fd8b0e5b165795def646dc99b8cb20b5a01bb1bf Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 01:15:22 +0800 Subject: [PATCH 43/71] Reverted README --- README.md | 368 +++--------------------------------------------------- 1 file changed, 17 insertions(+), 351 deletions(-) diff --git a/README.md b/README.md index 1507d7c..197dfc1 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,33 @@ Reactor.js ========== - -Reactor.js is a simple reactive front-end library. It provides +Reactor.js is a simple library for [reactive programming](http://en.wikipedia.org/wiki/Reactive_programming). It provides - `Reactor` objects that store reactive variables -- `Observer` functions that automatically track the reactive variables that they use and retrigger if any of these variables are updated. The function `ob` is shorthand for `new Observer` -- A function `el` that allows declarative element creation in javascript +- `Observer` functions that automatically track the reactive variables that they use and retrigger if any of these variables are updated -Here's a quick example of what Reactor does: +Here's a quick example of what Reactor.js does: ```javascript -import { Reactor, ob, el } from 'reactorjs' - -const rx = new Reactor({ - name: 'Anakin' +const reactor = new Reactor() +reactor.foo = 'bar' +const observer = new Observer(() => { + console.log('foo is ', reactor.foo) }) - -el(document.body, - el('main', - el('h1', 'Hello World!'), - el('h2', (x) => { x.id ='foo' }, () => 'returned text'), - el('defaults to div', ['this', 'is', 'an', 'array']), - el('p more class names', ob(() => ('My name is ' + rx.name))) - ) -) -//
-//

Hello World!

-//

returned text

-//
thisisanarray
-//

My name is Anakin

-//
- -rx.name = 'Darth' -//

My name is Anakin

-// Changes to -//

My name is Darth

+observer() // prints "foo is bar" +reactor.foo = 'moo' // prints "foo is moo" ``` - `Reactor` objects work like normal objects that you can set and get properties on - `Observer` functions work like normal functions that you can define and call - When an `Observer` reads a `Reactor` it registers itself as a dependent - When a `Reactor` is updated it automatically retriggers the dependent `Observer` functions -- `el` creates a DOM element - - The first argument is the type of element it creates - - Subsequent arguments are appended as children - - Function children are run with the context of the parent element - - Function return values are appended as children - - `Observer` functions automatically replace their child nodes when retriggered Reactor.js is meant to be unobtrusive and unopinionated. - No special syntax to learn. Everything is just plain javascript -- There is no need to manually declare listeners or bindings. Reactor automatically keeps track of all that for you. -- Use it for the whole front-end or just a few components. Elements created by Reactor are just normal DOM elements, and any variable can be easily replaced with a reactive one without changing the rest of your codebase. +- There is no need to manually declare listeners or bindings. Reactor.js automatically keeps track of all that for you. +- It imposes no particular structure on your code. Any variable can be easily replaced with a reactive one without changing the rest of your codebase. + +If you want to see Reactor.js in action, take a look at this [example todo list](https://jsfiddle.net/jgt46s0a/39/) -You try it yourself in a JSFiddle [here](https://jsfiddle.net/0voez9qn/) +Note: v2 of Reactor.js previously had some UI elements. This has been split out into a separate project [Elementary](https://github.com/fynyky/elementary) that is built ontop of Reactor.js. For v3 Reactor is focusing on just the core reactive components. Installation ------------ @@ -63,11 +39,7 @@ $ npm install reactorjs Import it using: ```javascript -import { - el, - ob, - attr, - bind, +import { Reactor, Observer, hide, @@ -78,223 +50,8 @@ import { It is also available directly from [unpkg](unpkg.com). You can import it in javascript using ```javascript -import { el, attr, bind, ob, Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactorjs' -``` - - -Elements --------- -The function `el(description, children...)` builds DOM elements. It appends the `children` arguments to a parent element created/referenced by the `description`. - -The `description` can be a `String` or an existing `Element`. If given a `String` it creates a new `Element` whose classes are the entire description, and the tag type is the first word of the description. - -```javascript -el('h1 foo bar') -``` -```html -

-``` - -If the first word is not a valid HTML tag it defaults to making a div - -```javascript -el('foo bar') -``` -```html -
-``` - -If given an existing `Element` it does nothing on its own but uses the provided element as a target for applying the `children` arguments. For example you can append things to the document body by doing -```javascript -el(document.body, 'hello world') -``` -```html - - hello world - -``` - -For convenience, if the string provided starts with `#` or `.` then instead of creating a new element, the description will be used as a [selector](https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors) and will try to find an existing matching element in the document. - -```javascript -el('#foo') // Finds an element with id="foo" -el('.bar') // Finds an element whose classes contain "bar" -``` - -This is admittedly a bit crude but should handle the most common cases. For cases which fall outside of this you can just use `document.querySelector` directly and provide the element as the argument. - -```javascript -el(document.querySelector('some query')) -``` - --------------------------------------------------------------------------------- - -`String` arguments provided as `children` are appended as text nodes -```javascript -el(h1, 'hello world') -``` -```html -

hello world

-``` -`Element` arguments are just appended directly -```javascript -el(h1, document.createElement('div')) -``` -```html -

-``` -Since `el` itself returns elements, this allows nesting of `el` calls to declaratively create the DOM - -```javascript -el(document.body, - el('main', - el('h1', 'Title Text'), - el('p', 'Paragraph text'), - ) -) +import { Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactorjs' ``` -```html - - -

Title Text

-

Paragraph text

- - -``` - --------------------------------------------------------------------------------- - -`Function` arguments are run in the context of the parent. This allows arbitrary manipulation of the parent such as attaching listeners, setting styles, etc - -```javascript -el('h1', function() { - this.id = 'foo' - this.onClick = () => console.log('clicked!') - this.style.color = 'red' -}) -``` -```html -

-``` - -The parent is also provided as the first argument to the function when it is called. This allows [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) to work - -```javascript -el('h1', x => { - x.id = 'foo' - x.onClick = () => console.log('clicked!') - x.style.color = 'red' -}) -``` -```html -

-``` -If the function returns a value, that value is appended as a child -```javascript -el('h1', - x => { - return 'some text' - }, - x => ' more text' -) -``` -```html -

some text more text

-``` - -The `attr(attribute, value)` function is provided as a shorthand for -```javascript -$ => { $.setAttribute(attribute, value) } -``` -This allows easy setting of attributes like this -```javascript -el('h1', attr('id', 'foo')) -``` -```html -

-``` - -Similarly the `bind(reactor, value)` function is provided as a shorthand for -```javascript -$ => { - $.oninput = () => { reactor[key] = $.value } - return new Observer(() => { $.value = reactor[key] }) -} -``` -This allows for easy 2-way binding for input fields and `Reactor` objects - -```javascript -const rx = new Reactor({ name: 'foo' }) -el('input', bind(rx, 'name')) -``` - - --------------------------------------------------------------------------------- - -`Array` arguments are flattened and its elements recursively appended - -```javascript -el('h1',[ - 'some text', - document.createElement('div'), - x => 'boop' -]) -``` -```html -

some text
boop

-``` - --------------------------------------------------------------------------------- - -`Promise` arguments create a comment placeholder. -```javascript -let somePromise = new Promise() -el('h1', somePromise) -``` -```html -

-``` -When the promise resolves this placeholder is replaced with the resolved value -```javascript -somePromise.resolve('resolved!') -``` -```html -

resolved!

-``` --------------------------------------------------------------------------------- - -`Observer` functions from Reactor.js are handled very similarly to functions. They are executed in the context of the parent. However they also leave a -set of comments bookmarking the children they produce. - -```javascript -const rx = new Reactor({ name: 'foo' }) -el('h1', ob(() => rx.name )) -``` -```html -

- - foo - -

-``` - -When the observer is retriggered, everything between the bookmarks is removed and replaced with the new output - - -```javascript -rx.name = 'bar' -``` -```html -

- - bar - -

-``` - -Read below for more details on how observers work - -Note: for observers attached as children via `el` they are deactivated automatically when their parent is not attached to the document. This should not affect most use cases since the observer is reactivated when the parent is reattached to the document. But note that unattached elements just being held in memory will not be changing. Reactors -------- @@ -664,99 +421,8 @@ Note that only the observer triggering is postponed till the end. The actual rea Summary ------- ```javascript -import { - el, attr, bind, ob, - Reactor, Observer, hide, batch, shuck -} from 'reactorjs' - -// el(description, children...) -el('h1') // Creates a h1 element with a class "h1" - -el('notAValidTag') // Creates a div with class "notAValidTag" - // Anything not a valid html tag defaults to a div - -el('notATag header body h1') // Creates a div with classes "notATag header body h1" - // Only the first word is used for tag type - // Subsequent words are just added as classes - -el('.foo') // Strings starting with '.' or '#' are parsed as query selectors -el('#foo') // They try to find a matching element instead of making a new one - -let aDiv = document.createElement('div') -el(aDiv) // Uses the provided element instead of creating a new one - - -el('h1', 'foo') // Creates

foo

- // Strings provided as children are inserted as text nodes - -el('h1', aDiv) // Creates

- // Elements provided as children are just appended - -el('h1', function(){this.id = 'foo'}) // Creates

- // Functions provided as children are - // executed in the context of the parent - -el('h1', x => { x.id = 'foo' }) // Also creates

- // The parent is also provided as an argument - // This allows arrow functions to work - -el('h1', () => "return value") // Creates

return value

- // Return values are appended as children - -let aPromise = new Promise() -el('h1', aPromise) // Creates

- // Places a comment to be replaced when the promise resolves -aPromise.resolve('resolved!') // Becomes

resolved!

- - -// Example of how el works with reactors and observers -// Full explanation of how Observers and Reactors work comes later on -// Attached observers use comments to bookmark their children -let rx = new Reactor({ foo: 'foo' }) -let reactiveEl = el('h1', ob(() => rx.foo)) -// Creates -//

- // - // foo - // -//

- -document.body.appendChild(reactiveEl) // Attached observers sleep when their - // parent is out of the DOM - // Need to attach it for reactivity - -// When updated anything inbetween the bookmarks gets replaces -rx.foo = 'bar' -// Updates to -//

- // - // bar - // -//

- - -el('h1', ['foo', 'bar', 'qux']) // Creates

foobarqux

- // Arrays or any iterable are done recursively - -// attr is shorthand for setting attributes -// These 2 are equivalent -el('h1', attr('id', 'foo')) -el('h1', self => self.setAttribute('id', 'foo')) - -// bind is shorthand for 2 way binding with a reactor -// These 2 are equivalent -el('h1', bind(rx, 'foo')) -el('h1', self => { - self.oninput = () => { rx['foo'] = self.value } - return new Observer(() => { self.value = rx['foo'] }) -}) - -// ob is shorthand for creating Observers -// These 2 are equivalent -ob(function(){}) -new Observer(function(){}) +import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' -// Reactors and Observers const reactor = new Reactor({ foo: 'bar' }) const observer = new Observer(() => { const result = 'reactor.foo is ' + reactor.foo // Sets a dependency on foo From 0e225fbfeb951c7fdb8dd9b43de2991421d1c267 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 01:35:09 +0800 Subject: [PATCH 44/71] Removed redundant index.js file --- src/index.js | 745 +++++++++++++++++++++++++++++++++++++++- src/reactor.js | 744 --------------------------------------- test/batching.test.js | 2 +- test/complex.test.js | 2 +- test/errors.test.js | 2 +- test/features.test.js | 2 +- test/hiding.test.js | 2 +- test/observer.test.js | 2 +- test/reactivity.test.js | 2 +- test/reactor.test.js | 2 +- test/signal.test.js | 2 +- 11 files changed, 753 insertions(+), 754 deletions(-) delete mode 100644 src/reactor.js diff --git a/src/index.js b/src/index.js index ad4f233..c1b59fc 100644 --- a/src/index.js +++ b/src/index.js @@ -1 +1,744 @@ -export * from './reactor.js' +import { WeakRefSet } from 'weak-ref-collections' + +// Global stack to automatically track dependencies +// - When an observer is updated, it first puts itself on the dependency stack +// - When a signal is read, it checks the top of the stack to see who is reading +// - The reader gets added as a dependent of the readee +// - The readee gets added as a dependency of the reader +// - When the signal evaluation is done, the observer pops itself off the stack +// The stack is used to track the latest signal caller automaticaly +// Using a stack allows nested signals to function correctly +const dependencyStack = [] + +// Allows "protected" variables by letting Signals/Reactors/Observers unwrap +// each others interfaces to access internal core variables +// In the constructor of each of them, they will map their external interfaces +// to their internal cores +const signalCoreExtractor = new WeakMap() +const reactorCoreExtractor = new WeakMap() +const observerCoreExtractor = new WeakMap() + +// A batcher is used to postpone observer triggers and batch them together +// When "batch" is called it adds sets a batcher to this global variable +// When a Signal is updated it checks if a batcher is set +// If it is, it adds that observer to this set instead of triggering it +// At the end of the execution, the batch call then calls all the observers +// Then clears the batcher again +let batcher = null + +// Cache of objects to their reactor proxies +// The same object should always get turned into the same Reactor +// This allows for consistent dependency tracking +// across multiple reads of the same object +const reactorCache = new WeakMap() + +// Helper function for checking if something is an object +function isObject (x) { + // functions are objects also but typeof to function + // nulls are not objects but typeof to objects + // the last bit is to check for nulls + const type = typeof (x) + return ((type === 'function' || type === 'object') && !!x) +} + +// Signals are observable functions representing values +// - Read a signal by calling it with no arguments +// - Write to a signal by calling it with the desired value as an argument +// - Define a "getter" signal by calling it with a definition as an argument +// When a Signal is read by an Observer it saves that Observer as a dependent +// When a Signal is written to it automatically triggers dependents +// When a Signal returns an object it is automatically wrapped in a Reactor +// ----------------------------------------------------------------------------- +// Examples +// let a = new Signal(1) Initializes it with value 1 +// a() Returns 1 +// a(2) Sets the value to 2 +const Signals = new WeakSet() +class Signal extends Function { + // Signals are made up of 2 main parts + // - The core: The properties & methods which lets signals work + // - The interface: The function returned to the user to use + constructor (initialValue) { + // Early rejection for multiple arguments + if (arguments.length > 1) { + throw new Error('Signal constructor takes at most one argument') + } + + // The "guts" of a Signal containing properties and methods + // All actual functionality & state should be built into the core + // Should be completely agnostic to syntactic sugar + const signalCore = { + // Signal state + // The set value. Purposely commented out to be undefined as a base + // value: undefined, + // The Observers which rely on this Signal + dependents: new Set(), + // callback set by parent Reactor to allow removal + // Used to delete Signals with no dependents + // To reduce memory leaks + removeSelf: () => {}, + // Life of a read + // - check to see who is asking + // - register them as a dependent and register self as their dependency + // - return the appropriate static or dynamic value + // - wrap the result in a Reactor if its an object + read () { + // Check the global stack for the most recent observer being updated + // Assume this is the caller and set it as a dependent + // Symmetrically register dependent/dependency relationship + const dependent = dependencyStack[dependencyStack.length - 1] + if (dependent) { + this.dependents.add(dependent) + dependent.addDependency(this) + } + const output = this.value + + // If it's not an object then just return it right away + // Cleaner and faster than the alternative approach of constructing a Reactor + // and catching an error + if (isObject(output)) return new Reactor(output) + else return output + }, + + // Life of a write + // - Store the provided value + // - Trigger any dependent Observers while collecting errors thrown + // - Throw a CompoundError if necessary + write (newValue) { + // Design decision to wrap even individual signal writes in a batch + // This allows for consistency with all dependent triggering + // since Reactor writes are also batched + // Wrap the whole function so we catch potential triggers + // from defining internal object values and wrapping output as a Reactor + return batch(() => { + // Avoid triggering observers if same value is written + if (this.value === newValue) return (this.value = newValue) + // Save the new value/definition + const output = (this.value = newValue) + + // Build dependency queue + // Do not trigger dependents directly and leave it to be handled by the batcher + Array.from(this.dependents).forEach(dependent => { + // Do this so that the dependent is added to the end of the batcher queue + // Needed to ensure downstream observers are triggered again when necessary + // as we iterate through the batched dependents + // Generally modifying an iterable while iterating through it is a bad idea + // But in this case it's necessary as we can't know all the downstream dependents ahead of time + batcher.delete(dependent) + batcher.add(dependent) + }) + // If it's not an object then just return it right away + // Cleaner and faster than the alternative approach of constructing a Reactor + // and catching an error + if (isObject(output)) return new Reactor(output) + else return output + }) + }, + // Used by observers to remove themselves from this as dependents + // Also removesSelf from any owners if there are no more dependents + removeDependent (dependent) { + this.dependents.delete(dependent) + // TODO should we be doing this? clean self up if no dependents + // What if you want it to stick around for future reads + if (this.dependents.size === 0) this.removeSelf() + } + + } + + // The interface function returned to the user to utilize the signal + // This is done to abstract away the messiness of how the signals work + // Should contain no additional functionality and be purely syntactic sugar + super() + const signalInterface = new Proxy(this, { + apply (target, thisArg, args) { + // Early rejection for multiple arguments + if (args.length > 1) { + throw new Error('Signal objects take at most one argument for writes and zero arguments for reads') + } + // An empty call is treated as a read + if (args.length === 0) return signalCore.read() + // A non empty call is treated as a write + return signalCore.write(args[0]) + } + }) + + // Register the Signal for debugging/typechecking purposes + signalCoreExtractor.set(signalInterface, signalCore) + Signals.add(signalInterface) + + // Initialize with the provided value before returning + signalCore.write(initialValue) + return signalInterface + } +} + +// WeakSet of all Reactors to check if something is a Reactor +// Need to implement it this way because you can check instanceof Proxies +const Reactors = new WeakSet() +// Reactors are observable object proxies +// - They mostly function transparently passing calls to the internal object +// - The main difference is that they track and notify Observers automatically +// - Any object returned from reading a property is itself wrapped in a Reactor +// - Setting a property as a Defintion converts it into a getter instead +// When a Reactor property is read by an Observer it saves it as a dependent +// When a Reactor property is updated it automatically notifies dependents +// ----------------------------------------------------------------------------- +// Examples +// const a = new Reactor() Initializes a new empty Reactor object +// a.foo = 2 +// a.foo Returns 2 as expected +// const b = new Reactor({ Wraps an existing object into a Reactor +// quu: "mux" +// moo: { +// cheese: "banana" +// } +// }) +class Reactor { + constructor (initializedSource) { + // If the source is already a reactor then do nothing and return it + // No double wrapping of reactors allowed + if (Reactors.has(initializedSource)) return initializedSource + + // Check to see if we've wrapped this object before + // This allows consistency of dependencies with repeated read calls + const existingReactor = reactorCache.get(initializedSource) + if (existingReactor) return existingReactor + + if (arguments.length > 1) { + throw new Error('Reactor constructor takes at most one argument') + } + + // The source is the internal proxied object + // If no source is provided then provide a new default object + if (arguments.length === 0) initializedSource = this + + // Early rejection for non-objects + // Could be handled later by proxy creation, but cleaner to have the logic here + // Can use the same function as Signal does for it's wrapping + if (!isObject(initializedSource)) { + throw new TypeError('Reactor source must be an Object') + } + + // The "guts" of a Reactor containing properties and methods + // All actual functionality & state should be built into the core + // Should be completely agnostic to syntactic sugar + const reactorCore = { + source: initializedSource, + // Dependency tracking not for any particular property + // but for the reactor overall + selfSignal: new Signal(null), + + apply (thisArg, argumentsList) { + // Function calls on reactor properties are automatically batched + // This allows compound function calls like "Array.push" + // to only trigger one round of observer updates + return batch(() => { + // For native object methods which cant use a Proxy as `this` + // try again with the underlying object + // Some limitations if the failed attempt has side effects prior to throwing an error + // this will double them + // Generally acceptable because native objects should be expected to not leave a mess + // Potentially some issues in user defined objects getting wrapped in Reactor + // using private properties and leaving a mess on error + // Also this still wont fix being unable to pass the proxy to static methods + // `proxiedMap.keys()` will work because keys gets wrapped by this handler + // `Map.prototype.keys.call(proxiedMap)` won't work because it doesnt get wrapped + try { + return Reflect.apply(this.source, thisArg, argumentsList) + } catch (error) { + if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { + const core = reactorCoreExtractor.get(thisArg) + if (typeof core !== 'undefined') { + // Note that this.source and core.source are different + // core.source is the underlying object + // this.source is the function which is being called with the object as `this` + return Reflect.apply(this.source, core.source, argumentsList) + } + } + // If any other type of error, or if there's nothing to unwrap throw error anyway + // because then its not a problem with Reactor wrapping + throw error + } + }) + }, + + // Instead of reading a property directly + // Reactor properties are read through a trivial Signal + // This handles dependency tracking and sub-object Reactor wrapping + // Accessor Signals need to be stored to allow persistent dependencies + getSignals: {}, + get (property, receiver) { + // Disable unnecessary wrapping for unmodifiable properties + // Needed because Array prototype checking fails if wrapped + // Specificaly [].map() + const descriptor = Object.getOwnPropertyDescriptor( + this.source, property + ) + if (descriptor && !descriptor.writable && !descriptor.configurable) { + return Reflect.get(this.source, property, receiver) + } + // Lazily instantiate accessor signals + this.getSignals[property] = + // Need to use hasOwnProperty instead of a normal get to avoid + // the basic Object prototype properties + // e.g. constructor + Object.prototype.hasOwnProperty.call(this.getSignals, property) + ? this.getSignals[property] + : new Signal() + // User accessor signals to give the actual output + // This enables automatic dependency tracking + const signalCore = signalCoreExtractor.get(this.getSignals[property]) + signalCore.removeSelf = () => delete this.getSignals[property] + const currentValue = (() => { + // Handle getters which require hidden/native properties + // If putting the proxy as `this` fails then reveal the underlying object + // There are limitations though + // - If the getter have any side effects on error this will trigger them twice + // - If the getter also reads other public properties this will not build dependencies + // For example this will fail to build a dependency on `this.normalProp` if proxied + // get (prop) { + // return this.#hiddenProp + this.normalProp + // } + // This is sort of a necessary limitation of dealing with native code though + // Better than failing overall? + // An alternative is to detect the "nativeness" of an object and pass through + // That seems quite messy though + try { + return Reflect.get(this.source, property, receiver) + } catch (error) { + // We trim to specific "incompatible receiver" TypeErrors to minimize unnecessary double retries to actual proxy problems + // but it could still happen for other TypeErrors + if (error.name === 'TypeError' && error.message.includes('incompatible receiver')) return Reflect.get(this.source, property, this.source) + throw error + } + })() + signalCore.value = currentValue + return signalCore.read() + }, + + // Notifies dependents of the defined property + // Also translates Definitions sets into getter methods + // We trap defineProperty instead of set because it avoids the ambiguity + // of access through the prototype chain + defineProperty (property, descriptor) { + const didSucceed = Reflect.defineProperty( + this.source, property, descriptor + ) + // Trigger dependents before returning + this.trigger(property) + return didSucceed + }, + + // Transparently delete the property but also trigger dependents + deleteProperty (property) { + const didSucceed = Reflect.deleteProperty(this.source, property) + this.trigger(property) + return didSucceed + }, + + // Have a map of dummy Signals to keep track of dependents on has + // We don't resuse the get Signals to avoid triggering getters + hasSignals: {}, + has (property) { + // Lazily instantiate has signals + this.hasSignals[property] = + // Need to use hasOwnProperty instead of a normal get to avoid + // the basic Object prototype properties + // e.g. constructor + Object.prototype.hasOwnProperty.call(this.hasSignals, property) + ? this.hasSignals[property] + : new Signal(null) + // User accessor signals to give the actual output + // This enables automatic dependency tracking + const signalCore = signalCoreExtractor.get(this.hasSignals[property]) + signalCore.removeSelf = () => delete this.hasSignals[property] + const currentValue = Reflect.has(this.source, property) + signalCore.value = currentValue + return signalCore.read() + }, + + // Subscribe to the overall reactor by reading the dummy signal + ownKeys () { + const currentKeys = Reflect.ownKeys(this.source) + const signalCore = signalCoreExtractor.get(this.selfSignal) + signalCore.value = currentKeys + return signalCore.read() + }, + + // Force dependencies to trigger + // Hack to do this by trivially "redefining" the signal + trigger (property) { + // Calculate the actual new values observers will receive + // This avoids redundant triggering if they were the same + const getValue = Reflect.get(this.source, property) + const hasValue = Reflect.has(this.source, property) + // For ownKeys you need to manually calculate the set comparison + const currentOwnKeysValue = Reflect.ownKeys(this.source) + const oldOwnKeysValue = signalCoreExtractor.get(this.selfSignal).value + const ownKeysChanged = (() => { + const currentSet = new Set(currentOwnKeysValue) + const oldSet = new Set(oldOwnKeysValue) + if (currentSet.size !== oldSet.size) return true + for (const key of currentSet) { + if (!oldSet.has(key)) return true + } + return false + })() + // Batch together to avoid redundant triggering for shared observers + // This might be redundant because the only way this happens is by calling native methods + // which are already batched anyway. But keeping for safety + batch(() => { + if (this.getSignals[property]) this.getSignals[property](getValue) + if (this.hasSignals[property]) this.hasSignals[property](hasValue) + if (ownKeysChanged) this.selfSignal(currentOwnKeysValue) + }) + } + } + + // The interface proxy returned to the user to utilize the Reactor + // This is done to abstract away the messiness of how the Reactors work + // Should contain no additional functionality and be purely syntactic sugar + const reactorInterface = new Proxy(reactorCore.source, { + apply (target, thisArg, argumentsList) { + if (target === reactorCore.source) { + return reactorCore.apply(thisArg, argumentsList) + } + throw new Error('Proxy target does not match initialized object') + }, + get (target, property, receiver) { + if (target === reactorCore.source) { + return reactorCore.get(property, receiver) + } + throw new Error('Proxy target does not match initialized object') + }, + defineProperty (target, property, descriptor) { + if (target === reactorCore.source) { + return reactorCore.defineProperty(property, descriptor) + } + throw new Error('Proxy target does not match initialized object') + }, + deleteProperty (target, property) { + if (target === reactorCore.source) { + return reactorCore.deleteProperty(property) + } + throw new Error('Proxy target does not match initialized object') + }, + has (target, property) { + if (target === reactorCore.source) { + return reactorCore.has(property) + } + throw new Error('Proxy target does not match initialized object') + }, + ownKeys (target) { + if (target === reactorCore.source) { + return reactorCore.ownKeys() + } + throw new Error('Proxy target does not match initialized object') + } + }) + // Register the reactor for debugging/typechecking purposes + Reactors.add(reactorInterface) + reactorCoreExtractor.set(reactorInterface, reactorCore) + reactorCache.set(initializedSource, reactorInterface) + return reactorInterface + } +} + +// Observers are functions which automatically track their dependencies +// Once triggered they automatically retrigger whenever a dependency is updated +// A dependency is any read of Signal or property of a Reactor +// Triggering an observer with parameters saves them for future auto triggers +// Observers can be stopped and restarted +// Starting after stopping causes the Observer to execute again +// Starting does nothing if an Observer is already awake +// ----------------------------------------------------------------------------- +// Examples +// let a = new Signal(1) +// let b = new Reactor() +// b.foo = "bar" +// let observer = new Observer(() => { This will trigger whenever +// console.log("a is now " + a()) a or b.foo are updated +// console.log("b.foois now " + b.foo) +// }) +// observer() +// a(2) This will trigger an update +// +// observer.stop() This will block triggers +// b.foo = "cheese" No trigger since we stopped it +// +// observer.start() Will rerun the function +// and allow updates again +// +// observer.start() Does nothing since already started +const Observers = new WeakSet() +class Observer extends Function { + constructor (execute) { + if (arguments.length !== 1) { + throw new Error('Observer constructor requires exactly one argument') + } + + // Parameter validation + if (typeof execute !== 'function') { + throw new TypeError('Cannot create observer with a non-function') + } + + // Internal engine of an Observer for how it works + // All actual functionality & state should be built into the core + // Should be completely agnostic to syntactic sugar + const observerCore = { + // Core function the observer is wrapping + execute, + // Whether automatic triggers will be accepted + awake: false, + // The Signals the execution block reads from + // Cleared and rebuilt at every trigger + // Store dependencies weakly to avoid memory loops + // They're only stored to break the connection later anyway + dependencies: new WeakRefSet(), + // Stored return value of the last successful execute + // Stored in a Signal which makes it observable itself + value: new Signal(), + // Flag on whether this is a unobserve block + // Avoids creating dependencies in that case + + // Symmetrically removes dependencies + clearDependencies () { + // Go upstream to break the connection + if (this.dependencies === null) return + this.dependencies.forEach(dependency => { + dependency.removeDependent(this) + }) + // Drop own references + this.dependencies = new WeakRefSet() + }, + + // External call to add a dependency + // Wrapped to to encapsulate implementation + addDependency (dependency) { + this.dependencies.add(dependency) + }, + + // Trigger the execute block and build dependencies + // Does nothing if observer is asleep + // If it was awake return true + // If it was asleep return false + trigger () { + if (this.awake) { + this.clearDependencies() + // Put self on the dependency stack + // So any signals read by execute know who is calling + dependencyStack.push(this) + let result + // Wrap execute in a try block so that + // dependency stack is popped even if an error is occured + // Allows users to catch errors themselves and handle them + try { + result = this.execute.apply(this.thisContext, this.argsContext) + } finally { + dependencyStack.pop() + } + // Store the result as a subscribable signal + // This will trigger any downstream observers + // which depend on this observers value + this.value(result) + return true + } + return false + }, + + // Redefines the observer with a new exec function + // Maintains the context, Signal dependents, and awake status + redefine (newExecute) { + if (typeof newExecute !== 'function') { + throw new TypeError('Cannot create observer with a non-function') + } + this.clearDependencies() + this.execute = newExecute + // If awake this will update the value Signal and notify observers downstream + // If alseep this will correctly do nothing leaving value to the last triggered value + return this.trigger() + }, + + // Pause the observer preventing further triggers + // Returns false if it was already asleep + // Returns true if it was awake + stop () { + if (!this.awake) return false + this.awake = false + this.clearDependencies() + return true + }, + + // Restart the observer if it is not already awake + // Returns false is already awake + // Returns true if it was woken up + start () { + if (this.awake) return false + this.awake = true + this.trigger() + return true + } + + } + + // Public interace to hide the ugliness of how observers work + // An empty call force triggers the block and turns it on + // A call with arguments gets those arguments passed as a context + // for that and future retriggers + super() + const observerInterface = new Proxy(this, { + apply (target, thisArg, args) { + observerCore.thisContext = thisArg + observerCore.argsContext = args + observerCore.awake = true + observerCore.trigger() + return observerCore.value() + }, + construct (target, args, receiver) { + return Reflect.construct(observerCore.execute, args, observerInterface) + } + }) + observerInterface.start = () => observerCore.start() + observerInterface.stop = () => observerCore.stop() + // Note that setting a new context does not cause the observer to trigger + // The observer will need to be started and triggered + // Named setContext instead of exposing context property for cleaner syntax + // `context` property is an array but trivial case of giving a single context argument + // Should be expected to work but it doesnt + // TODO: Consider removing these features to maintain the purity of calling the observer as a function + observerInterface.setThisContext = (that) => { + observerCore.thisContext = that + } + observerInterface.setArgsContext = (...args) => { + observerCore.argsContext = args + } + // Expose the wrapped execute function and restart the observer + // Setting it keeps the context and dependents + Object.defineProperty(observerInterface, 'execute', { + get () { return observerCore.execute }, + set (newValue) { return observerCore.redefine(newValue) } + }) + // Allow reads of the last return value of execute + // As a Signal this itself is observable and + // builds dependencies if done within another observer + Object.defineProperty(observerInterface, 'value', { + get () { return observerCore.value() } + }) + + // Register the observer for debugging/typechecking purposes + observerCoreExtractor.set(observerInterface, observerCore) + Observers.add(observerInterface) + + // Does not trigger on initialization until () or .start() are called + return observerInterface + } +} + +// Unobserve is syntactic sugar to create a dummy observer to block the triggers +// While also returning the contents of the block +const hide = function (execute) { + if (arguments.length !== 1 || typeof execute !== 'function') { + throw new Error('hide requires exactly one function argument') + } + let result + dependencyStack.push(null) + try { + result = execute() + } finally { + dependencyStack.pop() + } + return result +} + +// Method for allowing users to batch multiple observer updates together +const batch = function (execute) { + if (arguments.length !== 1 || typeof execute !== 'function') { + throw new Error('batch requires exactly one function argument') + } + + if (batcher === null) { + // If a batcher is set then signals will not trigger observers immediately + // Instead they will be saved into the batcher to trigger after + // Using a Set allows the removal of redundant triggering in observers + batcher = new Set() + const errorList = [] + + // Execute the given block and collect the triggerd observers + let result + try { result = execute() } catch (error) { + // If I want to fail forward store the error + // and try to trigger the relevant observers so far + errorList.push(error) + // If I want to fail fast instead + // batcher = null + // throw error + } + + // Trigger the collected observers + // If an error occurs, collect it and keep going + // A conslidated error will be thrown at the end of propagation + for (const observer of batcher) { + try { observer.trigger() } catch (error) { errorList.push(error) } + } + + // If any errors occured during propagation + // consolidate and throw them + batcher = null + if (errorList.length === 1) { + throw errorList[0] + } else if (errorList.length > 1) { + const errorMessage = 'Multiple errors from batched reactor observers' + throw new CompoundError(errorMessage, errorList) + } + + return result + // No need to do anything if batching is already taking place } + } else { + return execute() + } +} + +// Method for extracting the internal object from a Reactor +// or extracting the internal function from an Observer +const shuck = (shuckee) => { + let output = shuckee + if (Reactors.has(output)) output = reactorCoreExtractor.get(output).source + if (Observers.has(output)) output = observerCoreExtractor.get(output).execute + return output +} + +// Custom Error to consolidate multiple errors together +class CompoundError extends Error { + constructor (message, errorList) { + // Flatten any compound errors in the error list + errorList = errorList.flatMap(error => { + if (error instanceof CompoundError) return error.cause + return error + }) + // Build the message to display all the component errors + message = message + '\n' + errorList.length + ' errors in total' + for (const error of errorList) { + const errorDescription = + error.stack != null ? error.stack : error.toString() + message = message + '\n' + errorDescription + } + super(message, { cause: errorList }) + this.name = this.constructor.name + return this + } +} + +export { + Signal, + Reactor, + Observer, + Signals, + Reactors, + Observers, + signalCoreExtractor, + reactorCoreExtractor, + observerCoreExtractor, + hide, + batch, + shuck +} diff --git a/src/reactor.js b/src/reactor.js deleted file mode 100644 index c1b59fc..0000000 --- a/src/reactor.js +++ /dev/null @@ -1,744 +0,0 @@ -import { WeakRefSet } from 'weak-ref-collections' - -// Global stack to automatically track dependencies -// - When an observer is updated, it first puts itself on the dependency stack -// - When a signal is read, it checks the top of the stack to see who is reading -// - The reader gets added as a dependent of the readee -// - The readee gets added as a dependency of the reader -// - When the signal evaluation is done, the observer pops itself off the stack -// The stack is used to track the latest signal caller automaticaly -// Using a stack allows nested signals to function correctly -const dependencyStack = [] - -// Allows "protected" variables by letting Signals/Reactors/Observers unwrap -// each others interfaces to access internal core variables -// In the constructor of each of them, they will map their external interfaces -// to their internal cores -const signalCoreExtractor = new WeakMap() -const reactorCoreExtractor = new WeakMap() -const observerCoreExtractor = new WeakMap() - -// A batcher is used to postpone observer triggers and batch them together -// When "batch" is called it adds sets a batcher to this global variable -// When a Signal is updated it checks if a batcher is set -// If it is, it adds that observer to this set instead of triggering it -// At the end of the execution, the batch call then calls all the observers -// Then clears the batcher again -let batcher = null - -// Cache of objects to their reactor proxies -// The same object should always get turned into the same Reactor -// This allows for consistent dependency tracking -// across multiple reads of the same object -const reactorCache = new WeakMap() - -// Helper function for checking if something is an object -function isObject (x) { - // functions are objects also but typeof to function - // nulls are not objects but typeof to objects - // the last bit is to check for nulls - const type = typeof (x) - return ((type === 'function' || type === 'object') && !!x) -} - -// Signals are observable functions representing values -// - Read a signal by calling it with no arguments -// - Write to a signal by calling it with the desired value as an argument -// - Define a "getter" signal by calling it with a definition as an argument -// When a Signal is read by an Observer it saves that Observer as a dependent -// When a Signal is written to it automatically triggers dependents -// When a Signal returns an object it is automatically wrapped in a Reactor -// ----------------------------------------------------------------------------- -// Examples -// let a = new Signal(1) Initializes it with value 1 -// a() Returns 1 -// a(2) Sets the value to 2 -const Signals = new WeakSet() -class Signal extends Function { - // Signals are made up of 2 main parts - // - The core: The properties & methods which lets signals work - // - The interface: The function returned to the user to use - constructor (initialValue) { - // Early rejection for multiple arguments - if (arguments.length > 1) { - throw new Error('Signal constructor takes at most one argument') - } - - // The "guts" of a Signal containing properties and methods - // All actual functionality & state should be built into the core - // Should be completely agnostic to syntactic sugar - const signalCore = { - // Signal state - // The set value. Purposely commented out to be undefined as a base - // value: undefined, - // The Observers which rely on this Signal - dependents: new Set(), - // callback set by parent Reactor to allow removal - // Used to delete Signals with no dependents - // To reduce memory leaks - removeSelf: () => {}, - // Life of a read - // - check to see who is asking - // - register them as a dependent and register self as their dependency - // - return the appropriate static or dynamic value - // - wrap the result in a Reactor if its an object - read () { - // Check the global stack for the most recent observer being updated - // Assume this is the caller and set it as a dependent - // Symmetrically register dependent/dependency relationship - const dependent = dependencyStack[dependencyStack.length - 1] - if (dependent) { - this.dependents.add(dependent) - dependent.addDependency(this) - } - const output = this.value - - // If it's not an object then just return it right away - // Cleaner and faster than the alternative approach of constructing a Reactor - // and catching an error - if (isObject(output)) return new Reactor(output) - else return output - }, - - // Life of a write - // - Store the provided value - // - Trigger any dependent Observers while collecting errors thrown - // - Throw a CompoundError if necessary - write (newValue) { - // Design decision to wrap even individual signal writes in a batch - // This allows for consistency with all dependent triggering - // since Reactor writes are also batched - // Wrap the whole function so we catch potential triggers - // from defining internal object values and wrapping output as a Reactor - return batch(() => { - // Avoid triggering observers if same value is written - if (this.value === newValue) return (this.value = newValue) - // Save the new value/definition - const output = (this.value = newValue) - - // Build dependency queue - // Do not trigger dependents directly and leave it to be handled by the batcher - Array.from(this.dependents).forEach(dependent => { - // Do this so that the dependent is added to the end of the batcher queue - // Needed to ensure downstream observers are triggered again when necessary - // as we iterate through the batched dependents - // Generally modifying an iterable while iterating through it is a bad idea - // But in this case it's necessary as we can't know all the downstream dependents ahead of time - batcher.delete(dependent) - batcher.add(dependent) - }) - // If it's not an object then just return it right away - // Cleaner and faster than the alternative approach of constructing a Reactor - // and catching an error - if (isObject(output)) return new Reactor(output) - else return output - }) - }, - // Used by observers to remove themselves from this as dependents - // Also removesSelf from any owners if there are no more dependents - removeDependent (dependent) { - this.dependents.delete(dependent) - // TODO should we be doing this? clean self up if no dependents - // What if you want it to stick around for future reads - if (this.dependents.size === 0) this.removeSelf() - } - - } - - // The interface function returned to the user to utilize the signal - // This is done to abstract away the messiness of how the signals work - // Should contain no additional functionality and be purely syntactic sugar - super() - const signalInterface = new Proxy(this, { - apply (target, thisArg, args) { - // Early rejection for multiple arguments - if (args.length > 1) { - throw new Error('Signal objects take at most one argument for writes and zero arguments for reads') - } - // An empty call is treated as a read - if (args.length === 0) return signalCore.read() - // A non empty call is treated as a write - return signalCore.write(args[0]) - } - }) - - // Register the Signal for debugging/typechecking purposes - signalCoreExtractor.set(signalInterface, signalCore) - Signals.add(signalInterface) - - // Initialize with the provided value before returning - signalCore.write(initialValue) - return signalInterface - } -} - -// WeakSet of all Reactors to check if something is a Reactor -// Need to implement it this way because you can check instanceof Proxies -const Reactors = new WeakSet() -// Reactors are observable object proxies -// - They mostly function transparently passing calls to the internal object -// - The main difference is that they track and notify Observers automatically -// - Any object returned from reading a property is itself wrapped in a Reactor -// - Setting a property as a Defintion converts it into a getter instead -// When a Reactor property is read by an Observer it saves it as a dependent -// When a Reactor property is updated it automatically notifies dependents -// ----------------------------------------------------------------------------- -// Examples -// const a = new Reactor() Initializes a new empty Reactor object -// a.foo = 2 -// a.foo Returns 2 as expected -// const b = new Reactor({ Wraps an existing object into a Reactor -// quu: "mux" -// moo: { -// cheese: "banana" -// } -// }) -class Reactor { - constructor (initializedSource) { - // If the source is already a reactor then do nothing and return it - // No double wrapping of reactors allowed - if (Reactors.has(initializedSource)) return initializedSource - - // Check to see if we've wrapped this object before - // This allows consistency of dependencies with repeated read calls - const existingReactor = reactorCache.get(initializedSource) - if (existingReactor) return existingReactor - - if (arguments.length > 1) { - throw new Error('Reactor constructor takes at most one argument') - } - - // The source is the internal proxied object - // If no source is provided then provide a new default object - if (arguments.length === 0) initializedSource = this - - // Early rejection for non-objects - // Could be handled later by proxy creation, but cleaner to have the logic here - // Can use the same function as Signal does for it's wrapping - if (!isObject(initializedSource)) { - throw new TypeError('Reactor source must be an Object') - } - - // The "guts" of a Reactor containing properties and methods - // All actual functionality & state should be built into the core - // Should be completely agnostic to syntactic sugar - const reactorCore = { - source: initializedSource, - // Dependency tracking not for any particular property - // but for the reactor overall - selfSignal: new Signal(null), - - apply (thisArg, argumentsList) { - // Function calls on reactor properties are automatically batched - // This allows compound function calls like "Array.push" - // to only trigger one round of observer updates - return batch(() => { - // For native object methods which cant use a Proxy as `this` - // try again with the underlying object - // Some limitations if the failed attempt has side effects prior to throwing an error - // this will double them - // Generally acceptable because native objects should be expected to not leave a mess - // Potentially some issues in user defined objects getting wrapped in Reactor - // using private properties and leaving a mess on error - // Also this still wont fix being unable to pass the proxy to static methods - // `proxiedMap.keys()` will work because keys gets wrapped by this handler - // `Map.prototype.keys.call(proxiedMap)` won't work because it doesnt get wrapped - try { - return Reflect.apply(this.source, thisArg, argumentsList) - } catch (error) { - if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { - const core = reactorCoreExtractor.get(thisArg) - if (typeof core !== 'undefined') { - // Note that this.source and core.source are different - // core.source is the underlying object - // this.source is the function which is being called with the object as `this` - return Reflect.apply(this.source, core.source, argumentsList) - } - } - // If any other type of error, or if there's nothing to unwrap throw error anyway - // because then its not a problem with Reactor wrapping - throw error - } - }) - }, - - // Instead of reading a property directly - // Reactor properties are read through a trivial Signal - // This handles dependency tracking and sub-object Reactor wrapping - // Accessor Signals need to be stored to allow persistent dependencies - getSignals: {}, - get (property, receiver) { - // Disable unnecessary wrapping for unmodifiable properties - // Needed because Array prototype checking fails if wrapped - // Specificaly [].map() - const descriptor = Object.getOwnPropertyDescriptor( - this.source, property - ) - if (descriptor && !descriptor.writable && !descriptor.configurable) { - return Reflect.get(this.source, property, receiver) - } - // Lazily instantiate accessor signals - this.getSignals[property] = - // Need to use hasOwnProperty instead of a normal get to avoid - // the basic Object prototype properties - // e.g. constructor - Object.prototype.hasOwnProperty.call(this.getSignals, property) - ? this.getSignals[property] - : new Signal() - // User accessor signals to give the actual output - // This enables automatic dependency tracking - const signalCore = signalCoreExtractor.get(this.getSignals[property]) - signalCore.removeSelf = () => delete this.getSignals[property] - const currentValue = (() => { - // Handle getters which require hidden/native properties - // If putting the proxy as `this` fails then reveal the underlying object - // There are limitations though - // - If the getter have any side effects on error this will trigger them twice - // - If the getter also reads other public properties this will not build dependencies - // For example this will fail to build a dependency on `this.normalProp` if proxied - // get (prop) { - // return this.#hiddenProp + this.normalProp - // } - // This is sort of a necessary limitation of dealing with native code though - // Better than failing overall? - // An alternative is to detect the "nativeness" of an object and pass through - // That seems quite messy though - try { - return Reflect.get(this.source, property, receiver) - } catch (error) { - // We trim to specific "incompatible receiver" TypeErrors to minimize unnecessary double retries to actual proxy problems - // but it could still happen for other TypeErrors - if (error.name === 'TypeError' && error.message.includes('incompatible receiver')) return Reflect.get(this.source, property, this.source) - throw error - } - })() - signalCore.value = currentValue - return signalCore.read() - }, - - // Notifies dependents of the defined property - // Also translates Definitions sets into getter methods - // We trap defineProperty instead of set because it avoids the ambiguity - // of access through the prototype chain - defineProperty (property, descriptor) { - const didSucceed = Reflect.defineProperty( - this.source, property, descriptor - ) - // Trigger dependents before returning - this.trigger(property) - return didSucceed - }, - - // Transparently delete the property but also trigger dependents - deleteProperty (property) { - const didSucceed = Reflect.deleteProperty(this.source, property) - this.trigger(property) - return didSucceed - }, - - // Have a map of dummy Signals to keep track of dependents on has - // We don't resuse the get Signals to avoid triggering getters - hasSignals: {}, - has (property) { - // Lazily instantiate has signals - this.hasSignals[property] = - // Need to use hasOwnProperty instead of a normal get to avoid - // the basic Object prototype properties - // e.g. constructor - Object.prototype.hasOwnProperty.call(this.hasSignals, property) - ? this.hasSignals[property] - : new Signal(null) - // User accessor signals to give the actual output - // This enables automatic dependency tracking - const signalCore = signalCoreExtractor.get(this.hasSignals[property]) - signalCore.removeSelf = () => delete this.hasSignals[property] - const currentValue = Reflect.has(this.source, property) - signalCore.value = currentValue - return signalCore.read() - }, - - // Subscribe to the overall reactor by reading the dummy signal - ownKeys () { - const currentKeys = Reflect.ownKeys(this.source) - const signalCore = signalCoreExtractor.get(this.selfSignal) - signalCore.value = currentKeys - return signalCore.read() - }, - - // Force dependencies to trigger - // Hack to do this by trivially "redefining" the signal - trigger (property) { - // Calculate the actual new values observers will receive - // This avoids redundant triggering if they were the same - const getValue = Reflect.get(this.source, property) - const hasValue = Reflect.has(this.source, property) - // For ownKeys you need to manually calculate the set comparison - const currentOwnKeysValue = Reflect.ownKeys(this.source) - const oldOwnKeysValue = signalCoreExtractor.get(this.selfSignal).value - const ownKeysChanged = (() => { - const currentSet = new Set(currentOwnKeysValue) - const oldSet = new Set(oldOwnKeysValue) - if (currentSet.size !== oldSet.size) return true - for (const key of currentSet) { - if (!oldSet.has(key)) return true - } - return false - })() - // Batch together to avoid redundant triggering for shared observers - // This might be redundant because the only way this happens is by calling native methods - // which are already batched anyway. But keeping for safety - batch(() => { - if (this.getSignals[property]) this.getSignals[property](getValue) - if (this.hasSignals[property]) this.hasSignals[property](hasValue) - if (ownKeysChanged) this.selfSignal(currentOwnKeysValue) - }) - } - } - - // The interface proxy returned to the user to utilize the Reactor - // This is done to abstract away the messiness of how the Reactors work - // Should contain no additional functionality and be purely syntactic sugar - const reactorInterface = new Proxy(reactorCore.source, { - apply (target, thisArg, argumentsList) { - if (target === reactorCore.source) { - return reactorCore.apply(thisArg, argumentsList) - } - throw new Error('Proxy target does not match initialized object') - }, - get (target, property, receiver) { - if (target === reactorCore.source) { - return reactorCore.get(property, receiver) - } - throw new Error('Proxy target does not match initialized object') - }, - defineProperty (target, property, descriptor) { - if (target === reactorCore.source) { - return reactorCore.defineProperty(property, descriptor) - } - throw new Error('Proxy target does not match initialized object') - }, - deleteProperty (target, property) { - if (target === reactorCore.source) { - return reactorCore.deleteProperty(property) - } - throw new Error('Proxy target does not match initialized object') - }, - has (target, property) { - if (target === reactorCore.source) { - return reactorCore.has(property) - } - throw new Error('Proxy target does not match initialized object') - }, - ownKeys (target) { - if (target === reactorCore.source) { - return reactorCore.ownKeys() - } - throw new Error('Proxy target does not match initialized object') - } - }) - // Register the reactor for debugging/typechecking purposes - Reactors.add(reactorInterface) - reactorCoreExtractor.set(reactorInterface, reactorCore) - reactorCache.set(initializedSource, reactorInterface) - return reactorInterface - } -} - -// Observers are functions which automatically track their dependencies -// Once triggered they automatically retrigger whenever a dependency is updated -// A dependency is any read of Signal or property of a Reactor -// Triggering an observer with parameters saves them for future auto triggers -// Observers can be stopped and restarted -// Starting after stopping causes the Observer to execute again -// Starting does nothing if an Observer is already awake -// ----------------------------------------------------------------------------- -// Examples -// let a = new Signal(1) -// let b = new Reactor() -// b.foo = "bar" -// let observer = new Observer(() => { This will trigger whenever -// console.log("a is now " + a()) a or b.foo are updated -// console.log("b.foois now " + b.foo) -// }) -// observer() -// a(2) This will trigger an update -// -// observer.stop() This will block triggers -// b.foo = "cheese" No trigger since we stopped it -// -// observer.start() Will rerun the function -// and allow updates again -// -// observer.start() Does nothing since already started -const Observers = new WeakSet() -class Observer extends Function { - constructor (execute) { - if (arguments.length !== 1) { - throw new Error('Observer constructor requires exactly one argument') - } - - // Parameter validation - if (typeof execute !== 'function') { - throw new TypeError('Cannot create observer with a non-function') - } - - // Internal engine of an Observer for how it works - // All actual functionality & state should be built into the core - // Should be completely agnostic to syntactic sugar - const observerCore = { - // Core function the observer is wrapping - execute, - // Whether automatic triggers will be accepted - awake: false, - // The Signals the execution block reads from - // Cleared and rebuilt at every trigger - // Store dependencies weakly to avoid memory loops - // They're only stored to break the connection later anyway - dependencies: new WeakRefSet(), - // Stored return value of the last successful execute - // Stored in a Signal which makes it observable itself - value: new Signal(), - // Flag on whether this is a unobserve block - // Avoids creating dependencies in that case - - // Symmetrically removes dependencies - clearDependencies () { - // Go upstream to break the connection - if (this.dependencies === null) return - this.dependencies.forEach(dependency => { - dependency.removeDependent(this) - }) - // Drop own references - this.dependencies = new WeakRefSet() - }, - - // External call to add a dependency - // Wrapped to to encapsulate implementation - addDependency (dependency) { - this.dependencies.add(dependency) - }, - - // Trigger the execute block and build dependencies - // Does nothing if observer is asleep - // If it was awake return true - // If it was asleep return false - trigger () { - if (this.awake) { - this.clearDependencies() - // Put self on the dependency stack - // So any signals read by execute know who is calling - dependencyStack.push(this) - let result - // Wrap execute in a try block so that - // dependency stack is popped even if an error is occured - // Allows users to catch errors themselves and handle them - try { - result = this.execute.apply(this.thisContext, this.argsContext) - } finally { - dependencyStack.pop() - } - // Store the result as a subscribable signal - // This will trigger any downstream observers - // which depend on this observers value - this.value(result) - return true - } - return false - }, - - // Redefines the observer with a new exec function - // Maintains the context, Signal dependents, and awake status - redefine (newExecute) { - if (typeof newExecute !== 'function') { - throw new TypeError('Cannot create observer with a non-function') - } - this.clearDependencies() - this.execute = newExecute - // If awake this will update the value Signal and notify observers downstream - // If alseep this will correctly do nothing leaving value to the last triggered value - return this.trigger() - }, - - // Pause the observer preventing further triggers - // Returns false if it was already asleep - // Returns true if it was awake - stop () { - if (!this.awake) return false - this.awake = false - this.clearDependencies() - return true - }, - - // Restart the observer if it is not already awake - // Returns false is already awake - // Returns true if it was woken up - start () { - if (this.awake) return false - this.awake = true - this.trigger() - return true - } - - } - - // Public interace to hide the ugliness of how observers work - // An empty call force triggers the block and turns it on - // A call with arguments gets those arguments passed as a context - // for that and future retriggers - super() - const observerInterface = new Proxy(this, { - apply (target, thisArg, args) { - observerCore.thisContext = thisArg - observerCore.argsContext = args - observerCore.awake = true - observerCore.trigger() - return observerCore.value() - }, - construct (target, args, receiver) { - return Reflect.construct(observerCore.execute, args, observerInterface) - } - }) - observerInterface.start = () => observerCore.start() - observerInterface.stop = () => observerCore.stop() - // Note that setting a new context does not cause the observer to trigger - // The observer will need to be started and triggered - // Named setContext instead of exposing context property for cleaner syntax - // `context` property is an array but trivial case of giving a single context argument - // Should be expected to work but it doesnt - // TODO: Consider removing these features to maintain the purity of calling the observer as a function - observerInterface.setThisContext = (that) => { - observerCore.thisContext = that - } - observerInterface.setArgsContext = (...args) => { - observerCore.argsContext = args - } - // Expose the wrapped execute function and restart the observer - // Setting it keeps the context and dependents - Object.defineProperty(observerInterface, 'execute', { - get () { return observerCore.execute }, - set (newValue) { return observerCore.redefine(newValue) } - }) - // Allow reads of the last return value of execute - // As a Signal this itself is observable and - // builds dependencies if done within another observer - Object.defineProperty(observerInterface, 'value', { - get () { return observerCore.value() } - }) - - // Register the observer for debugging/typechecking purposes - observerCoreExtractor.set(observerInterface, observerCore) - Observers.add(observerInterface) - - // Does not trigger on initialization until () or .start() are called - return observerInterface - } -} - -// Unobserve is syntactic sugar to create a dummy observer to block the triggers -// While also returning the contents of the block -const hide = function (execute) { - if (arguments.length !== 1 || typeof execute !== 'function') { - throw new Error('hide requires exactly one function argument') - } - let result - dependencyStack.push(null) - try { - result = execute() - } finally { - dependencyStack.pop() - } - return result -} - -// Method for allowing users to batch multiple observer updates together -const batch = function (execute) { - if (arguments.length !== 1 || typeof execute !== 'function') { - throw new Error('batch requires exactly one function argument') - } - - if (batcher === null) { - // If a batcher is set then signals will not trigger observers immediately - // Instead they will be saved into the batcher to trigger after - // Using a Set allows the removal of redundant triggering in observers - batcher = new Set() - const errorList = [] - - // Execute the given block and collect the triggerd observers - let result - try { result = execute() } catch (error) { - // If I want to fail forward store the error - // and try to trigger the relevant observers so far - errorList.push(error) - // If I want to fail fast instead - // batcher = null - // throw error - } - - // Trigger the collected observers - // If an error occurs, collect it and keep going - // A conslidated error will be thrown at the end of propagation - for (const observer of batcher) { - try { observer.trigger() } catch (error) { errorList.push(error) } - } - - // If any errors occured during propagation - // consolidate and throw them - batcher = null - if (errorList.length === 1) { - throw errorList[0] - } else if (errorList.length > 1) { - const errorMessage = 'Multiple errors from batched reactor observers' - throw new CompoundError(errorMessage, errorList) - } - - return result - // No need to do anything if batching is already taking place } - } else { - return execute() - } -} - -// Method for extracting the internal object from a Reactor -// or extracting the internal function from an Observer -const shuck = (shuckee) => { - let output = shuckee - if (Reactors.has(output)) output = reactorCoreExtractor.get(output).source - if (Observers.has(output)) output = observerCoreExtractor.get(output).execute - return output -} - -// Custom Error to consolidate multiple errors together -class CompoundError extends Error { - constructor (message, errorList) { - // Flatten any compound errors in the error list - errorList = errorList.flatMap(error => { - if (error instanceof CompoundError) return error.cause - return error - }) - // Build the message to display all the component errors - message = message + '\n' + errorList.length + ' errors in total' - for (const error of errorList) { - const errorDescription = - error.stack != null ? error.stack : error.toString() - message = message + '\n' + errorDescription - } - super(message, { cause: errorList }) - this.name = this.constructor.name - return this - } -} - -export { - Signal, - Reactor, - Observer, - Signals, - Reactors, - Observers, - signalCoreExtractor, - reactorCoreExtractor, - observerCoreExtractor, - hide, - batch, - shuck -} diff --git a/test/batching.test.js b/test/batching.test.js index 83809c5..f8432b3 100644 --- a/test/batching.test.js +++ b/test/batching.test.js @@ -13,7 +13,7 @@ import { // hide, batch // shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Batching', () => { it('consolidates duplicate observer triggers within a batch', () => { diff --git a/test/complex.test.js b/test/complex.test.js index 0793986..533af51 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Complex Setups', () => { it('can chain observers off each other', () => { diff --git a/test/errors.test.js b/test/errors.test.js index f83fd73..983d52b 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Error Handling', () => { it('throws an error on an update if there is an observer throws an error', () => { diff --git a/test/features.test.js b/test/features.test.js index 8bf8aff..5546ecb 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Minor Features', () => { describe('Starting and stopping observers', () => { diff --git a/test/hiding.test.js b/test/hiding.test.js index 0812c1e..3800d5a 100644 --- a/test/hiding.test.js +++ b/test/hiding.test.js @@ -13,7 +13,7 @@ import { hide // batch, // shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Hiding', () => { it('does not create dependencies inside hide block', () => { diff --git a/test/observer.test.js b/test/observer.test.js index 0135146..e564b9a 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Observer', () => { describe('initializes with a function and returns it wrapped in an observer', () => { diff --git a/test/reactivity.test.js b/test/reactivity.test.js index 4e0cc33..d41cf50 100644 --- a/test/reactivity.test.js +++ b/test/reactivity.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Reactivity', () => { describe('Observers are inactive until they are run', () => { diff --git a/test/reactor.test.js b/test/reactor.test.js index 4e155f0..322c01b 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Reactor', () => { describe('initializes with an object and returns it wrapped in a reactor', () => { diff --git a/test/signal.test.js b/test/signal.test.js index c911a4e..1a0dfeb 100644 --- a/test/signal.test.js +++ b/test/signal.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/reactor.js' +} from '../src/index.js' describe('Signal', () => { describe('initializes with any single value', () => { From c6e9f9031fa4942c7b471d2b32bea2e40d393e1a Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 01:40:01 +0800 Subject: [PATCH 45/71] removed parcel --- .gitignore | 3 - package-lock.json | 8411 ++++++++++++--------------------------------- package.json | 6 +- 3 files changed, 2110 insertions(+), 6310 deletions(-) diff --git a/.gitignore b/.gitignore index 459aac1..9daa824 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ .DS_Store -.parcel-cache -dist node_modules -notes.js diff --git a/package-lock.json b/package-lock.json index 0ddf46b..170a8d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,116 +13,9 @@ }, "devDependencies": { "mocha": "^10.1.0", - "parcel": "^2.8.1", "standard": "^17.0.0" } }, - "node_modules/@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==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@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, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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/@babel/highlight/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, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -223,261 +116,6 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "node_modules/@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, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@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, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@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, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@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, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@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/@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==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@lezer/common": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", - "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==", - "dev": true - }, - "node_modules/@lezer/lr": { - "version": "0.15.8", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", - "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", - "dev": true, - "dependencies": { - "@lezer/common": "^0.15.0" - } - }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz", - "integrity": "sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz", - "integrity": "sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz", - "integrity": "sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz", - "integrity": "sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz", - "integrity": "sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-win32-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz", - "integrity": "sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@mischnic/json-sourcemap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", - "integrity": "sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA==", - "dev": true, - "dependencies": { - "@lezer/common": "^0.15.7", - "@lezer/lr": "^0.15.4", - "json5": "^2.2.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@mischnic/json-sourcemap/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, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz", - "integrity": "sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz", - "integrity": "sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz", - "integrity": "sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz", - "integrity": "sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz", - "integrity": "sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -513,1482 +151,1142 @@ "node": ">= 8" } }, - "node_modules/@parcel/bundler-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.1.tgz", - "integrity": "sha512-hyzrZdzjFWjKFh0s8ykFke5bTBwWdOkmnFEsB2zaJEALf83td6JaH18w3iYNwF1Q5qplSTu6AeNOeVbR7DXi4g==", + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/graph": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=0.4.0" } }, - "node_modules/@parcel/cache": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.1.tgz", - "integrity": "sha512-wvdn0B21bg227JzgxxlCwu6L8SryAZyTe/pZ32jsUsGxuVqT2BLYczyQL7OqCG5902rnImsBjETkOIxXeCgThg==", + "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, - "dependencies": { - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/utils": "2.8.1", - "lmdb": "2.5.2" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, "peerDependencies": { - "@parcel/core": "^2.8.1" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@parcel/codeframe": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.1.tgz", - "integrity": "sha512-VNmnWJHYDQP9vRo9WZIGV5YeBzDuJVeYLLBzmYYnT2QZx85gXYKUm05LfYqKYnP0FmMT1bv7AWLMKN6HFhVrfw==", + "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, "dependencies": { - "chalk": "^4.1.0" - }, - "engines": { - "node": ">= 12.0.0" + "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": "opencollective", - "url": "https://opencollective.com/parcel" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@parcel/compressor-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.1.tgz", - "integrity": "sha512-mm3RFiaofqzwdFxkuvUopsiOe4dyBIheY8D5Yh4BebuavPcgvLmrW3B3BaIR84kv6l6zy3i0QiuaLgbYhnrnuQ==", + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, - "dependencies": { - "@parcel/plugin": "2.8.1" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/config-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.1.tgz", - "integrity": "sha512-UGj4BZ6keEPZ+8RWYRDEQJkbTaVG0r6ewNxqV4kKew4vCejRg1TMnQL8OJYG2non10sQqbmisfZMqCECA6OJMg==", - "dev": true, - "dependencies": { - "@parcel/bundler-default": "2.8.1", - "@parcel/compressor-raw": "2.8.1", - "@parcel/namer-default": "2.8.1", - "@parcel/optimizer-css": "2.8.1", - "@parcel/optimizer-htmlnano": "2.8.1", - "@parcel/optimizer-image": "2.8.1", - "@parcel/optimizer-svgo": "2.8.1", - "@parcel/optimizer-terser": "2.8.1", - "@parcel/packager-css": "2.8.1", - "@parcel/packager-html": "2.8.1", - "@parcel/packager-js": "2.8.1", - "@parcel/packager-raw": "2.8.1", - "@parcel/packager-svg": "2.8.1", - "@parcel/reporter-dev-server": "2.8.1", - "@parcel/resolver-default": "2.8.1", - "@parcel/runtime-browser-hmr": "2.8.1", - "@parcel/runtime-js": "2.8.1", - "@parcel/runtime-react-refresh": "2.8.1", - "@parcel/runtime-service-worker": "2.8.1", - "@parcel/transformer-babel": "2.8.1", - "@parcel/transformer-css": "2.8.1", - "@parcel/transformer-html": "2.8.1", - "@parcel/transformer-image": "2.8.1", - "@parcel/transformer-js": "2.8.1", - "@parcel/transformer-json": "2.8.1", - "@parcel/transformer-postcss": "2.8.1", - "@parcel/transformer-posthtml": "2.8.1", - "@parcel/transformer-raw": "2.8.1", - "@parcel/transformer-react-refresh-wrap": "2.8.1", - "@parcel/transformer-svg": "2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.1" - } - }, - "node_modules/@parcel/core": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.1.tgz", - "integrity": "sha512-i84Ic+Ei907kChVGrTOhN3+AB46ymqia0wJCxio/BAbUJc3PLx0EmOAgLutACVNompCYcXpV9kASiGJHcfHW5w==", - "dev": true, - "dependencies": { - "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/cache": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/graph": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "abortcontroller-polyfill": "^1.1.9", - "base-x": "^3.0.8", - "browserslist": "^4.6.6", - "clone": "^2.1.1", - "dotenv": "^7.0.0", - "dotenv-expand": "^5.1.0", - "json5": "^2.2.0", - "msgpackr": "^1.5.4", - "nullthrows": "^1.1.1", - "semver": "^5.7.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=6" } }, - "node_modules/@parcel/core/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "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, - "bin": { - "json5": "lib/cli.js" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@parcel/core/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@parcel/diagnostic": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.1.tgz", - "integrity": "sha512-IyMREe9OkfEqTNi67ZmFRtc6dZ35w0Snj05yDnxv5fKcLftYgZ1UDl2/64WIQQ2MZQnrZV9qrdZssdPhY9Qf3A==", + "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, "dependencies": { - "@mischnic/json-sourcemap": "^0.1.0", - "nullthrows": "^1.1.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@parcel/events": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.1.tgz", - "integrity": "sha512-x3JOa9RgEhHTGhRusC9/Er4/KZQ4F5M2QVTaHTmCqWqA/eOVXpi5xQTERvNFsb/5cmfsDlFPXPd1g4ErRJfasw==", + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, - "engines": { - "node": ">= 12.0.0" + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">= 8" } }, - "node_modules/@parcel/fs": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.1.tgz", - "integrity": "sha512-+3lZfH0/2IoGrlq09SuOaULe55S6F+G2rGVHLqPt8JO9JJr1fMAZIGVA8YkPOv4Y/LhL0M1ly0gek4k+jl8iDg==", + "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 + }, + "node_modules/array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", "dev": true, "dependencies": { - "@parcel/fs-search": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/watcher": "^2.0.7", - "@parcel/workers": "2.8.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/fs-search": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.1.tgz", - "integrity": "sha512-zp1CjB3Va4Sp7JrS/8tUs5NzHYPiWgabsL70Xv7ExlvIBZC42HI0VEbBFvNn4/pra2s+VqJhStd2GTBvjnwk9g==", + "node_modules/array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", "dev": true, "dependencies": { - "detect-libc": "^1.0.3" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/graph": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.1.tgz", - "integrity": "sha512-ZNRZLGfpcASMRhKmu3nySyMybqXtddneCf29E3FLqYEqj5dqbp4jBfKI55E9vxVUssp4cNKmVfqcTHFGXfGEaQ==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", "dev": true, "dependencies": { - "nullthrows": "^1.1.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/hash": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.1.tgz", - "integrity": "sha512-qI2CDyN7ogdCi0Euha3pCr9oZ8+4XBO/hRlYPo6MQ7pAg/dfncg+xEpWyt/g2KRhbTapX/+Zk8SnRJyy+Pynvw==", + "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 + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, - "dependencies": { - "detect-libc": "^1.0.3", - "xxhash-wasm": "^0.4.2" - }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/logger": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.1.tgz", - "integrity": "sha512-jnZfAZT8OQVilATC+tgxoNgx1woc84akG6R3lYeYbmKByRQdZ5QzEUJ4IIgXKCXk6Vp+GhORs7Omot418zx1xg==", + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "balanced-match": "^1.0.0" } }, - "node_modules/@parcel/markdown-ansi": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.1.tgz", - "integrity": "sha512-5aNMdBlUniCjcJOdsgaLrr9xRKPgH7zmnifdJOlUOeW2wk95xRRVLIbTJoMtGxkN4gySxPZWX+SfOYXVLWqqAw==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "chalk": "^4.1.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/namer-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.1.tgz", - "integrity": "sha512-ewI1Rk7Fn3iqsgnU2bcelgQtckrhWtRip7mdeI7VWr+M/M1DiwVvaxOQCZ8E083umjooMvmRDXXx9YGAqT8Kgw==", + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "semver": "^7.0.0" } }, - "node_modules/@parcel/node-resolver-core": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.1.tgz", - "integrity": "sha512-kg7YQwYAIxVfV8DW8IjhiF1xf4XCQ9NReZSpgNZ1ubUvApakRqfLvttp4K1ZIpnm+OLvtgXn1euV4J9jhx7qXw==", + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "semver": "^5.7.1" - }, - "engines": { - "node": ">= 12.0.0" + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/node-resolver-core/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "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, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">=6" } }, - "node_modules/@parcel/optimizer-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.1.tgz", - "integrity": "sha512-iZqNhZiMtTg2z19FpGkFFx3SQpWakh3S7gaG75fN4Mt3o84G35ag920uHT/6a34wFBHSuH05lLZGUlDwKIU5Ng==", + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", - "nullthrows": "^1.1.1" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@parcel/optimizer-htmlnano": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.1.tgz", - "integrity": "sha512-lIm2nvU506fzNQl6VrsANKjHC1wVwqgfPLJreC7JazRLBYwTl2UvyjNmAEjtnmoGbwA6GS9+Y3TaYcbGjNvpwA==", + "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": { - "@parcel/plugin": "2.8.1", - "htmlnano": "^2.0.0", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "svgo": "^2.4.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@parcel/optimizer-image": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.1.tgz", - "integrity": "sha512-mi4pgr/aj47y5X7zLsHP+tFv9hW1wUDnAu9PxCrBKGE0uEqWs9L6boCzJ1dmjfnvNT9phs6ZXyv4zlayRBVQLw==", + "node_modules/chalk/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, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "detect-libc": "^1.0.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=8" } }, - "node_modules/@parcel/optimizer-svgo": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.1.tgz", - "integrity": "sha512-V8KP+EaO0jLI0l3hpiv/fTSVRKCRKyBwSZt0dnWU2LWPAOIK5H3ggeicXc61th+nEACk/u7YzoP7oxpU87VzHA==", + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "svgo": "^2.4.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">= 8.10.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/@parcel/optimizer-terser": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.1.tgz", - "integrity": "sha512-ELNtiq1nqvEfURwFgSzK93Zb3C0ruxIUT/ln8zGi8KQTxWKA0PLthzlAqwAotA/zKF5DwjUa3gw0pn2xKuZv8w==", + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "terser": "^5.2.0" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/@parcel/package-manager": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.1.tgz", - "integrity": "sha512-zv0hAOwlCHcV4jNM60hG9fkNcEwkI9O/FsZlPMqqXBq5rKJ4iMyvOoMCzkfWUqf3RkgqvXSqTfEaDD6MQJ0ZGg==", + "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": { - "@parcel/diagnostic": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "semver": "^5.7.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.1" + "node": ">=7.0.0" } }, - "node_modules/@parcel/package-manager/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } + "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 + }, + "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 }, - "node_modules/@parcel/packager-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.1.tgz", - "integrity": "sha512-nFeIwNgElEVZQCUKOU52T34TMpUhpCazNzAD79/Adrwu4YsFlIU6DmGePyGYlXDNlyuM+gCIu5uXgVUyn96ZnA==", + "node_modules/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, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 8" } }, - "node_modules/@parcel/packager-html": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.1.tgz", - "integrity": "sha512-9e1HM4kutardgEmWLJTqG+jGoA/sozaN8xVQ8tavFRyMS3dEjB78Kb/+nT887nIXmoWSFSkUkh1LM+9O4OqkJQ==", + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5" + "ms": "2.1.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=6.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@parcel/packager-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.1.tgz", - "integrity": "sha512-BWJsCjBZAexeCHGDxJrXYduVdlTygj6Ok6HIg2skIkAVfPLipx9GIh10EBsdHZy3GhWddvnvxaMXQdUvoADnEw==", + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "globals": "^13.2.0", - "nullthrows": "^1.1.1" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@parcel/packager-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.1.tgz", - "integrity": "sha512-VeXRLPT2WF03sVjxI1yaRvDJAvxorxCLm56xwxCWmDgRTBb4q/cv81AAVztLkYsOltjDWJnFSQLm1AvZz6oSaw==", + "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 + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/packager-svg": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.1.tgz", - "integrity": "sha512-Yln3iuAohtVN8XDDbBWqH0fUMVWfsmDpJ6pNjZPTyXeaFOw2GkqvRaQwQM5CDXKGstkLHCzYBBhIVrmEWxTyXA==", + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, - "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "posthtml": "^0.16.4" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=0.3.1" } }, - "node_modules/@parcel/plugin": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.1.tgz", - "integrity": "sha512-7rAKJ8UvjwMwyiOKy5nl1UEjeLLINN6tKU8Gr9rqjfC9lux/wrd0+wuixtncThpyNJHOdmPggqTA412s2pgbNQ==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "@parcel/types": "2.8.1" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=6.0.0" } }, - "node_modules/@parcel/reporter-cli": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.1.tgz", - "integrity": "sha512-9+Wk9eaQOTHAQs6h+aeoqPGCJxNJkMdLnD7eHbHd8Jn+Ge4ux29yBJUn5zfmWLo/5zGI8yXDjoLLOQNPqVgU2g==", + "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/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==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "chalk": "^4.1.0", - "term-size": "^2.2.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "is-arrayish": "^0.2.1" } }, - "node_modules/@parcel/reporter-dev-server": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.1.tgz", - "integrity": "sha512-LO3gu8r+NpKJHNzJPEum/Mvem0Pr8B66J7OAFJWCHkJ4QMJU7V8F40gcweKCbbVBctMelptz2eTqXr4pBgrlkg==", + "node_modules/es-abstract": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", + "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1" + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "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-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/resolver-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.1.tgz", - "integrity": "sha512-t203Y7PEGnwl4GEr9AthgMOgjLbtCCKzzKty3PLRSeZY4e2grc/SRUWZM7lQO2UMlKpheXuEJy4irvHl7qv43A==", + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", "dev": true, "dependencies": { - "@parcel/node-resolver-core": "2.8.1", - "@parcel/plugin": "2.8.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "has": "^1.0.3" } }, - "node_modules/@parcel/runtime-browser-hmr": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.1.tgz", - "integrity": "sha512-BmkJYQYGtkXNnI25sl1yE9sWDXK1t6Rtz3tTUDB0kD62ukV6rx6qjEpmcHdB2NgjvAkPIwZHnVK4KE1QX71dTg==", + "node_modules/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==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@parcel/runtime-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.1.tgz", - "integrity": "sha512-OMbjlunfk+b+4OUjjCZxsJOlxXAG878g6rUr1LIBBlukK65z1WxhjBukjf2y7ZbtIvIx3/k07fNgekQeFYBJaQ==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=6" } }, - "node_modules/@parcel/runtime-react-refresh": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.1.tgz", - "integrity": "sha512-HbPKocBTt9Adj01MTYJnkp+U8WODBCCE+j9GdUHnLEobuctupLLM+ARiGXEzc4T+dwxgo/1nKaYCki9segCBFg==", + "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, - "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "react-error-overlay": "6.0.9", - "react-refresh": "^0.9.0" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@parcel/runtime-service-worker": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.1.tgz", - "integrity": "sha512-hIwtcx6UxXTxv3LzQHX057jrlYXKSQMmLDq0+CNHMvStjIqMvE2inn6WBXL7fBC0iFbe4/wknRow+cX8nHKIzQ==", + "node_modules/eslint": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", + "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@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.15.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" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@parcel/source-map": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", - "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "node_modules/eslint-config-standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", + "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", "dev": true, - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": "^12.18.3 || >=14" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0", + "eslint-plugin-promise": "^6.0.0" } }, - "node_modules/@parcel/transformer-babel": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.1.tgz", - "integrity": "sha512-pIURnRJ1GU885tRrSHmmA6sE8JSC8/KpU9XM9wmK6Se/nWbSFTvNkiRx1sXxmUXBUPBCa0VFqQEcwrzGB4Py6A==", + "node_modules/eslint-config-standard-jsx": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", + "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "json5": "^2.2.0", - "nullthrows": "^1.1.1", - "semver": "^5.7.0" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.8.0", + "eslint-plugin-react": "^7.28.0" } }, - "node_modules/@parcel/transformer-babel/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" } }, - "node_modules/@parcel/transformer-babel/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/@parcel/transformer-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.1.tgz", - "integrity": "sha512-DUPIcfZpuPYR/6SAu1TI08n2zjb7p3qoAkqqh2lIQniL99uEq8OsNFl84JEwUIiESZS/ExpQ7yXxAN7G1qamVw==", + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", - "nullthrows": "^1.1.1" + "debug": "^3.2.7" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/transformer-html": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.1.tgz", - "integrity": "sha512-Ve9qjNE+gWdyHyDKyzq+UwYdX0KjoHGo8WVN2qX0UtH+TYwnoi51oi+GTBa96+0Rq8fzBHWkqf53sUTFzDaFdw==", - "dev": true, - "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" - }, - "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@parcel/transformer-html/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/@parcel/transformer-image": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.1.tgz", - "integrity": "sha512-K5PF00LXY1RelPEdMcZSc/rsQcjjmeBNDvLSrv9DWVbhiYZ+k3JRS9y5Ga+wPYRdEl0d+Z61ku0+cqz/uCoryA==", + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "nullthrows": "^1.1.1" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" }, "peerDependencies": { - "@parcel/core": "^2.8.1" + "eslint": ">=4.19.1" } }, - "node_modules/@parcel/transformer-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.1.tgz", - "integrity": "sha512-yGYpgBwL0DrkojXNvij+8f1Av6oU8PNUMVbfZRIVMdZ+Wtjx8NyAeY16cjSIxnG16vL5Pff+QhlBKRp9n6tnKA==", + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "@swc/helpers": "^0.4.12", - "browserslist": "^4.6.6", - "detect-libc": "^1.0.3", - "nullthrows": "^1.1.1", - "regenerator-runtime": "^0.13.7", - "semver": "^5.7.1" + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "peerDependencies": { - "@parcel/core": "^2.8.1" + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/@parcel/transformer-js/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "engines": { + "node": ">=4" } }, - "node_modules/@parcel/transformer-json": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.1.tgz", - "integrity": "sha512-CijTTmMModiyBJCJoPlQvjrByaAs4jKMF+8Mbbaap39A1hJPNVSReFvHbRBO/cZ+2uVgxuSmfYD00YuZ784aVg==", + "node_modules/eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "json5": "^2.2.0" + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/@parcel/transformer-json/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/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/@parcel/transformer-postcss": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.1.tgz", - "integrity": "sha512-xmO4zA8nCgCgPstqxHr2BzRSJtqAy8cyAY1R9oi5FHkU5xHEzOGrcj5JynlU0eJssFten48kf8Csx6ciOsH1ZA==", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "clone": "^2.1.1", - "nullthrows": "^1.1.1", - "postcss-value-parser": "^4.2.0", - "semver": "^5.7.1" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">=0.10.0" } }, - "node_modules/@parcel/transformer-postcss/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-plugin-import/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, - "bin": { - "semver": "bin/semver" + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/@parcel/transformer-posthtml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.1.tgz", - "integrity": "sha512-CLrSw+386j7RCrWV3Oyob4qNP+qyfVRDs1BzJZMMW8MFjxEC/ohPi2piGNzaqWPHOvATFodqXBvJBc2WcEZKGA==", + "node_modules/eslint-plugin-import/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/eslint-plugin-n": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.4.0.tgz", + "integrity": "sha512-MkoKy9/lfd52TAXK4fkABgCp0aglk82Q3viy2UOWIEpTVE/Cem5P/UAxMBA4vSw7Gy+2egPqImE9euitLGp5aw==", "dev": true, "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.10.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.7" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=12.22.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/@parcel/transformer-posthtml/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-plugin-n/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@parcel/transformer-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.1.tgz", - "integrity": "sha512-LVC6FX5tcLrZcOV1yzA8FMT5R+u2uQqCt/TXPhrt3MBw3WovKpaMicSkR0AI/802tg+nm1wpURVEfAA2S9+AQw==", + "node_modules/eslint-plugin-n/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, "dependencies": { - "@parcel/plugin": "2.8.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": "*" } }, - "node_modules/@parcel/transformer-react-refresh-wrap": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.1.tgz", - "integrity": "sha512-VkULeuyy0CrxfMwrRkn4V/HmbXzbuqp3+drvYFRCo29SFuC6rJbBF43XiewmvJijWIGCfEAa6bU9/csg2d5+3g==", + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", "dev": true, - "dependencies": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "react-refresh": "^0.9.0" - }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/@parcel/transformer-svg": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.1.tgz", - "integrity": "sha512-HSPve53tWttfKmoXgNLmrF49UCsE38xsA/CkWxI6wQM2qoqLMyei5DY9UsD0cjcAm87tSlZFTq9E/Nbol8g50w==", + "node_modules/eslint-plugin-react": { + "version": "7.31.10", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", + "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "array-includes": "^3.1.5", + "array.prototype.flatmap": "^1.3.0", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.5", + "object.fromentries": "^2.0.5", + "object.hasown": "^1.1.1", + "object.values": "^1.1.5", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.3", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.7" }, "engines": { - "node": ">= 12.0.0", - "parcel": "^2.8.1" + "node": ">=4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/@parcel/transformer-svg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@parcel/types": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.1.tgz", - "integrity": "sha512-sLkpjGCCJy8Hxe6+dme+sugyu6+RW5B8WcdXG1Ynp7SkdgEYV44TKNVGnhoxsHi50G+O1ktZ4jzAu+pzubidXQ==", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { - "@parcel/cache": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/workers": "2.8.1", - "utility-types": "^3.10.0" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@parcel/utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.1.tgz", - "integrity": "sha512-C01Iz+K7oUVNTEzMW6SLDpqTDpm+Z3S+Ms3TxImkLYmdvYpYtzdU+gAllv6ck9WgB1Kqgcxq3TC0yhFsNDb5WQ==", + "node_modules/eslint-plugin-react/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, "dependencies": { - "@parcel/codeframe": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/markdown-ansi": "2.8.1", - "@parcel/source-map": "^2.1.1", - "chalk": "^4.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 12.0.0" + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@parcel/watcher": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.7.tgz", - "integrity": "sha512-gc3hoS6e+2XdIQ4HHljDB1l0Yx2EWh/sBBtCEFNKGSMlwASWeAQsOY/fPbxOBcZ/pg0jBh4Ga+4xHlZc4faAEQ==", + "node_modules/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, - "hasInstallScript": true, "dependencies": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@parcel/workers": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.1.tgz", - "integrity": "sha512-6TnRPwBpxXUsekKK88OxPZ500gvApxF0TaZdSDvmMlvDWjZYgkDN3AAsaFS1gwFLS4XKogn2TgjUnocVof8DXg==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "dependencies": { - "@parcel/diagnostic": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "chrome-trace-event": "^1.0.2", - "nullthrows": "^1.1.1" + "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/mysticatea" }, "peerDependencies": { - "@parcel/core": "^2.8.1" + "eslint": ">=5" } }, - "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "node_modules/eslint-utils/node_modules/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, - "dependencies": { - "tslib": "^2.4.0" + "engines": { + "node": ">=10" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" - } - }, - "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, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "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" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "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==", + "node_modules/eslint/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": { - "color-convert": "^2.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=10.13.0" } }, - "node_modules/anymatch": { + "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 8" + "node": "*" } }, - "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 - }, - "node_modules/array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "node_modules/espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", - "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "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": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4.0" } }, - "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 - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "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, - "dependencies": { - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=4.0" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "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": ">=8" + "node": ">=0.10.0" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "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/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "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.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "reusify": "^1.0.4" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/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==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "node_modules/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==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" + "to-regex-range": "^5.0.1" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=8" } }, - "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 - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "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": { - "semver": "^7.0.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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" - } - }, - "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" }, @@ -1996,472 +1294,399 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001439", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", - "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] + "bin": { + "flat": "cli.js" + } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/chalk/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==", + "node_modules/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 + }, + "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.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/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/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==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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/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, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "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": ">=0.8" + "node": "6.* || 8.* || >= 10.*" } }, - "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==", + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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 - }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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 - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "node_modules/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==", "dev": true, "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cosmiconfig/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==", + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "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" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=8" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "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": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 8" + "node": ">= 6" } }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "node_modules/glob/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, "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8.0.0" + "node": "*" } }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">= 6" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/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/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { - "css-tree": "^1.1.2" + "function-bind": "^1.1.1" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4.0" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/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, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/decamelize": { + "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "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 - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "node_modules/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==", "dev": true, "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "get-intrinsic": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/detect-libc": { + "node_modules/has-symbols": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "bin": { + "he": "bin/he" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "engines": { + "node": ">= 4" + } }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { - "domelementtype": "^2.2.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">= 4" + "node": ">=6" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=0.8.19" } }, - "node_modules/dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", + "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==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "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/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } }, - "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==", + "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/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "engines": { - "node": ">=0.12" + "dependencies": { + "has-bigints": "^1.0.1" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", + "node_modules/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==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "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-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2470,25 +1695,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "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, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, "engines": { "node": ">= 0.4" }, @@ -2496,645 +1707,619 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "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==", + "node_modules/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==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "has": "^1.0.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", - "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "node_modules/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==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", - "@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.15.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" - }, - "bin": { - "eslint": "bin/eslint.js" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-config-standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0", - "eslint-plugin-promise": "^6.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peerDependencies": { - "eslint": "^8.8.0", - "eslint-plugin-react": "^7.28.0" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "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": { - "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/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==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "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.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { - "debug": "^3.2.7" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", "dev": true, "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/is-shared-array-buffer": { + "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==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" + "call-bind": "^1.0.2" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import/node_modules/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/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/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==", "dev": true, "dependencies": { - "ms": "2.0.0" + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "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/js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, + "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 + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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 + }, + "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 + }, + "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 + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "minimist": "^1.2.0" }, - "engines": { - "node": "*" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/eslint-plugin-import/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/eslint-plugin-n": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.4.0.tgz", - "integrity": "sha512-MkoKy9/lfd52TAXK4fkABgCp0aglk82Q3viy2UOWIEpTVE/Cem5P/UAxMBA4vSw7Gy+2egPqImE9euitLGp5aw==", + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "dependencies": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.10.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.7" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" }, "engines": { - "node": ">=12.22.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "node": ">=4.0" } }, - "node_modules/eslint-plugin-n/node_modules/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/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, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" }, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "node_modules/load-json-file/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "node": ">=6" } }, - "node_modules/eslint-plugin-react": { - "version": "7.31.10", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", - "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", + "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, "dependencies": { - "array-includes": "^3.1.5", - "array.prototype.flatmap": "^1.3.0", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.1", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.7" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-react/node_modules/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/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 + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "yallist": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "brace-expansion": "^2.0.1" }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/mocha": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, "bin": { - "semver": "bin/semver.js" + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" } }, - "node_modules/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==", + "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==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/eslint-utils": { + "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 + }, + "node_modules/normalize-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" + "node": ">=0.10.0" } }, - "node_modules/eslint-utils/node_modules/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==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/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/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, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/eslint/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==", + "node_modules/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==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" }, "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "node_modules/object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", "dev": true, "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "node_modules/object.hasown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", + "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" }, - "engines": { - "node": ">=0.10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" }, "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/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": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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-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.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "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, "dependencies": { - "reusify": "^1.0.4" + "wrappy": "1" } }, - "node_modules/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/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "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" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.8.0" } }, - "node_modules/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/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, "dependencies": { - "to-regex-range": "^5.0.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up": { + "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" @@ -3143,3727 +2328,981 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "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, - "bin": { - "flat": "cli.js" + "engines": { + "node": ">=6" } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "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, "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "callsites": "^3.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=6" } }, - "node_modules/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 - }, - "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.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=4" } }, - "node_modules/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/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/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, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "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==", + "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, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.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==", + "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": "6.* || 8.* || >= 10.*" + "node": ">=8" } }, - "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "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 + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "engines": { + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/get-port": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", - "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/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/pkg-conf/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "locate-path": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=6" + } + }, + "node_modules/pkg-conf/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/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "p-limit": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">=6" } }, - "node_modules/glob/node_modules/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/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=4" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">= 0.8.0" } }, - "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" - }, + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "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, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/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==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 0.4.0" + "node": ">=8.10.0" } }, - "node_modules/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==", + "node_modules/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==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "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==", + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, "engines": { "node": ">=8" - } - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "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, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/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/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "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, - "bin": { - "he": "bin/he" + "engines": { + "node": ">=4" } }, - "node_modules/htmlnano": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", - "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "cosmiconfig": "^7.0.1", - "posthtml": "^0.16.5", - "timsort": "^0.3.0" + "glob": "^7.1.3" }, - "peerDependencies": { - "cssnano": "^5.0.11", - "postcss": "^8.3.11", - "purgecss": "^5.0.0", - "relateurl": "^0.2.7", - "srcset": "4.0.0", - "svgo": "^2.8.0", - "terser": "^5.10.0", - "uncss": "^0.17.3" + "bin": { + "rimraf": "bin.js" }, - "peerDependenciesMeta": { - "cssnano": { - "optional": true + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "postcss": { - "optional": true - }, - "purgecss": { - "optional": true - }, - "relateurl": { - "optional": true - }, - "srcset": { - "optional": true - }, - "svgo": { - "optional": true - }, - "terser": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" }, - "uncss": { - "optional": true + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/htmlparser2": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", - "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "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, "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", { "type": "github", - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" - } - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "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/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==", - "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.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/safe-regex-test": { + "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==", "dev": true, "dependencies": { - "has-bigints": "^1.0.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "lru-cache": "^6.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "semver": "bin/semver.js" }, - "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": ">=10" } }, - "node_modules/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/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "randombytes": "^2.1.0" } }, - "node_modules/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/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": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "shebang-regex": "^3.0.0" }, - "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": ">=8" } }, - "node_modules/is-fullwidth-code-point": { + "node_modules/shebang-regex": { "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==", + "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/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-json": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", - "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", - "dev": true - }, - "node_modules/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==", - "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.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { + "node_modules/side-channel": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, - "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 - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "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 - }, - "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 - }, - "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 - }, - "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 - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" - }, - "engines": { - "node": ">=4.0" - } - }, - "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, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.17.1.tgz", - "integrity": "sha512-DwwM/YYqGwLLP3he41wzDXT/m+8jdEZ80i9ViQNLRgyhey3Vm6N7XHn+4o3PY6wSnVT23WLuaROIpbpIVTNOjg==", - "dev": true, - "dependencies": { - "detect-libc": "^1.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.17.1", - "lightningcss-darwin-x64": "1.17.1", - "lightningcss-linux-arm-gnueabihf": "1.17.1", - "lightningcss-linux-arm64-gnu": "1.17.1", - "lightningcss-linux-arm64-musl": "1.17.1", - "lightningcss-linux-x64-gnu": "1.17.1", - "lightningcss-linux-x64-musl": "1.17.1", - "lightningcss-win32-x64-msvc": "1.17.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.1.tgz", - "integrity": "sha512-YTAHEy4XlzI3sMbUVjbPi9P7+N7lGcgl2JhCZhiQdRAEKnZLQch8kb5601sgESxdGXjgei7JZFqi/vVEk81wYg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.1.tgz", - "integrity": "sha512-UhXPUS2+yTTf5sXwUV0+8QY2x0bPGLgC/uhcknWSQMqWn1zGty4fFvH04D7f7ij0ujwSuN+Q0HtU7lgmMrPz0A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.1.tgz", - "integrity": "sha512-alUZumuznB6K/9yZ0zuZkODXUm8uRnvs9t0CL46CXN16Y2h4gOx5ahUCMlelUb7inZEsgJIoepgLsJzBUrSsBw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.1.tgz", - "integrity": "sha512-/1XaH2cOjDt+ivmgfmVFUYCA0MtfNWwtC4P8qVi53zEQ7P8euyyZ1ynykZOyKXW9Q0DzrwcLTh6+hxVLcbtGBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.1.tgz", - "integrity": "sha512-/IgE7lYWFHCCQFTMIwtt+fXLcVOha8rcrNze1JYGPWNorO6NBc6MJo5u5cwn5qMMSz9fZCCDIlBBU4mGwjQszQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.1.tgz", - "integrity": "sha512-OyE802IAp4DB9vZrHlOyWunbHLM9dN08tJIKN/HhzzLKIHizubOWX6NMzUXMZLsaUrYwVAHHdyEA+712p8mMzA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.1.tgz", - "integrity": "sha512-ydwGgV3Usba5P53RAOqCA9MsRsbb8jFIEVhf7/BXFjpKNoIQyijVTXhwIgQr/oGwUNOHfgQ3F8ruiUjX/p2YKw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.1.tgz", - "integrity": "sha512-Ngqtx9NazaiAOk71XWwSsqgAuwYF+8PO6UYsoU7hAukdrSS98kwaBMEDw1igeIiZy1XD/4kh5KVnkjNf7ZOxVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "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 - }, - "node_modules/lmdb": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", - "integrity": "sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "msgpackr": "^1.5.4", - "node-addon-api": "^4.3.0", - "node-gyp-build-optional-packages": "5.0.3", - "ordered-binary": "^1.2.4", - "weak-lru-cache": "^1.2.2" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "2.5.2", - "@lmdb/lmdb-darwin-x64": "2.5.2", - "@lmdb/lmdb-linux-arm": "2.5.2", - "@lmdb/lmdb-linux-arm64": "2.5.2", - "@lmdb/lmdb-linux-x64": "2.5.2", - "@lmdb/lmdb-win32-x64": "2.5.2" - } - }, - "node_modules/lmdb/node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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 - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, - "node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "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==", - "dev": true - }, - "node_modules/msgpackr": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.8.1.tgz", - "integrity": "sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==", - "dev": true, - "optionalDependencies": { - "msgpackr-extract": "^2.2.0" - } - }, - "node_modules/msgpackr-extract": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz", - "integrity": "sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.0.3" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-arm": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-x64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "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 - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "node_modules/node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz", - "integrity": "sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==", - "dev": true, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/node-releases": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.7.tgz", - "integrity": "sha512-EJ3rzxL9pTWPjk5arA0s0dgXpnyiAbJDE6wHT62g7VsgrgQgmmZ+Ru++M1BFofncWja+Pnn3rEr3fieRySAdKQ==", - "dev": true - }, - "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/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.hasown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", - "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ordered-binary": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", - "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==", - "dev": true - }, - "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, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/parcel": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.1.tgz", - "integrity": "sha512-3hl31uIRG+k3N54Le0fLQU8a5VsKFN3j3igs3rEQv6GtXFUNjq58m/Fc1dbOI/v+0fPOv01wyHACn9MCQYesVA==", - "dev": true, - "dependencies": { - "@parcel/config-default": "2.8.1", - "@parcel/core": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/reporter-cli": "2.8.1", - "@parcel/reporter-dev-server": "2.8.1", - "@parcel/utils": "2.8.1", - "chalk": "^4.1.0", - "commander": "^7.0.0", - "get-port": "^4.2.0", - "v8-compile-cache": "^2.0.0" - }, - "bin": { - "parcel": "lib/bin.js" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "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, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "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, - "engines": { - "node": ">=8" - } - }, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "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" - } - }, - "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 - }, - "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, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/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-conf/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/posthtml": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", - "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", - "dev": true, - "dependencies": { - "posthtml-parser": "^0.11.0", - "posthtml-render": "^3.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/posthtml-parser": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", - "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", - "dev": true, - "dependencies": { - "htmlparser2": "^7.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/posthtml-render": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", - "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", - "dev": true, - "dependencies": { - "is-json": "^2.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/posthtml/node_modules/posthtml-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", - "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", - "dev": true, - "dependencies": { - "htmlparser2": "^7.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "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, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/react-error-overlay": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", - "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", - "dev": true - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/react-refresh": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", - "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, - "node_modules/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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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, - "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" - } - }, - "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "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/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true - }, - "node_modules/standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.0.0.tgz", - "integrity": "sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==", - "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" - } - ], - "dependencies": { - "eslint": "^8.13.0", - "eslint-config-standard": "17.0.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-n": "^15.1.0", - "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.28.0", - "standard-engine": "^15.0.0" - }, - "bin": { - "standard": "bin/cmd.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard-engine": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", - "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", - "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" - } - ], - "dependencies": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "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" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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" - } - }, - "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, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/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 - }, - "node_modules/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/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", - "dev": true - }, - "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, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "dev": true - }, - "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, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "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, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/weak-lru-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", - "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", - "dev": true - }, - "node_modules/weak-ref-collections": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.3.tgz", - "integrity": "sha512-N1fa+68+m2sMZW4MdERUf9zw1J9bALS2VB7hnhXplUe/KDlLIh0QE4CCm4/hy63hXKLAfgHJRHA6cYOnpBLiVA==" - }, - "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, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "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/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 - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/xxhash-wasm": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", - "integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==", - "dev": true - }, - "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, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@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==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@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 - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "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" - } - } - } - }, - "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.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" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", - "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "@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 - }, - "@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" - } - }, - "@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 - }, - "@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 - }, - "@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" - } - }, - "@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 - }, - "@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==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@lezer/common": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz", - "integrity": "sha512-edfwCxNLnzq5pBA/yaIhwJ3U3Kz8VAUOTRg0hhxaizaI1N+qxV7EXDv/kLCkLeq2RzSFvxexlaj5Mzfn2kY0Ig==", - "dev": true - }, - "@lezer/lr": { - "version": "0.15.8", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.8.tgz", - "integrity": "sha512-bM6oE6VQZ6hIFxDNKk8bKPa14hqFrV07J/vHGOeiAbJReIaQXmkVb6xQu4MR+JBTLa5arGRyAAjJe1qaQt3Uvg==", - "dev": true, - "requires": { - "@lezer/common": "^0.15.0" - } - }, - "@lmdb/lmdb-darwin-arm64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-2.5.2.tgz", - "integrity": "sha512-+F8ioQIUN68B4UFiIBYu0QQvgb9FmlKw2ctQMSBfW2QBrZIxz9vD9jCGqTCPqZBRbPHAS/vG1zSXnKqnS2ch/A==", - "dev": true, - "optional": true - }, - "@lmdb/lmdb-darwin-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-2.5.2.tgz", - "integrity": "sha512-KvPH56KRLLx4KSfKBx0m1r7GGGUMXm0jrKmNE7plbHlesZMuPJICtn07HYgQhj1LNsK7Yqwuvnqh1QxhJnF1EA==", - "dev": true, - "optional": true - }, - "@lmdb/lmdb-linux-arm": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-2.5.2.tgz", - "integrity": "sha512-5kQAP21hAkfW5Bl+e0P57dV4dGYnkNIpR7f/GAh6QHlgXx+vp/teVj4PGRZaKAvt0GX6++N6hF8NnGElLDuIDw==", - "dev": true, - "optional": true - }, - "@lmdb/lmdb-linux-arm64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-2.5.2.tgz", - "integrity": "sha512-aLl89VHL/wjhievEOlPocoefUyWdvzVrcQ/MHQYZm2JfV1jUsrbr/ZfkPPUFvZBf+VSE+Q0clWs9l29PCX1hTQ==", - "dev": true, - "optional": true - }, - "@lmdb/lmdb-linux-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-2.5.2.tgz", - "integrity": "sha512-xUdUfwDJLGjOUPH3BuPBt0NlIrR7f/QHKgu3GZIXswMMIihAekj2i97oI0iWG5Bok/b+OBjHPfa8IU9velnP/Q==", - "dev": true, - "optional": true - }, - "@lmdb/lmdb-win32-x64": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-2.5.2.tgz", - "integrity": "sha512-zrBczSbXKxEyK2ijtbRdICDygRqWSRPpZMN5dD1T8VMEW5RIhIbwFWw2phDRXuBQdVDpSjalCIUMWMV2h3JaZA==", - "dev": true, - "optional": true - }, - "@mischnic/json-sourcemap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@mischnic/json-sourcemap/-/json-sourcemap-0.1.0.tgz", - "integrity": "sha512-dQb3QnfNqmQNYA4nFSN/uLaByIic58gOXq4Y4XqLOWmOrw73KmJPt/HLyG0wvn1bnR6mBKs/Uwvkh+Hns1T0XA==", - "dev": true, - "requires": { - "@lezer/common": "^0.15.7", - "@lezer/lr": "^0.15.4", - "json5": "^2.2.1" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - } - } - }, - "@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz", - "integrity": "sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz", - "integrity": "sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz", - "integrity": "sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz", - "integrity": "sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw==", - "dev": true, - "optional": true - }, - "@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz", - "integrity": "sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA==", - "dev": true, - "optional": true - }, - "@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, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@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 - }, - "@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, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@parcel/bundler-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/bundler-default/-/bundler-default-2.8.1.tgz", - "integrity": "sha512-hyzrZdzjFWjKFh0s8ykFke5bTBwWdOkmnFEsB2zaJEALf83td6JaH18w3iYNwF1Q5qplSTu6AeNOeVbR7DXi4g==", - "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/graph": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" - } - }, - "@parcel/cache": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/cache/-/cache-2.8.1.tgz", - "integrity": "sha512-wvdn0B21bg227JzgxxlCwu6L8SryAZyTe/pZ32jsUsGxuVqT2BLYczyQL7OqCG5902rnImsBjETkOIxXeCgThg==", - "dev": true, - "requires": { - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/utils": "2.8.1", - "lmdb": "2.5.2" - } - }, - "@parcel/codeframe": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/codeframe/-/codeframe-2.8.1.tgz", - "integrity": "sha512-VNmnWJHYDQP9vRo9WZIGV5YeBzDuJVeYLLBzmYYnT2QZx85gXYKUm05LfYqKYnP0FmMT1bv7AWLMKN6HFhVrfw==", - "dev": true, - "requires": { - "chalk": "^4.1.0" - } - }, - "@parcel/compressor-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/compressor-raw/-/compressor-raw-2.8.1.tgz", - "integrity": "sha512-mm3RFiaofqzwdFxkuvUopsiOe4dyBIheY8D5Yh4BebuavPcgvLmrW3B3BaIR84kv6l6zy3i0QiuaLgbYhnrnuQ==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1" - } - }, - "@parcel/config-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/config-default/-/config-default-2.8.1.tgz", - "integrity": "sha512-UGj4BZ6keEPZ+8RWYRDEQJkbTaVG0r6ewNxqV4kKew4vCejRg1TMnQL8OJYG2non10sQqbmisfZMqCECA6OJMg==", - "dev": true, - "requires": { - "@parcel/bundler-default": "2.8.1", - "@parcel/compressor-raw": "2.8.1", - "@parcel/namer-default": "2.8.1", - "@parcel/optimizer-css": "2.8.1", - "@parcel/optimizer-htmlnano": "2.8.1", - "@parcel/optimizer-image": "2.8.1", - "@parcel/optimizer-svgo": "2.8.1", - "@parcel/optimizer-terser": "2.8.1", - "@parcel/packager-css": "2.8.1", - "@parcel/packager-html": "2.8.1", - "@parcel/packager-js": "2.8.1", - "@parcel/packager-raw": "2.8.1", - "@parcel/packager-svg": "2.8.1", - "@parcel/reporter-dev-server": "2.8.1", - "@parcel/resolver-default": "2.8.1", - "@parcel/runtime-browser-hmr": "2.8.1", - "@parcel/runtime-js": "2.8.1", - "@parcel/runtime-react-refresh": "2.8.1", - "@parcel/runtime-service-worker": "2.8.1", - "@parcel/transformer-babel": "2.8.1", - "@parcel/transformer-css": "2.8.1", - "@parcel/transformer-html": "2.8.1", - "@parcel/transformer-image": "2.8.1", - "@parcel/transformer-js": "2.8.1", - "@parcel/transformer-json": "2.8.1", - "@parcel/transformer-postcss": "2.8.1", - "@parcel/transformer-posthtml": "2.8.1", - "@parcel/transformer-raw": "2.8.1", - "@parcel/transformer-react-refresh-wrap": "2.8.1", - "@parcel/transformer-svg": "2.8.1" - } - }, - "@parcel/core": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/core/-/core-2.8.1.tgz", - "integrity": "sha512-i84Ic+Ei907kChVGrTOhN3+AB46ymqia0wJCxio/BAbUJc3PLx0EmOAgLutACVNompCYcXpV9kASiGJHcfHW5w==", - "dev": true, - "requires": { - "@mischnic/json-sourcemap": "^0.1.0", - "@parcel/cache": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/graph": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "abortcontroller-polyfill": "^1.1.9", - "base-x": "^3.0.8", - "browserslist": "^4.6.6", - "clone": "^2.1.1", - "dotenv": "^7.0.0", - "dotenv-expand": "^5.1.0", - "json5": "^2.2.0", - "msgpackr": "^1.5.4", - "nullthrows": "^1.1.1", - "semver": "^5.7.1" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@parcel/diagnostic": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/diagnostic/-/diagnostic-2.8.1.tgz", - "integrity": "sha512-IyMREe9OkfEqTNi67ZmFRtc6dZ35w0Snj05yDnxv5fKcLftYgZ1UDl2/64WIQQ2MZQnrZV9qrdZssdPhY9Qf3A==", - "dev": true, - "requires": { - "@mischnic/json-sourcemap": "^0.1.0", - "nullthrows": "^1.1.1" - } - }, - "@parcel/events": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/events/-/events-2.8.1.tgz", - "integrity": "sha512-x3JOa9RgEhHTGhRusC9/Er4/KZQ4F5M2QVTaHTmCqWqA/eOVXpi5xQTERvNFsb/5cmfsDlFPXPd1g4ErRJfasw==", - "dev": true - }, - "@parcel/fs": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/fs/-/fs-2.8.1.tgz", - "integrity": "sha512-+3lZfH0/2IoGrlq09SuOaULe55S6F+G2rGVHLqPt8JO9JJr1fMAZIGVA8YkPOv4Y/LhL0M1ly0gek4k+jl8iDg==", - "dev": true, - "requires": { - "@parcel/fs-search": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/watcher": "^2.0.7", - "@parcel/workers": "2.8.1" - } - }, - "@parcel/fs-search": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/fs-search/-/fs-search-2.8.1.tgz", - "integrity": "sha512-zp1CjB3Va4Sp7JrS/8tUs5NzHYPiWgabsL70Xv7ExlvIBZC42HI0VEbBFvNn4/pra2s+VqJhStd2GTBvjnwk9g==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3" - } - }, - "@parcel/graph": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/graph/-/graph-2.8.1.tgz", - "integrity": "sha512-ZNRZLGfpcASMRhKmu3nySyMybqXtddneCf29E3FLqYEqj5dqbp4jBfKI55E9vxVUssp4cNKmVfqcTHFGXfGEaQ==", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, - "requires": { - "nullthrows": "^1.1.1" + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/hash": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/hash/-/hash-2.8.1.tgz", - "integrity": "sha512-qI2CDyN7ogdCi0Euha3pCr9oZ8+4XBO/hRlYPo6MQ7pAg/dfncg+xEpWyt/g2KRhbTapX/+Zk8SnRJyy+Pynvw==", + "node_modules/standard": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.0.0.tgz", + "integrity": "sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==", "dev": true, - "requires": { - "detect-libc": "^1.0.3", - "xxhash-wasm": "^0.4.2" + "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": { + "eslint": "^8.13.0", + "eslint-config-standard": "17.0.0", + "eslint-config-standard-jsx": "^11.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-n": "^15.1.0", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-react": "^7.28.0", + "standard-engine": "^15.0.0" + }, + "bin": { + "standard": "bin/cmd.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "@parcel/logger": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/logger/-/logger-2.8.1.tgz", - "integrity": "sha512-jnZfAZT8OQVilATC+tgxoNgx1woc84akG6R3lYeYbmKByRQdZ5QzEUJ4IIgXKCXk6Vp+GhORs7Omot418zx1xg==", + "node_modules/standard-engine": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", + "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1" + "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": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.6", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "@parcel/markdown-ansi": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/markdown-ansi/-/markdown-ansi-2.8.1.tgz", - "integrity": "sha512-5aNMdBlUniCjcJOdsgaLrr9xRKPgH7zmnifdJOlUOeW2wk95xRRVLIbTJoMtGxkN4gySxPZWX+SfOYXVLWqqAw==", + "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, - "requires": { - "chalk": "^4.1.0" + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "@parcel/namer-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/namer-default/-/namer-default-2.8.1.tgz", - "integrity": "sha512-ewI1Rk7Fn3iqsgnU2bcelgQtckrhWtRip7mdeI7VWr+M/M1DiwVvaxOQCZ8E083umjooMvmRDXXx9YGAqT8Kgw==", + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1" + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/node-resolver-core": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/node-resolver-core/-/node-resolver-core-2.8.1.tgz", - "integrity": "sha512-kg7YQwYAIxVfV8DW8IjhiF1xf4XCQ9NReZSpgNZ1ubUvApakRqfLvttp4K1ZIpnm+OLvtgXn1euV4J9jhx7qXw==", + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "semver": "^5.7.1" - }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/optimizer-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-css/-/optimizer-css-2.8.1.tgz", - "integrity": "sha512-iZqNhZiMtTg2z19FpGkFFx3SQpWakh3S7gaG75fN4Mt3o84G35ag920uHT/6a34wFBHSuH05lLZGUlDwKIU5Ng==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", - "nullthrows": "^1.1.1" + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/optimizer-htmlnano": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-htmlnano/-/optimizer-htmlnano-2.8.1.tgz", - "integrity": "sha512-lIm2nvU506fzNQl6VrsANKjHC1wVwqgfPLJreC7JazRLBYwTl2UvyjNmAEjtnmoGbwA6GS9+Y3TaYcbGjNvpwA==", + "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": { - "@parcel/plugin": "2.8.1", - "htmlnano": "^2.0.0", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "svgo": "^2.4.0" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "@parcel/optimizer-image": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-image/-/optimizer-image-2.8.1.tgz", - "integrity": "sha512-mi4pgr/aj47y5X7zLsHP+tFv9hW1wUDnAu9PxCrBKGE0uEqWs9L6boCzJ1dmjfnvNT9phs6ZXyv4zlayRBVQLw==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "detect-libc": "^1.0.3" + "engines": { + "node": ">=4" } }, - "@parcel/optimizer-svgo": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-svgo/-/optimizer-svgo-2.8.1.tgz", - "integrity": "sha512-V8KP+EaO0jLI0l3hpiv/fTSVRKCRKyBwSZt0dnWU2LWPAOIK5H3ggeicXc61th+nEACk/u7YzoP7oxpU87VzHA==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "svgo": "^2.4.0" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@parcel/optimizer-terser": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/optimizer-terser/-/optimizer-terser-2.8.1.tgz", - "integrity": "sha512-ELNtiq1nqvEfURwFgSzK93Zb3C0ruxIUT/ln8zGi8KQTxWKA0PLthzlAqwAotA/zKF5DwjUa3gw0pn2xKuZv8w==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "terser": "^5.2.0" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "@parcel/package-manager": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/package-manager/-/package-manager-2.8.1.tgz", - "integrity": "sha512-zv0hAOwlCHcV4jNM60hG9fkNcEwkI9O/FsZlPMqqXBq5rKJ4iMyvOoMCzkfWUqf3RkgqvXSqTfEaDD6MQJ0ZGg==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "semver": "^5.7.1" + "engines": { + "node": ">= 0.4" }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/packager-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-css/-/packager-css-2.8.1.tgz", - "integrity": "sha512-nFeIwNgElEVZQCUKOU52T34TMpUhpCazNzAD79/Adrwu4YsFlIU6DmGePyGYlXDNlyuM+gCIu5uXgVUyn96ZnA==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" - } + "node_modules/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 }, - "@parcel/packager-html": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-html/-/packager-html-2.8.1.tgz", - "integrity": "sha512-9e1HM4kutardgEmWLJTqG+jGoA/sozaN8xVQ8tavFRyMS3dEjB78Kb/+nT887nIXmoWSFSkUkh1LM+9O4OqkJQ==", + "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": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5" + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "@parcel/packager-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-js/-/packager-js-2.8.1.tgz", - "integrity": "sha512-BWJsCjBZAexeCHGDxJrXYduVdlTygj6Ok6HIg2skIkAVfPLipx9GIh10EBsdHZy3GhWddvnvxaMXQdUvoADnEw==", + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "globals": "^13.2.0", - "nullthrows": "^1.1.1" + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "@parcel/packager-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-raw/-/packager-raw-2.8.1.tgz", - "integrity": "sha512-VeXRLPT2WF03sVjxI1yaRvDJAvxorxCLm56xwxCWmDgRTBb4q/cv81AAVztLkYsOltjDWJnFSQLm1AvZz6oSaw==", + "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": { - "@parcel/plugin": "2.8.1" + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "@parcel/packager-svg": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/packager-svg/-/packager-svg-2.8.1.tgz", - "integrity": "sha512-Yln3iuAohtVN8XDDbBWqH0fUMVWfsmDpJ6pNjZPTyXeaFOw2GkqvRaQwQM5CDXKGstkLHCzYBBhIVrmEWxTyXA==", + "node_modules/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, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "posthtml": "^0.16.4" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "@parcel/plugin": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/plugin/-/plugin-2.8.1.tgz", - "integrity": "sha512-7rAKJ8UvjwMwyiOKy5nl1UEjeLLINN6tKU8Gr9rqjfC9lux/wrd0+wuixtncThpyNJHOdmPggqTA412s2pgbNQ==", + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "requires": { - "@parcel/types": "2.8.1" + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/reporter-cli": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/reporter-cli/-/reporter-cli-2.8.1.tgz", - "integrity": "sha512-9+Wk9eaQOTHAQs6h+aeoqPGCJxNJkMdLnD7eHbHd8Jn+Ge4ux29yBJUn5zfmWLo/5zGI8yXDjoLLOQNPqVgU2g==", + "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": { - "@parcel/plugin": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "chalk": "^4.1.0", - "term-size": "^2.2.1" + "dependencies": { + "punycode": "^2.1.0" } }, - "@parcel/reporter-dev-server": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/reporter-dev-server/-/reporter-dev-server-2.8.1.tgz", - "integrity": "sha512-LO3gu8r+NpKJHNzJPEum/Mvem0Pr8B66J7OAFJWCHkJ4QMJU7V8F40gcweKCbbVBctMelptz2eTqXr4pBgrlkg==", + "node_modules/weak-ref-collections": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.3.tgz", + "integrity": "sha512-N1fa+68+m2sMZW4MdERUf9zw1J9bALS2VB7hnhXplUe/KDlLIh0QE4CCm4/hy63hXKLAfgHJRHA6cYOnpBLiVA==" + }, + "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": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1" + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "@parcel/resolver-default": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/resolver-default/-/resolver-default-2.8.1.tgz", - "integrity": "sha512-t203Y7PEGnwl4GEr9AthgMOgjLbtCCKzzKty3PLRSeZY4e2grc/SRUWZM7lQO2UMlKpheXuEJy4irvHl7qv43A==", + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, - "requires": { - "@parcel/node-resolver-core": "2.8.1", - "@parcel/plugin": "2.8.1" + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@parcel/runtime-browser-hmr": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-browser-hmr/-/runtime-browser-hmr-2.8.1.tgz", - "integrity": "sha512-BmkJYQYGtkXNnI25sl1yE9sWDXK1t6Rtz3tTUDB0kD62ukV6rx6qjEpmcHdB2NgjvAkPIwZHnVK4KE1QX71dTg==", + "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, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1" + "engines": { + "node": ">=0.10.0" } }, - "@parcel/runtime-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-js/-/runtime-js-2.8.1.tgz", - "integrity": "sha512-OMbjlunfk+b+4OUjjCZxsJOlxXAG878g6rUr1LIBBlukK65z1WxhjBukjf2y7ZbtIvIx3/k07fNgekQeFYBJaQ==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" - } + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, - "@parcel/runtime-react-refresh": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-react-refresh/-/runtime-react-refresh-2.8.1.tgz", - "integrity": "sha512-HbPKocBTt9Adj01MTYJnkp+U8WODBCCE+j9GdUHnLEobuctupLLM+ARiGXEzc4T+dwxgo/1nKaYCki9segCBFg==", + "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, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "react-error-overlay": "6.0.9", - "react-refresh": "^0.9.0" + "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" } }, - "@parcel/runtime-service-worker": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/runtime-service-worker/-/runtime-service-worker-2.8.1.tgz", - "integrity": "sha512-hIwtcx6UxXTxv3LzQHX057jrlYXKSQMmLDq0+CNHMvStjIqMvE2inn6WBXL7fBC0iFbe4/wknRow+cX8nHKIzQ==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1" - } + "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 }, - "@parcel/source-map": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@parcel/source-map/-/source-map-2.1.1.tgz", - "integrity": "sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==", + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true, - "requires": { - "detect-libc": "^1.0.3" + "engines": { + "node": ">=8" } }, - "@parcel/transformer-babel": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-babel/-/transformer-babel-2.8.1.tgz", - "integrity": "sha512-pIURnRJ1GU885tRrSHmmA6sE8JSC8/KpU9XM9wmK6Se/nWbSFTvNkiRx1sXxmUXBUPBCa0VFqQEcwrzGB4Py6A==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "json5": "^2.2.0", - "nullthrows": "^1.1.1", - "semver": "^5.7.0" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "engines": { + "node": ">=10" } }, - "@parcel/transformer-css": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-css/-/transformer-css-2.8.1.tgz", - "integrity": "sha512-DUPIcfZpuPYR/6SAu1TI08n2zjb7p3qoAkqqh2lIQniL99uEq8OsNFl84JEwUIiESZS/ExpQ7yXxAN7G1qamVw==", - "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "browserslist": "^4.6.6", - "lightningcss": "^1.16.1", - "nullthrows": "^1.1.1" - } + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "@parcel/transformer-html": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-html/-/transformer-html-2.8.1.tgz", - "integrity": "sha512-Ve9qjNE+gWdyHyDKyzq+UwYdX0KjoHGo8WVN2qX0UtH+TYwnoi51oi+GTBa96+0Rq8fzBHWkqf53sUTFzDaFdw==", + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" - }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, - "@parcel/transformer-image": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-image/-/transformer-image-2.8.1.tgz", - "integrity": "sha512-K5PF00LXY1RelPEdMcZSc/rsQcjjmeBNDvLSrv9DWVbhiYZ+k3JRS9y5Ga+wPYRdEl0d+Z61ku0+cqz/uCoryA==", + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "nullthrows": "^1.1.1" + "engines": { + "node": ">=10" } }, - "@parcel/transformer-js": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-js/-/transformer-js-2.8.1.tgz", - "integrity": "sha512-yGYpgBwL0DrkojXNvij+8f1Av6oU8PNUMVbfZRIVMdZ+Wtjx8NyAeY16cjSIxnG16vL5Pff+QhlBKRp9n6tnKA==", + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/utils": "2.8.1", - "@parcel/workers": "2.8.1", - "@swc/helpers": "^0.4.12", - "browserslist": "^4.6.6", - "detect-libc": "^1.0.3", - "nullthrows": "^1.1.1", - "regenerator-runtime": "^0.13.7", - "semver": "^5.7.1" - }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@parcel/transformer-json": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-json/-/transformer-json-2.8.1.tgz", - "integrity": "sha512-CijTTmMModiyBJCJoPlQvjrByaAs4jKMF+8Mbbaap39A1hJPNVSReFvHbRBO/cZ+2uVgxuSmfYD00YuZ784aVg==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "json5": "^2.2.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - } + "engines": { + "node": ">=10" } }, - "@parcel/transformer-postcss": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-postcss/-/transformer-postcss-2.8.1.tgz", - "integrity": "sha512-xmO4zA8nCgCgPstqxHr2BzRSJtqAy8cyAY1R9oi5FHkU5xHEzOGrcj5JynlU0eJssFten48kf8Csx6ciOsH1ZA==", + "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, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "clone": "^2.1.1", - "nullthrows": "^1.1.1", - "postcss-value-parser": "^4.2.0", - "semver": "^5.7.1" + "engines": { + "node": ">=10" }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } - }, - "@parcel/transformer-posthtml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-posthtml/-/transformer-posthtml-2.8.1.tgz", - "integrity": "sha512-CLrSw+386j7RCrWV3Oyob4qNP+qyfVRDs1BzJZMMW8MFjxEC/ohPi2piGNzaqWPHOvATFodqXBvJBc2WcEZKGA==", + } + }, + "dependencies": { + "@eslint/eslintrc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", + "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", "dev": true, "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.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" }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "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==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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": { + "brace-expansion": "^1.1.7" + } } } }, - "@parcel/transformer-raw": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-raw/-/transformer-raw-2.8.1.tgz", - "integrity": "sha512-LVC6FX5tcLrZcOV1yzA8FMT5R+u2uQqCt/TXPhrt3MBw3WovKpaMicSkR0AI/802tg+nm1wpURVEfAA2S9+AQw==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1" - } - }, - "@parcel/transformer-react-refresh-wrap": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-react-refresh-wrap/-/transformer-react-refresh-wrap-2.8.1.tgz", - "integrity": "sha512-VkULeuyy0CrxfMwrRkn4V/HmbXzbuqp3+drvYFRCo29SFuC6rJbBF43XiewmvJijWIGCfEAa6bU9/csg2d5+3g==", - "dev": true, - "requires": { - "@parcel/plugin": "2.8.1", - "@parcel/utils": "2.8.1", - "react-refresh": "^0.9.0" - } - }, - "@parcel/transformer-svg": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/transformer-svg/-/transformer-svg-2.8.1.tgz", - "integrity": "sha512-HSPve53tWttfKmoXgNLmrF49UCsE38xsA/CkWxI6wQM2qoqLMyei5DY9UsD0cjcAm87tSlZFTq9E/Nbol8g50w==", + "@humanwhocodes/config-array": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", + "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", "dev": true, "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/plugin": "2.8.1", - "nullthrows": "^1.1.1", - "posthtml": "^0.16.5", - "posthtml-parser": "^0.10.1", - "posthtml-render": "^3.0.0", - "semver": "^5.7.1" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "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==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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": { + "brace-expansion": "^1.1.7" + } } } }, - "@parcel/types": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/types/-/types-2.8.1.tgz", - "integrity": "sha512-sLkpjGCCJy8Hxe6+dme+sugyu6+RW5B8WcdXG1Ynp7SkdgEYV44TKNVGnhoxsHi50G+O1ktZ4jzAu+pzubidXQ==", - "dev": true, - "requires": { - "@parcel/cache": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/source-map": "^2.1.1", - "@parcel/workers": "2.8.1", - "utility-types": "^3.10.0" - } + "@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 }, - "@parcel/utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/utils/-/utils-2.8.1.tgz", - "integrity": "sha512-C01Iz+K7oUVNTEzMW6SLDpqTDpm+Z3S+Ms3TxImkLYmdvYpYtzdU+gAllv6ck9WgB1Kqgcxq3TC0yhFsNDb5WQ==", - "dev": true, - "requires": { - "@parcel/codeframe": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/hash": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/markdown-ansi": "2.8.1", - "@parcel/source-map": "^2.1.1", - "chalk": "^4.1.0" - } + "@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 }, - "@parcel/watcher": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.7.tgz", - "integrity": "sha512-gc3hoS6e+2XdIQ4HHljDB1l0Yx2EWh/sBBtCEFNKGSMlwASWeAQsOY/fPbxOBcZ/pg0jBh4Ga+4xHlZc4faAEQ==", + "@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, "requires": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" } }, - "@parcel/workers": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/@parcel/workers/-/workers-2.8.1.tgz", - "integrity": "sha512-6TnRPwBpxXUsekKK88OxPZ500gvApxF0TaZdSDvmMlvDWjZYgkDN3AAsaFS1gwFLS4XKogn2TgjUnocVof8DXg==", - "dev": true, - "requires": { - "@parcel/diagnostic": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/types": "2.8.1", - "@parcel/utils": "2.8.1", - "chrome-trace-event": "^1.0.2", - "nullthrows": "^1.1.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==", + "dev": true }, - "@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "@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, "requires": { - "tslib": "^2.4.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" } }, - "@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true - }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==", - "dev": true - }, "acorn": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", @@ -6969,27 +3408,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -7014,24 +3438,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "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 - }, "builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -7063,12 +3469,6 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, - "caniuse-lite": { - "version": "1.0.30001439", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", - "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", - "dev": true - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7106,12 +3506,6 @@ "readdirp": "~3.6.0" } }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -7123,12 +3517,6 @@ "wrap-ansi": "^7.0.0" } }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7144,45 +3532,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "dependencies": { - "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": { - "@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" - } - } - } - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -7194,44 +3549,6 @@ "which": "^2.0.1" } }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, - "requires": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dev": true, - "requires": { - "css-tree": "^1.1.2" - } - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -7271,12 +3588,6 @@ "object-keys": "^1.1.1" } }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true - }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -7292,81 +3603,12 @@ "esutils": "^2.0.2" } }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "dependencies": { - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - } - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", - "dev": true - }, - "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "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": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", - "dev": true - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -7983,12 +4225,6 @@ "has-symbols": "^1.0.3" } }, - "get-port": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", - "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", - "dev": true - }, "get-stdin": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", @@ -8121,29 +4357,6 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "htmlnano": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/htmlnano/-/htmlnano-2.0.3.tgz", - "integrity": "sha512-S4PGGj9RbdgW8LhbILNK7W9JhmYP8zmDY7KDV/8eCiJBQJlbmltp5I0gv8c5ntLljfdxxfmJ+UJVSqyH4mb41A==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.1", - "posthtml": "^0.16.5", - "timsort": "^0.3.0" - } - }, - "htmlparser2": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", - "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" - } - }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -8272,12 +4485,6 @@ "is-extglob": "^2.1.1" } }, - "is-json": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", - "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", - "dev": true - }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -8396,12 +4603,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "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": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8443,112 +4644,6 @@ "type-check": "~0.4.0" } }, - "lightningcss": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.17.1.tgz", - "integrity": "sha512-DwwM/YYqGwLLP3he41wzDXT/m+8jdEZ80i9ViQNLRgyhey3Vm6N7XHn+4o3PY6wSnVT23WLuaROIpbpIVTNOjg==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3", - "lightningcss-darwin-arm64": "1.17.1", - "lightningcss-darwin-x64": "1.17.1", - "lightningcss-linux-arm-gnueabihf": "1.17.1", - "lightningcss-linux-arm64-gnu": "1.17.1", - "lightningcss-linux-arm64-musl": "1.17.1", - "lightningcss-linux-x64-gnu": "1.17.1", - "lightningcss-linux-x64-musl": "1.17.1", - "lightningcss-win32-x64-msvc": "1.17.1" - } - }, - "lightningcss-darwin-arm64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.1.tgz", - "integrity": "sha512-YTAHEy4XlzI3sMbUVjbPi9P7+N7lGcgl2JhCZhiQdRAEKnZLQch8kb5601sgESxdGXjgei7JZFqi/vVEk81wYg==", - "dev": true, - "optional": true - }, - "lightningcss-darwin-x64": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.1.tgz", - "integrity": "sha512-UhXPUS2+yTTf5sXwUV0+8QY2x0bPGLgC/uhcknWSQMqWn1zGty4fFvH04D7f7ij0ujwSuN+Q0HtU7lgmMrPz0A==", - "dev": true, - "optional": true - }, - "lightningcss-linux-arm-gnueabihf": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.1.tgz", - "integrity": "sha512-alUZumuznB6K/9yZ0zuZkODXUm8uRnvs9t0CL46CXN16Y2h4gOx5ahUCMlelUb7inZEsgJIoepgLsJzBUrSsBw==", - "dev": true, - "optional": true - }, - "lightningcss-linux-arm64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.1.tgz", - "integrity": "sha512-/1XaH2cOjDt+ivmgfmVFUYCA0MtfNWwtC4P8qVi53zEQ7P8euyyZ1ynykZOyKXW9Q0DzrwcLTh6+hxVLcbtGBg==", - "dev": true, - "optional": true - }, - "lightningcss-linux-arm64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.1.tgz", - "integrity": "sha512-/IgE7lYWFHCCQFTMIwtt+fXLcVOha8rcrNze1JYGPWNorO6NBc6MJo5u5cwn5qMMSz9fZCCDIlBBU4mGwjQszQ==", - "dev": true, - "optional": true - }, - "lightningcss-linux-x64-gnu": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.1.tgz", - "integrity": "sha512-OyE802IAp4DB9vZrHlOyWunbHLM9dN08tJIKN/HhzzLKIHizubOWX6NMzUXMZLsaUrYwVAHHdyEA+712p8mMzA==", - "dev": true, - "optional": true - }, - "lightningcss-linux-x64-musl": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.1.tgz", - "integrity": "sha512-ydwGgV3Usba5P53RAOqCA9MsRsbb8jFIEVhf7/BXFjpKNoIQyijVTXhwIgQr/oGwUNOHfgQ3F8ruiUjX/p2YKw==", - "dev": true, - "optional": true - }, - "lightningcss-win32-x64-msvc": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.1.tgz", - "integrity": "sha512-Ngqtx9NazaiAOk71XWwSsqgAuwYF+8PO6UYsoU7hAukdrSS98kwaBMEDw1igeIiZy1XD/4kh5KVnkjNf7ZOxVQ==", - "dev": true, - "optional": true - }, - "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 - }, - "lmdb": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-2.5.2.tgz", - "integrity": "sha512-V5V5Xa2Hp9i2XsbDALkBTeHXnBXh/lEmk9p22zdr7jtuOIY9TGhjK6vAvTpOOx9IKU4hJkRWZxn/HsvR1ELLtA==", - "dev": true, - "requires": { - "@lmdb/lmdb-darwin-arm64": "2.5.2", - "@lmdb/lmdb-darwin-x64": "2.5.2", - "@lmdb/lmdb-linux-arm": "2.5.2", - "@lmdb/lmdb-linux-arm64": "2.5.2", - "@lmdb/lmdb-linux-x64": "2.5.2", - "@lmdb/lmdb-win32-x64": "2.5.2", - "msgpackr": "^1.5.4", - "node-addon-api": "^4.3.0", - "node-gyp-build-optional-packages": "5.0.3", - "ordered-binary": "^1.2.4", - "weak-lru-cache": "^1.2.2" - }, - "dependencies": { - "node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true - } - } - }, "load-json-file": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", @@ -8613,12 +4708,6 @@ "yallist": "^4.0.0" } }, - "mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true - }, "minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -8669,31 +4758,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "msgpackr": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.8.1.tgz", - "integrity": "sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==", - "dev": true, - "requires": { - "msgpackr-extract": "^2.2.0" - } - }, - "msgpackr-extract": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz", - "integrity": "sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog==", - "dev": true, - "optional": true, - "requires": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-arm": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-linux-x64": "2.2.0", - "@msgpackr-extract/msgpackr-extract-win32-x64": "2.2.0", - "node-gyp-build-optional-packages": "5.0.3" - } - }, "nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -8706,51 +4770,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", - "dev": true - }, - "node-gyp-build-optional-packages": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.3.tgz", - "integrity": "sha512-k75jcVzk5wnnc/FMxsf4udAoTEUv2jY3ycfdSd3yWu6Cnd1oee6/CfZJApyscA4FJOmdoixWwiwOyf16RzD5JA==", - "dev": true - }, - "node-releases": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.7.tgz", - "integrity": "sha512-EJ3rzxL9pTWPjk5arA0s0dgXpnyiAbJDE6wHT62g7VsgrgQgmmZ+Ru++M1BFofncWja+Pnn3rEr3fieRySAdKQ==", - "dev": true - }, "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 }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -8847,12 +4872,6 @@ "word-wrap": "^1.2.3" } }, - "ordered-binary": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.4.0.tgz", - "integrity": "sha512-EHQ/jk4/a9hLupIKxTfUsQRej1Yd/0QLQs3vGvIqg5ZtCYSzNhkzHoZc7Zf4e4kUlDaC3Uw8Q/1opOLNN2OKRQ==", - "dev": true - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8877,28 +4896,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "parcel": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/parcel/-/parcel-2.8.1.tgz", - "integrity": "sha512-3hl31uIRG+k3N54Le0fLQU8a5VsKFN3j3igs3rEQv6GtXFUNjq58m/Fc1dbOI/v+0fPOv01wyHACn9MCQYesVA==", - "dev": true, - "requires": { - "@parcel/config-default": "2.8.1", - "@parcel/core": "2.8.1", - "@parcel/diagnostic": "2.8.1", - "@parcel/events": "2.8.1", - "@parcel/fs": "2.8.1", - "@parcel/logger": "2.8.1", - "@parcel/package-manager": "2.8.1", - "@parcel/reporter-cli": "2.8.1", - "@parcel/reporter-dev-server": "2.8.1", - "@parcel/utils": "2.8.1", - "chalk": "^4.1.0", - "commander": "^7.0.0", - "get-port": "^4.2.0", - "v8-compile-cache": "^2.0.0" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8942,18 +4939,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "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 - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -9021,51 +5006,6 @@ } } }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "posthtml": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", - "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", - "dev": true, - "requires": { - "posthtml-parser": "^0.11.0", - "posthtml-render": "^3.0.0" - }, - "dependencies": { - "posthtml-parser": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", - "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", - "dev": true, - "requires": { - "htmlparser2": "^7.1.1" - } - } - } - }, - "posthtml-parser": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.10.2.tgz", - "integrity": "sha512-PId6zZ/2lyJi9LiKfe+i2xv57oEjJgWbsHGGANwos5AvdQp98i6AtamAl8gzSVFGfQ43Glb5D614cvZf012VKg==", - "dev": true, - "requires": { - "htmlparser2": "^7.1.1" - } - }, - "posthtml-render": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", - "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", - "dev": true, - "requires": { - "is-json": "^2.0.1" - } - }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9104,24 +5044,12 @@ "safe-buffer": "^5.1.0" } }, - "react-error-overlay": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", - "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", - "dev": true - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "react-refresh": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.9.0.tgz", - "integrity": "sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==", - "dev": true - }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -9131,12 +5059,6 @@ "picomatch": "^2.2.1" } }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true - }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -9262,28 +5184,6 @@ "object-inspect": "^1.9.0" } }, - "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 - }, - "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": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, "standard": { "version": "17.0.0", "resolved": "https://registry.npmjs.org/standard/-/standard-17.0.0.tgz", @@ -9397,59 +5297,12 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, - "svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dev": true, - "requires": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - } - }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true - }, - "terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "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 - } - } - }, "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 }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9471,12 +5324,6 @@ "strip-bom": "^3.0.0" } }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "dev": true - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9504,16 +5351,6 @@ "which-boxed-primitive": "^1.0.2" } }, - "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==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -9523,24 +5360,6 @@ "punycode": "^2.1.0" } }, - "utility-types": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", - "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "weak-lru-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", - "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", - "dev": true - }, "weak-ref-collections": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.3.tgz", @@ -9603,12 +5422,6 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, - "xxhash-wasm": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-0.4.2.tgz", - "integrity": "sha512-/eyHVRJQCirEkSZ1agRSCwriMhwlyUcFkXD5TPVSLP+IPzjsqMVzZwdoczLp1SoQU0R3dxz1RpIK+4YNQbCVOA==", - "dev": true - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9621,12 +5434,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", diff --git a/package.json b/package.json index eb93b3a..68415b7 100644 --- a/package.json +++ b/package.json @@ -16,16 +16,12 @@ ], "devDependencies": { "mocha": "^10.1.0", - "parcel": "^2.8.1", "standard": "^17.0.0" }, "scripts": { "lint": "standard --fix", - "build": "rm -rf dist/ && parcel build", - "prepare": "npm run build", - "pretest": "npm run build", "test": "standard && mocha test/test.js", - "prepublishOnly": "npm test" + "prepare": "npm test" }, "repository": { "type": "git", From 96bc97cc423aee0edf73eae7927300a2f85c8664 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 01:40:21 +0800 Subject: [PATCH 46/71] Updated dependencies --- package-lock.json | 484 ++++++++++++++++++++++------------------------ 1 file changed, 234 insertions(+), 250 deletions(-) diff --git a/package-lock.json b/package-lock.json index 170a8d3..1db760a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,10 +40,11 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -76,10 +77,11 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -195,10 +197,11 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -317,21 +320,23 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -477,10 +482,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -491,12 +497,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -507,12 +514,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", @@ -548,10 +549,11 @@ } }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -890,10 +892,11 @@ } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -964,10 +967,11 @@ } }, "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1026,10 +1030,11 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1077,10 +1082,11 @@ } }, "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -1135,10 +1141,11 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1267,10 +1274,11 @@ } }, "node_modules/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==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1459,10 +1467,11 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1781,6 +1790,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2060,23 +2070,12 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -2094,32 +2093,32 @@ } }, "node_modules/mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -2127,10 +2126,27 @@ }, "engines": { "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ms": { @@ -2139,18 +2155,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2544,6 +2548,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -2696,7 +2701,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.0.0", @@ -2713,13 +2719,11 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2728,10 +2732,11 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -2968,6 +2973,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -3081,10 +3087,11 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -3127,12 +3134,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -3152,10 +3153,11 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "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, + "license": "ISC", "engines": { "node": ">=10" } @@ -3207,9 +3209,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -3239,9 +3241,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -3329,9 +3331,9 @@ } }, "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true }, "ansi-regex": { @@ -3415,21 +3417,21 @@ "dev": true }, "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "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": { "balanced-match": "^1.0.0" } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-stdout": { @@ -3539,9 +3541,9 @@ "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -3550,20 +3552,12 @@ } }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } + "ms": "^2.1.3" } }, "decamelize": { @@ -3589,9 +3583,9 @@ } }, "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true }, "doctrine": { @@ -3730,9 +3724,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -3863,9 +3857,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -3924,9 +3918,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -3974,9 +3968,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -4013,9 +4007,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -4131,9 +4125,9 @@ } }, "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==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -4256,9 +4250,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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, "requires": { "balanced-match": "^1.0.0", @@ -4699,19 +4693,10 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -4724,32 +4709,46 @@ "dev": true }, "mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "dev": true, "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + } } }, "ms": { @@ -4758,12 +4757,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5141,18 +5134,15 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -5394,9 +5384,9 @@ "dev": true }, "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "wrap-ansi": { @@ -5428,12 +5418,6 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -5450,9 +5434,9 @@ } }, "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "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 }, "yargs-unparser": { From 93bdd655d7d2dd8485cedd058aaacd34c0d6c668 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 01:49:28 +0800 Subject: [PATCH 47/71] Updated github action node versions --- .github/workflows/npm-publish.yml | 4 ++-- .github/workflows/pull-request-test.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 7ac8a13..7dcc2b9 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 22 - run: npm ci - run: npm test @@ -25,7 +25,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 22 registry-url: https://registry.npmjs.org/ - run: npm ci - run: npm publish diff --git a/.github/workflows/pull-request-test.yml b/.github/workflows/pull-request-test.yml index e78b6e8..1e0667c 100644 --- a/.github/workflows/pull-request-test.yml +++ b/.github/workflows/pull-request-test.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - node-version: [18.x, 19.x] + node-version: [20.x, 22.x, 24.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: From 5630262147d0ebb0473098e4635f749aef49d2a3 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 02:12:26 +0800 Subject: [PATCH 48/71] Cleaned up readme --- README.md | 54 ++++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 197dfc1..4d6776d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Reactor.js ========== -Reactor.js is a simple library for [reactive programming](http://en.wikipedia.org/wiki/Reactive_programming). It provides +Reactor.js is a simple library for [reactive programming](http://en.wikipedia.org/wiki/Reactive_programming). It provides - `Reactor` objects that store reactive variables - `Observer` functions that automatically track the reactive variables that they use and retrigger if any of these variables are updated @@ -20,15 +20,11 @@ reactor.foo = 'moo' // prints "foo is moo" - When an `Observer` reads a `Reactor` it registers itself as a dependent - When a `Reactor` is updated it automatically retriggers the dependent `Observer` functions -Reactor.js is meant to be unobtrusive and unopinionated. +Reactor.js is meant to be unobtrusive and unopinionated. - No special syntax to learn. Everything is just plain javascript -- There is no need to manually declare listeners or bindings. Reactor.js automatically keeps track of all that for you. +- There is no need to manually declare listeners or bindings. Reactor.js automatically keeps track of all that for you. - It imposes no particular structure on your code. Any variable can be easily replaced with a reactive one without changing the rest of your codebase. -If you want to see Reactor.js in action, take a look at this [example todo list](https://jsfiddle.net/jgt46s0a/39/) - -Note: v2 of Reactor.js previously had some UI elements. This has been split out into a separate project [Elementary](https://github.com/fynyky/elementary) that is built ontop of Reactor.js. For v3 Reactor is focusing on just the core reactive components. - Installation ------------ @@ -39,13 +35,7 @@ $ npm install reactorjs Import it using: ```javascript -import { - Reactor, - Observer, - hide, - batch, - shuck -} from 'reactorjs' +import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' ``` It is also available directly from [unpkg](unpkg.com). You can import it in javascript using @@ -239,7 +229,7 @@ const capitalizer = new Observer(() => { const printer = new Observer(() => { // Manually calls capitalizer like a function which actives it // As well as accesses its return value as a dependency - console.log(capitalizer()) + console.log(capitalizer()) })() // Starts printer which starts capitalizer reactor.foo = 'baz' // Prints 'BAZ' ``` @@ -290,7 +280,7 @@ parameterizedObserver('beep', 'bop') // Prints bazbeepbop reactor.foo = 'bla' // Prints blabeepbop ``` -Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyboard instead of es6 arrow functions. +Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyboard instead of es6 arrow functions. ```javascript const holdingObject = { name: 'Mario', @@ -317,7 +307,7 @@ const taskList = new Reactor(["a", "b", "c", "d"]) new Observer(() => { // Even though we only want to modify the array // pop() also reads the length property of the array - console.log(taskList.pop()) + console.log(taskList.pop()) })() ``` @@ -332,7 +322,7 @@ new Observer(() => { // It is not create a depndency on the length property // Unlike our previous example hide(() => taskList.pop()) - ) + ) })() // prints "d" @@ -350,7 +340,7 @@ const observer = new Observer(myFunction) myFunction === observer.execute // true ``` -By setting this property you can change an observers internal logic. Doing so clears dependencies and retriggers the observer. Note that the previous `this` and arguments contexts will stay. +By setting this property you can change an observers internal logic. Doing so clears dependencies and retriggers the observer. Note that the previous `this` and arguments contexts will stay. ```javascript const reactor = new Reactor({ foo: "bar" }) @@ -371,29 +361,29 @@ reactor.foo = "blep" // prints "I am saying blap blep" One problem with automatic watchers is that you might end up with multiple repeated triggering when you're updating a whole lot of information all at once. The following code shows an example where you want to update multiple properties, but each property update prematurely triggers the observer since you are not done updating yet. ```javascript -const person = new Reactor({ +const person = new Reactor({ firstName: "Anakin", lastName: "Skywalker", faction: "Jedi", rank: "Knight" }) -// This observer tracks multiple properties +// This observer tracks multiple properties // and so will be triggered when any of the properties get updated const observer = new Observer(() => { console.log( "I am " + - person.firstName + - " " + - person.lastName + - ", " + - person.faction + - " " + + person.firstName + + " " + + person.lastName + + ", " + + person.faction + + " " + person.rank ) })() // prints "I am Anakin Skywalker, Jedi Knight" -// The following updates will each trigger the observer even though we only +// The following updates will each trigger the observer even though we only // want to trigger the observer once all the updates are complete person.firstName = "Darth" // prints "I am Darth Skywalker, Jedi Knight" person.lastName = "Vader" // prints "I am Darth Vader, Jedi Knight" @@ -407,7 +397,7 @@ The `batch` function is provided to allow you to batch multiple updates together // Triggers are deduplicated so any observer is triggered at most once batch(() => { // None of the following updates will trigger the observer yet - person.firstName = "Darth" + person.firstName = "Darth" person.lastName = "Vader" person.faction = "Sith" person.rank = "Lord" @@ -418,7 +408,7 @@ This is useful when you are making multiple data updates and want to avoid showi Note that only the observer triggering is postponed till the end. The actual reactor propertes are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. -Summary +Summary ------- ```javascript import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' @@ -426,7 +416,7 @@ import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' const reactor = new Reactor({ foo: 'bar' }) const observer = new Observer(() => { const result = 'reactor.foo is ' + reactor.foo // Sets a dependency on foo - console.log(result) + console.log(result) return result }) observer() // Prints 'reactor.foo is bar' and starts the observer @@ -492,7 +482,7 @@ new Observer(() => { })() // Prints 'Look its Clark Kent' batch(() => { // None of the following updates will trigger the observer yet - person.firstName = "Bruce" + person.firstName = "Bruce" person.lastName = "Wayne" }) // prints 'Look its Bruce Wayne' From 298761eae60877f079a9dafc410414d25d2a3aef Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 02:13:56 +0800 Subject: [PATCH 49/71] Removed README reference to ob since it is no longer there --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 4d6776d..008ec8c 100644 --- a/README.md +++ b/README.md @@ -168,13 +168,6 @@ new Observer(() => { })() // prints "hello world" and starts the observer ``` -For further simplicity the shorthand `ob` is also provided that is equivalent to `new Observer` -```javascript -ob(() => { - console.log("hello world") -})() // prints "hello world" and starts the observer -``` - When an `Observer` reads a `Reactor` property it gets saved as a dependent. When that property is updated it notifies the observer which reruns its function. This happens automatically without any need to manually declare dependencies. ```javascript const reactor = new Reactor() From ddff5d822e5e07306d443e40e20b840857d3aeeb Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 02:25:28 +0800 Subject: [PATCH 50/71] Fixed more readme problems --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 008ec8c..9df1b54 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ $ npm install reactorjs Import it using: ```javascript -import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' +import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' ``` It is also available directly from [unpkg](unpkg.com). You can import it in javascript using @@ -220,7 +220,7 @@ const capitalizer = new Observer(() => { return reactor.foo.toUpperCase() }) // Did not start the observer here const printer = new Observer(() => { - // Manually calls capitalizer like a function which actives it + // Manually calls capitalizer like a function which activates it // As well as accesses its return value as a dependency console.log(capitalizer()) })() // Starts printer which starts capitalizer @@ -273,7 +273,7 @@ parameterizedObserver('beep', 'bop') // Prints bazbeepbop reactor.foo = 'bla' // Prints blabeepbop ``` -Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyboard instead of es6 arrow functions. +Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of es6 arrow functions. ```javascript const holdingObject = { name: 'Mario', @@ -293,7 +293,7 @@ Sometimes you might want to read from a reactor without becoming dependent on it ```javascript const taskList = new Reactor(["a", "b", "c", "d"]) -// Creating the following observer will throw a LoopError +// Creating the following observer will cause an infinite loop // Because it both reads from and modifies the length property of taskList // As a result it triggers itself in the middle of execution // This loop is detected and creates an exception @@ -312,7 +312,7 @@ new Observer(() => { console.log( // Because we wrap pop() call in an hide block - // It is not create a depndency on the length property + // It should not create a depndency on the length property // Unlike our previous example hide(() => taskList.pop()) ) @@ -337,14 +337,14 @@ By setting this property you can change an observers internal logic. Doing so cl ```javascript const reactor = new Reactor({ foo: "bar" }) -let observerToBeOverriden = new Observer((arg) => { +let observerToBeOverridden = new Observer((arg) => { console.log(reactor.foo, 'and', arg) }) -observerToBeOverriden('blap') // prints "bar and blap" +observerToBeOverridden('blap') // prints "bar and blap" reactor.foo = "moo" // prints "moo and blap" // Setting the execute property replaces the old function -observerToBeOverriden.execute = (arg) => { +observerToBeOverridden.execute = (arg) => { console.log("I am saying", arg, reactor.foo) } // prints "I am saying blap moo" reactor.foo = "blep" // prints "I am saying blap blep" @@ -399,7 +399,7 @@ batch(() => { This is useful when you are making multiple data updates and want to avoid showing an "incomplete" view of the data to observers. -Note that only the observer triggering is postponed till the end. The actual reactor propertes are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. +Note that only the observer triggering is postponed till the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. Summary ------- @@ -480,7 +480,7 @@ batch(() => { }) // prints 'Look its Bruce Wayne' // shuck removes the Reactor layer and returns the base object -// This is necessary for some native objects which dont work with proxies +// This is necessary for some native objects which don't work with proxies const mapReactor = new Reactor(new Map()) Map.prototype.keys.call(mapReactor) // throws an Error Map.prototype.keys.call(shuck(mapReactor)) // works fine From 6382da104590c59d3562b67c7eeb16c565d417ea Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 02:29:32 +0800 Subject: [PATCH 51/71] More readme fixes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9df1b54..8d0bcc9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ $ npm install reactorjs Import it using: ```javascript -import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' +import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' ``` It is also available directly from [unpkg](unpkg.com). You can import it in javascript using @@ -312,7 +312,7 @@ new Observer(() => { console.log( // Because we wrap pop() call in an hide block - // It should not create a depndency on the length property + // It does not create a dependency on the length property // Unlike our previous example hide(() => taskList.pop()) ) @@ -490,6 +490,6 @@ Development & Testing --------------------- Tests are stored in `test.js` to be run using Mocha. -Run `npm install` to install the the dev dependencies. +Run `npm install` to install the dev dependencies. To run the tests run `npm test`. From 088eae5f59c539d54ff361543cd66c0515fb0762 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 20:30:45 +0800 Subject: [PATCH 52/71] readme consistency cleanup --- README.md | 141 ++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 8d0bcc9..92b1024 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ Reactor.js ========== -Reactor.js is a simple library for [reactive programming](http://en.wikipedia.org/wiki/Reactive_programming). It provides +Reactor.js is a simple library for [reactive programming](http://en.wikipedia.org/wiki/Reactive_programming). It provides: - `Reactor` objects that store reactive variables -- `Observer` functions that automatically track the reactive variables that they use and retrigger if any of these variables are updated +- `Observer` functions that automatically track the reactive variables they use and retrigger when any of these variables are updated Here's a quick example of what Reactor.js does: ```javascript @@ -17,13 +17,13 @@ reactor.foo = 'moo' // prints "foo is moo" ``` - `Reactor` objects work like normal objects that you can set and get properties on - `Observer` functions work like normal functions that you can define and call -- When an `Observer` reads a `Reactor` it registers itself as a dependent -- When a `Reactor` is updated it automatically retriggers the dependent `Observer` functions +- When an `Observer` reads a `Reactor`, it registers itself as a dependent +- When a `Reactor` is updated, it automatically retriggers the dependent `Observer` functions -Reactor.js is meant to be unobtrusive and unopinionated. -- No special syntax to learn. Everything is just plain javascript -- There is no need to manually declare listeners or bindings. Reactor.js automatically keeps track of all that for you. -- It imposes no particular structure on your code. Any variable can be easily replaced with a reactive one without changing the rest of your codebase. +Reactor.js is designed to be unobtrusive and unopinionated: +- No special syntax to learn. Everything is just plain JavaScript +- There is no need to manually declare listeners or bindings. Reactor.js automatically keeps track of all that for you +- It imposes no particular structure on your code. Any variable can be easily replaced with a reactive one without changing the rest of your codebase Installation ------------ @@ -38,7 +38,7 @@ Import it using: import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' ``` -It is also available directly from [unpkg](unpkg.com). You can import it in javascript using +It is also available directly from [unpkg](unpkg.com). You can import it in JavaScript using: ```javascript import { Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactorjs' ``` @@ -46,21 +46,21 @@ import { Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactor Reactors -------- -A `Reactor` is an object wrapper which automatically tracks `Observer` functions that read its properties and notifies the observers when those properties are updated. +A `Reactor` is an object wrapper that automatically tracks `Observer` functions that read its properties and notifies the observers when those properties are updated. -You create a new reactor by just calling its constructor. +You create a new reactor by calling its constructor: ```javascript const reactor = new Reactor() ``` -You can also wrap an existing object with a reactor by passing it to the constructor. Changes to the reactor are passed through to the underlying object. +You can also wrap an existing object with a reactor by passing it to the constructor. Changes to the reactor are passed through to the underlying object: ```javascript const reactor = new Reactor({ foo: "bar" }) ``` -Reactors behave mostly like plain javascript objects. +Reactors behave mostly like plain JavaScript objects: ```javascript const reactor = new Reactor({ foo: "bar" @@ -78,7 +78,7 @@ delete reactor.foo reactor.foo // undefined ``` -The key difference of `Reactor` objects is that they track when one of their properties is read by an `Observer` function and will notify that observer when the property is updated. +The key difference of `Reactor` objects is that they track when one of their properties is read by an `Observer` function and will notify that observer when the property is updated: ```javascript const reactor = new Reactor({ foo: "bar" }) @@ -96,7 +96,7 @@ Object.defineProperty(reactor, "foo", { delete reactor.foo // prints "foo is undefined" ``` -Tracking is property specific so observers will not trigger if a different property is updated +Tracking is property-specific, so observers will not trigger if a different property is updated: ```javascript const reactor = new Reactor({ foo: "bar", @@ -116,7 +116,7 @@ reactor.moo = "mar2" // prints "moo tracker is now mar2" reactor.goo = "goop" // does not trigger any observers ``` -If reading a reactor's property also returns an object, that object is recursively also wrapped in a reactor before being returned. This allows observers to tracks dependencies in nested objects easily. +If reading a reactor's property returns an object, that object is recursively wrapped in a reactor before being returned. This allows observers to track dependencies in nested objects easily: ```javascript const reactor = new Reactor({ outer: { @@ -129,7 +129,7 @@ new Observer(() => { })() // prints "inner value is cake" ``` -Reactors are implemented using [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) objects. This means reactors created from scratch typecheck as Reactors, but Reactors created from an existing object typecheck as the original object. +Reactors are implemented using [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) objects. This means reactors created from scratch typecheck as Reactors, but reactors created from an existing object typecheck as the original object: ```javascript const baseReactor = new Reactor() @@ -139,7 +139,7 @@ mapReactor instanceof Reactor // false mapReactor instanceof Map // true ``` -This also has implications for native objects or objects which use private properties. Since proxies can't access native or private properties, some methods will fail. To get around this, we provide the `shuck` function which returns a reactor's internal object. +This also has implications for native objects or objects that use private properties. Since proxies can't access native or private properties, some methods will fail. To work around this, we provide the `shuck` function which returns a reactor's internal object: ```javascript // Native object example @@ -151,9 +151,9 @@ Map.prototype.keys.apply(shuck(mapReactor)) // works fine Observers --------- -An `Observer` is like a normal function that you can define and call. When an `Observer` reads from a `Reactor` it automatically tracks that dependency, and when that reactor's property is updated it automatically triggers the observer again. +An `Observer` is like a normal function that you can define and call. When an `Observer` reads from a `Reactor`, it automatically tracks that dependency, and when that reactor's property is updated, it automatically triggers the observer again. -`Observer` functions are created by passing a function to its constructor. +`Observer` functions are created by passing a function to its constructor: ```javascript const observer = new Observer(() => { console.log("hello world") @@ -161,14 +161,14 @@ const observer = new Observer(() => { observer() // prints "hello world" and starts the observer ``` -For brevity observers can also be created and instantly executed like this +For brevity, observers can also be created and instantly executed like this: ```javascript new Observer(() => { console.log("hello world") })() // prints "hello world" and starts the observer ``` -When an `Observer` reads a `Reactor` property it gets saved as a dependent. When that property is updated it notifies the observer which reruns its function. This happens automatically without any need to manually declare dependencies. +When an `Observer` reads a `Reactor` property, it gets saved as a dependent. When that property is updated, it notifies the observer which reruns its function. This happens automatically without any need to manually declare dependencies: ```javascript const reactor = new Reactor() new Observer(() => { @@ -178,7 +178,7 @@ new Observer(() => { reactor.foo = "bar" // prints "reactor.foo is bar" ``` -An observer's dependencies are dynamically determined. Only the dependencies actually read in the last execution of an observer can trigger it again. This means that Reactor reads that are only conditionally used will not trigger the observer unnecessarily. +An observer's dependencies are dynamically determined. Only the dependencies actually read in the last execution of an observer can trigger it again. This means that reactor reads that are only conditionally used will not trigger the observer unnecessarily: ```javascript const reactor = new Reactor({ a: true, @@ -201,7 +201,7 @@ reactor.b = "blue" // does not trigger the observer reactor.c = "cheese" // prints "reactor.c is cheese" ``` -An observer's results are themselves observable via either the `value` property, or by triggering the observer via `observer()` and using the return value. This allows you to chain observers together. +An observer's results are themselves observable via either the `value` property or by triggering the observer via `observer()` and using the return value. This allows you to chain observers together: ```javascript const reactor = new Reactor({ foo: 'bar' }) const capitalizer = new Observer(() => { @@ -210,10 +210,10 @@ const capitalizer = new Observer(() => { const printer = new Observer(() => { console.log(capitalizer.value) })() // prints 'BAR' -reactor.foo = 'baz' // Prints 'BAZ' +reactor.foo = 'baz' // prints 'BAZ' ``` -This works too: +This also works: ```javascript const reactor = new Reactor({ foo: 'bar' }) const capitalizer = new Observer(() => { @@ -223,11 +223,11 @@ const printer = new Observer(() => { // Manually calls capitalizer like a function which activates it // As well as accesses its return value as a dependency console.log(capitalizer()) -})() // Starts printer which starts capitalizer -reactor.foo = 'baz' // Prints 'BAZ' +})() // starts printer which starts capitalizer +reactor.foo = 'baz' // prints 'BAZ' ``` -You can stop an observer by just calling `stop()` on the returned observer object. This clears any existing dependencies and prevents triggering. You can restart the observer by just calling `start()`. Starting is idempotent so calling `start()` on an already running observer will have no effect. +You can stop an observer by calling `stop()` on the returned observer object. This clears any existing dependencies and prevents triggering. You can restart the observer by calling `start()`. Starting is idempotent, so calling `start()` on an already running observer will have no effect: ```javascript const reactor = new Reactor() const observer = new Observer(() => { @@ -248,7 +248,7 @@ observer.start() // No effect reactor.foo = "moo" // prints "moo" ``` -For convenience, you can call an observer to execute like a normal function. This works regardless of whether the observer is stopped. Doing so starts the observer up again. +For convenience, you can call an observer to execute like a normal function. This works regardless of whether the observer is stopped. Doing so starts the observer up again: ```javascript const reactor = new Reactor({ foo: "hello" }) @@ -259,43 +259,42 @@ reactor.foo = "hi" // prints "hi" observer() // prints "hi" again observer.stop() -reactor.foo = "hola" // does not trigger the observer since its stopped +reactor.foo = "hola" // does not trigger the observer since it's stopped observer() // prints "hola" ``` -Like normal functions, observers can expect and be called with arguments. They remember the arguments from the last time they were called and reuse them when automatically triggered. +Like normal functions, observers can expect and be called with arguments. They remember the arguments from the last time they were called and reuse them when automatically triggered: ```javascript const parameterizedObserver = new Observer((arg1, arg2) => { console.log(reactor.foo + arg1 + arg2) }) -parameterizedObserver('beep', 'bop') // Prints bazbeepbop -reactor.foo = 'bla' // Prints blabeepbop +parameterizedObserver('beep', 'bop') // prints bazbeepbop +reactor.foo = 'bla' // prints blabeepbop ``` -Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of es6 arrow functions. +Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of ES6 arrow functions: ```javascript const holdingObject = { name: 'Mario', - greet: new Observer(function () { // Need to use of `function` - console.log("Hello " + reactor.foo + " itsa me " + this.name) + greet: new Observer(function () { // Need to use `function` + console.log("Hello " + reactor.foo + " itsa me " + this.name) }) } -holdingObject.greet() // Prints "Hello bla itsa me Mario" -reactor.foo = 'bonk' // Prints "Hello bonk itsa me Mario" -holdingObject.name = 'Luigi' // Prints nothing since holdingObject is not a Reactor +holdingObject.greet() // prints "Hello bla itsa me Mario" +reactor.foo = 'bonk' // prints "Hello bonk itsa me Mario" +holdingObject.name = 'Luigi' // prints nothing since holdingObject is not a Reactor ``` - ### Hide -Sometimes you might want to read from a reactor without becoming dependent on it. A common case for this is when using array modification methods. These often also read from the array in order to do the modification. +Sometimes you might want to read from a reactor without becoming dependent on it. A common case for this is when using array modification methods. These often also read from the array in order to do the modification: ```javascript const taskList = new Reactor(["a", "b", "c", "d"]) // Creating the following observer will cause an infinite loop -// Because it both reads from and modifies the length property of taskList -// As a result it triggers itself in the middle of execution +// because it both reads from and modifies the length property of taskList +// As a result, it triggers itself in the middle of execution // This loop is detected and creates an exception new Observer(() => { // Even though we only want to modify the array @@ -304,19 +303,17 @@ new Observer(() => { })() ``` -In these cases you can use "hide" to shield a block of code from creating dependencies. It takes a function and any reactor properties read inside that function will not be set as dependencies. `hide` also passes through the return value of its function for syntactic simplicity. +In these cases, you can use "hide" to shield a block of code from creating dependencies. It takes a function and any reactor properties read inside that function will not be set as dependencies. `hide` also passes through the return value of its function for syntactic simplicity: ```javascript const taskList = new Reactor(["a", "b", "c", "d"]) new Observer(() => { - console.log( - // Because we wrap pop() call in an hide block - // It does not create a dependency on the length property - // Unlike our previous example + // Because we wrap the pop() call in a hide block + // it does not create a dependency on the length property + // unlike our previous example hide(() => taskList.pop()) ) - })() // prints "d" taskList.push("e") // does not trigger the observer @@ -325,7 +322,7 @@ taskList.push("e") // does not trigger the observer Note that only the reads inside the hide block are shielded from creating dependencies. The rest of the observe block still creates dependencies as normal. ### Overrides -If you need to access the raw function the observer is wrapping you do so with the `execute` property. +If you need to access the raw function the observer is wrapping, you do so with the `execute` property: ```javascript const myFunction = () => {} @@ -333,7 +330,7 @@ const observer = new Observer(myFunction) myFunction === observer.execute // true ``` -By setting this property you can change an observers internal logic. Doing so clears dependencies and retriggers the observer. Note that the previous `this` and arguments contexts will stay. +By setting this property, you can change an observer's internal logic. Doing so clears dependencies and retriggers the observer. Note that the previous `this` and arguments contexts will stay: ```javascript const reactor = new Reactor({ foo: "bar" }) @@ -351,7 +348,7 @@ reactor.foo = "blep" // prints "I am saying blap blep" ``` ### Batching -One problem with automatic watchers is that you might end up with multiple repeated triggering when you're updating a whole lot of information all at once. The following code shows an example where you want to update multiple properties, but each property update prematurely triggers the observer since you are not done updating yet. +One problem with automatic watchers is that you might end up with multiple repeated triggering when you're updating a lot of information all at once. The following code shows an example where you want to update multiple properties, but each property update prematurely triggers the observer since you are not done updating yet: ```javascript const person = new Reactor({ @@ -399,7 +396,7 @@ batch(() => { This is useful when you are making multiple data updates and want to avoid showing an "incomplete" view of the data to observers. -Note that only the observer triggering is postponed till the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. +Note that only the observer triggering is postponed until the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. Summary ------- @@ -412,42 +409,42 @@ const observer = new Observer(() => { console.log(result) return result }) -observer() // Prints 'reactor.foo is bar' and starts the observer -reactor.foo = 'baz' // Prints 'reactor.foo is baz' +observer() // prints 'reactor.foo is bar' and starts the observer +reactor.foo = 'baz' // prints 'reactor.foo is baz' observer.stop() -reactor.foo = 'qux' // Prints nothing since observer is stopped +reactor.foo = 'qux' // prints nothing since observer is stopped -observer.start() // Prints 'reactor.foo is baz' -observer.start() // Prints nothing since observer is already started -observer() // Prints 'reactor.foo is baz' even if it is already running +observer.start() // prints 'reactor.foo is baz' +observer.start() // prints nothing since observer is already started +observer() // prints 'reactor.foo is baz' even if it is already running -// Observers return values are themselves observable +// Observer return values are themselves observable const trailingObserver = new Observer(() => { const result = 'Did you hear: ' + observer.value console.log(result) }) -trailingObserver() // Prints 'Did you hear: reactor.foo is baz' -reactor.foo = 'blorp' // Prints 'reactor.foo is blorp' from observer - // Also prints 'Did you hear: reactor.foo is blorp' from trailingObserver +trailingObserver() // prints 'Did you hear: reactor.foo is baz' +reactor.foo = 'blorp' // prints 'reactor.foo is blorp' from observer + // also prints 'Did you hear: reactor.foo is blorp' from trailingObserver // Observers can be given parameters and remember these parameters when triggered const parameterizedObserver = new Observer((arg1, arg2) => { console.log(reactor.foo + arg1 + arg2) }) -parameterizedObserver('beep', 'bop') // Prints bazbeepbop -reactor.foo = 'bla' // Prints blabeepbop +parameterizedObserver('beep', 'bop') // prints bazbeepbop +reactor.foo = 'bla' // prints blabeepbop // Observers can also access and remember the last `this` context const holdingObject = { name: 'Mario', greet: new Observer(function () { // Need to use traditional functions instead of arrow functions - console.log("Hello " + reactor.foo + " itsa me " + this.name) + console.log("Hello " + reactor.foo + " itsa me " + this.name) }) } -holdingObject.greet() // Prints "Hello bla itsa me Mario" -reactor.foo = 'bonk' // Prints "Hello bonk itsa me Mario" -holdingObject.name = 'Luigi' // Prints nothing since holdingObject is not a Reactor +holdingObject.greet() // prints "Hello bla itsa me Mario" +reactor.foo = 'bonk' // prints "Hello bonk itsa me Mario" +holdingObject.name = 'Luigi' // prints nothing since holdingObject is not a Reactor // hide allows you to avoid particular dependencies in an observer // This is useful especially when using Array methods that both read and write @@ -472,7 +469,7 @@ const person = new Reactor({ }) new Observer(() => { console.log('Look its ' + person.firstName + ' ' + person.lastName) -})() // Prints 'Look its Clark Kent' +})() // prints 'Look its Clark Kent' batch(() => { // None of the following updates will trigger the observer yet person.firstName = "Bruce" @@ -492,4 +489,4 @@ Tests are stored in `test.js` to be run using Mocha. Run `npm install` to install the dev dependencies. -To run the tests run `npm test`. +To run the tests, run `npm test`. From 87eca494d348603646dd8850b527135db4954fc7 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 20:36:18 +0800 Subject: [PATCH 53/71] Removed documentation of access to the execute property --- README.md | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 92b1024..7c889c1 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,7 @@ reactor.foo = 'bla' // prints blabeepbop ``` Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of ES6 arrow functions: + ```javascript const holdingObject = { name: 'Mario', @@ -286,6 +287,14 @@ reactor.foo = 'bonk' // prints "Hello bonk itsa me Mario" holdingObject.name = 'Luigi' // prints nothing since holdingObject is not a Reactor ``` +If you ever need to access the raw function the observer is wrapping, you do so by using `shuck`: + +```javascript +const myFunction = () => {} +const observer = new Observer(myFunction) +myFunction === shuck(observer) // true +``` + ### Hide Sometimes you might want to read from a reactor without becoming dependent on it. A common case for this is when using array modification methods. These often also read from the array in order to do the modification: @@ -321,32 +330,6 @@ taskList.push("e") // does not trigger the observer Note that only the reads inside the hide block are shielded from creating dependencies. The rest of the observe block still creates dependencies as normal. -### Overrides -If you need to access the raw function the observer is wrapping, you do so with the `execute` property: - -```javascript -const myFunction = () => {} -const observer = new Observer(myFunction) -myFunction === observer.execute // true -``` - -By setting this property, you can change an observer's internal logic. Doing so clears dependencies and retriggers the observer. Note that the previous `this` and arguments contexts will stay: - -```javascript -const reactor = new Reactor({ foo: "bar" }) -let observerToBeOverridden = new Observer((arg) => { - console.log(reactor.foo, 'and', arg) -}) -observerToBeOverridden('blap') // prints "bar and blap" -reactor.foo = "moo" // prints "moo and blap" - -// Setting the execute property replaces the old function -observerToBeOverridden.execute = (arg) => { - console.log("I am saying", arg, reactor.foo) -} // prints "I am saying blap moo" -reactor.foo = "blep" // prints "I am saying blap blep" -``` - ### Batching One problem with automatic watchers is that you might end up with multiple repeated triggering when you're updating a lot of information all at once. The following code shows an example where you want to update multiple properties, but each property update prematurely triggers the observer since you are not done updating yet: From 083aeff242e8ba96a1da045c13a352e5da4cf73a Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 20:59:34 +0800 Subject: [PATCH 54/71] Removed the execute property and redefining --- src/index.js | 19 ------------ test/features.test.js | 67 ------------------------------------------- test/observer.test.js | 8 ------ 3 files changed, 94 deletions(-) diff --git a/src/index.js b/src/index.js index c1b59fc..e458b7e 100644 --- a/src/index.js +++ b/src/index.js @@ -546,19 +546,6 @@ class Observer extends Function { return false }, - // Redefines the observer with a new exec function - // Maintains the context, Signal dependents, and awake status - redefine (newExecute) { - if (typeof newExecute !== 'function') { - throw new TypeError('Cannot create observer with a non-function') - } - this.clearDependencies() - this.execute = newExecute - // If awake this will update the value Signal and notify observers downstream - // If alseep this will correctly do nothing leaving value to the last triggered value - return this.trigger() - }, - // Pause the observer preventing further triggers // Returns false if it was already asleep // Returns true if it was awake @@ -612,12 +599,6 @@ class Observer extends Function { observerInterface.setArgsContext = (...args) => { observerCore.argsContext = args } - // Expose the wrapped execute function and restart the observer - // Setting it keeps the context and dependents - Object.defineProperty(observerInterface, 'execute', { - get () { return observerCore.execute }, - set (newValue) { return observerCore.redefine(newValue) } - }) // Allow reads of the last return value of execute // As a Signal this itself is observable and // builds dependencies if done within another observer diff --git a/test/features.test.js b/test/features.test.js index 5546ecb..44937f6 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -169,71 +169,4 @@ describe('Minor Features', () => { assert.equal(contextChecker, '') }) }) - - describe('Observer execute setting', () => { - it('exposes the wrapped function through the execute property', () => { - const dummyFunction = function () {} - const observer = new Observer(dummyFunction) - assert.strictEqual(observer.execute, dummyFunction) - }) - it('deactivates the observer when setting the execute property', () => { - let runCounter = 0 - let runValue = null - const reactor = new Reactor({ foo: 'bar' }) - const observer = new Observer(() => { - runCounter += 1 - runValue = reactor.foo - }) - observer() - assert.equal(runCounter, 1) - assert.equal(runValue, 'bar') - reactor.foo = 'baz' - assert.equal(runCounter, 2) - assert.equal(runValue, 'baz') - observer.execute = () => { - runCounter += 1 - runValue = 'new' + reactor.foo - } - assert.equal(runCounter, 3) - assert.equal(runValue, 'newbaz') - }) - it('uses the new execute after being restarted') - it('redefines an observer by setting the execute property', () => { - const reactor = new Reactor({ - first: 'foo', - second: 'bar' - }) - let firstCounter = 0 - let secondCounter = 0 - let firstTracker - let secondTracker - const observer = new Observer(() => { - firstCounter += 1 - firstTracker = reactor.first - }) - observer() - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 0) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, undefined) - observer.execute = () => { - secondCounter += 1 - secondTracker = reactor.second - } - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.first = 'moo' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 1) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'bar') - reactor.second = 'baz' - assert.equal(firstCounter, 1) - assert.equal(secondCounter, 2) - assert.equal(firstTracker, 'foo') - assert.equal(secondTracker, 'baz') - }) - }) }) diff --git a/test/observer.test.js b/test/observer.test.js index e564b9a..e481e96 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -232,14 +232,6 @@ describe('Observer', () => { }) }) - describe('exposes the wrapped function through the execute property', () => { - it('', () => { - const dummyFunction = function () {} - const observer = new Observer(dummyFunction) - assert.strictEqual(observer.execute, dummyFunction) - }) - }) - describe('exposes the last return value throught the value property', () => { it('exposes the last derived value for primitive values', () => { let counter = 0 From cac0c01576366171803b69da45394da3989a83e7 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 23:50:57 +0800 Subject: [PATCH 55/71] Cleaned up package.json --- package.json | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 68415b7..d96bc43 100644 --- a/package.json +++ b/package.json @@ -2,17 +2,9 @@ "name": "reactorjs", "version": "2.1.2", "description": "Simple reactive programming without frameworks", - "source": "src/index.js", - "main": "dist/index.js", - "targets": { - "main": { - "context": "browser", - "includeNodeModules": true, - "optimize": true - } - }, + "main": "src/index.js", "files": [ - "dist/index.*" + "src/index.js" ], "devDependencies": { "mocha": "^10.1.0", @@ -21,14 +13,28 @@ "scripts": { "lint": "standard --fix", "test": "standard && mocha test/test.js", - "prepare": "npm test" + "prepublishOnly": "npm test" }, "repository": { "type": "git", "url": "git+https://github.com/fynyky/reactor.js.git" }, "keywords": [ - "reactive" + "reactive", + "reactivity", + "signals", + "observers", + "state-management", + "observable", + "dependency-tracking", + "automatic-updates", + "proxy-based", + "vanilla-js", + "reactive-programming", + "data-binding", + "change-detection", + "computed-values", + "derived-state" ], "author": "Hongyi Li", "license": "MIT", From 905ea41d5cb108851696620a044c38f311a16453 Mon Sep 17 00:00:00 2001 From: fynyky Date: Wed, 27 Aug 2025 23:54:04 +0800 Subject: [PATCH 56/71] Updated version number --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1db760a..16d73bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "reactorjs", - "version": "2.1.2", + "version": "3.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "reactorjs", - "version": "2.1.2", + "version": "3.1.0", "license": "MIT", "dependencies": { "weak-ref-collections": "^1.2.3" diff --git a/package.json b/package.json index d96bc43..dc1cfbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reactorjs", - "version": "2.1.2", + "version": "3.1.0", "description": "Simple reactive programming without frameworks", "main": "src/index.js", "files": [ From 00ff9d84fc68f4b73c4b2a13afc16c1398e8ee63 Mon Sep 17 00:00:00 2001 From: fynyky Date: Thu, 28 Aug 2025 00:20:41 +0800 Subject: [PATCH 57/71] Changed structure to removed redundant src folder --- src/index.js => index.js | 0 package.json | 14 +++++++------- test/batching.test.js | 2 +- test/complex.test.js | 2 +- test/errors.test.js | 2 +- test/features.test.js | 2 +- test/hiding.test.js | 2 +- test/observer.test.js | 2 +- test/reactivity.test.js | 2 +- test/reactor.test.js | 2 +- test/signal.test.js | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) rename src/index.js => index.js (100%) diff --git a/src/index.js b/index.js similarity index 100% rename from src/index.js rename to index.js diff --git a/package.json b/package.json index dc1cfbc..ebad512 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,14 @@ "name": "reactorjs", "version": "3.1.0", "description": "Simple reactive programming without frameworks", - "main": "src/index.js", + "type": "module", + "main": "index.js", "files": [ - "src/index.js" + "index.js" ], + "dependencies": { + "weak-ref-collections": "^1.2.3" + }, "devDependencies": { "mocha": "^10.1.0", "standard": "^17.0.0" @@ -41,9 +45,5 @@ "bugs": { "url": "https://github.com/fynyky/reactor.js/issues" }, - "homepage": "https://github.com/fynyky/reactor.js#readme", - "type": "module", - "dependencies": { - "weak-ref-collections": "^1.2.3" - } + "homepage": "https://github.com/fynyky/reactor.js#readme" } diff --git a/test/batching.test.js b/test/batching.test.js index f8432b3..46de738 100644 --- a/test/batching.test.js +++ b/test/batching.test.js @@ -13,7 +13,7 @@ import { // hide, batch // shuck -} from '../src/index.js' +} from '../index.js' describe('Batching', () => { it('consolidates duplicate observer triggers within a batch', () => { diff --git a/test/complex.test.js b/test/complex.test.js index 533af51..0e802b2 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/index.js' +} from '../index.js' describe('Complex Setups', () => { it('can chain observers off each other', () => { diff --git a/test/errors.test.js b/test/errors.test.js index 983d52b..35a219b 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/index.js' +} from '../index.js' describe('Error Handling', () => { it('throws an error on an update if there is an observer throws an error', () => { diff --git a/test/features.test.js b/test/features.test.js index 44937f6..eb93b78 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, // shuck -} from '../src/index.js' +} from '../index.js' describe('Minor Features', () => { describe('Starting and stopping observers', () => { diff --git a/test/hiding.test.js b/test/hiding.test.js index 3800d5a..2811a6c 100644 --- a/test/hiding.test.js +++ b/test/hiding.test.js @@ -13,7 +13,7 @@ import { hide // batch, // shuck -} from '../src/index.js' +} from '../index.js' describe('Hiding', () => { it('does not create dependencies inside hide block', () => { diff --git a/test/observer.test.js b/test/observer.test.js index e481e96..2a28b79 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/index.js' +} from '../index.js' describe('Observer', () => { describe('initializes with a function and returns it wrapped in an observer', () => { diff --git a/test/reactivity.test.js b/test/reactivity.test.js index d41cf50..a823875 100644 --- a/test/reactivity.test.js +++ b/test/reactivity.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/index.js' +} from '../index.js' describe('Reactivity', () => { describe('Observers are inactive until they are run', () => { diff --git a/test/reactor.test.js b/test/reactor.test.js index 322c01b..31d7f1c 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/index.js' +} from '../index.js' describe('Reactor', () => { describe('initializes with an object and returns it wrapped in a reactor', () => { diff --git a/test/signal.test.js b/test/signal.test.js index 1a0dfeb..0183e95 100644 --- a/test/signal.test.js +++ b/test/signal.test.js @@ -13,7 +13,7 @@ import { // hide, // batch, shuck -} from '../src/index.js' +} from '../index.js' describe('Signal', () => { describe('initializes with any single value', () => { From 077457f8002d20d227724cc6fe1d21652b0438ab Mon Sep 17 00:00:00 2001 From: fynyky Date: Thu, 28 Aug 2025 01:21:03 +0800 Subject: [PATCH 58/71] Removed unused tests --- test/complex.test.js | 77 -------------------------------------------- test/reactor.test.js | 2 -- test/signal.test.js | 6 ---- 3 files changed, 85 deletions(-) diff --git a/test/complex.test.js b/test/complex.test.js index 0e802b2..ac71b36 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -41,41 +41,6 @@ describe('Complex Setups', () => { assert.strictEqual(thirdObserver.value, '!!!baz!!!') }) - it.skip('triggers observers once per write for triangle dependencies', () => { - // We have the following triangle dependency - // reactor -> first -> second - // reactor -> second - // Ideally we have reactor trigger first then second - // However, a naive depth first implementation would trigger first when in turn trigger second - // then go back to trigger second again because it's a dependency of reactor as well - // So we have an observer unnecessarily triggering twice off a single write - // Right now this is the naive implementation - let firstRunCount = 0 - let secondRunCount = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - const firstObserver = new Observer(() => { - firstRunCount += 1 - return reactor.foo.toUpperCase() - }) - firstObserver() - assert.strictEqual(firstRunCount, 1) - assert.strictEqual(firstObserver.value, 'BAR') - const secondObserver = new Observer(() => { - secondRunCount += 1 - return reactor.foo + firstObserver.value - }) - secondObserver() - assert.strictEqual(secondRunCount, 1) - assert.strictEqual(secondObserver.value, 'barBAR') - reactor.foo = 'baz' - assert.strictEqual(firstRunCount, 2) - assert.strictEqual(firstObserver.value, 'BAZ') - assert.strictEqual(secondRunCount, 2) - assert.strictEqual(secondObserver.value, 'bazBAZ') - }) - it('does not trivially infinite loop when an observer calls another', () => { // Trivial case // observer2 = observer1() + 1 @@ -115,48 +80,6 @@ describe('Complex Setups', () => { assert.strictEqual(secondObserver.value, 'baz1') }) - it.skip('does not infinite loop with three observers calling each other like functions', () => { - // This is a more complex case - // observer2 = observer1() + 1 - // observer3 = observer1() + observer2() - // So observer1 triggers observer2 which triggers observer3 - // Then observer3 triggers observer2 which does not loop because it is rebuilding dependencies when it sets its value - // But observer3 triggers observer1 which still triggers observer2 which still triggers observer3 - let firstRunCount = 0 - let secondRunCount = 0 - let thirdRunCount = 0 - const reactor = new Reactor({ - foo: 'bar' - }) - const firstObserver = new Observer(() => { - firstRunCount += 1 - if (firstRunCount > 100) throw new Error('infinite loop detected') - return [reactor.foo] - }) - firstObserver() - const secondObserver = new Observer(() => { - secondRunCount += 1 - if (secondRunCount > 100) throw new Error('infinite loop detected') - return [firstObserver() + 'baz'] - }) - secondObserver() - const thirdObserver = new Observer(() => { - thirdRunCount += 1 - if (thirdRunCount > 100) throw new Error('infinite loop detected') - return [firstObserver() + secondObserver()] - }) - thirdObserver() - // assert.strictEqual(firstRunCount, 2) - // assert.strictEqual(secondRunCount, 1) - // assert.deepEqual(firstObserver.value, ['bar']) - // assert.strictEqual(secondObserver.value, 'bar1') - // reactor.foo = 'baz' - // assert.strictEqual(firstRunCount, 4) - // assert.strictEqual(secondRunCount, 2) - // assert.deepEqual(firstObserver.value, ['baz']) - // assert.strictEqual(secondObserver.value, 'baz1') - }) - it('can create observers inside other observers', () => { const reactor = new Reactor({ outer: 'foo', diff --git a/test/reactor.test.js b/test/reactor.test.js index 31d7f1c..75e5529 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -31,8 +31,6 @@ describe('Reactor', () => { assert.strictEqual(shuck(reactor), func) }) - it('initializes with a promise') // TODO: Figure out promises - it('initializes with no arguments automatically making an object and returning it wrapped in a reactor', () => { const reactor = new Reactor() assert(Reactors.has(reactor)) diff --git a/test/signal.test.js b/test/signal.test.js index 0183e95..64b7c1b 100644 --- a/test/signal.test.js +++ b/test/signal.test.js @@ -29,7 +29,6 @@ describe('Signal', () => { it('initializes with undefined', () => new Signal(undefined)) it('initializes with an object', () => new Signal({})) it('initializes with a function', () => new Signal(() => {})) - it('initializes with a promise') // TODO: Figure out promises it('initializes with no arguments', () => new Signal()) it('throws an error when initialized with multiple arguments', () => { assert.throws(() => new Signal('foo', 'bar'), { @@ -116,9 +115,6 @@ describe('Signal', () => { assert(Reactors.has(result)) assert.strictEqual(shuck(result), dummyFunction) }) - - // TODO figure out promises - it('returns a promise') }) }) @@ -249,8 +245,6 @@ describe('Signal', () => { assert.strictEqual(writeReturn, readReturn) }) - it('updates with a Promise') // TODO: Figure out promises - it('throws an error when called with multiple arguments', () => { const signal = new Signal() assert.throws(() => signal(1, 2), { From 0bd6d690734bf529deedd4af479cfda1db9d531e Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 15:11:10 +0000 Subject: [PATCH 59/71] Added a devcontainer config --- .devcontainer/devcontainer.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..14bfd8c --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,19 @@ +{ + "name": "Dev", + "image": "mcr.microsoft.com/devcontainers/javascript-node:22", + "forwardPorts": [3000], + "portsAttributes": { + "3000": { + "label": "App", + "onAutoForward": "openPreview" + } + }, + "postCreateCommand": "npm install && npm install -g @anthropic-ai/claude-code", + "customizations": { + "vscode": { + "extensions": [ + "anthropic.claude-code" + ] + } + } +} \ No newline at end of file From f9fc6dcd8c9a5e8f5ca5c0fed0da9d2751aa6475 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 15:17:50 +0000 Subject: [PATCH 60/71] Add serialize-javascript override to fix npm audit vulnerabilities --- package-lock.json | 334 ++++++++++++++++++++-------------------------- package.json | 3 + 2 files changed, 151 insertions(+), 186 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16d73bf..80b5234 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,9 +40,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -51,10 +51,11 @@ } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -77,9 +78,9 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -88,10 +89,11 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -181,10 +183,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -320,9 +323,9 @@ } }, "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==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { @@ -549,9 +552,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -892,9 +895,9 @@ } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -924,10 +927,11 @@ } }, "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -967,9 +971,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -978,10 +982,11 @@ } }, "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1030,9 +1035,9 @@ } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -1053,10 +1058,11 @@ } }, "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1141,9 +1147,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -1164,10 +1170,11 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1325,10 +1332,11 @@ } }, "node_modules/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 + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -1467,9 +1475,9 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "license": "MIT", "dependencies": { @@ -1478,10 +1486,11 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1929,10 +1938,11 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2071,9 +2081,9 @@ } }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "license": "ISC", "dependencies": { @@ -2400,10 +2410,11 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -2543,16 +2554,6 @@ } ] }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -2683,27 +2684,6 @@ "queue-microtask": "^1.2.2" } }, - "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -2732,13 +2712,13 @@ } }, "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==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=20.0.0" } }, "node_modules/shebang-command": { @@ -3209,9 +3189,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3219,9 +3199,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -3241,9 +3221,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3251,9 +3231,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -3319,9 +3299,9 @@ "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -3417,9 +3397,9 @@ "dev": true }, "brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -3583,9 +3563,9 @@ } }, "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true }, "doctrine": { @@ -3724,9 +3704,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3743,9 +3723,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -3857,9 +3837,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3885,9 +3865,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -3918,9 +3898,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3928,9 +3908,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -3968,9 +3948,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -3987,9 +3967,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -4160,9 +4140,9 @@ } }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "fs.realpath": { @@ -4250,9 +4230,9 @@ }, "dependencies": { "brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -4260,9 +4240,9 @@ } }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -4583,9 +4563,9 @@ "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==", + "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": { "argparse": "^2.0.1" @@ -4694,9 +4674,9 @@ } }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -4727,7 +4707,7 @@ "log-symbols": "^4.1.0", "minimatch": "^5.1.6", "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", + "serialize-javascript": "7.0.5", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", @@ -4933,9 +4913,9 @@ "dev": true }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true }, "pify": { @@ -5028,15 +5008,6 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5116,12 +5087,6 @@ "queue-microtask": "^1.2.2" } }, - "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 - }, "safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -5140,13 +5105,10 @@ "dev": true }, "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": { - "randombytes": "^2.1.0" - } + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", + "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", + "dev": true }, "shebang-command": { "version": "2.0.0", diff --git a/package.json b/package.json index ebad512..587e48b 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,9 @@ "files": [ "index.js" ], + "overrides": { + "serialize-javascript": "7.0.5" + }, "dependencies": { "weak-ref-collections": "^1.2.3" }, From 2684b91c841af5609e9f5c21c8e1274e30d2d64b Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 15:20:44 +0000 Subject: [PATCH 61/71] Update dependencies to latest versions --- package-lock.json | 4814 +++++++++++++++++++++++++++++++++------------ package.json | 9 +- 2 files changed, 3580 insertions(+), 1243 deletions(-) diff --git a/package-lock.json b/package-lock.json index 80b5234..c448690 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,23 +9,53 @@ "version": "3.1.0", "license": "MIT", "dependencies": { - "weak-ref-collections": "^1.2.3" + "weak-ref-collections": "^1.2.4" }, "devDependencies": { - "mocha": "^10.1.0", - "standard": "^17.0.0" + "mocha": "^11.7.6", + "standard": "^17.1.2" + } + }, + "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, + "license": "MIT", + "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" + } + }, + "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, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -63,14 +93,26 @@ "node": "*" } }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", - "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -115,10 +157,115 @@ } }, "node_modules/@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 + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "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, + "license": "ISC", + "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" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT", + "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" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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, + "license": "MIT", + "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" + } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -155,17 +302,44 @@ "node": ">= 8" } }, + "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, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -178,6 +352,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -199,16 +374,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -233,36 +398,87 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "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 }, + "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, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -272,15 +488,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -290,15 +507,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", - "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -307,42 +525,85 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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 - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "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, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "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" } }, - "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==", + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "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, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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 + }, + "node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/browser-stdout": { @@ -352,22 +613,73 @@ "dev": true }, "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.0.0" } }, + "node_modules/builtins/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -378,6 +690,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -423,41 +736,34 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/color-convert": { @@ -499,6 +805,60 @@ "node": ">= 8" } }, + "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, + "license": "MIT", + "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" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "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, + "license": "MIT", + "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" + } + }, + "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, + "license": "MIT", + "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.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -533,14 +893,35 @@ "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 + "dev": true, + "license": "MIT" }, - "node_modules/define-properties": { + "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "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, + "license": "MIT", + "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" + } + }, + "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, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -552,9 +933,9 @@ } }, "node_modules/diff": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -573,51 +954,106 @@ "node": ">=6.0.0" } }, + "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==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT" + }, "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 + "dev": true, + "license": "MIT" }, "node_modules/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==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "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-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "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.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "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" @@ -626,24 +1062,106 @@ "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.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", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -653,10 +1171,11 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -674,49 +1193,50 @@ } }, "node_modules/eslint": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", - "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "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", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "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.15.0", - "grapheme-splitter": "^1.0.4", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "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", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -730,9 +1250,9 @@ } }, "node_modules/eslint-config-standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", "dev": true, "funding": [ { @@ -748,10 +1268,14 @@ "url": "https://feross.org/support" } ], + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "eslint": "^8.0.1", "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", "eslint-plugin-promise": "^6.0.0" } }, @@ -780,13 +1304,15 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -794,15 +1320,17 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -820,6 +1348,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -829,6 +1358,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", "dev": true, + "license": "MIT", "dependencies": { "eslint-utils": "^2.0.0", "regexpp": "^3.0.0" @@ -848,6 +1378,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -863,35 +1394,43 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=4" } }, "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { @@ -906,12 +1445,13 @@ } }, "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import/node_modules/doctrine": { @@ -919,6 +1459,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -939,26 +1480,21 @@ "node": "*" } }, - "node_modules/eslint-plugin-import/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/eslint-plugin-n": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.4.0.tgz", - "integrity": "sha512-MkoKy9/lfd52TAXK4fkABgCp0aglk82Q3viy2UOWIEpTVE/Cem5P/UAxMBA4vSw7Gy+2egPqImE9euitLGp5aw==", + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", "dev": true, + "license": "MIT", "dependencies": { "builtins": "^5.0.1", "eslint-plugin-es": "^4.1.0", "eslint-utils": "^3.0.0", "ignore": "^5.1.1", - "is-core-module": "^2.10.0", + "is-core-module": "^2.11.0", "minimatch": "^3.1.2", "resolve": "^1.22.1", - "semver": "^7.3.7" + "semver": "^7.3.8" }, "engines": { "node": ">=12.22.0" @@ -994,44 +1530,88 @@ "node": "*" } }, + "node_modules/eslint-plugin-n/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", + "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", "dev": true, + "license": "ISC", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-react": { - "version": "7.31.10", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", - "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.5", - "array.prototype.flatmap": "^1.3.0", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.1", - "object.values": "^1.1.5", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.7" + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { @@ -1070,44 +1650,21 @@ "node": "*" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/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==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { @@ -1115,6 +1672,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -1133,17 +1691,22 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "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, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/brace-expansion": { @@ -1183,14 +1746,15 @@ } }, "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1200,10 +1764,11 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -1216,6 +1781,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1245,19 +1811,22 @@ "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 + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.13.0", @@ -1277,20 +1846,7 @@ "flat-cache": "^3.0.4" }, "engines": { - "node": "^10.12.0 || >=12.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, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/find-up": { @@ -1338,42 +1894,68 @@ "dev": true, "license": "ISC" }, + "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, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "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.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "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==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "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" @@ -1387,38 +1969,76 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "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, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "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-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stdin": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1427,13 +2047,15 @@ } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -1462,18 +2084,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "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/glob/node_modules/brace-expansion": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", @@ -1499,10 +2109,11 @@ } }, "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -1513,35 +2124,59 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/grapheme-splitter": { + "node_modules/globalthis": { "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/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1" + "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==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, + "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, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1556,22 +2191,40 @@ } }, "node_modules/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==", + "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, + "license": "MIT", + "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, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1580,12 +2233,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -1594,6 +2248,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -1604,19 +2271,21 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -1654,57 +2323,90 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "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 + "dev": true, + "license": "MIT" }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "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, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "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-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "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, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1718,6 +2420,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1726,24 +2429,48 @@ } }, "node_modules/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==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "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, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "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.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "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, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1761,15 +2488,52 @@ "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, + "license": "MIT", + "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, + "license": "MIT", "engines": { "node": ">=8" } }, + "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, + "license": "MIT", + "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-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1782,11 +2546,12 @@ "node": ">=0.10.0" } }, - "node_modules/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/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, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1794,23 +2559,28 @@ "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==", + "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, "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1838,13 +2608,16 @@ } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -1853,25 +2626,62 @@ "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "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==", + "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, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "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, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1880,13 +2690,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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/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, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -1907,29 +2718,98 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "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, + "license": "MIT" + }, "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/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } }, "node_modules/js-tokens": { "version": "4.0.0", @@ -1954,13 +2834,15 @@ "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 + "dev": true, + "license": "MIT" }, "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 + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -1973,6 +2855,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -1998,6 +2881,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2011,6 +2895,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.15", "parse-json": "^4.0.0", @@ -2027,6 +2912,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=6" } @@ -2080,54 +2966,86 @@ "loose-envify": "cli.js" } }, + "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, + "license": "ISC" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "version": "11.7.6", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", + "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", - "glob": "^8.1.0", + "glob": "^10.4.5", "he": "^1.2.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -2135,25 +3053,26 @@ "mocha": "bin/mocha.js" }, "engines": { - "node": ">= 14.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/mocha/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "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" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2171,13 +3090,23 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "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==", + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object-assign": { @@ -2190,10 +3119,14 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2208,14 +3141,17 @@ } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "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": { @@ -2226,28 +3162,32 @@ } }, "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "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" @@ -2256,28 +3196,32 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.hasown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", - "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2296,22 +3240,41 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "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, + "license": "MIT", + "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" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2347,15 +3310,24 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "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, + "license": "BlueOak-1.0.0" + }, "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, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -2368,6 +3340,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, + "license": "MIT", "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -2407,26 +3380,39 @@ "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 + "dev": true, + "license": "MIT" }, - "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "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, - "license": "MIT", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=8.6" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/isaacs" } }, + "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, + "license": "ISC" + }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2436,6 +3422,7 @@ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^3.0.0", "load-json-file": "^5.2.0" @@ -2449,6 +3436,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -2461,6 +3449,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -2474,6 +3463,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -2489,6 +3479,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -2501,15 +3492,27 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "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, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -2526,10 +3529,11 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2561,26 +3565,55 @@ "dev": true }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "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": ">=8.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/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==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "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" @@ -2594,6 +3627,7 @@ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2606,23 +3640,31 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.9.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.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" } @@ -2632,6 +3674,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2684,31 +3727,69 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-regex-test": { + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "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" } }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/serialize-javascript": { @@ -2716,9 +3797,58 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, - "license": "BSD-3-Clause", + "license": "BSD-3-Clause", + "engines": { + "node": ">=20.0.0" + } + }, + "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, + "license": "MIT", + "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" + } + }, + "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, + "license": "MIT", + "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" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=20.0.0" + "node": ">= 0.4" } }, "node_modules/shebang-command": { @@ -2743,23 +3873,98 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "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.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/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, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.0.0.tgz", - "integrity": "sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.2.tgz", + "integrity": "sha512-WLm12WoXveKkvnPnPnaFUUHuOB2cUdAsJ4AiGHL2G0UNMrcRAWY2WriQaV8IQ3oRmYr0AWUbLNr94ekYFAHOrA==", "dev": true, "funding": [ { @@ -2775,27 +3980,29 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { - "eslint": "^8.13.0", - "eslint-config-standard": "17.0.0", + "eslint": "^8.41.0", + "eslint-config-standard": "17.1.0", "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-n": "^15.1.0", - "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.28.0", - "standard-engine": "^15.0.0" + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.36.1", + "standard-engine": "^15.1.0", + "version-guard": "^1.1.1" }, "bin": { - "standard": "bin/cmd.js" + "standard": "bin/cmd.cjs" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/standard-engine": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", - "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", + "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", "dev": true, "funding": [ { @@ -2811,6 +4018,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "get-stdin": "^8.0.0", "minimist": "^1.2.6", @@ -2821,11 +4029,42 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "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, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2836,47 +4075,98 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" + "es-abstract": "^1.17.5" + } + }, + "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, + "license": "MIT", + "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" } }, "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "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.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "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, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "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" @@ -2894,11 +4184,26 @@ "node": ">=8" } }, + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "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, + "license": "MIT", "engines": { "node": ">=4" } @@ -2935,6 +4240,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2948,27 +4254,15 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "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, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -2978,6 +4272,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -2990,6 +4285,7 @@ "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, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2997,16 +4293,98 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "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" + } + }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "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" @@ -3017,14 +4395,26 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/version-guard": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.3.tgz", + "integrity": "sha512-JwPr6erhX53EWH/HCSzfy1tTFrtPXUe927wdM1jqBBeYp1OM+qPHjWbsvv6pIBduqdgxxS+ScfG7S28pzyr2DQ==", + "dev": true, + "license": "0BSD", + "engines": { + "node": ">=0.10.48" + } + }, "node_modules/weak-ref-collections": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.3.tgz", - "integrity": "sha512-N1fa+68+m2sMZW4MdERUf9zw1J9bALS2VB7hnhXplUe/KDlLIh0QE4CCm4/hy63hXKLAfgHJRHA6cYOnpBLiVA==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.4.tgz", + "integrity": "sha512-+hY1xbBc/Tj9d0EjDbhjZD7eGWT+rIoNVfQChjOFBV25HJUEDd1o1cy9RRxeH8nAOQ1ksiiALlmJco0vzxIoBg==", + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", @@ -3042,16 +4432,89 @@ } }, "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, + "license": "MIT", + "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, + "license": "MIT", + "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" + } + }, + "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, + "license": "MIT", + "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" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "dev": true, + "license": "MIT", "dependencies": { - "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" + "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" @@ -3062,14 +4525,15 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, "license": "Apache-2.0" }, @@ -3078,6 +4542,26 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", + "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, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3101,6 +4585,7 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3110,36 +4595,38 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "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": ">=10" + "node": ">=12" } }, "node_modules/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==", + "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, "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -3171,16 +4658,31 @@ } }, "dependencies": { + "@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": { + "eslint-visitor-keys": "^3.4.3" + } + }, + "@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 + }, "@eslint/eslintrc": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", - "integrity": "sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -3209,14 +4711,20 @@ } } }, + "@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.7.tgz", - "integrity": "sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "dependencies": { @@ -3248,11 +4756,76 @@ "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "@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, + "requires": { + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true + }, + "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 + }, + "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 + }, + "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": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "requires": { + "ansi-regex": "^6.2.2" + } + }, + "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": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3279,16 +4852,35 @@ "fastq": "^1.6.0" } }, + "@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 + }, + "@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true + }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true }, "acorn-jsx": { @@ -3310,12 +4902,6 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3331,57 +4917,132 @@ "color-convert": "^2.0.1" } }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, "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 }, + "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-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + } + }, "array-includes": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", - "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + } + }, + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" } }, "array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.flatmap": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", - "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "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": { + "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" + } + }, + "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 + }, + "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": { + "possible-typed-array-names": "^1.0.0" } }, "balanced-match": { @@ -3390,12 +5051,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, "brace-expansion": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", @@ -3405,15 +5060,6 @@ "balanced-match": "^1.0.0" } }, - "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, - "requires": { - "fill-range": "^7.1.1" - } - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -3421,22 +5067,52 @@ "dev": true }, "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", "dev": true, "requires": { "semver": "^7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true + } } }, "call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "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": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "callsites": { @@ -3473,29 +5149,22 @@ } }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, @@ -3531,6 +5200,39 @@ "which": "^2.0.1" } }, + "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-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-length": { + "version": "1.0.2", + "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-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "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, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -3552,20 +5254,32 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "define-properties": { + "define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "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": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "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, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "diff": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "dev": true }, "doctrine": { @@ -3577,6 +5291,23 @@ "esutils": "^2.0.2" } }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3584,70 +5315,157 @@ "dev": true }, "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==", + "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, "requires": { "is-arrayish": "^0.2.1" } }, "es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "requires": { + "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-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "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.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "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" + } + }, + "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==", + "dev": true + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "requires": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.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", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + } + }, + "es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, + "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==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.2" } }, "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==", + "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, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { @@ -3657,49 +5475,48 @@ "dev": true }, "eslint": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.26.0.tgz", - "integrity": "sha512-kzJkpaw1Bfwheq4VXUezFriD1GxszX6dUekM7Z3aC2o4hju+tsR/XyTC3RcoSD7jmy9VkPU3+N6YjVU2e96Oyg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.3", - "@humanwhocodes/config-array": "^0.11.6", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "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", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "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.15.0", - "grapheme-splitter": "^1.0.4", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "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", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { @@ -3734,9 +5551,9 @@ } }, "eslint-config-standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz", - "integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", "dev": true, "requires": {} }, @@ -3748,13 +5565,14 @@ "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", "dev": true, "requires": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" }, "dependencies": { "debug": { @@ -3769,9 +5587,9 @@ } }, "eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -3816,24 +5634,30 @@ } }, "eslint-plugin-import": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", - "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "brace-expansion": { @@ -3847,12 +5671,12 @@ } }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "doctrine": { @@ -3872,29 +5696,23 @@ "requires": { "brace-expansion": "^1.1.7" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true } } }, "eslint-plugin-n": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.4.0.tgz", - "integrity": "sha512-MkoKy9/lfd52TAXK4fkABgCp0aglk82Q3viy2UOWIEpTVE/Cem5P/UAxMBA4vSw7Gy+2egPqImE9euitLGp5aw==", + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", "dev": true, "requires": { "builtins": "^5.0.1", "eslint-plugin-es": "^4.1.0", "eslint-utils": "^3.0.0", "ignore": "^5.1.1", - "is-core-module": "^2.10.0", + "is-core-module": "^2.11.0", "minimatch": "^3.1.2", "resolve": "^1.22.1", - "semver": "^7.3.7" + "semver": "^7.3.8" }, "dependencies": { "brace-expansion": { @@ -3915,36 +5733,58 @@ "requires": { "brace-expansion": "^1.1.7" } + }, + "resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "dev": true } } }, "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", + "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", "dev": true, "requires": {} }, "eslint-plugin-react": { - "version": "7.31.10", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.10.tgz", - "integrity": "sha512-e4N/nc6AAlg4UKW/mXeYWd3R++qUano5/o+t+wnWxIf+bLsOaH3a4q74kX3nDjYym3VBN4HyO9nEn1GcAqgQOA==", + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, "requires": { - "array-includes": "^3.1.5", - "array.prototype.flatmap": "^1.3.0", + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", - "object.entries": "^1.1.5", - "object.fromentries": "^2.0.5", - "object.hasown": "^1.1.1", - "object.values": "^1.1.5", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.3", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.7" + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "dependencies": { "brace-expansion": { @@ -3974,30 +5814,13 @@ "requires": { "brace-expansion": "^1.1.7" } - }, - "resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true } } }, "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==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -4022,26 +5845,26 @@ } }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "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 }, "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" } }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -4104,15 +5927,6 @@ "flat-cache": "^3.0.4" } }, - "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, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -4145,35 +5959,49 @@ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, + "for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "requires": { + "is-callable": "^1.2.7" + } + }, + "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, + "requires": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + } + }, "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 }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "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==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "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" } }, "functions-have-names": { @@ -4182,6 +6010,12 @@ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, + "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 + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -4189,14 +6023,31 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "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" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, "get-stdin": { @@ -4206,13 +6057,14 @@ "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==", + "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, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" } }, "glob": { @@ -4250,49 +6102,47 @@ } } }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { - "is-glob": "^4.0.1" + "type-fest": "^0.20.2" } }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "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, "requires": { - "type-fest": "^0.20.2" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "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==", + "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 }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true }, "has-flag": { @@ -4302,27 +6152,45 @@ "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==", + "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, + "requires": { + "es-define-property": "^1.0.0" + } + }, + "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, "requires": { - "get-intrinsic": "^1.1.1" + "dunder-proto": "^1.0.0" } }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "function-bind": "^1.1.2" } }, "he": { @@ -4332,15 +6200,15 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "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==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -4370,14 +6238,25 @@ "dev": true }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + } + }, + "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, "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, "is-arrayish": { @@ -4386,32 +6265,36 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "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, "requires": { - "has-bigints": "^1.0.1" + "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" } }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "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, "requires": { - "binary-extensions": "^2.0.0" + "has-bigints": "^1.0.2" } }, "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==", + "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, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-callable": { @@ -4421,21 +6304,33 @@ "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==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "requires": { + "hasown": "^2.0.3" + } + }, + "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, "requires": { - "has": "^1.0.3" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" } }, "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==", + "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, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" } }, "is-extglob": { @@ -4444,12 +6339,34 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, + "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, + "requires": { + "call-bound": "^1.0.3" + } + }, "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 }, + "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, + "requires": { + "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" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -4459,25 +6376,26 @@ "is-extglob": "^2.1.1" } }, - "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==", + "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 }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "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 }, "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==", + "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, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-path-inside": { @@ -4493,40 +6411,60 @@ "dev": true }, "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==", + "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, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, + "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 + }, "is-shared-array-buffer": { - "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==", + "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, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" } }, "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "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, + "requires": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + } + }, + "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, "requires": { - "has-symbols": "^1.0.2" + "which-typed-array": "^1.1.16" } }, "is-unicode-supported": { @@ -4535,26 +6473,66 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, + "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 + }, "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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" } }, + "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, + "requires": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true + "iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + } + }, + "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, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } }, "js-tokens": { "version": "4.0.0", @@ -4673,60 +6651,80 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "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 + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true + }, "minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } }, "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true }, "mocha": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", - "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "version": "11.7.6", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", + "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", "dev": true, "requires": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^9.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", - "glob": "^8.1.0", + "glob": "^10.4.5", "he": "^1.2.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "7.0.5", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "dependencies": { "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "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" } } } @@ -4743,11 +6741,17 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "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-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "requires": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + } }, "object-assign": { "version": "4.1.1", @@ -4756,9 +6760,9 @@ "dev": true }, "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true }, "object-keys": { @@ -4768,58 +6772,64 @@ "dev": true }, "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==", + "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", + "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" } }, "object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" } }, "object.fromentries": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", - "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, - "object.hasown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", - "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", + "object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "requires": { - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" } }, "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "once": { @@ -4832,9 +6842,9 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "requires": { "deep-is": "^0.1.3", @@ -4842,7 +6852,18 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" + } + }, + "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, + "requires": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" } }, "p-limit": { @@ -4869,6 +6890,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "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": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4912,10 +6939,20 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "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": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "pify": { @@ -4979,6 +7016,12 @@ } } }, + "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 + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4997,9 +7040,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { @@ -5015,23 +7058,39 @@ "dev": true }, "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true + }, + "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": { - "picomatch": "^2.2.1" + "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" } }, "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==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "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" } }, "regexpp": { @@ -5047,12 +7106,15 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -5087,21 +7149,44 @@ "queue-microtask": "^1.2.2" } }, - "safe-regex-test": { + "safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "requires": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + } + }, + "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, + "requires": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + } + }, + "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" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" } }, "semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, "serialize-javascript": { @@ -5110,6 +7195,43 @@ "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true }, + "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": { + "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" + } + }, + "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": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5126,36 +7248,80 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "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, + "requires": { + "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" + } + }, + "side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + } + }, + "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-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "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, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "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" } }, + "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 + }, "standard": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.0.0.tgz", - "integrity": "sha512-GlCM9nzbLUkr+TYR5I2WQoIah4wHA2lMauqbyPLV/oI5gJxqhHzhjl9EG2N0lr/nRqI3KCbCvm/W3smxvLaChA==", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.2.tgz", + "integrity": "sha512-WLm12WoXveKkvnPnPnaFUUHuOB2cUdAsJ4AiGHL2G0UNMrcRAWY2WriQaV8IQ3oRmYr0AWUbLNr94ekYFAHOrA==", "dev": true, "requires": { - "eslint": "^8.13.0", - "eslint-config-standard": "17.0.0", + "eslint": "^8.41.0", + "eslint-config-standard": "17.1.0", "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-n": "^15.1.0", - "eslint-plugin-promise": "^6.0.0", - "eslint-plugin-react": "^7.28.0", - "standard-engine": "^15.0.0" + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.36.1", + "standard-engine": "^15.1.0", + "version-guard": "^1.1.1" } }, "standard-engine": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.0.0.tgz", - "integrity": "sha512-4xwUhJNo1g/L2cleysUqUv7/btn7GEbYJvmgKrQ2vd/8pkTmN8cpqAZg+BT8Z1hNeEH787iWUdOpL8fmApLtxA==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", + "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", "dev": true, "requires": { "get-stdin": "^8.0.0", @@ -5164,6 +7330,16 @@ "xdg-basedir": "^4.0.0" } }, + "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, + "requires": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -5175,42 +7351,84 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@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": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "string.prototype.matchall": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", - "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "requires": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + } + }, + "string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, "requires": { - "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.1", - "side-channel": "^1.0.4" + "es-abstract": "^1.17.5" + } + }, + "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.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" } }, "string.prototype.trimend": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", - "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "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, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", - "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "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.19.5" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "strip-ansi": { @@ -5222,6 +7440,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -5255,23 +7482,14 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "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": { - "is-number": "^7.0.0" - } - }, "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } @@ -5291,16 +7509,69 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "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, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + } + }, + "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, + "requires": { + "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" + } + }, + "typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "requires": { + "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" + } + }, + "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.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + } + }, "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "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", + "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" } }, "uri-js": { @@ -5312,10 +7583,16 @@ "punycode": "^2.1.0" } }, + "version-guard": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.3.tgz", + "integrity": "sha512-JwPr6erhX53EWH/HCSzfy1tTFrtPXUe927wdM1jqBBeYp1OM+qPHjWbsvv6pIBduqdgxxS+ScfG7S28pzyr2DQ==", + "dev": true + }, "weak-ref-collections": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.3.tgz", - "integrity": "sha512-N1fa+68+m2sMZW4MdERUf9zw1J9bALS2VB7hnhXplUe/KDlLIh0QE4CCm4/hy63hXKLAfgHJRHA6cYOnpBLiVA==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/weak-ref-collections/-/weak-ref-collections-1.2.4.tgz", + "integrity": "sha512-+hY1xbBc/Tj9d0EjDbhjZD7eGWT+rIoNVfQChjOFBV25HJUEDd1o1cy9RRxeH8nAOQ1ksiiALlmJco0vzxIoBg==" }, "which": { "version": "2.0.2", @@ -5327,16 +7604,64 @@ } }, "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, + "requires": { + "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" + } + }, + "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, + "requires": { + "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" + } + }, + "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-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + } + }, + "which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", "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" + "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" } }, "word-wrap": { @@ -5346,9 +7671,9 @@ "dev": true }, "workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true }, "wrap-ansi": { @@ -5362,6 +7687,17 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@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": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5381,24 +7717,24 @@ "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "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", + "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" } }, "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==", + "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 }, "yargs-unparser": { diff --git a/package.json b/package.json index 587e48b..825af1d 100644 --- a/package.json +++ b/package.json @@ -8,14 +8,15 @@ "index.js" ], "overrides": { - "serialize-javascript": "7.0.5" + "serialize-javascript": "7.0.5", + "diff": "^9.0.0" }, "dependencies": { - "weak-ref-collections": "^1.2.3" + "weak-ref-collections": "^1.2.4" }, "devDependencies": { - "mocha": "^10.1.0", - "standard": "^17.0.0" + "mocha": "^11.7.6", + "standard": "^17.1.2" }, "scripts": { "lint": "standard --fix", From 55a5b0a8c3906137c9249a2813f3e579efedb69f Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 15:39:01 +0000 Subject: [PATCH 62/71] Minor cleanups --- index.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index e458b7e..9ef16c1 100644 --- a/index.js +++ b/index.js @@ -214,7 +214,7 @@ class Reactor { // Early rejection for non-objects // Could be handled later by proxy creation, but cleaner to have the logic here - // Can use the same function as Signal does for it's wrapping + // Can use the same function as Signal does for its wrapping if (!isObject(initializedSource)) { throw new TypeError('Reactor source must be an Object') } @@ -270,7 +270,7 @@ class Reactor { get (property, receiver) { // Disable unnecessary wrapping for unmodifiable properties // Needed because Array prototype checking fails if wrapped - // Specificaly [].map() + // Specifically [].map() const descriptor = Object.getOwnPropertyDescriptor( this.source, property ) @@ -285,7 +285,7 @@ class Reactor { Object.prototype.hasOwnProperty.call(this.getSignals, property) ? this.getSignals[property] : new Signal() - // User accessor signals to give the actual output + // Use accessor signals to give the actual output // This enables automatic dependency tracking const signalCore = signalCoreExtractor.get(this.getSignals[property]) signalCore.removeSelf = () => delete this.getSignals[property] @@ -337,7 +337,7 @@ class Reactor { }, // Have a map of dummy Signals to keep track of dependents on has - // We don't resuse the get Signals to avoid triggering getters + // We don't reuse the get Signals to avoid triggering getters hasSignals: {}, has (property) { // Lazily instantiate has signals @@ -348,7 +348,7 @@ class Reactor { Object.prototype.hasOwnProperty.call(this.hasSignals, property) ? this.hasSignals[property] : new Signal(null) - // User accessor signals to give the actual output + // Use accessor signals to give the actual output // This enables automatic dependency tracking const signalCore = signalCoreExtractor.get(this.hasSignals[property]) signalCore.removeSelf = () => delete this.hasSignals[property] @@ -498,13 +498,10 @@ class Observer extends Function { // Stored return value of the last successful execute // Stored in a Signal which makes it observable itself value: new Signal(), - // Flag on whether this is a unobserve block - // Avoids creating dependencies in that case // Symmetrically removes dependencies clearDependencies () { // Go upstream to break the connection - if (this.dependencies === null) return this.dependencies.forEach(dependency => { dependency.removeDependent(this) }) @@ -568,7 +565,7 @@ class Observer extends Function { } - // Public interace to hide the ugliness of how observers work + // Public interface to hide the ugliness of how observers work // An empty call force triggers the block and turns it on // A call with arguments gets those arguments passed as a context // for that and future retriggers @@ -673,7 +670,7 @@ const batch = function (execute) { } return result - // No need to do anything if batching is already taking place } + // No need to do anything if batching is already taking place } else { return execute() } From 00d5a5c29df3a9ffc76830bf395303cd4386ea96 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 15:48:23 +0000 Subject: [PATCH 63/71] Test fixes --- test/batching.test.js | 5 +++++ test/hiding.test.js | 8 +++++++- test/observer.test.js | 6 +++--- test/reactivity.test.js | 15 +++++++++++++++ test/reactor.test.js | 14 ++------------ 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/test/batching.test.js b/test/batching.test.js index 46de738..d5ce843 100644 --- a/test/batching.test.js +++ b/test/batching.test.js @@ -276,6 +276,11 @@ describe('Batching', () => { assert.strictEqual(runCount, 2) }) + it('returns the return value of the batch function', () => { + const result = batch(() => 'foo') + assert.strictEqual(result, 'foo') + }) + it('throws an error if the batch function it is called with no arguments', () => { assert.throws(() => batch(), { name: 'Error', diff --git a/test/hiding.test.js b/test/hiding.test.js index 2811a6c..2643c55 100644 --- a/test/hiding.test.js +++ b/test/hiding.test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ import assert from 'assert' import { - // Signal, + Signal, Reactor, Observer, // Signals, @@ -97,6 +97,12 @@ describe('Hiding', () => { assert.strictEqual(runValue, 'c') }) + it('can read reactive values outside an observer without error', () => { + const signal = new Signal('foo') + const result = hide(() => signal()) + assert.strictEqual(result, 'foo') + }) + it('throws an error if the hide function is not called with a function', () => { assert.throws(() => hide(), { name: 'Error', diff --git a/test/observer.test.js b/test/observer.test.js index 2a28b79..aa55aa9 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -117,7 +117,7 @@ describe('Observer', () => { message: 'Cannot create observer with a non-function' }) }) - it('fails to initialize with an array', () => { + it('throws an error when initialized with an array', () => { assert.throws(() => new Observer([]), { name: 'TypeError', message: 'Cannot create observer with a non-function' @@ -222,7 +222,7 @@ describe('Observer', () => { }) describe('returns object values wrapped in a reactor', () => { - it('', () => { + it('returns object values wrapped in a reactor', () => { const object = {} const observer = new Observer(() => object) const result = observer() @@ -232,7 +232,7 @@ describe('Observer', () => { }) }) - describe('exposes the last return value throught the value property', () => { + describe('exposes the last return value through the value property', () => { it('exposes the last derived value for primitive values', () => { let counter = 0 const dummyFunction = () => (counter += 1) diff --git a/test/reactivity.test.js b/test/reactivity.test.js index a823875..18009b4 100644 --- a/test/reactivity.test.js +++ b/test/reactivity.test.js @@ -136,6 +136,21 @@ describe('Reactivity', () => { assert.deepEqual(runValue, ['foo', 'baz']) }) + it('builds a dependency when using Object.keys and triggers on property deletion', () => { + let runCount = 0 + let runValue + const reactor = new Reactor({ foo: 'bar', baz: 'qux' }) + new Observer(() => { + runCount += 1 + runValue = Object.keys(reactor) + })() + assert.strictEqual(runCount, 1) + assert.deepEqual(runValue, ['foo', 'baz']) + delete reactor.foo + assert.strictEqual(runCount, 2) + assert.deepEqual(runValue, ['baz']) + }) + it('builds a dependency when using the in operator', () => { let runCount = 0 let runValue diff --git a/test/reactor.test.js b/test/reactor.test.js index 75e5529..5ef3624 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -196,14 +196,14 @@ describe('Reactor', () => { const object = { foo: 'bar' } const reactor = new Reactor(object) delete reactor.foo - assert.equal(object.foo, undefined) + assert.strictEqual(object.foo, undefined) }) it('deletes properties from itself', () => { const object = { foo: 'bar' } const reactor = new Reactor(object) delete reactor.foo - assert.equal(reactor.foo, undefined) + assert.strictEqual(reactor.foo, undefined) }) it('works with Object.defineProperty', () => { @@ -347,16 +347,6 @@ describe('Reactor', () => { assert.deepStrictEqual(shuck(result), [1, 2, 3, 4, [5, 6]]) }) - // it('test flat', () => { - // const array = [1, [2, 3], [4, [5, 6]]] - // const result = array.flat() - // const original56 = array[2][1] - // const result56 = result[4] - // console.log(original56, result56) - // assert(original56 === result56) - // assert.strictEqual(array[2][1], result[4]) - // }) - it('works with Array.prototype.flatMap()', () => { const reactor = new Reactor([1, 2, 3]) const result = reactor.flatMap(x => [x, x * 2]) From c4b00dc49b46300aa683f3142828eafc3668a1dc Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 16:21:23 +0000 Subject: [PATCH 64/71] Fixed array flat --- index.js | 19 ++++++++++++++++++- test/reactor.test.js | 12 ++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 9ef16c1..5094ffe 100644 --- a/index.js +++ b/index.js @@ -244,7 +244,24 @@ class Reactor { // `proxiedMap.keys()` will work because keys gets wrapped by this handler // `Map.prototype.keys.call(proxiedMap)` won't work because it doesnt get wrapped try { - return Reflect.apply(this.source, thisArg, argumentsList) + const result = Reflect.apply(this.source, thisArg, argumentsList) + // flat() reads elements through the proxy to build dependencies correctly, + // but sub-arrays at the un-flattened cut-off depth end up reactor-wrapped + // in the result because they were read from inner reactor proxies. + // Calling flat() on the raw source instead would avoid this, but it + // bypasses the proxy entirely so no dependencies are built. + // Instead we call on the proxy and then unwrap any reactor-wrapped arrays + // left in the result. + if (this.source === Array.prototype.flat && Array.isArray(result)) { + const unwrapReactorArrays = (el) => { + if (!Reactors.has(el)) return el + const source = reactorCoreExtractor.get(el).source + if (!Array.isArray(source)) return el + return source.map(unwrapReactorArrays) + } + return result.map(unwrapReactorArrays) + } + return result } catch (error) { if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { const core = reactorCoreExtractor.get(thisArg) diff --git a/test/reactor.test.js b/test/reactor.test.js index 5ef3624..25806bd 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -334,17 +334,9 @@ describe('Reactor', () => { assert.deepStrictEqual(shuck(result), [5, 4, 3, 1, 1]) }) - it.skip('works with Array.prototype.flat()', () => { + it('works with Array.prototype.flat()', () => { const reactor = new Reactor([1, [2, 3], [4, [5, 6]]]) - const result = reactor.flat() - // Interesting edge case here - // Flat returns a new array with the subarrays being reactor wrapped too - // But the subarrays are reactor wrapped even in the internal object - // This is because flat is constructing them from reactor reads - // Making the apply call use the internal object as `this` solves this - // but it breaks a bunch of other stuff - // TODO find a way to fix this - assert.deepStrictEqual(shuck(result), [1, 2, 3, 4, [5, 6]]) + assert.deepStrictEqual(reactor.flat(), [1, 2, 3, 4, [5, 6]]) }) it('works with Array.prototype.flatMap()', () => { From d9905ff9fbab72c116f47fec721dfdafba856810 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 18:14:32 +0000 Subject: [PATCH 65/71] Optimise Reactor array performance for sort, forEach, and map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three distinct problems caused Reactor arrays to be slow: 1. sort() was O(n² log n) instead of O(n log n) Array.prototype.sort() performs O(n log n) element swaps. Each swap goes through the defineProperty trap, which called trigger(), which unconditionally called Reflect.ownKeys() — an O(n) scan — then built two full Sets to compare them. The result was O(n) work per swap: O(n log n) swaps × O(n) per swap = O(n² log n) overall. For n=5000 this was ~6800ms; after the fix it is ~80ms. 2. forEach/map had high constant-factor overhead outside observers Every element read through the get trap created or looked up a Signal, called signalCore.read(), and checked the dependency stack, even when no observer was tracking the read. For large arrays this added up to a ~10–15× overhead over a direct array access. 3. ownKeys check was coupled into the public batch() API The initial fix for (1) deferred the ownKeys scan to the end of each batch() call, which required batch() to know about pendingOwnKeyChecks — an internal reactor concern that had no place in a public utility. --- How the new system works --- checkReactorOwnKeys(reactorCore) [new top-level helper] Computes the current key set of a reactor's source, compares it against the previously stored set using a Set-difference check, and writes to selfSignal only if the set actually changed. Used in two places: the apply trap's flush loop and trigger()'s synchronous fallback. pendingOwnKeyChecks [global, null when no apply trap is active] A Set of reactor cores that need their ownKeys checked before observers fire. Non-null only while an apply trap's batch execute is running. null is the signal to trigger() that no apply trap is in the call stack. apply trap [owns the pendingOwnKeyChecks lifecycle] On entry to its batch execute it saves the current pendingOwnKeyChecks (handles nested apply traps, e.g. a map callback that calls sort) and installs a fresh empty Set. The native method runs; every trigger() call during that method finds a non-null Set and defers into it rather than computing ownKeys immediately. A try/finally then iterates the Set and calls checkReactorOwnKeys() once per unique reactor — still inside batch's execute phase, so before the observer loop runs. The saved Set is restored on exit, keeping the lifecycles properly nested. get trap [fast path when no observer is watching] If dependencyStack.length === 0 no observer is tracking reads, so the entire signal machinery (lazy Signal creation, signalCore lookup, read registration) can be skipped. The raw value is resolved and returned directly (wrapped in a Reactor if it is an object). The slow path with full signal tracking is taken only when an observer is present. trigger() [defers or checks synchronously] After updating the per-property getSignal and hasSignal, it checks pendingOwnKeyChecks. If non-null (apply trap is active), it adds the reactor core to the set and returns — O(1), deduplicated automatically by Set semantics. If null (direct property write, or a user-level batch() call with no apply trap), it calls checkReactorOwnKeys() immediately so that ownKeys-watching observers are still notified. batch() [unchanged from its original form] The public API knows nothing about ownKeys. It only manages the batcher Set and the observer trigger loop. All ownKeys logic lives in the apply trap and trigger(). Co-Authored-By: Claude Sonnet 4.6 --- index.js | 114 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/index.js b/index.js index e458b7e..d409adc 100644 --- a/index.js +++ b/index.js @@ -26,6 +26,14 @@ const observerCoreExtractor = new WeakMap() // Then clears the batcher again let batcher = null +// Set of reactor cores whose ownKeys need checking before observers fire. +// Owned by the apply trap: each method call (sort, push, …) initialises a +// fresh Set, trigger() adds to it, and the apply trap flushes it once in a +// try/finally — all inside batch's execute, before the observer loop runs. +// null means no apply trap is currently active; trigger() falls back to an +// immediate synchronous check in that case. +let pendingOwnKeyChecks = null + // Cache of objects to their reactor proxies // The same object should always get turned into the same Reactor // This allows for consistent dependency tracking @@ -172,6 +180,26 @@ class Signal extends Function { } } +// Check whether the key set of a reactor has changed and, if so, update its +// selfSignal so that any ownKeys-watching observers are notified. +// Shared by the apply trap (called once per method via pendingOwnKeyChecks) +// and by trigger() when no apply trap is active (direct property writes). +function checkReactorOwnKeys (reactorCore) { + const selfSignalCore = signalCoreExtractor.get(reactorCore.selfSignal) + if (selfSignalCore.dependents.size === 0) return + const currentOwnKeysValue = Reflect.ownKeys(reactorCore.source) + const oldOwnKeysValue = selfSignalCore.value + const currentSet = new Set(currentOwnKeysValue) + const oldSet = new Set(oldOwnKeysValue) + let changed = currentSet.size !== oldSet.size + if (!changed) { + for (const key of currentSet) { + if (!oldSet.has(key)) { changed = true; break } + } + } + if (changed) reactorCore.selfSignal(currentOwnKeysValue) +} + // WeakSet of all Reactors to check if something is a Reactor // Need to implement it this way because you can check instanceof Proxies const Reactors = new WeakSet() @@ -233,6 +261,10 @@ class Reactor { // This allows compound function calls like "Array.push" // to only trigger one round of observer updates return batch(() => { + // Own the pendingOwnKeyChecks lifecycle for this method call. + // Save any outer set (handles nested apply traps), install a fresh + // one so trigger() defers into it, then flush exactly once in the + // finally — still inside batch's execute, so before observers fire. // For native object methods which cant use a Proxy as `this` // try again with the underlying object // Some limitations if the failed attempt has side effects prior to throwing an error @@ -243,21 +275,28 @@ class Reactor { // Also this still wont fix being unable to pass the proxy to static methods // `proxiedMap.keys()` will work because keys gets wrapped by this handler // `Map.prototype.keys.call(proxiedMap)` won't work because it doesnt get wrapped + const savedPendingOwnKeyChecks = pendingOwnKeyChecks + pendingOwnKeyChecks = new Set() try { - return Reflect.apply(this.source, thisArg, argumentsList) - } catch (error) { - if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { - const core = reactorCoreExtractor.get(thisArg) - if (typeof core !== 'undefined') { - // Note that this.source and core.source are different - // core.source is the underlying object - // this.source is the function which is being called with the object as `this` - return Reflect.apply(this.source, core.source, argumentsList) + try { + return Reflect.apply(this.source, thisArg, argumentsList) + } catch (error) { + if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { + const core = reactorCoreExtractor.get(thisArg) + if (typeof core !== 'undefined') { + // Note that this.source and core.source are different + // core.source is the underlying object + // this.source is the function which is being called with the object as `this` + return Reflect.apply(this.source, core.source, argumentsList) + } } + // If any other type of error, or if there's nothing to unwrap throw error anyway + // because then its not a problem with Reactor wrapping + throw error } - // If any other type of error, or if there's nothing to unwrap throw error anyway - // because then its not a problem with Reactor wrapping - throw error + } finally { + for (const reactorCore of pendingOwnKeyChecks) checkReactorOwnKeys(reactorCore) + pendingOwnKeyChecks = savedPendingOwnKeyChecks } }) }, @@ -277,18 +316,7 @@ class Reactor { if (descriptor && !descriptor.writable && !descriptor.configurable) { return Reflect.get(this.source, property, receiver) } - // Lazily instantiate accessor signals - this.getSignals[property] = - // Need to use hasOwnProperty instead of a normal get to avoid - // the basic Object prototype properties - // e.g. constructor - Object.prototype.hasOwnProperty.call(this.getSignals, property) - ? this.getSignals[property] - : new Signal() - // User accessor signals to give the actual output - // This enables automatic dependency tracking - const signalCore = signalCoreExtractor.get(this.getSignals[property]) - signalCore.removeSelf = () => delete this.getSignals[property] + // Resolve the raw value first — needed for both paths below const currentValue = (() => { // Handle getters which require hidden/native properties // If putting the proxy as `this` fails then reveal the underlying object @@ -312,6 +340,26 @@ class Reactor { throw error } })() + // Fast path: nothing on the dependency stack means no observer is + // tracking reads right now, so signal machinery is unnecessary. + // This avoids per-element signal creation overhead in forEach/map + // called outside an observer context. + if (dependencyStack.length === 0) { + if (isObject(currentValue)) return new Reactor(currentValue) + return currentValue + } + // Lazily instantiate accessor signals + this.getSignals[property] = + // Need to use hasOwnProperty instead of a normal get to avoid + // the basic Object prototype properties + // e.g. constructor + Object.prototype.hasOwnProperty.call(this.getSignals, property) + ? this.getSignals[property] + : new Signal() + // User accessor signals to give the actual output + // This enables automatic dependency tracking + const signalCore = signalCoreExtractor.get(this.getSignals[property]) + signalCore.removeSelf = () => delete this.getSignals[property] signalCore.value = currentValue return signalCore.read() }, @@ -372,25 +420,17 @@ class Reactor { // This avoids redundant triggering if they were the same const getValue = Reflect.get(this.source, property) const hasValue = Reflect.has(this.source, property) - // For ownKeys you need to manually calculate the set comparison - const currentOwnKeysValue = Reflect.ownKeys(this.source) - const oldOwnKeysValue = signalCoreExtractor.get(this.selfSignal).value - const ownKeysChanged = (() => { - const currentSet = new Set(currentOwnKeysValue) - const oldSet = new Set(oldOwnKeysValue) - if (currentSet.size !== oldSet.size) return true - for (const key of currentSet) { - if (!oldSet.has(key)) return true - } - return false - })() // Batch together to avoid redundant triggering for shared observers // This might be redundant because the only way this happens is by calling native methods // which are already batched anyway. But keeping for safety batch(() => { if (this.getSignals[property]) this.getSignals[property](getValue) if (this.hasSignals[property]) this.hasSignals[property](hasValue) - if (ownKeysChanged) this.selfSignal(currentOwnKeysValue) + // If an apply trap is active it owns pendingOwnKeyChecks and will + // flush once after the whole method finishes (O(1) per write). + // Otherwise (direct property write, user-level batch()) check now. + if (pendingOwnKeyChecks !== null) pendingOwnKeyChecks.add(this) + else checkReactorOwnKeys(this) }) } } From d11523bf3679dcfdfed648e79f112917d25028a0 Mon Sep 17 00:00:00 2001 From: fynyky Date: Mon, 25 May 2026 18:23:11 +0000 Subject: [PATCH 66/71] Five targeted micro-optimisations across the hot paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Signal.write() — eliminate throwaway Array allocation Array.from(this.dependents).forEach(...) was called on every signal write, allocating a temporary Array purely to iterate it once. The only reason for the snapshot was to allow safe modification of the batcher Set while iterating — but batcher is a *different* Set from this.dependents, so the snapshot was never necessary. Replaced with a plain for...of loop directly over the Set. 2. Object.create(null) for getSignals and hasSignals Both maps were plain {} objects, so accessing a key like "constructor" or "toString" would traverse the prototype chain and find Object prototype properties instead of returning undefined. The workaround was Object.prototype.hasOwnProperty.call(map, key) on every read — a long call chain for every property access. Switching both to Object.create(null) gives prototype-free maps, so a simple truthiness check (!map[key]) is sufficient and safe. 3. trigger() — lazy Reflect.get / Reflect.has trigger() previously pre-computed getValue and hasValue unconditionally, paying for two Reflect calls on every property write even when neither getSignals[property] nor hasSignals[property] existed (i.e. nobody was watching that property). Moved both inside their respective if-guards so they are only evaluated when the corresponding signal is actually present. For sort() on an unwatched array this saves O(n log n) Reflect calls. 4. has trap — fast path when no observer is active The `in` operator went through full signal machinery (lazy Signal creation, signalCore lookups, read registration) even outside any observer context. Added dependencyStack.length === 0 early return that delegates straight to Reflect.has, matching the pattern already used by the get trap. Measured improvement: 31ms → 7ms for 100k checks. 5. ownKeys trap — fast path when no observer is active Object.keys() / for…in / Reflect.ownKeys() on a Reactor was going through selfSignal machinery on every call regardless of whether any observer was watching, making it 1731ms for 100k calls. Added the same dependencyStack.length === 0 fast path. Measured improvement: 1731ms → 204ms (the residual cost is the Proxy runtime's internal getOwnPropertyDescriptor calls for enumerability filtering, which are unavoidable without adding a getOwnPropertyDescriptor trap). Co-Authored-By: Claude Sonnet 4.6 --- index.js | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index d409adc..3082e13 100644 --- a/index.js +++ b/index.js @@ -126,7 +126,9 @@ class Signal extends Function { // Build dependency queue // Do not trigger dependents directly and leave it to be handled by the batcher - Array.from(this.dependents).forEach(dependent => { + // Iterate the Set directly — we only modify batcher (not this.dependents) + // so for...of is safe without snapshotting into a temporary Array + for (const dependent of this.dependents) { // Do this so that the dependent is added to the end of the batcher queue // Needed to ensure downstream observers are triggered again when necessary // as we iterate through the batched dependents @@ -134,7 +136,7 @@ class Signal extends Function { // But in this case it's necessary as we can't know all the downstream dependents ahead of time batcher.delete(dependent) batcher.add(dependent) - }) + } // If it's not an object then just return it right away // Cleaner and faster than the alternative approach of constructing a Reactor // and catching an error @@ -305,7 +307,9 @@ class Reactor { // Reactor properties are read through a trivial Signal // This handles dependency tracking and sub-object Reactor wrapping // Accessor Signals need to be stored to allow persistent dependencies - getSignals: {}, + // Null-prototype objects avoid prototype-chain collisions on keys like + // "constructor" and remove the need for hasOwnProperty.call checks + getSignals: Object.create(null), get (property, receiver) { // Disable unnecessary wrapping for unmodifiable properties // Needed because Array prototype checking fails if wrapped @@ -349,13 +353,8 @@ class Reactor { return currentValue } // Lazily instantiate accessor signals - this.getSignals[property] = - // Need to use hasOwnProperty instead of a normal get to avoid - // the basic Object prototype properties - // e.g. constructor - Object.prototype.hasOwnProperty.call(this.getSignals, property) - ? this.getSignals[property] - : new Signal() + // Safe to use plain property access because getSignals has no prototype + if (!this.getSignals[property]) this.getSignals[property] = new Signal() // User accessor signals to give the actual output // This enables automatic dependency tracking const signalCore = signalCoreExtractor.get(this.getSignals[property]) @@ -386,16 +385,13 @@ class Reactor { // Have a map of dummy Signals to keep track of dependents on has // We don't resuse the get Signals to avoid triggering getters - hasSignals: {}, + // Null-prototype avoids prototype collisions (same rationale as getSignals) + hasSignals: Object.create(null), has (property) { + if (dependencyStack.length === 0) return Reflect.has(this.source, property) // Lazily instantiate has signals - this.hasSignals[property] = - // Need to use hasOwnProperty instead of a normal get to avoid - // the basic Object prototype properties - // e.g. constructor - Object.prototype.hasOwnProperty.call(this.hasSignals, property) - ? this.hasSignals[property] - : new Signal(null) + // Safe to use plain property access because hasSignals has no prototype + if (!this.hasSignals[property]) this.hasSignals[property] = new Signal(null) // User accessor signals to give the actual output // This enables automatic dependency tracking const signalCore = signalCoreExtractor.get(this.hasSignals[property]) @@ -407,6 +403,7 @@ class Reactor { // Subscribe to the overall reactor by reading the dummy signal ownKeys () { + if (dependencyStack.length === 0) return Reflect.ownKeys(this.source) const currentKeys = Reflect.ownKeys(this.source) const signalCore = signalCoreExtractor.get(this.selfSignal) signalCore.value = currentKeys @@ -416,16 +413,15 @@ class Reactor { // Force dependencies to trigger // Hack to do this by trivially "redefining" the signal trigger (property) { - // Calculate the actual new values observers will receive - // This avoids redundant triggering if they were the same - const getValue = Reflect.get(this.source, property) - const hasValue = Reflect.has(this.source, property) // Batch together to avoid redundant triggering for shared observers // This might be redundant because the only way this happens is by calling native methods // which are already batched anyway. But keeping for safety batch(() => { - if (this.getSignals[property]) this.getSignals[property](getValue) - if (this.hasSignals[property]) this.hasSignals[property](hasValue) + // Reflect.get/has are computed lazily — only when a signal for that + // property actually exists — so trigger() is cheap for unobserved + // properties (e.g. every element write during sort when nobody watches) + if (this.getSignals[property]) this.getSignals[property](Reflect.get(this.source, property)) + if (this.hasSignals[property]) this.hasSignals[property](Reflect.has(this.source, property)) // If an apply trap is active it owns pendingOwnKeyChecks and will // flush once after the whole method finishes (O(1) per write). // Otherwise (direct property write, user-level batch()) check now. From 1433dabbbbb4d61b40292bc81e4b257afc35bb31 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 26 May 2026 02:45:21 +0000 Subject: [PATCH 67/71] Flatten nested try into try-catch-finally The outer try-finally and inner try-catch had identical behavior to a single try-catch-finally, since finally runs unconditionally regardless of whether the catch returns or re-throws. Co-Authored-By: Claude Sonnet 4.6 --- index.js | 56 ++++++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/index.js b/index.js index 8b1b026..d95a879 100644 --- a/index.js +++ b/index.js @@ -280,39 +280,35 @@ class Reactor { const savedPendingOwnKeyChecks = pendingOwnKeyChecks pendingOwnKeyChecks = new Set() try { - try { - const result = Reflect.apply(this.source, thisArg, argumentsList) - // flat() reads elements through the proxy to build dependencies correctly, - // but sub-arrays at the un-flattened cut-off depth end up reactor-wrapped - // in the result because they were read from inner reactor proxies. - // Calling flat() on the raw source instead would avoid this, but it - // bypasses the proxy entirely so no dependencies are built. - // Instead we call on the proxy and then unwrap any reactor-wrapped arrays - // left in the result. - if (this.source === Array.prototype.flat && Array.isArray(result)) { - const unwrapReactorArrays = (el) => { - if (!Reactors.has(el)) return el - const source = reactorCoreExtractor.get(el).source - if (!Array.isArray(source)) return el - return source.map(unwrapReactorArrays) - } - return result.map(unwrapReactorArrays) + const result = Reflect.apply(this.source, thisArg, argumentsList) + // flat() reads elements through the proxy to build dependencies correctly, + // but sub-arrays at the un-flattened cut-off depth end up reactor-wrapped + // in the result because they were read from inner reactor proxies. + // Calling flat() on the raw source instead would avoid this, but it + // bypasses the proxy entirely so no dependencies are built. + // Instead we call on the proxy and then unwrap any reactor-wrapped arrays + // left in the result. + if (this.source === Array.prototype.flat && Array.isArray(result)) { + const unwrapReactorArrays = (el) => { + if (!Reactors.has(el)) return el + const source = reactorCoreExtractor.get(el).source + if (!Array.isArray(source)) return el + return source.map(unwrapReactorArrays) } - return result - } catch (error) { - if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { - const core = reactorCoreExtractor.get(thisArg) - if (typeof core !== 'undefined') { - // Note that this.source and core.source are different - // core.source is the underlying object - // this.source is the function which is being called with the object as `this` - return Reflect.apply(this.source, core.source, argumentsList) - } + return result.map(unwrapReactorArrays) + } + return result + } catch (error) { + if (error.name === 'TypeError' && error.message.includes('called on incompatible receiver #')) { + const core = reactorCoreExtractor.get(thisArg) + if (typeof core !== 'undefined') { + // Note that this.source and core.source are different + // core.source is the underlying object + // this.source is the function which is being called with the object as `this` + return Reflect.apply(this.source, core.source, argumentsList) } - // If any other type of error, or if there's nothing to unwrap throw error anyway - // because then its not a problem with Reactor wrapping - throw error } + throw error } finally { for (const reactorCore of pendingOwnKeyChecks) checkReactorOwnKeys(reactorCore) pendingOwnKeyChecks = savedPendingOwnKeyChecks From 49234ef8ddaf3ae03c6bcd55e8d90ae5630218b0 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 26 May 2026 04:23:09 +0000 Subject: [PATCH 68/71] Replace mocha with node:test built-in test runner Removes mocha and the overrides that patched its vulnerable transitive dependencies (serialize-javascript, diff). All test files now import describe/it from node:test directly; the test command switches to node --test. 215 tests pass. Co-Authored-By: Claude Sonnet 4.6 --- package-lock.json | 1100 +-------------------------------------- package.json | 7 +- test/batching.test.js | 2 +- test/complex.test.js | 2 +- test/errors.test.js | 2 +- test/features.test.js | 2 +- test/hiding.test.js | 2 +- test/observer.test.js | 2 +- test/reactivity.test.js | 2 +- test/reactor.test.js | 2 +- test/signal.test.js | 2 +- 11 files changed, 18 insertions(+), 1107 deletions(-) diff --git a/package-lock.json b/package-lock.json index c448690..6858ebf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "weak-ref-collections": "^1.2.4" }, "devDependencies": { - "mocha": "^11.7.6", "standard": "^17.1.2" } }, @@ -164,109 +163,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "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, - "license": "ISC", - "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" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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, - "license": "MIT" - }, - "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, - "license": "MIT", - "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" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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, - "license": "MIT", - "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" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -302,17 +198,6 @@ "node": ">= 8" } }, - "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, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -596,22 +481,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, "node_modules/builtins": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", @@ -695,18 +564,6 @@ "node": ">=6" } }, - "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/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -735,37 +592,6 @@ "node": ">=8" } }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "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, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -877,18 +703,6 @@ } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -932,16 +746,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", - "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -969,20 +773,6 @@ "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, - "license": "MIT" - }, - "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, - "license": "MIT" - }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -1170,16 +960,6 @@ "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, - "license": "MIT", - "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", @@ -1865,15 +1645,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -1910,23 +1681,6 @@ "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, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1984,16 +1738,6 @@ "node": ">= 0.4" } }, - "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, - "license": "ISC", - "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", @@ -2261,15 +2005,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2504,16 +2239,6 @@ "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-generator-function": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", @@ -2598,15 +2323,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -2706,18 +2422,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -2795,22 +2499,6 @@ "node": ">= 0.4" } }, - "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, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2938,22 +2626,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2966,13 +2638,6 @@ "loose-envify": "cli.js" } }, - "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, - "license": "ISC" - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2983,22 +2648,6 @@ "node": ">= 0.4" } }, - "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -3009,75 +2658,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "11.7.6", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", - "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "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/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3315,13 +2895,6 @@ "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, - "license": "BlueOak-1.0.0" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3383,30 +2956,6 @@ "dev": true, "license": "MIT" }, - "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, - "license": "BlueOak-1.0.0", - "dependencies": { - "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" - } - }, - "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, - "license": "ISC" - }, "node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -3564,20 +3113,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -3635,16 +3170,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "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, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve": { "version": "2.0.0-next.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", @@ -3792,16 +3317,6 @@ "semver": "bin/semver.js" } }, - "node_modules/serialize-javascript": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", - "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -3948,19 +3463,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/standard": { "version": "17.1.2", "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.2.tgz", @@ -4026,52 +3528,21 @@ "xdg-basedir": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "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, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "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==", + "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, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, "node_modules/string.prototype.matchall": { @@ -4184,20 +3655,6 @@ "node": ">=8" } }, - "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, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -4220,21 +3677,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "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", @@ -4530,50 +3972,6 @@ "node": ">=0.10.0" } }, - "node_modules/workerpool": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", - "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", - "dev": true, - "license": "Apache-2.0" - }, - "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, - "license": "MIT", - "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, - "license": "MIT", - "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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4590,60 +3988,6 @@ "node": ">=8" } }, - "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, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "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, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "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, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4761,71 +4105,6 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, - "@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, - "requires": { - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true - }, - "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 - }, - "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 - }, - "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": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "requires": { - "ansi-regex": "^6.2.2" - } - }, - "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": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4852,13 +4131,6 @@ "fastq": "^1.6.0" } }, - "@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 - }, "@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -5051,21 +4323,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, "builtins": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", @@ -5121,12 +4378,6 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "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", @@ -5148,26 +4399,6 @@ } } }, - "chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "requires": { - "readdirp": "^4.0.1" - } - }, - "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": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -5242,12 +4473,6 @@ "ms": "^2.1.3" } }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5276,12 +4501,6 @@ "object-keys": "^1.1.1" } }, - "diff": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", - "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", - "dev": true - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -5302,18 +4521,6 @@ "gopd": "^1.2.0" } }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "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 - }, "error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -5462,12 +4669,6 @@ "is-symbol": "^1.0.4" } }, - "escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -5937,12 +5138,6 @@ "path-exists": "^4.0.0" } }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -5968,16 +5163,6 @@ "is-callable": "^1.2.7" } }, - "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, - "requires": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -6016,12 +5201,6 @@ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true }, - "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 - }, "get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -6193,12 +5372,6 @@ "function-bind": "^1.1.2" } }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, "ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -6348,12 +5521,6 @@ "call-bound": "^1.0.3" } }, - "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 - }, "is-generator-function": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", @@ -6404,12 +5571,6 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, "is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -6467,12 +5628,6 @@ "which-typed-array": "^1.1.16" } }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, "is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -6524,16 +5679,6 @@ "set-function-name": "^2.0.2" } }, - "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, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6632,16 +5777,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6651,84 +5786,18 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "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 - }, "math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true }, - "minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.2" - } - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, - "minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true - }, - "mocha": { - "version": "11.7.6", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", - "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", - "dev": true, - "requires": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^9.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "7.0.5", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "requires": { - "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" - } - } - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6890,12 +5959,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "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": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6939,22 +6002,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "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": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - } - }, - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -7057,12 +6104,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, - "readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true - }, "reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -7099,12 +6140,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "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 - }, "resolve": { "version": "2.0.0-next.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", @@ -7189,12 +6224,6 @@ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, - "serialize-javascript": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", - "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", - "dev": true - }, "set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -7295,12 +6324,6 @@ "side-channel-map": "^1.0.1" } }, - "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 - }, "standard": { "version": "17.1.2", "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.2.tgz", @@ -7340,28 +6363,6 @@ "internal-slot": "^1.1.0" } }, - "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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, "string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -7440,15 +6441,6 @@ "ansi-regex": "^5.0.1" } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -7461,15 +6453,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "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" - } - }, "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", @@ -7670,34 +6653,6 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, - "workerpool": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", - "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", - "dev": true - }, - "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": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@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": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -7710,45 +6665,6 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "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": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "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 - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 825af1d..feff1a0 100644 --- a/package.json +++ b/package.json @@ -7,20 +7,15 @@ "files": [ "index.js" ], - "overrides": { - "serialize-javascript": "7.0.5", - "diff": "^9.0.0" - }, "dependencies": { "weak-ref-collections": "^1.2.4" }, "devDependencies": { - "mocha": "^11.7.6", "standard": "^17.1.2" }, "scripts": { "lint": "standard --fix", - "test": "standard && mocha test/test.js", + "test": "standard && node --test test/test.js", "prepublishOnly": "npm test" }, "repository": { diff --git a/test/batching.test.js b/test/batching.test.js index d5ce843..82a641e 100644 --- a/test/batching.test.js +++ b/test/batching.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { Signal, diff --git a/test/complex.test.js b/test/complex.test.js index ac71b36..ba478d1 100644 --- a/test/complex.test.js +++ b/test/complex.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { // Signal, diff --git a/test/errors.test.js b/test/errors.test.js index 35a219b..87a4c34 100644 --- a/test/errors.test.js +++ b/test/errors.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { // Signal, diff --git a/test/features.test.js b/test/features.test.js index eb93b78..7653d21 100644 --- a/test/features.test.js +++ b/test/features.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { // Signal, diff --git a/test/hiding.test.js b/test/hiding.test.js index 2643c55..54504d1 100644 --- a/test/hiding.test.js +++ b/test/hiding.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { Signal, diff --git a/test/observer.test.js b/test/observer.test.js index aa55aa9..53520e8 100644 --- a/test/observer.test.js +++ b/test/observer.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { // Signal, diff --git a/test/reactivity.test.js b/test/reactivity.test.js index 18009b4..aa4330b 100644 --- a/test/reactivity.test.js +++ b/test/reactivity.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { Signal, diff --git a/test/reactor.test.js b/test/reactor.test.js index 25806bd..8739296 100644 --- a/test/reactor.test.js +++ b/test/reactor.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { // Signal, diff --git a/test/signal.test.js b/test/signal.test.js index 64b7c1b..a6224d2 100644 --- a/test/signal.test.js +++ b/test/signal.test.js @@ -1,4 +1,4 @@ -/* eslint-env mocha */ +import { describe, it } from 'node:test' import assert from 'assert' import { Signal, From ee5b69b57b008b0fa5afcfcebe3c7dab4281d267 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 26 May 2026 04:24:11 +0000 Subject: [PATCH 69/71] Update CI workflows and add project instructions Replaces the old npm-publish and pull-request-test workflows with updated publish and test workflows (actions v6, Node 24). Adds the Claude Code GitHub Actions workflow and CLAUDE.md project instructions. Co-Authored-By: Claude Sonnet 4.6 --- .claude/CLAUDE.md | 16 +++++++ .github/workflows/claude.yml | 58 +++++++++++++++++++++++++ .github/workflows/npm-publish.yml | 33 -------------- .github/workflows/publish.yml | 22 ++++++++++ .github/workflows/pull-request-test.yml | 27 ------------ .github/workflows/test.yml | 17 ++++++++ 6 files changed, 113 insertions(+), 60 deletions(-) create mode 100644 .claude/CLAUDE.md create mode 100644 .github/workflows/claude.yml delete mode 100644 .github/workflows/npm-publish.yml create mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/pull-request-test.yml create mode 100644 .github/workflows/test.yml diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..a42873d --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,16 @@ +## Git Workflow + +Always work on a feature branch. Never commit or push directly to +master, main, or any release branch. + +Branch naming: `claude/` +e.g. `claude/fix-login-bug`, `claude/add-payment-endpoint` + +Workflow for every task: +1. `git checkout master && git pull` +2. `git checkout -b claude/` +3. Make changes and commit +4. `git push -u origin claude/` +5. `gh pr create` + +Never force push. Never delete branches. Never merge your own PRs. \ No newline at end of file diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 0000000..81c9430 --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,58 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + + # Optional: Customize the trigger phrase (default: @claude) + # trigger_phrase: "/claude" + + # Optional: Trigger when specific user is assigned to an issue + # assignee_trigger: "claude-bot" + + # Optional: Configure Claude's behavior with CLI arguments + # claude_args: | + # --model claude-opus-4-1-20250805 + # --max-turns 10 + # --allowedTools "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)" + # --system-prompt "Follow our coding standards. Ensure all new code has tests. Use TypeScript for new files." + + # Optional: Advanced settings configuration + # settings: | + # { + # "env": { + # "NODE_ENV": "test" + # } + # } \ No newline at end of file diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml deleted file mode 100644 index 7dcc2b9..0000000 --- a/.github/workflows/npm-publish.yml +++ /dev/null @@ -1,33 +0,0 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - -name: Publish to NPM - -on: - push: - branches: release - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 22 - - run: npm ci - - run: npm test - - publish-npm: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 22 - registry-url: https://registry.npmjs.org/ - - run: npm ci - - run: npm publish - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..0cac25d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,22 @@ +name: Publish +on: + push: + branches: release + +permissions: + id-token: write + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: 'https://registry.npmjs.org' + package-manager-cache: false + - run: npm ci + - run: npm test + - run: npm publish \ No newline at end of file diff --git a/.github/workflows/pull-request-test.yml b/.github/workflows/pull-request-test.yml deleted file mode 100644 index 1e0667c..0000000 --- a/.github/workflows/pull-request-test.yml +++ /dev/null @@ -1,27 +0,0 @@ -# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - -name: Test on Pull Request - -on: pull_request - -jobs: - test: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20.x, 22.x, 24.x] - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - - steps: - - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - run: npm ci - - run: npm run build --if-present - - run: npm test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..5de1f1c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,17 @@ +name: Test +on: + push: + branches: master + pull_request: + branches: master + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version: 24 + - run: npm ci + - run: npm test \ No newline at end of file From 6e90fa603e35e6239ff37d1fc71bf863037fe943 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 26 May 2026 08:36:58 +0000 Subject: [PATCH 70/71] Fix stale expected outputs, missing declarations, and typos in docs and comments Co-Authored-By: Claude Sonnet 4.6 --- README.md | 16 +++++++++------- index.js | 10 +++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7c889c1..0dd8b0a 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Import it using: import { Reactor, Observer, hide, batch, shuck } from 'reactorjs' ``` -It is also available directly from [unpkg](unpkg.com). You can import it in JavaScript using: +It is also available directly from [unpkg](https://unpkg.com). You can import it in JavaScript using: ```javascript import { Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactorjs' ``` @@ -266,6 +266,7 @@ observer() // prints "hola" Like normal functions, observers can expect and be called with arguments. They remember the arguments from the last time they were called and reuse them when automatically triggered: ```javascript +const reactor = new Reactor({ foo: 'baz' }) const parameterizedObserver = new Observer((arg1, arg2) => { console.log(reactor.foo + arg1 + arg2) }) @@ -276,6 +277,7 @@ reactor.foo = 'bla' // prints blabeepbop Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of ES6 arrow functions: ```javascript +const reactor = new Reactor({ foo: 'bla' }) const holdingObject = { name: 'Mario', greet: new Observer(function () { // Need to use `function` @@ -379,7 +381,7 @@ batch(() => { This is useful when you are making multiple data updates and want to avoid showing an "incomplete" view of the data to observers. -Note that only the observer triggering is postponed until the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine. +Note that only the observer triggering is postponed until the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the batch block working just fine. Summary ------- @@ -398,16 +400,16 @@ reactor.foo = 'baz' // prints 'reactor.foo is baz' observer.stop() reactor.foo = 'qux' // prints nothing since observer is stopped -observer.start() // prints 'reactor.foo is baz' +observer.start() // prints 'reactor.foo is qux' observer.start() // prints nothing since observer is already started -observer() // prints 'reactor.foo is baz' even if it is already running +observer() // prints 'reactor.foo is qux' even if it is already running // Observer return values are themselves observable const trailingObserver = new Observer(() => { const result = 'Did you hear: ' + observer.value console.log(result) }) -trailingObserver() // prints 'Did you hear: reactor.foo is baz' +trailingObserver() // prints 'Did you hear: reactor.foo is qux' reactor.foo = 'blorp' // prints 'reactor.foo is blorp' from observer // also prints 'Did you hear: reactor.foo is blorp' from trailingObserver @@ -415,7 +417,7 @@ reactor.foo = 'blorp' // prints 'reactor.foo is blorp' from observer const parameterizedObserver = new Observer((arg1, arg2) => { console.log(reactor.foo + arg1 + arg2) }) -parameterizedObserver('beep', 'bop') // prints bazbeepbop +parameterizedObserver('beep', 'bop') // prints blorpbeepbop reactor.foo = 'bla' // prints blabeepbop // Observers can also access and remember the last `this` context @@ -468,7 +470,7 @@ Map.prototype.keys.call(shuck(mapReactor)) // works fine Development & Testing --------------------- -Tests are stored in `test.js` to be run using Mocha. +Tests are stored in `test/` to be run using the Node.js built-in test runner. Run `npm install` to install the dev dependencies. diff --git a/index.js b/index.js index d95a879..bd76eeb 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ import { WeakRefSet } from 'weak-ref-collections' // - The reader gets added as a dependent of the readee // - The readee gets added as a dependency of the reader // - When the signal evaluation is done, the observer pops itself off the stack -// The stack is used to track the latest signal caller automaticaly +// The stack is used to track the latest active observer automatically // Using a stack allows nested signals to function correctly const dependencyStack = [] @@ -19,7 +19,7 @@ const reactorCoreExtractor = new WeakMap() const observerCoreExtractor = new WeakMap() // A batcher is used to postpone observer triggers and batch them together -// When "batch" is called it adds sets a batcher to this global variable +// When "batch" is called it sets a batcher to this global variable // When a Signal is updated it checks if a batcher is set // If it is, it adds that observer to this set instead of triggering it // At the end of the execution, the batch call then calls all the observers @@ -42,8 +42,8 @@ const reactorCache = new WeakMap() // Helper function for checking if something is an object function isObject (x) { - // functions are objects also but typeof to function - // nulls are not objects but typeof to objects + // functions are objects but typeof returns 'function' + // nulls are not objects but typeof returns 'object' // the last bit is to check for nulls const type = typeof (x) return ((type === 'function' || type === 'object') && !!x) @@ -507,7 +507,7 @@ class Reactor { // b.foo = "bar" // let observer = new Observer(() => { This will trigger whenever // console.log("a is now " + a()) a or b.foo are updated -// console.log("b.foois now " + b.foo) +// console.log("b.foo is now " + b.foo) // }) // observer() // a(2) This will trigger an update From 42963016d2c918ffaed4b1f44ecea240d59fe0c0 Mon Sep 17 00:00:00 2001 From: fynyky Date: Tue, 26 May 2026 08:58:36 +0000 Subject: [PATCH 71/71] Bump version to 3.1.1 Co-Authored-By: Claude Sonnet 4.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index feff1a0..97f794e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reactorjs", - "version": "3.1.0", + "version": "3.1.1", "description": "Simple reactive programming without frameworks", "type": "module", "main": "index.js",